summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-11-30 13:39:19 -0500
committerRich Hickey <richhickey@gmail.com>2009-11-30 13:39:19 -0500
commit77173bbf8eea48729deaf4cac0dc10918b3720e9 (patch)
tree33d9de2c812c25c37ce4b08034bc23d844bd48b8
parent9fc359815618f1cec7ea722e9f7b516f70057e92 (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.clj2
-rw-r--r--src/clj/clojure/core_deftype.clj26
-rw-r--r--src/clj/clojure/genclass.clj6
-rw-r--r--src/jvm/clojure/lang/Compiler.java16
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