Skip to content

Commit 56dc8bc

Browse files
committed
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)
1 parent be302bb commit 56dc8bc

5 files changed

Lines changed: 81 additions & 29 deletions

File tree

src/clj/clojure/core.clj

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,25 +1840,31 @@
18401840
~@body
18411841
(recur (unchecked-inc ~i)))))))
18421842

1843-
(defn import
1843+
(defn into
1844+
"Returns a new coll consisting of to-coll with all of the items of
1845+
from-coll conjoined."
1846+
[to from]
1847+
(let [ret to items (seq from)]
1848+
(if items
1849+
(recur (conj ret (first items)) (next items))
1850+
ret)))
1851+
1852+
(defmacro import
18441853
"import-list => (package-symbol class-name-symbols*)
18451854
18461855
For each name in class-name-symbols, adds a mapping from name to the
18471856
class named by package.name to the current namespace. Use :import in the ns
18481857
macro in preference to calling this directly."
18491858
[& import-symbols-or-lists]
1850-
(let [#^clojure.lang.Namespace ns *ns*]
1851-
(doseq [spec import-symbols-or-lists]
1852-
(if (symbol? spec)
1853-
(let [n (name spec)
1854-
dot (.lastIndexOf n (. clojure.lang.RT (intCast \.)))
1855-
c (symbol (.substring n (inc dot)))]
1856-
(. ns (importClass c (. clojure.lang.RT (classForName (name spec))))))
1857-
(let [pkg (first spec)
1858-
classes (next spec)]
1859-
(doseq [c classes]
1860-
(. ns (importClass c (. clojure.lang.RT (classForName (str pkg "." c)))))))))))
1861-
1859+
(let [specs (map #(if (and (seq? %) (= 'quote (first %))) (second %) %)
1860+
import-symbols-or-lists)]
1861+
`(do ~@(map #(list 'clojure.core/import* %)
1862+
(reduce (fn [v spec]
1863+
(if (symbol? spec)
1864+
(conj v (name spec))
1865+
(let [p (first spec) cs (rest spec)]
1866+
(into v (map #(str p "." %) cs)))))
1867+
[] specs)))))
18621868

18631869
(defn into-array
18641870
"Returns an array with components set to the values in aseq. The array's
@@ -1871,15 +1877,6 @@
18711877
([type aseq]
18721878
(clojure.lang.RT/seqToTypedArray type (seq aseq))))
18731879

1874-
(defn into
1875-
"Returns a new coll consisting of to-coll with all of the items of
1876-
from-coll conjoined."
1877-
[to from]
1878-
(let [ret to items (seq from)]
1879-
(if items
1880-
(recur (conj ret (first items)) (next items))
1881-
ret)))
1882-
18831880
(defn #^{:private true}
18841881
array [& items]
18851882
(into-array items))

src/clj/clojure/core_proxy.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@
255255
pname (proxy-name super interfaces)]
256256
(or (RT/loadClassForName pname)
257257
(let [[cname bytecode] (generate-proxy super interfaces)]
258-
(. (RT/getRootClassLoader) (defineClass pname bytecode))))))
258+
(. (deref clojure.lang.Compiler/LOADER) (defineClass pname bytecode))))))
259259

260260
(defn construct-proxy
261261
"Takes a proxy class and any arguments for its superclass ctor and

src/jvm/clojure/lang/Compiler.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class Compiler implements Opcodes{
5353
static final Symbol THROW = Symbol.create("throw");
5454
static final Symbol MONITOR_ENTER = Symbol.create("monitor-enter");
5555
static final Symbol MONITOR_EXIT = Symbol.create("monitor-exit");
56+
static final Symbol IMPORT = Symbol.create("clojure.core", "import*");
5657
//static final Symbol INSTANCE = Symbol.create("instance?");
5758

5859
//static final Symbol THISFN = Symbol.create("thisfn");
@@ -91,6 +92,7 @@ public class Compiler implements Opcodes{
9192
FN, null,
9293
QUOTE, new ConstantExpr.Parser(),
9394
THE_VAR, new TheVarExpr.Parser(),
95+
IMPORT, new ImportExpr.Parser(),
9496
DOT, new HostExpr.Parser(),
9597
ASSIGN, new AssignExpr.Parser(),
9698
// TRY_FINALLY, new TryFinallyExpr.Parser(),
@@ -120,6 +122,7 @@ public class Compiler implements Opcodes{
120122
private static final Type IFN_TYPE = Type.getType(IFn.class);
121123
private static final Type RT_TYPE = Type.getType(RT.class);
122124
final static Type CLASS_TYPE = Type.getType(Class.class);
125+
final static Type NS_TYPE = Type.getType(Namespace.class);
123126
final static Type REFLECTOR_TYPE = Type.getType(Reflector.class);
124127
final static Type THROWABLE_TYPE = Type.getType(Throwable.class);
125128
final static Type BOOLEAN_OBJECT_TYPE = Type.getType(Boolean.class);
@@ -520,6 +523,48 @@ public Class getJavaClass() throws ClassNotFoundException{
520523
}
521524
}
522525

526+
public static class ImportExpr implements Expr{
527+
public final String c;
528+
final static Method forNameMethod = Method.getMethod("Class forName(String)");
529+
final static Method importClassMethod = Method.getMethod("Class importClass(Class)");
530+
final static Method derefMethod = Method.getMethod("Object deref()");
531+
532+
public ImportExpr(String c){
533+
this.c = c;
534+
}
535+
536+
public Object eval() throws Exception{
537+
Namespace ns = (Namespace) RT.CURRENT_NS.deref();
538+
ns.importClass(RT.classForName(c));
539+
return null;
540+
}
541+
542+
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
543+
gen.getStatic(RT_TYPE,"CURRENT_NS",VAR_TYPE);
544+
gen.invokeVirtual(VAR_TYPE, derefMethod);
545+
gen.checkCast(NS_TYPE);
546+
gen.push(c);
547+
gen.invokeStatic(CLASS_TYPE, forNameMethod);
548+
gen.invokeVirtual(NS_TYPE, importClassMethod);
549+
if(context == C.STATEMENT)
550+
gen.pop();
551+
}
552+
553+
public boolean hasJavaClass(){
554+
return false;
555+
}
556+
557+
public Class getJavaClass() throws ClassNotFoundException{
558+
throw new IllegalArgumentException("ImportExpr has no Java class");
559+
}
560+
561+
static class Parser implements IParser{
562+
public Expr parse(C context, Object form) throws Exception{
563+
return new ImportExpr((String) RT.second(form));
564+
}
565+
}
566+
}
567+
523568
public static abstract class LiteralExpr implements Expr{
524569
abstract Object val();
525570

@@ -952,8 +997,8 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
952997
public final String fieldName;
953998
public final Class c;
954999
public final java.lang.reflect.Field field;
955-
final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)");
956-
final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)");
1000+
// final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)");
1001+
// final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)");
9571002
final int line;
9581003

9591004
public StaticFieldExpr(int line, Class c, String fieldName) throws Exception{
@@ -1238,8 +1283,9 @@ static class StaticMethodExpr extends MethodExpr{
12381283
public final String source;
12391284
public final int line;
12401285
public final java.lang.reflect.Method method;
1286+
final static Method forNameMethod = Method.getMethod("Class forName(String)");
12411287
final static Method invokeStaticMethodMethod =
1242-
Method.getMethod("Object invokeStaticMethod(String,String,Object[])");
1288+
Method.getMethod("Object invokeStaticMethod(Class,String,Object[])");
12431289

12441290

12451291
public StaticMethodExpr(String source, int line, Class c, String methodName, IPersistentVector args)
@@ -1338,6 +1384,7 @@ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
13381384
else
13391385
{
13401386
gen.push(c.getName());
1387+
gen.invokeStatic(CLASS_TYPE, forNameMethod);
13411388
gen.push(methodName);
13421389
emitArgsAsArray(args, fn, gen);
13431390
if(context == C.RETURN)
@@ -2083,7 +2130,8 @@ public static class NewExpr implements Expr{
20832130
public final Class c;
20842131
final static Method invokeConstructorMethod =
20852132
Method.getMethod("Object invokeConstructor(Class,Object[])");
2086-
final static Method forNameMethod = Method.getMethod("Class classForName(String)");
2133+
// final static Method forNameMethod = Method.getMethod("Class classForName(String)");
2134+
final static Method forNameMethod = Method.getMethod("Class forName(String)");
20872135

20882136

20892137
public NewExpr(Class c, IPersistentVector args, int line) throws Exception{
@@ -2149,7 +2197,7 @@ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
21492197
else
21502198
{
21512199
gen.push(c.getName());
2152-
gen.invokeStatic(RT_TYPE, forNameMethod);
2200+
gen.invokeStatic(CLASS_TYPE, forNameMethod);
21532201
MethodExpr.emitArgsAsArray(args, fn, gen);
21542202
if(context == C.RETURN)
21552203
{

src/jvm/clojure/lang/Namespace.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ public Class importClass(Symbol sym, Class c){
105105

106106
}
107107

108+
public Class importClass(Class c){
109+
String n = c.getName();
110+
return importClass(Symbol.intern(n.substring(n.lastIndexOf('.') + 1)), c);
111+
}
112+
108113
public Var refer(Symbol sym, Var var){
109114
return (Var) reference(sym, var);
110115

src/jvm/clojure/lang/RT.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,9 @@ public Object run(){
14751475
}
14761476

14771477
static public ClassLoader baseLoader(){
1478-
if(booleanCast(USE_CONTEXT_CLASSLOADER.deref()))
1478+
if(Compiler.LOADER.isBound())
1479+
return (ClassLoader) Compiler.LOADER.deref();
1480+
else if(booleanCast(USE_CONTEXT_CLASSLOADER.deref()))
14791481
return Thread.currentThread().getContextClassLoader();
14801482
else if(ROOT_CLASSLOADER != null)
14811483
return ROOT_CLASSLOADER;

0 commit comments

Comments
 (0)