]> gitweb.factorcode.org Git - factor.git/commitdiff
generic.single: fix bug where dynamic and static dispatch didn't co-incide (reported...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sun, 22 Aug 2010 01:12:00 +0000 (18:12 -0700)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sun, 22 Aug 2010 01:12:00 +0000 (18:12 -0700)
core/generic/single/single.factor
core/generic/standard/standard-tests.factor

index b39956c731763e583c4e76dd843f508ec865d6c9..219c52b75e99fb585e5822278d5a8d090f8ee9b3 100644 (file)
@@ -104,8 +104,23 @@ TUPLE: tuple-dispatch-engine echelons ;
     #! is always there
     H{ { 0 f } } clone [ [ push-echelon ] curry assoc-each ] keep ;
 
+: copy-superclass-methods ( engine superclass assoc -- )
+    at* [ [ methods>> ] bi@ assoc-union! drop ] [ 2drop ] if ;
+
+: copy-superclasses-methods ( class engine assoc -- )
+    [ superclasses ] 2dip
+    [ swapd copy-superclass-methods ] 2curry each ;
+
+: convert-tuple-inheritance ( assoc -- assoc' )
+    #! A method on a superclass A might have a higher precedence
+    #! than a method on a subclass B, if the methods are
+    #! defined on incomparable classes that happen to contain
+    #! A and B, respectively. Copy A's methods into B's set so
+    #! that they can be sorted and selected properly.
+    dup dup [ copy-superclasses-methods ] curry assoc-each ;
+
 : <tuple-dispatch-engine> ( methods -- engine )
-    echelon-sort
+    convert-tuple-inheritance echelon-sort
     [ dupd <echelon-dispatch-engine> ] assoc-map
     \ tuple-dispatch-engine boa ;
 
index 37946102a14f6a6e444f6d1f830e9441ee050b8f..f69cd2a8231b82b6bfc9a411facbb5717ae19000 100644 (file)
@@ -414,20 +414,156 @@ M: integer non-flushable-generic ; flushable
 [ f ] [ \ non-flushable-generic flushable? ] unit-test
 [ t ] [ M\ integer non-flushable-generic flushable? ] unit-test
 
-! method-for-object and method-for-class
+! method-for-object, method-for-class, effective-method
 GENERIC: foozul ( a -- b )
 M: reversed foozul ;
 M: integer foozul ;
 M: slice foozul ;
 
-[ t ] [
-    reversed \ foozul method-for-class
-    reversed \ foozul method
-    eq?
+[ ] [ reversed \ foozul method-for-class M\ reversed foozul assert= ] unit-test
+[ ] [ { 1 2 3 } <reversed> \ foozul method-for-object M\ reversed foozul assert= ] unit-test
+[ ] [ { 1 2 3 } <reversed> \ foozul effective-method M\ reversed foozul assert= drop ] unit-test
+
+[ ] [ fixnum \ foozul method-for-class M\ integer foozul assert= ] unit-test
+[ ] [ 13 \ foozul method-for-object M\ integer foozul assert= ] unit-test
+[ ] [ 13 \ foozul effective-method M\ integer foozul assert= drop ] unit-test
+
+! Ensure dynamic and static dispatch match in ambiguous cases
+UNION: amb-union-1a integer float ;
+UNION: amb-union-1b float string ;
+
+GENERIC: amb-generic-1 ( a -- b )
+
+M: amb-union-1a amb-generic-1 drop "a" ;
+M: amb-union-1b amb-generic-1 drop "b" ;
+
+[ ] [
+    5.0 amb-generic-1
+    5.0 \ amb-generic-1 effective-method execute( a -- b ) assert=
 ] unit-test
 
-[ t ] [
-    fixnum \ <=> method-for-class
-    real \ <=> method
-    eq?
+[ ] [
+    5.0 amb-generic-1
+    5.0 float \ amb-generic-1 method-for-class execute( a -- b ) assert=
+] unit-test
+
+UNION: amb-union-2a float string ;
+UNION: amb-union-2b integer float ;
+
+GENERIC: amb-generic-2 ( a -- b )
+
+M: amb-union-2a amb-generic-2 drop "a" ;
+M: amb-union-2b amb-generic-2 drop "b" ;
+
+[ ] [
+    5.0 amb-generic-1
+    5.0 \ amb-generic-1 effective-method execute( a -- b ) assert=
+] unit-test
+
+[ ] [
+    5.0 amb-generic-1
+    5.0 float \ amb-generic-1 method-for-class execute( a -- b ) assert=
+] unit-test
+
+TUPLE: amb-tuple-a x ;
+TUPLE: amb-tuple-b < amb-tuple-a ;
+PREDICATE: amb-tuple-c < amb-tuple-a x>> 3 = ;
+
+GENERIC: amb-generic-3 ( a -- b )
+
+M: amb-tuple-b amb-generic-3 drop "b" ;
+M: amb-tuple-c amb-generic-3 drop "c" ;
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-3
+    T{ amb-tuple-b f 3 } \ amb-generic-3 effective-method execute( a -- b ) assert=
+] unit-test
+
+TUPLE: amb-tuple-d ;
+UNION: amb-union-4 amb-tuple-a amb-tuple-d ;
+
+GENERIC: amb-generic-4 ( a -- b )
+
+M: amb-tuple-b amb-generic-4 drop "b" ;
+M: amb-union-4 amb-generic-4 drop "4" ;
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-4
+    T{ amb-tuple-b f 3 } \ amb-generic-4 effective-method execute( a -- b ) assert=
+] unit-test
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-4
+    T{ amb-tuple-b f 3 } amb-tuple-b \ amb-generic-4 method-for-class execute( a -- b ) assert=
+] unit-test
+
+MIXIN: amb-mixin-5
+INSTANCE: amb-tuple-a amb-mixin-5
+INSTANCE: amb-tuple-d amb-mixin-5
+
+GENERIC: amb-generic-5 ( a -- b )
+
+M: amb-tuple-b amb-generic-5 drop "b" ;
+M: amb-mixin-5 amb-generic-5 drop "5" ;
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-5
+    T{ amb-tuple-b f 3 } \ amb-generic-5 effective-method execute( a -- b ) assert=
+] unit-test
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-5
+    T{ amb-tuple-b f 3 } amb-tuple-b \ amb-generic-5 method-for-class execute( a -- b ) assert=
+] unit-test
+
+UNION: amb-union-6 amb-tuple-b amb-tuple-d ;
+
+GENERIC: amb-generic-6 ( a -- b )
+
+M: amb-tuple-a amb-generic-6 drop "a" ;
+M: amb-union-6 amb-generic-6 drop "6" ;
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-6
+    T{ amb-tuple-b f 3 } \ amb-generic-6 effective-method execute( a -- b ) assert=
+] unit-test
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-6
+    T{ amb-tuple-b f 3 } amb-tuple-b \ amb-generic-6 method-for-class execute( a -- b ) assert=
+] unit-test
+
+MIXIN: amb-mixin-7
+INSTANCE: amb-tuple-b amb-mixin-7
+INSTANCE: amb-tuple-d amb-mixin-7
+
+GENERIC: amb-generic-7 ( a -- b )
+
+M: amb-tuple-a amb-generic-7 drop "a" ;
+M: amb-mixin-7 amb-generic-7 drop "7" ;
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-7
+    T{ amb-tuple-b f 3 } \ amb-generic-7 effective-method execute( a -- b ) assert=
+] unit-test
+
+[ ] [
+    T{ amb-tuple-b f 3 } amb-generic-7
+    T{ amb-tuple-b f 3 } amb-tuple-b \ amb-generic-7 method-for-class execute( a -- b ) assert=
+] unit-test
+
+! Same thing as above but with predicate classes
+PREDICATE: amb-predicate-a < integer 10 mod even? ;
+PREDICATE: amb-predicate-b < amb-predicate-a 10 mod 4 = ;
+
+UNION: amb-union-8 amb-predicate-b string ;
+
+GENERIC: amb-generic-8 ( a -- b )
+
+M: amb-union-8 amb-generic-8 drop "8" ;
+M: amb-predicate-a amb-generic-8 drop "a" ;
+
+[ ] [
+    4 amb-generic-8
+    4 \ amb-generic-8 effective-method execute( a -- b ) assert=
 ] unit-test