2008-03-24 20:52:21 -04:00
|
|
|
! Copyright (C) 2004, 2008 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-04-03 22:19:20 -04:00
|
|
|
USING: kernel classes classes.builtin combinators accessors
|
|
|
|
sequences arrays vectors assocs namespaces words sorting layouts
|
2008-05-02 03:51:38 -04:00
|
|
|
math hashtables kernel.private sets math.order ;
|
2008-03-24 20:52:21 -04:00
|
|
|
IN: classes.algebra
|
|
|
|
|
|
|
|
: 2cache ( key1 key2 assoc quot -- value )
|
|
|
|
>r >r 2array r> [ first2 ] r> compose cache ; inline
|
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
DEFER: (class<=)
|
2008-03-24 20:52:21 -04:00
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: class<= ( first second -- ? )
|
|
|
|
class<=-cache get [ (class<=) ] 2cache ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
DEFER: (class-not)
|
|
|
|
|
|
|
|
: class-not ( class -- complement )
|
|
|
|
class-not-cache get [ (class-not) ] cache ;
|
|
|
|
|
|
|
|
DEFER: (classes-intersect?) ( first second -- ? )
|
|
|
|
|
|
|
|
: classes-intersect? ( first second -- ? )
|
|
|
|
classes-intersect-cache get [ (classes-intersect?) ] 2cache ;
|
|
|
|
|
|
|
|
DEFER: (class-and)
|
|
|
|
|
|
|
|
: class-and ( first second -- class )
|
|
|
|
class-and-cache get [ (class-and) ] 2cache ;
|
|
|
|
|
|
|
|
DEFER: (class-or)
|
|
|
|
|
|
|
|
: class-or ( first second -- class )
|
|
|
|
class-or-cache get [ (class-or) ] 2cache ;
|
|
|
|
|
|
|
|
TUPLE: anonymous-union members ;
|
|
|
|
|
|
|
|
C: <anonymous-union> anonymous-union
|
|
|
|
|
|
|
|
TUPLE: anonymous-intersection members ;
|
|
|
|
|
|
|
|
C: <anonymous-intersection> anonymous-intersection
|
|
|
|
|
|
|
|
TUPLE: anonymous-complement class ;
|
|
|
|
|
|
|
|
C: <anonymous-complement> anonymous-complement
|
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: superclass<= ( first second -- ? )
|
|
|
|
>r superclass r> class<= ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: left-union-class<= ( first second -- ? )
|
|
|
|
>r members r> [ class<= ] curry all? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: right-union-class<= ( first second -- ? )
|
|
|
|
members [ class<= ] with contains? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: left-anonymous-union< ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
>r members>> r> [ class<= ] curry all? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: right-anonymous-union< ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
members>> [ class<= ] with contains? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: left-anonymous-intersection< ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
>r members>> r> [ class<= ] curry contains? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: right-anonymous-intersection< ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
members>> [ class<= ] with all? ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: anonymous-complement< ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
[ class>> ] bi@ swap class<= ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: (class<=) ( first second -- -1/0/1 )
|
2008-03-24 20:52:21 -04:00
|
|
|
{
|
|
|
|
{ [ 2dup eq? ] [ 2drop t ] }
|
|
|
|
{ [ dup object eq? ] [ 2drop t ] }
|
|
|
|
{ [ over null eq? ] [ 2drop t ] }
|
|
|
|
{ [ 2dup [ anonymous-complement? ] both? ] [ anonymous-complement< ] }
|
|
|
|
{ [ over anonymous-union? ] [ left-anonymous-union< ] }
|
|
|
|
{ [ over anonymous-intersection? ] [ left-anonymous-intersection< ] }
|
2008-05-02 03:51:38 -04:00
|
|
|
{ [ over members ] [ left-union-class<= ] }
|
2008-03-24 20:52:21 -04:00
|
|
|
{ [ dup anonymous-union? ] [ right-anonymous-union< ] }
|
|
|
|
{ [ dup anonymous-intersection? ] [ right-anonymous-intersection< ] }
|
2008-04-19 03:11:40 -04:00
|
|
|
{ [ over anonymous-complement? ] [ 2drop f ] }
|
2008-03-24 20:52:21 -04:00
|
|
|
{ [ dup anonymous-complement? ] [ class>> classes-intersect? not ] }
|
2008-05-02 03:51:38 -04:00
|
|
|
{ [ dup members ] [ right-union-class<= ] }
|
|
|
|
{ [ over superclass ] [ superclass<= ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ 2drop f ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: anonymous-union-intersect? ( first second -- ? )
|
|
|
|
members>> [ classes-intersect? ] with contains? ;
|
|
|
|
|
|
|
|
: anonymous-intersection-intersect? ( first second -- ? )
|
|
|
|
members>> [ classes-intersect? ] with all? ;
|
|
|
|
|
|
|
|
: anonymous-complement-intersect? ( first second -- ? )
|
2008-05-02 03:51:38 -04:00
|
|
|
class>> class<= not ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: union-class-intersect? ( first second -- ? )
|
|
|
|
members [ classes-intersect? ] with contains? ;
|
|
|
|
|
|
|
|
: tuple-class-intersect? ( first second -- ? )
|
|
|
|
{
|
|
|
|
{ [ over tuple eq? ] [ 2drop t ] }
|
|
|
|
{ [ over builtin-class? ] [ 2drop f ] }
|
2008-05-02 03:51:38 -04:00
|
|
|
{ [ over tuple-class? ] [ [ class<= ] [ swap class<= ] 2bi or ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ swap classes-intersect? ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: builtin-class-intersect? ( first second -- ? )
|
|
|
|
{
|
|
|
|
{ [ 2dup eq? ] [ 2drop t ] }
|
|
|
|
{ [ over builtin-class? ] [ 2drop f ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ swap classes-intersect? ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: (classes-intersect?) ( first second -- ? )
|
|
|
|
{
|
|
|
|
{ [ dup anonymous-union? ] [ anonymous-union-intersect? ] }
|
|
|
|
{ [ dup anonymous-intersection? ] [ anonymous-intersection-intersect? ] }
|
|
|
|
{ [ dup anonymous-complement? ] [ anonymous-complement-intersect? ] }
|
|
|
|
{ [ dup tuple-class? ] [ tuple-class-intersect? ] }
|
|
|
|
{ [ dup builtin-class? ] [ builtin-class-intersect? ] }
|
|
|
|
{ [ dup superclass ] [ superclass classes-intersect? ] }
|
|
|
|
{ [ dup members ] [ union-class-intersect? ] }
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: left-union-and ( first second -- class )
|
|
|
|
>r members r> [ class-and ] curry map <anonymous-union> ;
|
|
|
|
|
|
|
|
: right-union-and ( first second -- class )
|
|
|
|
members [ class-and ] with map <anonymous-union> ;
|
|
|
|
|
|
|
|
: left-anonymous-union-and ( first second -- class )
|
|
|
|
>r members>> r> [ class-and ] curry map <anonymous-union> ;
|
|
|
|
|
|
|
|
: right-anonymous-union-and ( first second -- class )
|
|
|
|
members>> [ class-and ] with map <anonymous-union> ;
|
|
|
|
|
|
|
|
: left-anonymous-intersection-and ( first second -- class )
|
2008-03-31 20:18:05 -04:00
|
|
|
>r members>> r> suffix <anonymous-intersection> ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: right-anonymous-intersection-and ( first second -- class )
|
2008-03-31 20:18:05 -04:00
|
|
|
members>> swap suffix <anonymous-intersection> ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: (class-and) ( first second -- class )
|
|
|
|
{
|
2008-05-02 03:51:38 -04:00
|
|
|
{ [ 2dup class<= ] [ drop ] }
|
|
|
|
{ [ 2dup swap class<= ] [ nip ] }
|
2008-03-24 20:52:21 -04:00
|
|
|
{ [ 2dup classes-intersect? not ] [ 2drop null ] }
|
|
|
|
{ [ dup members ] [ right-union-and ] }
|
|
|
|
{ [ dup anonymous-union? ] [ right-anonymous-union-and ] }
|
|
|
|
{ [ dup anonymous-intersection? ] [ right-anonymous-intersection-and ] }
|
|
|
|
{ [ over members ] [ left-union-and ] }
|
|
|
|
{ [ over anonymous-union? ] [ left-anonymous-union-and ] }
|
|
|
|
{ [ over anonymous-intersection? ] [ left-anonymous-intersection-and ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ 2array <anonymous-intersection> ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: left-anonymous-union-or ( first second -- class )
|
2008-03-31 20:18:05 -04:00
|
|
|
>r members>> r> suffix <anonymous-union> ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: right-anonymous-union-or ( first second -- class )
|
2008-03-31 20:18:05 -04:00
|
|
|
members>> swap suffix <anonymous-union> ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: (class-or) ( first second -- class )
|
|
|
|
{
|
2008-05-02 03:51:38 -04:00
|
|
|
{ [ 2dup class<= ] [ nip ] }
|
|
|
|
{ [ 2dup swap class<= ] [ drop ] }
|
2008-03-24 20:52:21 -04:00
|
|
|
{ [ dup anonymous-union? ] [ right-anonymous-union-or ] }
|
|
|
|
{ [ over anonymous-union? ] [ left-anonymous-union-or ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ 2array <anonymous-union> ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: (class-not) ( class -- complement )
|
|
|
|
{
|
|
|
|
{ [ dup anonymous-complement? ] [ class>> ] }
|
|
|
|
{ [ dup object eq? ] [ drop null ] }
|
|
|
|
{ [ dup null eq? ] [ drop object ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ <anonymous-complement> ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
2008-05-02 03:51:38 -04:00
|
|
|
: class< ( first second -- ? )
|
|
|
|
{
|
|
|
|
{ [ 2dup class<= not ] [ 2drop f ] }
|
|
|
|
{ [ 2dup swap class<= not ] [ 2drop t ] }
|
|
|
|
[ [ rank-class ] bi@ < ]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: class-tie-breaker ( first second -- n )
|
|
|
|
2dup [ rank-class ] compare {
|
|
|
|
{ +lt+ [ 2drop +lt+ ] }
|
|
|
|
{ +gt+ [ 2drop +gt+ ] }
|
|
|
|
{ +eq+ [ <=> ] }
|
|
|
|
} case ;
|
|
|
|
|
|
|
|
: (class<=>) ( first second -- n )
|
|
|
|
{
|
|
|
|
{ [ 2dup class<= ] [
|
|
|
|
2dup swap class<=
|
|
|
|
[ class-tie-breaker ] [ 2drop +lt+ ] if
|
|
|
|
] }
|
|
|
|
{ [ 2dup swap class<= ] [
|
|
|
|
2dup class<=
|
|
|
|
[ class-tie-breaker ] [ 2drop +gt+ ] if
|
|
|
|
] }
|
|
|
|
[ class-tie-breaker ]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: class<=> ( first second -- n )
|
|
|
|
class<=>-cache get [ (class<=>) ] 2cache ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: sort-classes ( seq -- newseq )
|
2008-05-02 03:51:38 -04:00
|
|
|
[ class<=> invert-comparison ] sort ;
|
2008-03-24 20:52:21 -04:00
|
|
|
|
|
|
|
: min-class ( class seq -- class/f )
|
2008-04-26 00:12:44 -04:00
|
|
|
over [ classes-intersect? ] curry filter
|
2008-04-19 03:11:40 -04:00
|
|
|
dup empty? [ 2drop f ] [
|
2008-05-02 03:51:38 -04:00
|
|
|
tuck [ class<= ] with all? [ peek ] [ drop f ] if
|
2008-03-24 20:52:21 -04:00
|
|
|
] if ;
|
|
|
|
|
|
|
|
: (flatten-class) ( class -- )
|
|
|
|
{
|
|
|
|
{ [ dup tuple-class? ] [ dup set ] }
|
|
|
|
{ [ dup builtin-class? ] [ dup set ] }
|
|
|
|
{ [ dup members ] [ members [ (flatten-class) ] each ] }
|
|
|
|
{ [ dup superclass ] [ superclass (flatten-class) ] }
|
2008-04-11 13:53:22 -04:00
|
|
|
[ drop ]
|
2008-03-24 20:52:21 -04:00
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: flatten-class ( class -- assoc )
|
|
|
|
[ (flatten-class) ] H{ } make-assoc ;
|
|
|
|
|
|
|
|
: flatten-builtin-class ( class -- assoc )
|
|
|
|
flatten-class [
|
2008-05-02 03:51:38 -04:00
|
|
|
dup tuple class<= [ 2drop tuple tuple ] when
|
2008-03-24 20:52:21 -04:00
|
|
|
] assoc-map ;
|
|
|
|
|
|
|
|
: class-types ( class -- seq )
|
|
|
|
flatten-builtin-class keys
|
|
|
|
[ "type" word-prop ] map natural-sort ;
|
|
|
|
|
|
|
|
: class-tags ( class -- tag/f )
|
|
|
|
class-types [
|
|
|
|
dup num-tags get >=
|
2008-04-02 19:50:21 -04:00
|
|
|
[ drop \ hi-tag tag-number ] when
|
2008-03-24 20:52:21 -04:00
|
|
|
] map prune ;
|