! Copyright (C) 2004, 2006 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. IN: generic USING: arrays definitions errors hashtables kernel kernel-internals namespaces sequences strings words vectors math parser ; PREDICATE: word class ( obj -- ? ) "class" word-prop ; SYMBOL: typemap SYMBOL: classclass ( n -- class ) builtins get nth ; : predicate-word ( word -- predicate ) word-name "?" append create-in ; : predicate-effect 1 1 ; : define-predicate ( class predicate quot -- ) over [ over predicate-effect "declared-effect" set-word-prop dupd define-compound 2dup unit "predicate" set-word-prop swap "predicating" set-word-prop ] [ 3drop ] if ; : superclass ( class -- super ) "superclass" word-prop ; : members ( class -- seq ) "members" word-prop ; : (flatten-class) ( class -- ) dup members [ [ (flatten-class) ] each ] [ dup set ] ?if ; : flatten-class ( class -- seq ) [ (flatten-class) ] make-hash ; : (types) ( class -- ) flatten-class [ drop dup superclass [ (types) ] [ "type" word-prop dup set ] ?if ] hash-each ; : types ( class -- seq ) [ (types) ] make-hash hash-keys natural-sort ; DEFER: (class<) : superclass< ( cls1 cls2 -- ? ) >r superclass r> 2dup and [ (class<) ] [ 2drop f ] if ; : union-class< ( cls1 cls2 -- ? ) [ flatten-class ] 2apply hash-keys swap [ drop swap [ (class<) ] contains-with? ] hash-all-with? ; : class-empty? ( class -- ? ) members dup [ empty? ] when ; : (class<) ( class1 class2 -- ? ) { { [ 2dup eq? ] [ 2drop t ] } { [ over class-empty? ] [ 2drop t ] } { [ 2dup superclass< ] [ 2drop t ] } { [ 2dup [ members ] 2apply or not ] [ 2drop f ] } { [ t ] [ union-class< ] } } cond ; : class< ( class1 class2 -- ? ) classclass dup ] map>hash ; : (class-or) ( class class -- class ) [ types* ] 2apply hash-union lookup-union ; : class-or ( class1 class2 -- class ) { { [ 2dup class< ] [ nip ] } { [ 2dup swap class< ] [ drop ] } { [ t ] [ (class-or) ] } } cond ; : (class-and) ( class class -- class ) [ types* ] 2apply hash-intersect lookup-union ; : class-and ( class1 class2 -- class ) { { [ 2dup class< ] [ drop ] } { [ 2dup swap class< ] [ nip ] } { [ 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< ] all-with? [ peek ] [ drop f ] if ] if ; : smaller-classes ( class -- seq ) classes [ swap (class<) ] subset-with ; : smaller-classes+ ( class -- ) [ smaller-classes [ dup ] map>hash ] keep classquot ; : set-members ( class members -- ) [ bootstrap-word ] map "members" set-word-prop ; : define-union ( class predicate members -- ) 3dup nip set-members pick define-class union-predicate define-predicate ; PREDICATE: class union members ; ! Definition protocol : smaller-classes- ( class -- ) class