! Copyright (C) 2004, 2010 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs classes classes.algebra classes.algebra.private classes.private classes.union classes.union.private combinators definitions kernel sequences words ; IN: classes.mixin PREDICATE: mixin-class < union-class "mixin" word-prop ; M: mixin-class normalize-class ; M: mixin-class (classes-intersect?) class-members [ classes-intersect? ] with any? ; M: mixin-class reset-class [ call-next-method ] [ "mixin" remove-word-prop ] bi ; M: mixin-class rank-class drop 8 ; ERROR: not-a-class object ; ERROR: not-a-mixin-class object ; : check-types ( class mixin -- class mixin ) [ dup class? [ not-a-class ] unless ] [ dup mixin-class? [ not-a-mixin-class ] unless ] bi* ; : add-mixin-instance ( class mixin -- ) check-types [ 2drop ] [ (add-mixin-instance) ] if-mixin-member? ; : remove-mixin-instance ( class mixin -- ) [ (remove-mixin-instance) ] [ 2drop ] if-mixin-member? ; M: mixin-class metaclass-changed over class? [ 2drop ] [ remove-mixin-instance ] if ; : define-mixin-class ( class -- ) dup mixin-class? [ drop ] [ [ { } redefine-mixin-class ] [ H{ } clone "instances" set-word-prop ] [ update-classes ] tri ] if ; ! Definition protocol implementation ensures that removing an ! INSTANCE: declaration from a source file updates the mixin. TUPLE: mixin-instance class mixin ; C: mixin-instance mixin-instance< ( mixin-instance -- class mixin ) [ class>> ] [ mixin>> ] bi ; inline PRIVATE> M: mixin-instance where >mixin-instance< "instances" word-prop at ; M: mixin-instance set-where >mixin-instance< "instances" word-prop set-at ; M: mixin-instance definer drop \ INSTANCE: f ; M: mixin-instance definition drop f ; M: mixin-instance forget* >mixin-instance< dup mixin-class? [ remove-mixin-instance ] [ 2drop ] if ;