2008-01-05 19:37:13 -05:00
|
|
|
! Copyright (C) 2004, 2008 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-01-04 21:10:49 -05:00
|
|
|
USING: classes classes.union words kernel sequences
|
2008-06-09 03:14:14 -04:00
|
|
|
definitions combinators arrays assocs generic accessors ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: classes.mixin
|
|
|
|
|
2008-03-26 19:23:19 -04:00
|
|
|
PREDICATE: mixin-class < union-class "mixin" word-prop ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
M: mixin-class reset-class
|
2008-06-25 04:25:08 -04:00
|
|
|
[ call-next-method ] [ { "mixin" } reset-props ] bi ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
M: mixin-class rank-class drop 3 ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: redefine-mixin-class ( class members -- )
|
2008-06-09 03:14:14 -04:00
|
|
|
[ (define-union-class) ]
|
|
|
|
[ drop t "mixin" set-word-prop ]
|
|
|
|
2bi ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: define-mixin-class ( class -- )
|
|
|
|
dup mixin-class? [
|
|
|
|
drop
|
|
|
|
] [
|
2008-08-28 23:28:34 -04:00
|
|
|
[ { } redefine-mixin-class ]
|
|
|
|
[ update-classes ]
|
|
|
|
bi
|
2007-09-20 18:09:08 -04:00
|
|
|
] if ;
|
|
|
|
|
2008-01-04 21:10:49 -05:00
|
|
|
TUPLE: check-mixin-class mixin ;
|
|
|
|
|
|
|
|
: check-mixin-class ( mixin -- mixin )
|
|
|
|
dup mixin-class? [
|
2008-04-13 16:06:09 -04:00
|
|
|
\ check-mixin-class boa throw
|
2008-01-04 21:10:49 -05:00
|
|
|
] unless ;
|
|
|
|
|
|
|
|
: if-mixin-member? ( class mixin true false -- )
|
2008-06-09 03:14:14 -04:00
|
|
|
[ check-mixin-class 2dup members memq? ] 2dip if ; inline
|
2008-01-04 21:10:49 -05:00
|
|
|
|
|
|
|
: change-mixin-class ( class mixin quot -- )
|
2008-06-09 03:14:14 -04:00
|
|
|
[ [ members swap bootstrap-word ] dip call ] [ drop ] 2bi
|
2008-01-04 21:10:49 -05:00
|
|
|
swap redefine-mixin-class ; inline
|
|
|
|
|
2008-08-30 03:31:27 -04:00
|
|
|
: update-classes/new ( mixin -- )
|
|
|
|
class-usages
|
|
|
|
[ [ update-class ] each ]
|
|
|
|
[ implementors [ make-generic ] each ] bi ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: add-mixin-instance ( class mixin -- )
|
2008-06-09 03:14:14 -04:00
|
|
|
#! Note: we call update-classes on the new member, not the
|
|
|
|
#! mixin. This ensures that we only have to update the
|
|
|
|
#! methods whose specializer intersects the new member, not
|
|
|
|
#! the entire mixin (since the other mixin members are not
|
|
|
|
#! affected at all). Also, all usages of the mixin will get
|
|
|
|
#! updated by transitivity; the mixins usages appear in
|
|
|
|
#! class-usages of the member, now that it's been added.
|
|
|
|
[ 2drop ] [
|
2008-08-30 03:31:27 -04:00
|
|
|
[ [ suffix ] change-mixin-class ] 2keep
|
|
|
|
tuck [ new-class? ] either? [
|
|
|
|
update-classes/new
|
|
|
|
] [
|
|
|
|
update-classes
|
|
|
|
] if
|
2008-06-09 03:14:14 -04:00
|
|
|
] if-mixin-member? ;
|
2008-01-04 21:10:49 -05:00
|
|
|
|
|
|
|
: remove-mixin-instance ( class mixin -- )
|
2008-09-03 18:24:06 -04:00
|
|
|
#! The order of the three clauses is important here. The last
|
|
|
|
#! one must come after the other two so that the entries it
|
|
|
|
#! adds to changed-generics are not overwritten.
|
2008-06-09 03:14:14 -04:00
|
|
|
[
|
2008-08-31 02:34:00 -04:00
|
|
|
[ [ swap remove ] change-mixin-class ]
|
|
|
|
[ nip update-classes ]
|
2008-09-03 18:24:06 -04:00
|
|
|
[ class-usages update-methods ]
|
2008-08-31 02:34:00 -04:00
|
|
|
2tri
|
2008-06-09 03:14:14 -04:00
|
|
|
] [ 2drop ] if-mixin-member? ;
|
2008-01-04 21:10:49 -05:00
|
|
|
|
2008-07-04 02:32:11 -04:00
|
|
|
M: mixin-class class-forgotten remove-mixin-instance ;
|
|
|
|
|
2008-01-04 21:10:49 -05:00
|
|
|
! Definition protocol implementation ensures that removing an
|
|
|
|
! INSTANCE: declaration from a source file updates the mixin.
|
|
|
|
TUPLE: mixin-instance loc class mixin ;
|
|
|
|
|
2008-01-05 19:37:13 -05:00
|
|
|
M: mixin-instance equal?
|
|
|
|
{
|
|
|
|
{ [ over mixin-instance? not ] [ f ] }
|
2008-08-31 08:45:33 -04:00
|
|
|
{ [ 2dup [ class>> ] bi@ = not ] [ f ] }
|
|
|
|
{ [ 2dup [ mixin>> ] bi@ = not ] [ f ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ t ]
|
2008-01-05 19:37:13 -05:00
|
|
|
} cond 2nip ;
|
|
|
|
|
2008-01-05 21:06:01 -05:00
|
|
|
M: mixin-instance hashcode*
|
2008-03-29 01:59:05 -04:00
|
|
|
[ class>> ] [ mixin>> ] bi 2array hashcode* ;
|
2008-01-05 21:06:01 -05:00
|
|
|
|
2008-01-04 21:10:49 -05:00
|
|
|
: <mixin-instance> ( class mixin -- definition )
|
2008-06-30 06:22:05 -04:00
|
|
|
mixin-instance new
|
|
|
|
swap >>mixin
|
|
|
|
swap >>class ;
|
2008-01-04 21:10:49 -05:00
|
|
|
|
2008-08-31 08:45:33 -04:00
|
|
|
M: mixin-instance where loc>> ;
|
2008-01-04 21:10:49 -05:00
|
|
|
|
2008-08-31 08:45:33 -04:00
|
|
|
M: mixin-instance set-where (>>loc) ;
|
2008-01-04 21:10:49 -05:00
|
|
|
|
|
|
|
M: mixin-instance definer drop \ INSTANCE: f ;
|
|
|
|
|
|
|
|
M: mixin-instance definition drop f ;
|
|
|
|
|
2008-01-09 16:51:55 -05:00
|
|
|
M: mixin-instance forget*
|
2008-08-31 08:45:33 -04:00
|
|
|
[ class>> ] [ mixin>> ] bi
|
2008-08-31 08:55:34 -04:00
|
|
|
dup mixin-class? [ remove-mixin-instance ] [ 2drop ] if ;
|