diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-05-08 20:10:48 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-05-08 20:10:48 +0000 |
commit | 56dc8bc5e6fdfd3e358e4c0d0428ce3067485f4d (patch) | |
tree | 699c718154eea4094a97ecf2b0416c7d14d8622a /src | |
parent | be302bb20730215bfa584ba0ca2c577f15b2d4c8 (diff) |
first steps in improving modularity - moving classname resolution towards consumer in: new, static calls, class literals and import. Note import is now a macro (but tolerant of quotes for backwards compatibility)
Diffstat (limited to 'src')
-rw-r--r-- | src/clj/clojure/core.clj | 41 | ||||
-rw-r--r-- | src/clj/clojure/core_proxy.clj | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 58 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Namespace.java | 5 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 |
5 files changed, 81 insertions, 29 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 8fee8bcb..62da5a61 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -1840,25 +1840,31 @@ ~@body (recur (unchecked-inc ~i))))))) -(defn import +(defn into + "Returns a new coll consisting of to-coll with all of the items of + from-coll conjoined." + [to from] + (let [ret to items (seq from)] + (if items + (recur (conj ret (first items)) (next items)) + ret))) + +(defmacro import "import-list => (package-symbol class-name-symbols*) For each name in class-name-symbols, adds a mapping from name to the class named by package.name to the current namespace. Use :import in the ns macro in preference to calling this directly." [& import-symbols-or-lists] - (let [#^clojure.lang.Namespace ns *ns*] - (doseq [spec import-symbols-or-lists] - (if (symbol? spec) - (let [n (name spec) - dot (.lastIndexOf n (. clojure.lang.RT (intCast \.))) - c (symbol (.substring n (inc dot)))] - (. ns (importClass c (. clojure.lang.RT (classForName (name spec)))))) - (let [pkg (first spec) - classes (next spec)] - (doseq [c classes] - (. ns (importClass c (. clojure.lang.RT (classForName (str pkg "." c))))))))))) - + (let [specs (map #(if (and (seq? %) (= 'quote (first %))) (second %) %) + import-symbols-or-lists)] + `(do ~@(map #(list 'clojure.core/import* %) + (reduce (fn [v spec] + (if (symbol? spec) + (conj v (name spec)) + (let [p (first spec) cs (rest spec)] + (into v (map #(str p "." %) cs))))) + [] specs))))) (defn into-array "Returns an array with components set to the values in aseq. The array's @@ -1871,15 +1877,6 @@ ([type aseq] (clojure.lang.RT/seqToTypedArray type (seq aseq)))) -(defn into - "Returns a new coll consisting of to-coll with all of the items of - from-coll conjoined." - [to from] - (let [ret to items (seq from)] - (if items - (recur (conj ret (first items)) (next items)) - ret))) - (defn #^{:private true} array [& items] (into-array items)) diff --git a/src/clj/clojure/core_proxy.clj b/src/clj/clojure/core_proxy.clj index 860621c4..93e3e0ba 100644 --- a/src/clj/clojure/core_proxy.clj +++ b/src/clj/clojure/core_proxy.clj @@ -255,7 +255,7 @@ pname (proxy-name super interfaces)] (or (RT/loadClassForName pname) (let [[cname bytecode] (generate-proxy super interfaces)] - (. (RT/getRootClassLoader) (defineClass pname bytecode)))))) + (. (deref clojure.lang.Compiler/LOADER) (defineClass pname bytecode)))))) (defn construct-proxy "Takes a proxy class and any arguments for its superclass ctor and diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 66568e58..82d4a77a 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -53,6 +53,7 @@ static final Symbol FINALLY = Symbol.create("finally"); static final Symbol THROW = Symbol.create("throw"); static final Symbol MONITOR_ENTER = Symbol.create("monitor-enter"); static final Symbol MONITOR_EXIT = Symbol.create("monitor-exit"); +static final Symbol IMPORT = Symbol.create("clojure.core", "import*"); //static final Symbol INSTANCE = Symbol.create("instance?"); //static final Symbol THISFN = Symbol.create("thisfn"); @@ -91,6 +92,7 @@ static final public IPersistentMap specials = PersistentHashMap.create( FN, null, QUOTE, new ConstantExpr.Parser(), THE_VAR, new TheVarExpr.Parser(), + IMPORT, new ImportExpr.Parser(), DOT, new HostExpr.Parser(), ASSIGN, new AssignExpr.Parser(), // TRY_FINALLY, new TryFinallyExpr.Parser(), @@ -120,6 +122,7 @@ private static final Type SYMBOL_TYPE = Type.getType(Symbol.class); private static final Type IFN_TYPE = Type.getType(IFn.class); private static final Type RT_TYPE = Type.getType(RT.class); final static Type CLASS_TYPE = Type.getType(Class.class); +final static Type NS_TYPE = Type.getType(Namespace.class); final static Type REFLECTOR_TYPE = Type.getType(Reflector.class); final static Type THROWABLE_TYPE = Type.getType(Throwable.class); final static Type BOOLEAN_OBJECT_TYPE = Type.getType(Boolean.class); @@ -520,6 +523,48 @@ public static class KeywordExpr implements Expr{ } } +public static class ImportExpr implements Expr{ + public final String c; + final static Method forNameMethod = Method.getMethod("Class forName(String)"); + final static Method importClassMethod = Method.getMethod("Class importClass(Class)"); + final static Method derefMethod = Method.getMethod("Object deref()"); + + public ImportExpr(String c){ + this.c = c; + } + + public Object eval() throws Exception{ + Namespace ns = (Namespace) RT.CURRENT_NS.deref(); + ns.importClass(RT.classForName(c)); + return null; + } + + public void emit(C context, FnExpr fn, GeneratorAdapter gen){ + gen.getStatic(RT_TYPE,"CURRENT_NS",VAR_TYPE); + gen.invokeVirtual(VAR_TYPE, derefMethod); + gen.checkCast(NS_TYPE); + gen.push(c); + gen.invokeStatic(CLASS_TYPE, forNameMethod); + gen.invokeVirtual(NS_TYPE, importClassMethod); + if(context == C.STATEMENT) + gen.pop(); + } + + public boolean hasJavaClass(){ + return false; + } + + public Class getJavaClass() throws ClassNotFoundException{ + throw new IllegalArgumentException("ImportExpr has no Java class"); + } + + static class Parser implements IParser{ + public Expr parse(C context, Object form) throws Exception{ + return new ImportExpr((String) RT.second(form)); + } + } +} + public static abstract class LiteralExpr implements Expr{ abstract Object val(); @@ -952,8 +997,8 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ public final String fieldName; public final Class c; public final java.lang.reflect.Field field; - final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)"); - final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)"); +// final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)"); +// final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)"); final int line; public StaticFieldExpr(int line, Class c, String fieldName) throws Exception{ @@ -1238,8 +1283,9 @@ static class StaticMethodExpr extends MethodExpr{ public final String source; public final int line; public final java.lang.reflect.Method method; + final static Method forNameMethod = Method.getMethod("Class forName(String)"); final static Method invokeStaticMethodMethod = - Method.getMethod("Object invokeStaticMethod(String,String,Object[])"); + Method.getMethod("Object invokeStaticMethod(Class,String,Object[])"); public StaticMethodExpr(String source, int line, Class c, String methodName, IPersistentVector args) @@ -1338,6 +1384,7 @@ static class StaticMethodExpr extends MethodExpr{ else { gen.push(c.getName()); + gen.invokeStatic(CLASS_TYPE, forNameMethod); gen.push(methodName); emitArgsAsArray(args, fn, gen); if(context == C.RETURN) @@ -2083,7 +2130,8 @@ public static class NewExpr implements Expr{ public final Class c; final static Method invokeConstructorMethod = Method.getMethod("Object invokeConstructor(Class,Object[])"); - final static Method forNameMethod = Method.getMethod("Class classForName(String)"); +// final static Method forNameMethod = Method.getMethod("Class classForName(String)"); + final static Method forNameMethod = Method.getMethod("Class forName(String)"); public NewExpr(Class c, IPersistentVector args, int line) throws Exception{ @@ -2149,7 +2197,7 @@ public static class NewExpr implements Expr{ else { gen.push(c.getName()); - gen.invokeStatic(RT_TYPE, forNameMethod); + gen.invokeStatic(CLASS_TYPE, forNameMethod); MethodExpr.emitArgsAsArray(args, fn, gen); if(context == C.RETURN) { diff --git a/src/jvm/clojure/lang/Namespace.java b/src/jvm/clojure/lang/Namespace.java index 77335308..09d87037 100644 --- a/src/jvm/clojure/lang/Namespace.java +++ b/src/jvm/clojure/lang/Namespace.java @@ -105,6 +105,11 @@ public Class importClass(Symbol sym, Class c){ } +public Class importClass(Class c){ + String n = c.getName(); + return importClass(Symbol.intern(n.substring(n.lastIndexOf('.') + 1)), c); +} + public Var refer(Symbol sym, Var var){ return (Var) reference(sym, var); diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index e095ed04..d9e7594b 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -1475,7 +1475,9 @@ static public ClassLoader makeClassLoader(){ } static public ClassLoader baseLoader(){ - if(booleanCast(USE_CONTEXT_CLASSLOADER.deref())) + if(Compiler.LOADER.isBound()) + return (ClassLoader) Compiler.LOADER.deref(); + else if(booleanCast(USE_CONTEXT_CLASSLOADER.deref())) return Thread.currentThread().getContextClassLoader(); else if(ROOT_CLASSLOADER != null) return ROOT_CLASSLOADER; |