Implemented per-defmulti hierarchies via IRef instead of Var

Modified MultiFn to receive another parameter on object creation:
the IRef containing a hierarchy. This can be any of the four
reference types of Clojure.

The hierarchy might be passed via the :hierarchy keyword
argument. Hence the patch attached to issue #8 is also
needed as a prerequisite.

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -997,12 +997,16 @@
   ([x form & more] `(-> (-> ~x ~form) ~@more)))
 
 ;;multimethods
+(def global-hierarchy)
+
 (defmacro defmulti
   "Creates a new multimethod with the associated dispatch function.
   The docstring and attribute-map are optional.
 
   Options are key-value pairs and may be one of:
-    :default    the default dispatch value, defaults to :default"
+    :default    the default dispatch value, defaults to :default
+    :hierarchy  the isa? hierarchy to use for dispatching
+                defaults to the global hierarchy"
   {:arglists '([name docstring? attr-map? dispatch-fn & options])}
   [mm-name & options]
   (let [docstring   (if (string? (first options))
@@ -1028,10 +1032,11 @@
                       m)]
     (when (= (count options) 1)
       (throw (Exception. "The syntax for defmulti has changed. Example: (defmulti name dispatch-fn :default dispatch-value)")))
-    (let [options (apply hash-map options)
-          default (get options :default :default)]
+    (let [options   (apply hash-map options)
+          default   (get options :default :default)
+          hierarchy (get options :hierarchy #'global-hierarchy)]
       `(def ~(with-meta mm-name m)
-         (new clojure.lang.MultiFn ~dispatch-fn ~default)))))
+         (new clojure.lang.MultiFn ~dispatch-fn ~default ~hierarchy)))))
 
 (defmacro defmethod
   "Creates and installs a new method of multimethod associated with dispatch-value. "
diff --git a/src/jvm/clojure/lang/MultiFn.java b/src/jvm/clojure/lang/MultiFn.java
--- a/src/jvm/clojure/lang/MultiFn.java
+++ b/src/jvm/clojure/lang/MultiFn.java
@@ -18,6 +18,7 @@
 public class MultiFn extends AFn{
 final public IFn dispatchFn;
 final public Object defaultDispatchVal;
+final public IRef hierarchy;
 IPersistentMap methodTable;
 IPersistentMap preferTable;
 IPersistentMap methodCache;
@@ -27,11 +28,11 @@
 static final Var dissoc = RT.var("clojure.core", "dissoc");
 static final Var isa = RT.var("clojure.core", "isa?");
 static final Var parents = RT.var("clojure.core", "parents");
-static final Var hierarchy = RT.var("clojure.core", "global-hierarchy");
 
-public MultiFn(IFn dispatchFn, Object defaultDispatchVal) throws Exception{
+public MultiFn(IFn dispatchFn, Object defaultDispatchVal, IRef hierarchy) throws Exception{
 	this.dispatchFn = dispatchFn;
 	this.defaultDispatchVal = defaultDispatchVal;
+	this.hierarchy = hierarchy;
 	this.methodTable = PersistentHashMap.EMPTY;
 	this.methodCache = methodTable;
 	this.preferTable = PersistentHashMap.EMPTY;
@@ -80,14 +81,14 @@
 }
 
 private boolean isA(Object x, Object y) throws Exception{
-	return RT.booleanCast(isa.invoke(x, y));
+	return RT.booleanCast(isa.invoke(hierarchy.get(), x, y));
 }
 
 private boolean dominates(Object x, Object y) throws Exception{
 	return prefers(x, y) || isA(x, y);
 }
 
-private IPersistentMap resetCache(){
+private IPersistentMap resetCache() throws Exception{
 	methodCache = methodTable;
 	cachedHierarchy = hierarchy.get();
 	return methodCache;
