282 lines
7.0 KiB
Factor
282 lines
7.0 KiB
Factor
! Copyright (C) 2004, 2007 Slava Pestov.
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
IN: classes
|
|
USING: arrays definitions assocs kernel
|
|
kernel.private slots.private namespaces sequences strings words
|
|
vectors math quotations combinators sorting effects graphs ;
|
|
|
|
PREDICATE: word class ( obj -- ? ) "class" word-prop ;
|
|
|
|
SYMBOL: typemap
|
|
SYMBOL: class<map
|
|
SYMBOL: update-map
|
|
SYMBOL: builtins
|
|
|
|
PREDICATE: word builtin-class
|
|
"metaclass" word-prop builtin-class eq? ;
|
|
|
|
PREDICATE: class tuple-class
|
|
"metaclass" word-prop tuple-class eq? ;
|
|
|
|
: classes ( -- seq ) class<map get keys ;
|
|
|
|
: type>class ( n -- class ) builtins get nth ;
|
|
|
|
: predicate-word ( word -- predicate )
|
|
[ word-name "?" append ] keep word-vocabulary create ;
|
|
|
|
: predicate-effect 1 { "?" } <effect> ;
|
|
|
|
PREDICATE: compound predicate
|
|
"predicating" word-prop >boolean ;
|
|
|
|
: define-predicate ( class predicate quot -- )
|
|
over [
|
|
dupd predicate-effect define-declared
|
|
2dup 1quotation "predicate" set-word-prop
|
|
swap "predicating" set-word-prop
|
|
] [
|
|
3drop
|
|
] if ;
|
|
|
|
: superclass ( class -- super )
|
|
"superclass" word-prop ;
|
|
|
|
: members ( class -- seq ) "members" word-prop ;
|
|
|
|
: class-empty? ( class -- ? ) members dup [ empty? ] when ;
|
|
|
|
: (flatten-union-class) ( class -- )
|
|
dup members [
|
|
[ (flatten-union-class) ] each
|
|
] [
|
|
dup set
|
|
] ?if ;
|
|
|
|
: flatten-union-class ( class -- assoc )
|
|
[ (flatten-union-class) ] H{ } make-assoc ;
|
|
|
|
: (flatten-class) ( class -- )
|
|
{
|
|
{ [ dup tuple-class? ] [ dup set ] }
|
|
{ [ dup builtin-class? ] [ dup set ] }
|
|
{ [ dup members ] [ members [ (flatten-class) ] each ] }
|
|
{ [ dup superclass ] [ superclass (flatten-class) ] }
|
|
} cond ;
|
|
|
|
: flatten-class ( class -- assoc )
|
|
[ (flatten-class) ] H{ } make-assoc ;
|
|
|
|
: class-hashes ( class -- seq )
|
|
flatten-class keys [
|
|
dup builtin-class?
|
|
[ "type" word-prop ] [ hashcode ] if
|
|
] map ;
|
|
|
|
: (flatten-builtin-class) ( class -- )
|
|
{
|
|
{ [ dup members ] [ members [ (flatten-builtin-class) ] each ] }
|
|
{ [ dup superclass ] [ superclass (flatten-builtin-class) ] }
|
|
{ [ t ] [ dup set ] }
|
|
} cond ;
|
|
|
|
: flatten-builtin-class ( class -- assoc )
|
|
[ (flatten-builtin-class) ] H{ } make-assoc ;
|
|
|
|
: types ( class -- seq )
|
|
flatten-builtin-class keys
|
|
[ "type" word-prop ] map natural-sort ;
|
|
|
|
: class< ( class1 class2 -- ? ) swap class<map get at key? ;
|
|
|
|
<PRIVATE
|
|
|
|
DEFER: (class<)
|
|
|
|
: superclass< ( cls1 cls2 -- ? )
|
|
>r superclass r> 2dup and [ (class<) ] [ 2drop f ] if ;
|
|
|
|
: union-class< ( cls1 cls2 -- ? )
|
|
[ flatten-union-class ] 2apply keys
|
|
[ nip [ (class<) ] curry* contains? ] curry assoc-all? ;
|
|
|
|
: (class<) ( class1 class2 -- ? )
|
|
{
|
|
{ [ 2dup eq? ] [ 2drop t ] }
|
|
{ [ over class-empty? ] [ 2drop t ] }
|
|
{ [ 2dup superclass< ] [ 2drop t ] }
|
|
{ [ 2dup [ members not ] both? ] [ 2drop f ] }
|
|
{ [ t ] [ union-class< ] }
|
|
} cond ;
|
|
|
|
: lookup-union ( classes -- class )
|
|
typemap get at dup empty? [ drop object ] [ first ] if ;
|
|
|
|
: (class-or) ( class class -- class )
|
|
[ flatten-builtin-class ] 2apply union lookup-union ;
|
|
|
|
: (class-and) ( class class -- class )
|
|
[ flatten-builtin-class ] 2apply intersect lookup-union ;
|
|
|
|
: tuple-class-and ( class1 class2 -- class )
|
|
dupd eq? [ drop null ] unless ;
|
|
|
|
: largest-class ( seq -- n elt )
|
|
dup [
|
|
[ 2dup class< >r swap class< not r> and ]
|
|
curry* subset empty?
|
|
] curry find [ "Topological sort failed" throw ] unless* ;
|
|
|
|
: (sort-classes) ( vec -- )
|
|
dup empty?
|
|
[ drop ]
|
|
[ dup largest-class , over delete-nth (sort-classes) ] if ;
|
|
|
|
PRIVATE>
|
|
|
|
: sort-classes ( seq -- newseq )
|
|
[ >vector (sort-classes) ] { } make ;
|
|
|
|
: class-or ( class1 class2 -- class )
|
|
{
|
|
{ [ 2dup class< ] [ nip ] }
|
|
{ [ 2dup swap class< ] [ drop ] }
|
|
{ [ t ] [ (class-or) ] }
|
|
} cond ;
|
|
|
|
: class-and ( class1 class2 -- class )
|
|
{
|
|
{ [ 2dup class< ] [ drop ] }
|
|
{ [ 2dup swap class< ] [ nip ] }
|
|
{ [ 2dup [ tuple-class? ] both? ] [ tuple-class-and ] }
|
|
{ [ t ] [ (class-and) ] }
|
|
} cond ;
|
|
|
|
: classes-intersect? ( class1 class2 -- ? )
|
|
class-and class-empty? not ;
|
|
|
|
: min-class ( class seq -- class/f )
|
|
[ dupd classes-intersect? ] subset dup empty? [
|
|
2drop f
|
|
] [
|
|
tuck [ class< ] curry* all? [ peek ] [ drop f ] if
|
|
] if ;
|
|
|
|
GENERIC: reset-class ( class -- )
|
|
|
|
M: word reset-class drop ;
|
|
|
|
<PRIVATE
|
|
|
|
! class<map
|
|
: bigger-classes ( class -- seq )
|
|
classes [ (class<) ] curry* subset ;
|
|
|
|
: bigger-classes+ ( class -- )
|
|
[ bigger-classes [ dup ] H{ } map>assoc ] keep
|
|
class<map get set-at ;
|
|
|
|
: bigger-classes- ( class -- )
|
|
class<map get delete-at ;
|
|
|
|
: smaller-classes ( class -- seq )
|
|
classes swap [ (class<) ] curry subset ;
|
|
|
|
: smaller-classes+ ( class -- )
|
|
dup smaller-classes class<map get add-vertex ;
|
|
|
|
: smaller-classes- ( class -- )
|
|
dup smaller-classes class<map get remove-vertex ;
|
|
|
|
: class<map+ ( class -- )
|
|
H{ } clone over class<map get set-at
|
|
dup smaller-classes+ bigger-classes+ ;
|
|
|
|
: class<map- ( class -- )
|
|
dup smaller-classes- bigger-classes- ;
|
|
|
|
! update-map
|
|
: class-uses ( class -- seq )
|
|
[ dup members % superclass [ , ] when* ] { } make ;
|
|
|
|
: class-usages ( class -- assoc )
|
|
[ update-map get at ] closure ;
|
|
|
|
: update-map+ ( class -- )
|
|
dup class-uses update-map get add-vertex ;
|
|
|
|
: update-map- ( class -- )
|
|
dup class-uses update-map get remove-vertex ;
|
|
|
|
! typemap
|
|
: push-at ( value key assoc -- )
|
|
2dup at* [
|
|
2nip push
|
|
] [
|
|
drop >r >r 1vector r> r> set-at
|
|
] if ;
|
|
|
|
: typemap+ ( class -- )
|
|
dup flatten-builtin-class typemap get push-at ;
|
|
|
|
: pop-at ( value key assoc -- )
|
|
at* [ delete ] [ 2drop ] if ;
|
|
|
|
: typemap- ( class -- )
|
|
dup flatten-builtin-class typemap get pop-at ;
|
|
|
|
! Class definition
|
|
: cache-class ( class -- )
|
|
dup typemap+ dup class<map+ update-map+ ;
|
|
|
|
: cache-classes ( assoc -- )
|
|
[ drop cache-class ] assoc-each ;
|
|
|
|
GENERIC: uncache-class ( class -- )
|
|
|
|
M: class uncache-class
|
|
dup update-map- dup class<map- typemap- ;
|
|
|
|
M: word uncache-class drop ;
|
|
|
|
: uncache-classes ( assoc -- )
|
|
[ drop uncache-class ] assoc-each ;
|
|
|
|
GENERIC: update-methods ( class -- )
|
|
|
|
PRIVATE>
|
|
|
|
: define-class-props ( members superclass metaclass -- assoc )
|
|
[
|
|
"metaclass" set
|
|
dup [ bootstrap-word ] when "superclass" set
|
|
[ bootstrap-word ] map "members" set
|
|
] H{ } make-assoc ;
|
|
|
|
: (define-class) ( word props -- )
|
|
over reset-class
|
|
>r dup word-props r> union over set-word-props
|
|
dup intern-symbol
|
|
t "class" set-word-prop ;
|
|
|
|
: define-class ( word members superclass metaclass -- )
|
|
#! If it was already a class, update methods after.
|
|
define-class-props
|
|
over class? >r
|
|
over class-usages [
|
|
uncache-classes
|
|
dupd (define-class)
|
|
] keep cache-classes
|
|
r> [ update-methods ] [ drop ] if ;
|
|
|
|
GENERIC: class ( object -- class ) inline
|
|
|
|
M: object class type type>class ;
|
|
|
|
<PRIVATE
|
|
|
|
: class-of-tuple ( obj -- class )
|
|
2 slot { word } declare ; inline
|
|
|
|
PRIVATE>
|