summaryrefslogtreecommitdiff
path: root/src/jvm
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-10-11 19:33:56 +0000
committerRich Hickey <richhickey@gmail.com>2008-10-11 19:33:56 +0000
commitfafdad68d92dfc695a2f040a0422db691cbb5556 (patch)
tree2b973e70e9931690f24b42dfc8c77fbfe4d4ade3 /src/jvm
parent3b3e540c03f726486ff5712354bc0a9796e7d570 (diff)
enhanced prefers to prefer whole trees to others
fixed supers, which didn't trace interfaces
Diffstat (limited to 'src/jvm')
-rw-r--r--src/jvm/clojure/lang/MultiFn.java19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/jvm/clojure/lang/MultiFn.java b/src/jvm/clojure/lang/MultiFn.java
index 954f0b56..527a0d38 100644
--- a/src/jvm/clojure/lang/MultiFn.java
+++ b/src/jvm/clojure/lang/MultiFn.java
@@ -26,6 +26,7 @@ Object cachedHierarchy;
static final Var assoc = RT.var("clojure", "assoc");
static final Var dissoc = RT.var("clojure", "dissoc");
static final Var isa = RT.var("clojure", "isa?");
+static final Var parents = RT.var("clojure", "parents");
static final Var hierarchy = RT.var("clojure", "global-hierarchy");
public MultiFn(IFn dispatchFn, Object defaultDispatchVal) throws Exception{
@@ -49,7 +50,7 @@ synchronized public MultiFn removeMethod(Object dispatchVal) throws Exception{
return this;
}
-synchronized public MultiFn preferMethod(Object dispatchValX, Object dispatchValY){
+synchronized public MultiFn preferMethod(Object dispatchValX, Object dispatchValY) throws Exception{
if(prefers(dispatchValY, dispatchValX))
throw new IllegalStateException(
String.format("Preference conflict: %s is already preferred to %s", dispatchValY, dispatchValX));
@@ -61,9 +62,21 @@ synchronized public MultiFn preferMethod(Object dispatchValX, Object dispatchVal
return this;
}
-private boolean prefers(Object x, Object y){
+private boolean prefers(Object x, Object y) throws Exception{
IPersistentSet xprefs = (IPersistentSet) preferTable.valAt(x);
- return xprefs != null && xprefs.contains(y);
+ if(xprefs != null && xprefs.contains(y))
+ return true;
+ for(ISeq ps = RT.seq(parents.invoke(y)); ps != null; ps = ps.rest())
+ {
+ if(prefers(x, ps.first()))
+ return true;
+ }
+ for(ISeq ps = RT.seq(parents.invoke(x)); ps != null; ps = ps.rest())
+ {
+ if(prefers(ps.first(), y))
+ return true;
+ }
+ return false;
}
private boolean isA(Object x, Object y) throws Exception{