diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-01-05 21:23:45 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-01-05 21:23:45 +0000 |
commit | 82e8dc1deaa37a52515f353d8494dc03be2c6e50 (patch) | |
tree | 9fd140495a42b71a9953fada4dc44ad9496d786f /src | |
parent | 443cce766feb8477b2480840bea6d7967212da0c (diff) |
compilation of field access, string tags, array classname resolution, rseq factored into Reversible
boot.clj generates NO reflective calls
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 12 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 76 | ||||
-rw-r--r-- | src/jvm/clojure/lang/IPersistentVector.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentTreeMap.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Reversible.java | 17 |
6 files changed, 82 insertions, 31 deletions
diff --git a/src/boot.clj b/src/boot.clj index 9e71bb93..21a1fb5d 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -360,8 +360,8 @@ (defn val [#^java.util.Map$Entry e] (. e (getValue))) -(defn rseq [smap] - (. smap (rseq))) +(defn rseq [#^clojure.lang.Reversible rev] + (. rev (rseq))) (defn name [#^clojure.lang.Named x] (. x (getName))) @@ -700,7 +700,7 @@ (throw (new Exception (strcat "Name conflict: " name " already exists in this namespace")))) (let [varsym (sym (str ns) (str name)) var (. clojure.lang.Var (find varsym)) - rvar ((. refers (get)) name)] + #^clojure.lang.Var rvar ((. refers (get)) name)] (if var (if rvar (when (not (eql? rvar var)) @@ -868,11 +868,11 @@ (def-aset aset-char setChar char) (defn make-array - ([type len] + ([#^Class type len] (. Array (newInstance type (int len)))) - ([type dim & more-dims] + ([#^Class type dim & more-dims] (let [dims (cons dim more-dims) - dimarray (make-array (. Integer TYPE) (count dims))] + #^"[I" dimarray (make-array (. Integer TYPE) (count dims))] (dotimes i (alength dimarray) (aset-int dimarray i (nth dims i))) (. Array (newInstance type dimarray))))) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 903759aa..c725e7ad 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -12,13 +12,13 @@ package clojure.lang; -//* +/* import clojure.asm.*; import clojure.asm.commons.Method; import clojure.asm.commons.GeneratorAdapter; /*/ -/* +//* import org.objectweb.asm.*; import org.objectweb.asm.commons.Method; @@ -691,7 +691,7 @@ static abstract class HostExpr implements Expr{ Symbol sym = (Symbol) form; if(sym.ns == null) //if ns-qualified can't be classname { - if(sym.name.indexOf('.') > 0) + if(sym.name.indexOf('.') > 0 || sym.name.charAt(0) == '[') className = sym.name; else { @@ -706,7 +706,7 @@ static abstract class HostExpr implements Expr{ } static Class tagToClass(Symbol tag) throws ClassNotFoundException{ - String className = maybeClassName(tag, false); + String className = maybeClassName(tag, true); if(className != null) return Class.forName(className); throw new IllegalArgumentException("Unable to resolve classname: " + tag); @@ -718,14 +718,18 @@ static abstract class FieldExpr extends HostExpr{ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ final Expr target; + final Class targetClass; + final java.lang.reflect.Field field; final String fieldName; final int line; final static Method getInstanceFieldMethod = Method.getMethod("Object getInstanceField(Object,String)"); final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)"); - public InstanceFieldExpr(int line, Expr target, String fieldName){ + public InstanceFieldExpr(int line, Expr target, String fieldName) throws Exception{ this.target = target; + this.targetClass = target.hasJavaClass() ? target.getJavaClass() : null; + this.field = targetClass != null ? targetClass.getField(fieldName) : null; this.fieldName = fieldName; this.line = line; } @@ -738,14 +742,24 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ if(context != C.STATEMENT) { gen.visitLineNumber(line, gen.mark()); - target.emit(C.EXPRESSION, fn, gen); - gen.push(fieldName); - gen.invokeStatic(REFLECTOR_TYPE, getInstanceFieldMethod); + if(targetClass != null) + { + target.emit(C.EXPRESSION, fn, gen); + gen.checkCast(Type.getType(targetClass)); + gen.getField(Type.getType(targetClass), fieldName, Type.getType(field.getType())); + HostExpr.emitBoxReturn(fn, gen, field.getType()); + } + else + { + target.emit(C.EXPRESSION, fn, gen); + gen.push(fieldName); + gen.invokeStatic(REFLECTOR_TYPE, getInstanceFieldMethod); + } } } public boolean hasJavaClass() throws Exception{ - return target.hasJavaClass(); + return targetClass != null; } public Class getJavaClass() throws Exception{ @@ -760,10 +774,23 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen, Expr val){ - target.emit(C.EXPRESSION, fn, gen); - gen.push(fieldName); - val.emit(C.EXPRESSION, fn, gen); - gen.invokeStatic(REFLECTOR_TYPE, setInstanceFieldMethod); + gen.visitLineNumber(line, gen.mark()); + if(targetClass != null) + { + target.emit(C.EXPRESSION, fn, gen); + gen.checkCast(Type.getType(targetClass)); + val.emit(C.EXPRESSION, fn, gen); + gen.dupX1(); + HostExpr.emitUnboxArg(fn, gen, field.getType()); + gen.putField(Type.getType(targetClass), fieldName, Type.getType(field.getType())); + } + else + { + target.emit(C.EXPRESSION, fn, gen); + gen.push(fieldName); + val.emit(C.EXPRESSION, fn, gen); + gen.invokeStatic(REFLECTOR_TYPE, setInstanceFieldMethod); + } if(context == C.STATEMENT) gen.pop(); } @@ -808,8 +835,8 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ } public Class getJavaClass() throws Exception{ - Class c = Class.forName(className); - java.lang.reflect.Field field = c.getField(fieldName); + //Class c = Class.forName(className); + //java.lang.reflect.Field field = c.getField(fieldName); return field.getType(); } @@ -819,10 +846,11 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen, Expr val){ - gen.push(className); - gen.push(fieldName); + gen.visitLineNumber(line, gen.mark()); val.emit(C.EXPRESSION, fn, gen); - gen.invokeStatic(REFLECTOR_TYPE, setStaticFieldMethod); + gen.dup(); + HostExpr.emitUnboxArg(fn, gen, field.getType()); + gen.putStatic(Type.getType(c), fieldName, Type.getType(field.getType())); if(context == C.STATEMENT) gen.pop(); } @@ -2268,8 +2296,8 @@ static class FnExpr implements Expr{ //derived from AFn/RestFn ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); // ClassWriter cw = new ClassWriter(0); - ClassVisitor cv = cw; - //ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out)); + //ClassVisitor cv = cw; + ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out)); //ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out)); cv.visit(V1_5, ACC_PUBLIC, internalName, null, isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFn", null); String source = (String) SOURCE.get(); @@ -3070,7 +3098,13 @@ private static Symbol tagOf(Object o){ { IObj obj = (IObj) o; if(obj.meta() != null) - return (Symbol) obj.meta().valAt(RT.TAG_KEY); + { + Object tag = obj.meta().valAt(RT.TAG_KEY); + if(tag instanceof Symbol) + return (Symbol) tag; + else if(tag instanceof String) + return Symbol.intern(null, (String) tag); + } } return null; } diff --git a/src/jvm/clojure/lang/IPersistentVector.java b/src/jvm/clojure/lang/IPersistentVector.java index 7dafa553..086c40f5 100644 --- a/src/jvm/clojure/lang/IPersistentVector.java +++ b/src/jvm/clojure/lang/IPersistentVector.java @@ -10,7 +10,7 @@ package clojure.lang; * You must not remove this notice, or any other, from this software.
*/
-public interface IPersistentVector extends Associative, Sequential, IPersistentStack{
+public interface IPersistentVector extends Associative, Sequential, IPersistentStack, Reversible{
int length();
Object nth(int i);
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 8fd86832..c41ff6fb 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -358,10 +358,10 @@ static class MetaReader extends AFn{ if(r instanceof LineNumberingPushbackReader)
line = ((LineNumberingPushbackReader) r).getLineNumber();
Object meta = read(r, true, null, true);
- if(meta instanceof Symbol || meta instanceof Keyword)
+ if(meta instanceof Symbol || meta instanceof Keyword || meta instanceof String)
meta = RT.map(RT.TAG_KEY, meta);
else if(!(meta instanceof IPersistentMap))
- throw new IllegalArgumentException("Metadata must be Symbol,Keyword or Map");
+ throw new IllegalArgumentException("Metadata must be Symbol,Keyword,String or Map");
Object o = read(r, true, null, true);
if(o instanceof IObj)
diff --git a/src/jvm/clojure/lang/PersistentTreeMap.java b/src/jvm/clojure/lang/PersistentTreeMap.java index 2015a8e0..5316c482 100644 --- a/src/jvm/clojure/lang/PersistentTreeMap.java +++ b/src/jvm/clojure/lang/PersistentTreeMap.java @@ -22,7 +22,7 @@ import java.util.*; * See Okasaki, Kahrs, Larsen et al */ -public class PersistentTreeMap extends APersistentMap{ +public class PersistentTreeMap extends APersistentMap implements Reversible{ public final Comparator comp; public final Node tree; diff --git a/src/jvm/clojure/lang/Reversible.java b/src/jvm/clojure/lang/Reversible.java new file mode 100644 index 00000000..0e035f3d --- /dev/null +++ b/src/jvm/clojure/lang/Reversible.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) + * which can be found in the file CPL.TXT at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Jan 5, 2008 */ + +package clojure.lang; + +public interface Reversible{ +ISeq rseq() throws Exception; +} |