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
@@ -994,6 +994,8 @@
   ([x form & more] `(-> (-> ~x ~form) ~@more)))
 
 ;;multimethods
+(def global-hierarchy)
+
 (defmacro defmulti
   "Creates a new multimethod with the associated dispatch function. If
   default-dispatch-val is supplied it becomes the default dispatch
@@ -1002,11 +1004,12 @@
   [mm-name dispatch-fn & options]
   (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 (assoc (meta mm-name)
                                      :tag 'clojure.lang.MultiFn))
-       (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;
