summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-01-05 21:23:45 +0000
committerRich Hickey <richhickey@gmail.com>2008-01-05 21:23:45 +0000
commit82e8dc1deaa37a52515f353d8494dc03be2c6e50 (patch)
tree9fd140495a42b71a9953fada4dc44ad9496d786f /src
parent443cce766feb8477b2480840bea6d7967212da0c (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.clj12
-rw-r--r--src/jvm/clojure/lang/Compiler.java76
-rw-r--r--src/jvm/clojure/lang/IPersistentVector.java2
-rw-r--r--src/jvm/clojure/lang/LispReader.java4
-rw-r--r--src/jvm/clojure/lang/PersistentTreeMap.java2
-rw-r--r--src/jvm/clojure/lang/Reversible.java17
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;
+}