1 ! Copyright (C) 2004, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: classes classes.union words kernel sequences
4 definitions combinators arrays assocs generic accessors ;
7 PREDICATE: mixin-class < union-class "mixin" word-prop ;
9 M: mixin-class reset-class
10 [ call-next-method ] [ { "mixin" } reset-props ] bi ;
12 M: mixin-class rank-class drop 3 ;
14 : redefine-mixin-class ( class members -- )
15 [ (define-union-class) ]
16 [ drop t "mixin" set-word-prop ]
19 : define-mixin-class ( class -- )
23 [ { } redefine-mixin-class ]
28 TUPLE: check-mixin-class class ;
30 : check-mixin-class ( mixin -- mixin )
32 \ check-mixin-class boa throw
35 : if-mixin-member? ( class mixin true false -- )
36 [ check-mixin-class 2dup members memq? ] 2dip if ; inline
38 : change-mixin-class ( class mixin quot -- )
39 [ [ members swap bootstrap-word ] dip call ] [ drop ] 2bi
40 swap redefine-mixin-class ; inline
42 : update-classes/new ( mixin -- )
44 [ [ update-class ] each ]
45 [ implementors [ remake-generic ] each ] bi ;
47 : add-mixin-instance ( class mixin -- )
48 #! Note: we call update-classes on the new member, not the
49 #! mixin. This ensures that we only have to update the
50 #! methods whose specializer intersects the new member, not
51 #! the entire mixin (since the other mixin members are not
52 #! affected at all). Also, all usages of the mixin will get
53 #! updated by transitivity; the mixins usages appear in
54 #! class-usages of the member, now that it's been added.
56 [ [ suffix ] change-mixin-class ] 2keep
57 tuck [ new-class? ] either? [
64 : remove-mixin-instance ( class mixin -- )
65 #! The order of the three clauses is important here. The last
66 #! one must come after the other two so that the entries it
67 #! adds to changed-generics are not overwritten.
69 [ [ swap remove ] change-mixin-class ]
70 [ nip update-classes ]
71 [ class-usages update-methods ]
73 ] [ 2drop ] if-mixin-member? ;
75 M: mixin-class class-forgotten remove-mixin-instance ;
77 ! Definition protocol implementation ensures that removing an
78 ! INSTANCE: declaration from a source file updates the mixin.
79 TUPLE: mixin-instance loc class mixin ;
81 M: mixin-instance equal?
83 { [ over mixin-instance? not ] [ f ] }
84 { [ 2dup [ class>> ] bi@ = not ] [ f ] }
85 { [ 2dup [ mixin>> ] bi@ = not ] [ f ] }
89 M: mixin-instance hashcode*
90 [ class>> ] [ mixin>> ] bi 2array hashcode* ;
92 : <mixin-instance> ( class mixin -- definition )
97 M: mixin-instance where loc>> ;
99 M: mixin-instance set-where (>>loc) ;
101 M: mixin-instance definer drop \ INSTANCE: f ;
103 M: mixin-instance definition drop f ;
105 M: mixin-instance forget*
106 [ class>> ] [ mixin>> ] bi
107 dup mixin-class? [ remove-mixin-instance ] [ 2drop ] if ;