diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-11-30 13:39:19 -0500 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-11-30 13:39:19 -0500 |
commit | 77173bbf8eea48729deaf4cac0dc10918b3720e9 (patch) | |
tree | 33d9de2c812c25c37ce4b08034bc23d844bd48b8 | |
parent | 9fc359815618f1cec7ea722e9f7b516f70057e92 (diff) |
protocols gen interface of same name, e.g. my.ns/Protocol gens my.ns.Protocol interface
names get munged
reify, deftype, protocol callsites and . calling munge
gen-interface is dynamic (undocumented as yet, interface TBD)
-rw-r--r-- | src/clj/clojure/core.clj | 2 | ||||
-rw-r--r-- | src/clj/clojure/core_deftype.clj | 26 | ||||
-rw-r--r-- | src/clj/clojure/genclass.clj | 6 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 16 |
4 files changed, 35 insertions, 15 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 1825d898..7fa7d8f0 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -4552,8 +4552,8 @@ (alter-meta! (find-ns 'clojure.core) assoc :doc "Fundamental library of the Clojure language") (load "core_proxy") (load "core_print") -(load "core_deftype") (load "genclass") +(load "core_deftype") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; (defn future-call diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj index e68f5874..2f962669 100644 --- a/src/clj/clojure/core_deftype.clj +++ b/src/clj/clojure/core_deftype.clj @@ -13,6 +13,9 @@ (defn hash-combine [x y] (clojure.lang.Util/hashCombine x (clojure.lang.Util/hash y))) +(defn munge [s] + ((if (symbol? s) symbol str) (clojure.lang.Compiler/munge (str s)))) + (defn- emit-deftype* "Do not use this directly - use deftype" [tagname name fields interfaces methods] @@ -185,6 +188,14 @@ ;;;;;;;;;;;;;;;;;;;;;;; protocols ;;;;;;;;;;;;;;;;;;;;;;;; +(defn dtype + "Returns the dynamic type of x, or its Class if none" + [x] + (if (instance? clojure.lang.IDynamicType x) + (let [x #^ clojure.lang.IDynamicType x] + (.getDynamicType x)) + (class x))) + (defn- expand-method-impl-cache [#^clojure.lang.MethodImplCache cache c f] (let [cs (into {} (remove (fn [[c f]] (nil? f)) (map vec (partition 2 (.table cache))))) cs (assoc cs c f) @@ -205,7 +216,7 @@ (defn find-protocol-impl [protocol x] (if (and (:on protocol) (instance? (:on protocol) x)) x - (let [t (type x) + (let [t (dtype x) c (class x) impl #(get (:impls protocol) %)] (or (impl t) @@ -288,8 +299,9 @@ (str "function " (.sym v))))))))) (defn- emit-protocol [name opts+sigs] - (let [[opts sigs] - (loop [opts {:on nil} sigs opts+sigs] + (let [iname (symbol (str (munge *ns*) "." (munge name))) + [opts sigs] + (loop [opts {:on iname} sigs opts+sigs] (condp #(%1 %2) (first sigs) string? (recur (assoc opts :doc (first sigs)) (next sigs)) keyword? (recur (assoc opts (first sigs) (second sigs)) (nnext sigs)) @@ -307,9 +319,15 @@ {:name (vary-meta mname assoc :doc doc :arglists arglists) :arglists arglists :doc doc})))) - {} sigs)] + {} sigs) + meths (mapcat (fn [sig] + (let [m (munge (:name sig))] + (map #(vector m (vec (repeat (dec (count %))'Object)) 'Object) + (:arglists sig)))) + (vals sigs))] `(do (defonce ~name {}) + (gen-interface :name ~iname :methods ~meths) (alter-meta! (var ~name) assoc :doc ~(:doc opts)) (#'assert-same-protocol (var ~name) '~(map :name (vals sigs))) (alter-var-root (var ~name) merge diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index 4947b3b3..cc1072d7 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -660,10 +660,12 @@ here." [& options] - (when *compile-files* (let [options-map (apply hash-map options) [cname bytecode] (generate-interface options-map)] - (clojure.lang.Compiler/writeClassFile cname bytecode)))) + (if *compile-files* + (clojure.lang.Compiler/writeClassFile cname bytecode) + (.defineClass #^DynamicClassLoader (deref clojure.lang.Compiler/LOADER) + (str (:name options-map)) bytecode)))) (comment diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index c9fd7acf..1896225b 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -768,18 +768,18 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{ { Symbol sym = (Symbol) RT.third(form); if(c != null) - maybeField = Reflector.getMethods(c, 0, sym.name, true).size() == 0; + maybeField = Reflector.getMethods(c, 0, munge(sym.name), true).size() == 0; else if(instance != null && instance.hasJavaClass() && instance.getJavaClass() != null) - maybeField = Reflector.getMethods(instance.getJavaClass(), 0, sym.name, false).size() == 0; + maybeField = Reflector.getMethods(instance.getJavaClass(), 0, munge(sym.name), false).size() == 0; } if(maybeField) //field { Symbol sym = (Symbol) RT.third(form); Symbol tag = tagOf(form); if(c != null) { - return new StaticFieldExpr(line, c, sym.name, tag); + return new StaticFieldExpr(line, c, munge(sym.name), tag); } else - return new InstanceFieldExpr(line, instance, sym.name, tag); + return new InstanceFieldExpr(line, instance, munge(sym.name), tag); } else { @@ -792,9 +792,9 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{ for(ISeq s = RT.next(call); s != null; s = s.next()) args = args.cons(analyze(context == C.EVAL ? context : C.EXPRESSION, s.first())); if(c != null) - return new StaticMethodExpr(source, line, tag, c, sym.name, args); + return new StaticMethodExpr(source, line, tag, c, munge(sym.name), args); else - return new InstanceMethodExpr(source, line, tag, instance, sym.name, args); + return new InstanceMethodExpr(source, line, tag, instance, munge(sym.name), args); } } } @@ -2773,7 +2773,7 @@ static class InvokeExpr implements Expr{ if(this.protocolOn != null) { IPersistentMap mmap = (IPersistentMap) RT.get(pvar.get(), methodMapKey); - String mname = ((Keyword) mmap.valAt(Keyword.intern(fvar.sym))).sym.toString(); + String mname = munge(((Keyword) mmap.valAt(Keyword.intern(fvar.sym))).sym.toString()); List methods = Reflector.getMethods(protocolOn, args.count() - 1, mname, false); if(methods.size() != 1) throw new IllegalArgumentException( @@ -6157,7 +6157,7 @@ public static class NewInstanceMethod extends ObjMethod{ Symbol dotname = (Symbol)RT.first(form); if(!dotname.name.startsWith(".")) throw new IllegalArgumentException("Method names must begin with '.': " + dotname); - Symbol name = (Symbol) Symbol.intern(null,dotname.name.substring(1)).withMeta(RT.meta(dotname)); + Symbol name = (Symbol) Symbol.intern(null,munge(dotname.name.substring(1))).withMeta(RT.meta(dotname)); IPersistentVector parms = (IPersistentVector) RT.second(form); ISeq body = RT.next(RT.next(form)); try |