classes.intersection: make flatten-class more accurate. It is still not perfect, but it fixes the case where a generic word has a method on a tuple class, and another method on an intersection of a mixin with another tuple classes

db4
Slava Pestov 2009-08-07 22:30:57 -05:00
parent b85d842ca6
commit 926c46841b
4 changed files with 67 additions and 14 deletions

View File

@ -50,13 +50,6 @@ M: builtin-class (classes-intersect?)
[ swap classes-intersect? ]
} cond ;
M: anonymous-intersection (flatten-class)
participants>> [ flatten-builtin-class ] map
[
builtins get sift [ (flatten-class) ] each
] [
[ ] [ assoc-intersect ] map-reduce [ swap set ] assoc-each
] if-empty ;
: full-cover ( -- ) builtins get sift [ (flatten-class) ] each ;
M: anonymous-complement (flatten-class)
drop builtins get sift [ (flatten-class) ] each ;
M: anonymous-complement (flatten-class) drop full-cover ;

View File

@ -0,0 +1,38 @@
USING: kernel tools.test generic generic.standard ;
IN: classes.intersection.tests
TUPLE: a ;
TUPLE: a1 < a ; TUPLE: a2 < a ; TUPLE: a3 < a2 ;
MIXIN: b
INSTANCE: a3 b
INSTANCE: a1 b
INTERSECTION: c a2 b ;
GENERIC: x ( a -- b )
M: c x drop c ;
M: a x drop a ;
[ a ] [ T{ a } x ] unit-test
[ a ] [ T{ a1 } x ] unit-test
[ a ] [ T{ a2 } x ] unit-test
[ t ] [ T{ a3 } c? ] unit-test
[ t ] [ T{ a3 } \ x effective-method M\ c x eq? nip ] unit-test
[ c ] [ T{ a3 } x ] unit-test
! More complex case
TUPLE: t1 ;
TUPLE: t2 < t1 ; TUPLE: t3 < t1 ;
TUPLE: t4 < t2 ; TUPLE: t5 < t2 ;
UNION: m t4 t5 t3 ;
INTERSECTION: i t2 m ;
GENERIC: g ( a -- b )
M: i g drop i ;
M: t4 g drop t4 ;
[ t4 ] [ T{ t4 } g ] unit-test
[ i ] [ T{ t5 } g ] unit-test

View File

@ -1,6 +1,6 @@
! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: words sequences kernel assocs combinators classes
USING: words accessors sequences kernel assocs combinators classes
classes.algebra classes.builtin namespaces arrays math quotations ;
IN: classes.intersection
@ -34,3 +34,15 @@ M: intersection-class instance?
M: intersection-class (flatten-class)
participants <anonymous-intersection> (flatten-class) ;
! Horribly inefficient and inaccurate
: intersect-flattened-classes ( seq1 seq2 -- seq3 )
! Only keep those in seq1 that intersect something in seq2.
[ [ classes-intersect? ] with any? ] curry filter ;
M: anonymous-intersection (flatten-class)
participants>> [ full-cover ] [
[ flatten-class keys ]
[ intersect-flattened-classes ] map-reduce
[ dup set ] each
] if-empty ;

View File

@ -27,8 +27,18 @@ TUPLE: tuple-b < tuple-a ;
PREDICATE: tuple-c < tuple-b slot>> ;
GENERIC: ptest ( tuple -- )
M: tuple-a ptest drop ;
M: tuple-c ptest drop ;
GENERIC: ptest ( tuple -- x )
M: tuple-a ptest drop tuple-a ;
M: tuple-c ptest drop tuple-c ;
[ ] [ tuple-b new ptest ] unit-test
[ tuple-a ] [ tuple-b new ptest ] unit-test
[ tuple-c ] [ tuple-b new t >>slot ptest ] unit-test
PREDICATE: tuple-d < tuple-a slot>> ;
GENERIC: ptest' ( tuple -- x )
M: tuple-a ptest' drop tuple-a ;
M: tuple-d ptest' drop tuple-d ;
[ tuple-a ] [ tuple-b new ptest' ] unit-test
[ tuple-d ] [ tuple-b new t >>slot ptest' ] unit-test