summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clj/clojure/core.clj8
-rw-r--r--src/jvm/clojure/lang/Compiler.java1825
-rw-r--r--src/jvm/clojure/lang/PersistentList.java8
-rw-r--r--src/jvm/clojure/lang/Reflector.java3
-rw-r--r--src/jvm/clojure/lang/RestFn.java55
5 files changed, 1066 insertions, 833 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 90e3f76f..c4ab4785 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -4380,10 +4380,10 @@
not yet finished, calls to deref/@ will block."
[#^Callable f]
(let [fut (.submit clojure.lang.Agent/soloExecutor f)]
- (proxy [clojure.lang.IDeref java.util.concurrent.Future] []
+ (new [clojure.lang.IDeref java.util.concurrent.Future]
(deref [] (.get fut))
- (get ([] (.get fut))
- ([timeout unit] (.get fut timeout unit)))
+ (get [] (.get fut))
+ (get [timeout unit] (.get fut timeout unit))
(isCancelled [] (.isCancelled fut))
(isDone [] (.isDone fut))
(cancel [interrupt?] (.cancel fut interrupt?)))))
@@ -4493,7 +4493,7 @@
[]
(let [d (java.util.concurrent.CountDownLatch. 1)
v (atom nil)]
- (proxy [clojure.lang.AFn clojure.lang.IDeref] []
+ (new [clojure.lang.AFn clojure.lang.IDeref] this
(deref [] (.await d) @v)
(invoke [x]
(locking d
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index e9ba4335..c5c9f922 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -73,6 +73,8 @@ static final Symbol ISEQ = Symbol.create("clojure.lang.ISeq");
static final Keyword inlineKey = Keyword.intern(null, "inline");
static final Keyword inlineAritiesKey = Keyword.intern(null, "inline-arities");
+static final Keyword volatileKey = Keyword.intern(null, "volatile");
+
static final Symbol NS = Symbol.create("ns");
static final Symbol IN_NS = Symbol.create("in-ns");
@@ -219,7 +221,7 @@ public enum C{
interface Expr{
Object eval() throws Exception;
- void emit(C context, FnExpr fn, GeneratorAdapter gen);
+ void emit(C context, ObjExpr objx, GeneratorAdapter gen);
boolean hasJavaClass() throws Exception;
@@ -316,18 +318,18 @@ static class DefExpr implements Expr{
}
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitVar(gen, var);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitVar(gen, var);
if(initProvided)
{
gen.dup();
- init.emit(C.EXPRESSION, fn, gen);
+ init.emit(C.EXPRESSION, objx, gen);
gen.invokeVirtual(VAR_TYPE, bindRootMethod);
}
if(meta != null)
{
gen.dup();
- meta.emit(C.EXPRESSION, fn, gen);
+ meta.emit(C.EXPRESSION, objx, gen);
gen.checkCast(IPERSISTENTMAP_TYPE);
gen.invokeVirtual(VAR_TYPE, setMetaMethod);
}
@@ -390,8 +392,8 @@ public static class AssignExpr implements Expr{
return target.evalAssign(val);
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- target.emitAssign(context, fn, gen, val);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ target.emitAssign(context, objx, gen, val);
}
public boolean hasJavaClass() throws Exception{
@@ -430,8 +432,8 @@ public static class VarExpr implements Expr, AssignableExpr{
return var.deref();
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitVar(gen, var);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitVar(gen, var);
gen.invokeVirtual(VAR_TYPE, getMethod);
if(context == C.STATEMENT)
{
@@ -451,10 +453,10 @@ public static class VarExpr implements Expr, AssignableExpr{
return var.set(val.eval());
}
- public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
+ public void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen,
Expr val){
- fn.emitVar(gen, var);
- val.emit(C.EXPRESSION, fn, gen);
+ objx.emitVar(gen, var);
+ val.emit(C.EXPRESSION, objx, gen);
gen.invokeVirtual(VAR_TYPE, setMethod);
if(context == C.STATEMENT)
gen.pop();
@@ -472,8 +474,8 @@ public static class TheVarExpr implements Expr{
return var;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitVar(gen, var);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitVar(gen, var);
if(context == C.STATEMENT)
gen.pop();
}
@@ -508,8 +510,8 @@ public static class KeywordExpr implements Expr{
return k;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitKeyword(gen, k);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitKeyword(gen, k);
if(context == C.STATEMENT)
gen.pop();
@@ -540,7 +542,7 @@ public static class ImportExpr implements Expr{
return null;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.getStatic(RT_TYPE,"CURRENT_NS",VAR_TYPE);
gen.invokeVirtual(VAR_TYPE, derefMethod);
gen.checkCast(NS_TYPE);
@@ -577,11 +579,12 @@ public static abstract class LiteralExpr implements Expr{
static interface AssignableExpr{
Object evalAssign(Expr val) throws Exception;
- void emitAssign(C context, FnExpr fn, GeneratorAdapter gen, Expr val);
+ void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen, Expr val);
}
-static public interface MaybePrimitiveExpr{
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen);
+static public interface MaybePrimitiveExpr extends Expr{
+ public boolean canEmitPrimitive();
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen);
}
static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{
@@ -618,57 +621,8 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{
final static Method fromDoubleMethod = Method.getMethod("clojure.lang.Num from(double)");
- /*
- public static void emitBoxReturn(FnExpr fn, GeneratorAdapter gen, Class returnType){
- if(returnType.isPrimitive())
- {
- if(returnType == boolean.class)
- {
- Label falseLabel = gen.newLabel();
- Label endLabel = gen.newLabel();
- gen.ifZCmp(GeneratorAdapter.EQ, falseLabel);
- gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
- gen.goTo(endLabel);
- gen.mark(falseLabel);
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
- gen.mark(endLabel);
- }
- else if(returnType == void.class)
- {
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
- }
- else if(returnType == char.class)
- {
- gen.invokeStatic(CHAR_TYPE, charValueOfMethod);
- }
- else if(returnType == int.class)
- gen.invokeStatic(INTEGER_TYPE, intValueOfMethod);
- //m = fromIntMethod;
- else
- {
- Method m = fromIntMethod;
- if(returnType == int.class)
- m = fromIntMethod;
- else if(returnType == float.class)
- {
- gen.visitInsn(F2D);
- m = fromDoubleMethod;
- }
- else if(returnType == double.class)
- m = fromDoubleMethod;
- else if(returnType == long.class)
- m = fromLongMethod;
- else if(returnType == byte.class)
- m = fromIntMethod;
- else if(returnType == short.class)
- m = fromIntMethod;
- gen.invokeStatic(NUM_TYPE, m);
- }
- }
- }
- */
//*
- public static void emitBoxReturn(FnExpr fn, GeneratorAdapter gen, Class returnType){
+ public static void emitBoxReturn(ObjExpr objx, GeneratorAdapter gen, Class returnType){
if(returnType.isPrimitive())
{
if(returnType == boolean.class)
@@ -685,7 +639,7 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{
}
else if(returnType == void.class)
{
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
+ NIL_EXPR.emit(C.EXPRESSION, objx, gen);
}
else if(returnType == char.class)
{
@@ -715,7 +669,7 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{
}
//*/
- public static void emitUnboxArg(FnExpr fn, GeneratorAdapter gen, Class paramType){
+ public static void emitUnboxArg(ObjExpr objx, GeneratorAdapter gen, Class paramType){
if(paramType.isPrimitive())
{
if(paramType == boolean.class)
@@ -923,11 +877,16 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
return Reflector.invokeNoArgInstanceMember(target.eval(), fieldName);
}
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen){
+ public boolean canEmitPrimitive(){
+ return targetClass != null && field != null &&
+ Util.isPrimitive(field.getType());
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(targetClass != null && field != null)
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.checkCast(Type.getType(targetClass));
gen.getField(Type.getType(targetClass), fieldName, Type.getType(field.getType()));
}
@@ -935,15 +894,15 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
throw new UnsupportedOperationException("Unboxed emit of unknown member");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(targetClass != null && field != null)
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.checkCast(Type.getType(targetClass));
gen.getField(Type.getType(targetClass), fieldName, Type.getType(field.getType()));
//if(context != C.STATEMENT)
- HostExpr.emitBoxReturn(fn, gen, field.getType());
+ HostExpr.emitBoxReturn(objx, gen, field.getType());
if(context == C.STATEMENT)
{
gen.pop();
@@ -951,7 +910,7 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
}
else
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.push(fieldName);
gen.invokeStatic(REFLECTOR_TYPE, invokeNoArgInstanceMember);
if(context == C.STATEMENT)
@@ -971,23 +930,23 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
return Reflector.setInstanceField(target.eval(), fieldName, val.eval());
}
- public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
+ public void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen,
Expr val){
gen.visitLineNumber(line, gen.mark());
if(targetClass != null && field != null)
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.checkCast(Type.getType(targetClass));
- val.emit(C.EXPRESSION, fn, gen);
+ val.emit(C.EXPRESSION, objx, gen);
gen.dupX1();
- HostExpr.emitUnboxArg(fn, gen, field.getType());
+ HostExpr.emitUnboxArg(objx, gen, field.getType());
gen.putField(Type.getType(targetClass), fieldName, Type.getType(field.getType()));
}
else
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.push(fieldName);
- val.emit(C.EXPRESSION, fn, gen);
+ val.emit(C.EXPRESSION, objx, gen);
gen.invokeStatic(REFLECTOR_TYPE, setInstanceFieldMethod);
}
if(context == C.STATEMENT)
@@ -1017,17 +976,21 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
return Reflector.getStaticField(c, fieldName);
}
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen){
+ public boolean canEmitPrimitive(){
+ return Util.isPrimitive(field.getType());
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
gen.getStatic(Type.getType(c), fieldName, Type.getType(field.getType()));
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
gen.getStatic(Type.getType(c), fieldName, Type.getType(field.getType()));
//if(context != C.STATEMENT)
- HostExpr.emitBoxReturn(fn, gen, field.getType());
+ HostExpr.emitBoxReturn(objx, gen, field.getType());
if(context == C.STATEMENT)
{
gen.pop();
@@ -1051,12 +1014,12 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
return Reflector.setStaticField(c, fieldName, val.eval());
}
- public void emitAssign(C context, FnExpr fn, GeneratorAdapter gen,
+ public void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen,
Expr val){
gen.visitLineNumber(line, gen.mark());
- val.emit(C.EXPRESSION, fn, gen);
+ val.emit(C.EXPRESSION, objx, gen);
gen.dup();
- HostExpr.emitUnboxArg(fn, gen, field.getType());
+ HostExpr.emitUnboxArg(objx, gen, field.getType());
gen.putStatic(Type.getType(c), fieldName, Type.getType(field.getType()));
if(context == C.STATEMENT)
gen.pop();
@@ -1068,7 +1031,7 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
static Class maybePrimitiveType(Expr e){
try
{
- if(e instanceof MaybePrimitiveExpr && e.hasJavaClass())
+ if(e instanceof MaybePrimitiveExpr && e.hasJavaClass() && ((MaybePrimitiveExpr)e).canEmitPrimitive())
{
Class c = e.getJavaClass();
if(Util.isPrimitive(c))
@@ -1083,19 +1046,19 @@ static Class maybePrimitiveType(Expr e){
}
static abstract class MethodExpr extends HostExpr{
- static void emitArgsAsArray(IPersistentVector args, FnExpr fn, GeneratorAdapter gen){
+ static void emitArgsAsArray(IPersistentVector args, ObjExpr objx, GeneratorAdapter gen){
gen.push(args.count());
gen.newArray(OBJECT_TYPE);
for(int i = 0; i < args.count(); i++)
{
gen.dup();
gen.push(i);
- ((Expr) args.nth(i)).emit(C.EXPRESSION, fn, gen);
+ ((Expr) args.nth(i)).emit(C.EXPRESSION, objx, gen);
gen.arrayStore(OBJECT_TYPE);
}
}
- public static void emitTypedArgs(FnExpr fn, GeneratorAdapter gen, Class[] parameterTypes, IPersistentVector args){
+ public static void emitTypedArgs(ObjExpr objx, GeneratorAdapter gen, Class[] parameterTypes, IPersistentVector args){
for(int i = 0; i < parameterTypes.length; i++)
{
Expr e = (Expr) args.nth(i);
@@ -1103,12 +1066,12 @@ static abstract class MethodExpr extends HostExpr{
{
if(maybePrimitiveType(e) == parameterTypes[i])
{
- ((MaybePrimitiveExpr) e).emitUnboxed(C.EXPRESSION, fn, gen);
+ ((MaybePrimitiveExpr) e).emitUnboxed(C.EXPRESSION, objx, gen);
}
else
{
- e.emit(C.EXPRESSION, fn, gen);
- HostExpr.emitUnboxArg(fn, gen, parameterTypes[i]);
+ e.emit(C.EXPRESSION, objx, gen);
+ HostExpr.emitUnboxArg(objx, gen, parameterTypes[i]);
}
}
catch(Exception e1)
@@ -1206,18 +1169,22 @@ static class InstanceMethodExpr extends MethodExpr{
}
}
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen){
+ public boolean canEmitPrimitive(){
+ return method != null && Util.isPrimitive(method.getReturnType());
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(method != null)
{
Type type = Type.getType(method.getDeclaringClass());
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
//if(!method.getDeclaringClass().isInterface())
gen.checkCast(type);
- MethodExpr.emitTypedArgs(fn, gen, method.getParameterTypes(), args);
+ MethodExpr.emitTypedArgs(objx, gen, method.getParameterTypes(), args);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
Method m = new Method(methodName, Type.getReturnType(method), Type.getArgumentTypes(method));
@@ -1230,18 +1197,18 @@ static class InstanceMethodExpr extends MethodExpr{
throw new UnsupportedOperationException("Unboxed emit of unknown member");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(method != null)
{
Type type = Type.getType(method.getDeclaringClass());
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
//if(!method.getDeclaringClass().isInterface())
gen.checkCast(type);
- MethodExpr.emitTypedArgs(fn, gen, method.getParameterTypes(), args);
+ MethodExpr.emitTypedArgs(objx, gen, method.getParameterTypes(), args);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
Method m = new Method(methodName, Type.getReturnType(method), Type.getArgumentTypes(method));
@@ -1250,16 +1217,16 @@ static class InstanceMethodExpr extends MethodExpr{
else
gen.invokeVirtual(type, m);
//if(context != C.STATEMENT || method.getReturnType() == Void.TYPE)
- HostExpr.emitBoxReturn(fn, gen, method.getReturnType());
+ HostExpr.emitBoxReturn(objx, gen, method.getReturnType());
}
else
{
- target.emit(C.EXPRESSION, fn, gen);
+ target.emit(C.EXPRESSION, objx, gen);
gen.push(methodName);
- emitArgsAsArray(args, fn, gen);
+ emitArgsAsArray(args, objx, gen);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
gen.invokeStatic(REFLECTOR_TYPE, invokeInstanceMethodMethod);
@@ -1348,15 +1315,19 @@ static class StaticMethodExpr extends MethodExpr{
}
}
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen){
+ public boolean canEmitPrimitive(){
+ return method != null && Util.isPrimitive(method.getReturnType());
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(method != null)
{
- MethodExpr.emitTypedArgs(fn, gen, method.getParameterTypes(), args);
+ MethodExpr.emitTypedArgs(objx, gen, method.getParameterTypes(), args);
//Type type = Type.getObjectType(className.replace('.', '/'));
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
Type type = Type.getType(c);
@@ -1367,32 +1338,32 @@ static class StaticMethodExpr extends MethodExpr{
throw new UnsupportedOperationException("Unboxed emit of unknown member");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
if(method != null)
{
- MethodExpr.emitTypedArgs(fn, gen, method.getParameterTypes(), args);
+ MethodExpr.emitTypedArgs(objx, gen, method.getParameterTypes(), args);
//Type type = Type.getObjectType(className.replace('.', '/'));
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
Type type = Type.getType(c);
Method m = new Method(methodName, Type.getReturnType(method), Type.getArgumentTypes(method));
gen.invokeStatic(type, m);
//if(context != C.STATEMENT || method.getReturnType() == Void.TYPE)
- HostExpr.emitBoxReturn(fn, gen, method.getReturnType());
+ HostExpr.emitBoxReturn(objx, gen, method.getReturnType());
}
else
{
gen.push(c.getName());
gen.invokeStatic(CLASS_TYPE, forNameMethod);
gen.push(methodName);
- emitArgsAsArray(args, fn, gen);
+ emitArgsAsArray(args, objx, gen);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
gen.invokeStatic(REFLECTOR_TYPE, invokeStaticMethodMethod);
@@ -1426,7 +1397,7 @@ static class UnresolvedVarExpr implements Expr{
"UnresolvedVarExpr has no Java class");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
}
public Object eval() throws Exception{
@@ -1453,8 +1424,8 @@ static class ConstantExpr extends LiteralExpr{
return v;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitConstant(gen, id);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitConstant(gen, id);
if(context == C.STATEMENT)
{
gen.pop();
@@ -1505,7 +1476,7 @@ static class NilExpr extends LiteralExpr{
return null;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitInsn(Opcodes.ACONST_NULL);
if(context == C.STATEMENT)
gen.pop();
@@ -1534,7 +1505,7 @@ static class BooleanExpr extends LiteralExpr{
return val ? RT.T : RT.F;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
if(val)
gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
else
@@ -1568,7 +1539,7 @@ static class StringExpr extends LiteralExpr{
return str;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
if(context != C.STATEMENT)
gen.push(str);
}
@@ -1582,104 +1553,7 @@ static class StringExpr extends LiteralExpr{
}
}
-/*
-static class NumExpr extends LiteralExpr{
- final Num num;
- final static Method numFromIntMethod = Method.getMethod("clojure.lang.Num from(int)");
- final static Method numFromDoubleMethod = Method.getMethod("clojure.lang.Num from(double)");
- final static Method numFromBigIntMethod = Method.getMethod("clojure.lang.Num from(java.math.BigInteger)");
- final static Method numDivideMethod =
- Method.getMethod("clojure.lang.Num divide(java.math.BigInteger,java.math.BigInteger)");
- final static Type BIGINT_TYPE = Type.getType(BigInteger.class);
- final static Method bigintFromStringCtor = Method.getMethod("void <init>(String)");
-
- public NumExpr(Num num){
- this.num = num;
- }
-
- Object val(){
- return num;
- }
-
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- if(context != C.STATEMENT)
- {
- Class nclass = num.getClass();
- if(nclass == FixNum.class)
- {
- gen.push(num.intValue());
- gen.invokeStatic(NUM_TYPE, numFromIntMethod);
- }
- else if(nclass == DoubleNum.class)
- {
- gen.push(num.doubleValue());
- gen.invokeStatic(NUM_TYPE, numFromDoubleMethod);
- }
- else if(nclass == BigNum.class)
- {
- emitBigInteger(gen, num);
- gen.invokeStatic(NUM_TYPE, numFromBigIntMethod);
- }
- else if(nclass == RatioNum.class)
- {
- RatioNum r = (RatioNum) num;
- emitBigInteger(gen, r.numerator);
- emitBigInteger(gen, r.denominator);
- gen.invokeStatic(NUM_TYPE, numDivideMethod);
- }
- else
- throw new UnsupportedOperationException("Unknown Num type");
- }
- }
-
- public boolean hasJavaClass(){
- return true;
- }
-
- public Class getJavaClass() throws Exception{
- return Num.class;
- }
-
- static void emitBigInteger(GeneratorAdapter gen, Num num){
- gen.newInstance(BIGINT_TYPE);
- gen.dup();
- gen.push(num.toString());
- gen.invokeConstructor(BIGINT_TYPE, bigintFromStringCtor);
- }
-}
-
-
-
-static class CharExpr extends LiteralExpr{
- final Character ch;
- final static Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character");
- final static Method charValueOfMethod = Method.getMethod("Character valueOf(char)");
-
- public CharExpr(Character ch){
- this.ch = ch;
- }
- Object val(){
- return ch;
- }
-
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- if(context != C.STATEMENT)
- {
- gen.push(ch.charValue());
- gen.invokeStatic(CHARACTER_TYPE, charValueOfMethod);
- }
- }
-
- public boolean hasJavaClass(){
- return true;
- }
-
- public Class getJavaClass() throws Exception{
- return Character.class;
- }
-}
- */
static class MonitorEnterExpr extends UntypedExpr{
final Expr target;
@@ -1691,10 +1565,10 @@ static class MonitorEnterExpr extends UntypedExpr{
throw new UnsupportedOperationException("Can't eval monitor-enter");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- target.emit(C.EXPRESSION, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ target.emit(C.EXPRESSION, objx, gen);
gen.monitorEnter();
- NIL_EXPR.emit(context, fn, gen);
+ NIL_EXPR.emit(context, objx, gen);
}
static class Parser implements IParser{
@@ -1715,10 +1589,10 @@ static class MonitorExitExpr extends UntypedExpr{
throw new UnsupportedOperationException("Can't eval monitor-exit");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- target.emit(C.EXPRESSION, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ target.emit(C.EXPRESSION, objx, gen);
gen.monitorExit();
- NIL_EXPR.emit(context, fn, gen);
+ NIL_EXPR.emit(context, objx, gen);
}
static class Parser implements IParser{
@@ -1764,7 +1638,7 @@ public static class TryExpr implements Expr{
throw new UnsupportedOperationException("Can't eval try");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
Label startTry = gen.newLabel();
Label endTry = gen.newLabel();
Label endTryCatch = gen.newLabel();
@@ -1779,12 +1653,12 @@ public static class TryExpr implements Expr{
}
gen.mark(startTry);
- tryExpr.emit(context, fn, gen);
+ tryExpr.emit(context, objx, gen);
if(context != C.STATEMENT)
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), retLocal);
gen.mark(endTry);
if(finallyExpr != null)
- finallyExpr.emit(C.STATEMENT, fn, gen);
+ finallyExpr.emit(C.STATEMENT, objx, gen);
gen.goTo(ret);
for(int i = 0; i < catchExprs.count(); i++)
@@ -1794,13 +1668,13 @@ public static class TryExpr implements Expr{
//exception should be on stack
//put in clause local
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), clause.lb.idx);
- clause.handler.emit(context, fn, gen);
+ clause.handler.emit(context, objx, gen);
if(context != C.STATEMENT)
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), retLocal);
gen.mark(clause.endLabel);
if(finallyExpr != null)
- finallyExpr.emit(C.STATEMENT, fn, gen);
+ finallyExpr.emit(C.STATEMENT, objx, gen);
gen.goTo(ret);
}
gen.mark(endTryCatch);
@@ -1809,7 +1683,7 @@ public static class TryExpr implements Expr{
gen.mark(finallyLabel);
//exception should be on stack
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), finallyLocal);
- finallyExpr.emit(C.STATEMENT, fn, gen);
+ finallyExpr.emit(C.STATEMENT, objx, gen);
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ILOAD), finallyLocal);
gen.throwException();
}
@@ -1891,7 +1765,8 @@ public static class TryExpr implements Expr{
Var.pushThreadBindings(dynamicBindings);
LocalBinding lb = registerLocal(sym,
(Symbol) (RT.second(f) instanceof Symbol ? RT.second(f)
- : null), null);
+ : null),
+ null,false);
Expr handler = (new BodyExpr.Parser()).parse(context, RT.next(RT.next(RT.next(f))));
catches = catches.cons(new CatchClause(c, lb, handler));
}
@@ -1993,8 +1868,8 @@ static class ThrowExpr extends UntypedExpr{
throw new Exception("Can't eval throw");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- excExpr.emit(C.EXPRESSION, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ excExpr.emit(C.EXPRESSION, objx, gen);
gen.checkCast(THROWABLE_TYPE);
gen.throwException();
}
@@ -2008,50 +1883,6 @@ static class ThrowExpr extends UntypedExpr{
}
}
-/*
-static class ClassExpr implements Expr{
- final Class c;
- final static Method forNameMethod = Method.getMethod("Class forName(String)");
-
-
- public ClassExpr(Class c){
- this.c = c;
- }
-
- public Object eval() throws Exception{
- return c;
- }
-
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- if(context != C.STATEMENT)
- {
- gen.push(c.getName());
- gen.invokeStatic(CLASS_TYPE, forNameMethod);
- }
- }
-
- public boolean hasJavaClass(){
- return true;
- }
-
- public Class getJavaClass() throws Exception{
- return Class.class;
- }
-
- static class Parser implements IParser{
- public Expr parse(C context, Object frm) throws Exception{
- ISeq form = (ISeq) frm;
- //(class Classname)
- if(form.count() != 2)
- throw new Exception("wrong number of arguments, expecting: (class Classname)");
- Class c = HostExpr.maybeClass(RT.second(form), true);
- if(c == null)
- throw new IllegalArgumentException("Unable to resolve classname: " + RT.second(form));
- return new ClassExpr(c);
- }
- }
-}
-*/
static public boolean subsumes(Class[] c1, Class[] c2){
//presumes matching lengths
@@ -2183,16 +2014,16 @@ public static class NewExpr implements Expr{
return Reflector.invokeConstructor(c, argvals);
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
if(this.ctor != null)
{
Type type = Type.getType(c);
gen.newInstance(type);
gen.dup();
- MethodExpr.emitTypedArgs(fn, gen, ctor.getParameterTypes(), args);
+ MethodExpr.emitTypedArgs(objx, gen, ctor.getParameterTypes(), args);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
gen.invokeConstructor(type, new Method("<init>", Type.getConstructorDescriptor(ctor)));
@@ -2201,10 +2032,10 @@ public static class NewExpr implements Expr{
{
gen.push(c.getName());
gen.invokeStatic(CLASS_TYPE, forNameMethod);
- MethodExpr.emitArgsAsArray(args, fn, gen);
+ MethodExpr.emitArgsAsArray(args, objx, gen);
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
gen.invokeStatic(REFLECTOR_TYPE, invokeConstructorMethod);
@@ -2225,6 +2056,8 @@ public static class NewExpr implements Expr{
public Expr parse(C context, Object frm) throws Exception{
int line = (Integer) LINE.deref();
ISeq form = (ISeq) frm;
+ if(RT.second(form) instanceof IPersistentVector)
+ return NewInstanceExpr.parse(context, form);
//(new Classname args...)
if(form.count() < 2)
throw new Exception("wrong number of arguments, expecting: (new Classname args...)");
@@ -2240,113 +2073,6 @@ public static class NewExpr implements Expr{
}
-//static class IdenticalExpr implements Expr{
-// final Expr expr1;
-// final Expr expr2;
-//
-//
-// public IdenticalExpr(Expr expr1, Expr expr2){
-// this.expr1 = expr1;
-// this.expr2 = expr2;
-// }
-//
-// public boolean hasJavaClass(){
-// return true;
-// }
-//
-// public Class getJavaClass(){
-// return Boolean.class;
-// }
-//
-// public Object eval() throws Exception{
-// return expr1.eval() == expr2.eval() ?
-// RT.T : RT.F;
-// }
-//
-// public void emit(C context, FnExpr fn, GeneratorAdapter gen){
-// if(context != C.STATEMENT)
-// {
-// Label not = gen.newLabel();
-// Label end = gen.newLabel();
-// expr1.emit(C.EXPRESSION, fn, gen);
-// expr2.emit(C.EXPRESSION, fn, gen);
-// gen.visitJumpInsn(IF_ACMPNE, not);
-// gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
-//// gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
-// gen.goTo(end);
-// gen.mark(not);
-// gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
-//// NIL_EXPR.emit(C.EXPRESSION, fn, gen);
-// gen.mark(end);
-// }
-// }
-//
-// static class Parser implements IParser{
-// public Expr parse(C context, Object frm) throws Exception{
-// ISeq form = (ISeq) frm;
-// if(form.count() != 3)
-// throw new Exception("wrong number of arguments, expecting: (identical? x y)");
-//
-// return new IdenticalExpr(analyze(C.EXPRESSION, RT.second(form)), analyze(C.EXPRESSION, RT.third(form)));
-// }
-// }
-//}
-
-//static class InstanceExpr implements Expr{
-// final Expr expr;
-// final Class c;
-//
-//
-// public InstanceExpr(Expr expr, Class c){
-// this.expr = expr;
-// this.c = c;
-// }
-//
-// public Object eval() throws Exception{
-// return c.isInstance(expr.eval()) ?
-// RT.T : RT.F;
-// }
-//
-// public boolean hasJavaClass(){
-// return true;
-// }
-//
-// public Class getJavaClass(){
-// return Boolean.class;
-// }
-//
-// public void emit(C context, FnExpr fn, GeneratorAdapter gen){
-// if(context != C.STATEMENT)
-// {
-// Label not = gen.newLabel();
-// Label end = gen.newLabel();
-// expr.emit(C.EXPRESSION, fn, gen);
-// gen.instanceOf(Type.getType(c));
-// gen.ifZCmp(GeneratorAdapter.EQ, not);
-// gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
-//// gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
-// gen.goTo(end);
-// gen.mark(not);
-// gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
-//// NIL_EXPR.emit(C.EXPRESSION, fn, gen);
-// gen.mark(end);
-// }
-// }
-//
-// static class Parser implements IParser{
-// public Expr parse(C context, Object frm) throws Exception{
-// ISeq form = (ISeq) frm;
-// //(instance? x Classname)
-// if(form.count() != 3)
-// throw new Exception("wrong number of arguments, expecting: (instance? x Classname)");
-// Class c = HostExpr.maybeClass(RT.third(form), true);
-// if(c == null)
-// throw new IllegalArgumentException("Unable to resolve classname: " + RT.third(form));
-// return new InstanceExpr(analyze(C.EXPRESSION, RT.second(form)), c);
-// }
-// }
-//}
-
public static class MetaExpr implements Expr{
public final Expr expr;
public final MapExpr meta;
@@ -2363,10 +2089,10 @@ public static class MetaExpr implements Expr{
return ((IObj) expr.eval()).withMeta((IPersistentMap) meta.eval());
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- expr.emit(C.EXPRESSION, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ expr.emit(C.EXPRESSION, objx, gen);
gen.checkCast(IOBJ_TYPE);
- meta.emit(C.EXPRESSION, fn, gen);
+ meta.emit(C.EXPRESSION, objx, gen);
gen.checkCast(IPERSISTENTMAP_TYPE);
gen.invokeInterface(IOBJ_TYPE, withMetaMethod);
if(context == C.STATEMENT)
@@ -2405,7 +2131,7 @@ public static class IfExpr implements Expr{
return elseExpr.eval();
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
Label nullLabel = gen.newLabel();
Label falseLabel = gen.newLabel();
Label endLabel = gen.newLabel();
@@ -2414,15 +2140,14 @@ public static class IfExpr implements Expr{
try
{
- if(testExpr instanceof MaybePrimitiveExpr && testExpr.hasJavaClass() &&
- testExpr.getJavaClass() == boolean.class)
+ if(maybePrimitiveType(testExpr) == boolean.class)
{
- ((MaybePrimitiveExpr) testExpr).emitUnboxed(C.EXPRESSION, fn, gen);
+ ((MaybePrimitiveExpr) testExpr).emitUnboxed(C.EXPRESSION, objx, gen);
gen.ifZCmp(gen.EQ, falseLabel);
}
else
{
- testExpr.emit(C.EXPRESSION, fn, gen);
+ testExpr.emit(C.EXPRESSION, objx, gen);
gen.dup();
gen.ifNull(nullLabel);
gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
@@ -2433,12 +2158,12 @@ public static class IfExpr implements Expr{
{
throw new RuntimeException(e);
}
- thenExpr.emit(context, fn, gen);
+ thenExpr.emit(context, objx, gen);
gen.goTo(endLabel);
gen.mark(nullLabel);
gen.pop();
gen.mark(falseLabel);
- elseExpr.emit(context, fn, gen);
+ elseExpr.emit(context, objx, gen);
gen.mark(endLabel);
}
@@ -2530,7 +2255,7 @@ public static class EmptyExpr implements Expr{
return coll;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
if(coll instanceof IPersistentList)
gen.getStatic(LIST_TYPE, "EMPTY", EMPTY_LIST_TYPE);
else if(coll instanceof IPersistentVector)
@@ -2581,8 +2306,8 @@ public static class ListExpr implements Expr{
return ret.seq();
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- MethodExpr.emitArgsAsArray(args, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ MethodExpr.emitArgsAsArray(args, objx, gen);
gen.invokeStatic(RT_TYPE, arrayToListMethod);
if(context == C.STATEMENT)
gen.pop();
@@ -2614,8 +2339,8 @@ public static class MapExpr implements Expr{
return RT.map(ret);
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- MethodExpr.emitArgsAsArray(keyvals, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ MethodExpr.emitArgsAsArray(keyvals, objx, gen);
gen.invokeStatic(RT_TYPE, mapMethod);
if(context == C.STATEMENT)
gen.pop();
@@ -2663,8 +2388,8 @@ public static class SetExpr implements Expr{
return RT.set(ret);
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- MethodExpr.emitArgsAsArray(keys, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ MethodExpr.emitArgsAsArray(keys, objx, gen);
gen.invokeStatic(RT_TYPE, setMethod);
if(context == C.STATEMENT)
gen.pop();
@@ -2711,8 +2436,8 @@ public static class VectorExpr implements Expr{
return ret;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- MethodExpr.emitArgsAsArray(args, fn, gen);
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ MethodExpr.emitArgsAsArray(args, objx, gen);
gen.invokeStatic(RT_TYPE, vectorMethod);
if(context == C.STATEMENT)
gen.pop();
@@ -2773,14 +2498,14 @@ static class InvokeExpr implements Expr{
}
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
gen.visitLineNumber(line, gen.mark());
- fexpr.emit(C.EXPRESSION, fn, gen);
+ fexpr.emit(C.EXPRESSION, objx, gen);
gen.checkCast(IFN_TYPE);
for(int i = 0; i < Math.min(MAX_POSITIONAL_ARITY, args.count()); i++)
{
Expr e = (Expr) args.nth(i);
- e.emit(C.EXPRESSION, fn, gen);
+ e.emit(C.EXPRESSION, objx, gen);
}
if(args.count() > MAX_POSITIONAL_ARITY)
{
@@ -2789,12 +2514,12 @@ static class InvokeExpr implements Expr{
{
restArgs = restArgs.cons(args.nth(i));
}
- MethodExpr.emitArgsAsArray(restArgs, fn, gen);
+ MethodExpr.emitArgsAsArray(restArgs, objx, gen);
}
if(context == C.RETURN)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.emitClearLocals(gen);
}
@@ -2840,154 +2565,62 @@ static class SourceDebugExtensionAttribute extends Attribute{
}
}
-static class FnLoaderThunk extends RestFn{
- FnExpr fx;
- Var v;
- IFn f;
-
- FnLoaderThunk(FnExpr fx, Var v){
- super(0);
- this.fx = fx;
- this.v = v;
- }
-
- protected Object doInvoke(Object args) throws Exception{
- IFn f = loadFn();
- return f.applyTo((ISeq) args);
- }
-
- synchronized private IFn loadFn() throws Exception{
- if(f == null)
- {
- Class fc = fx.getCompiledClass();
- f = (IFn) fc.newInstance();
- v.swapRoot(f);
- }
- return f;
- }
-}
-
-static public class FnExpr implements Expr{
- static final String CONST_PREFIX = "const__";
- IPersistentCollection methods;
+static public class FnExpr extends ObjExpr{
+ final static Type aFnType = Type.getType(AFunction.class);
+ final static Type restFnType = Type.getType(RestFn.class);
//if there is a variadic overload (there can only be one) it is stored here
FnMethod variadicMethod = null;
- String name;
- String simpleName;
- String internalName;
- String thisName;
- Type fntype;
- public final Object tag;
- //localbinding->itself
- IPersistentMap closes = PersistentHashMap.EMPTY;
- //Keyword->KeywordExpr
- IPersistentMap keywords = PersistentHashMap.EMPTY;
- IPersistentMap vars = PersistentHashMap.EMPTY;
- Class compiledClass;
- int line;
- PersistentVector constants;
- int constantsID;
+ IPersistentCollection methods;
+ // String superName = null;
boolean onceOnly = false;
- String superName = null;
-
- public final IPersistentCollection methods(){
- return methods;
- }
- public final FnMethod variadicMethod(){
- return variadicMethod;
- }
-
- public final String name(){
- return name;
- }
-
- public final String simpleName(){
- return simpleName;
- }
-
- public final String internalName(){
- return internalName;
- }
-
- public final String thisName(){
- return thisName;
- }
-
- public final Type fntype(){
- return fntype;
- }
-
- public final IPersistentMap closes(){
- return closes;
- }
-
- public final IPersistentMap keywords(){
- return keywords;
- }
-
- public final IPersistentMap vars(){
- return vars;
- }
-
- public final Class compiledClass(){
- return compiledClass;
- }
-
- public final int line(){
- return line;
- }
-
- public final PersistentVector constants(){
- return constants;
- }
-
- public final int constantsID(){
- return constantsID;
+ public FnExpr(Object tag){
+ super(tag);
}
- final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)");
- final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)");
- final static Method varintern =
- Method.getMethod("clojure.lang.Var intern(clojure.lang.Symbol, clojure.lang.Symbol)");
- final static Method afnctor = Method.getMethod("void <init>()");
- final static Method restfnctor = Method.getMethod("void <init>(int)");
- final static Type aFnType = Type.getType(AFunction.class);
- final static Type restFnType = Type.getType(RestFn.class);
-
- final static Type DYNAMIC_CLASSLOADER_TYPE = Type.getType(DynamicClassLoader.class);
- final static Method getClassMethod = Method.getMethod("Class getClass()");
- final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()");
- final static Method getConstantsMethod = Method.getMethod("Object[] getConstants(int)");
- final static Method readStringMethod = Method.getMethod("Object readString(String)");
- private DynamicClassLoader loader;
- private byte[] bytecode;
+ protected void emitMethods(ClassVisitor cv){
+ //override of invoke/doInvoke for each method
+ for(ISeq s = RT.seq(methods); s != null; s = s.next())
+ {
+ ObjMethod method = (ObjMethod) s.first();
+ method.emit(this, cv);
+ }
- public FnExpr(Object tag){
- this.tag = tag;
+ if(isVariadic())
+ {
+ GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC,
+ Method.getMethod("int getRequiredArity()"),
+ null,
+ null,
+ cv);
+ gen.visitCode();
+ gen.push(variadicMethod.reqParms.count());
+ gen.returnValue();
+ gen.endMethod();
+ }
}
static Expr parse(C context, ISeq form, String name) throws Exception{
FnExpr fn = new FnExpr(tagOf(form));
- FnMethod enclosingMethod = (FnMethod) METHOD.deref();
+ ObjMethod enclosingMethod = (ObjMethod) METHOD.deref();
if(((IMeta) form.first()).meta() != null)
{
fn.onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), Keyword.intern(null, "once")));
- fn.superName = (String) RT.get(RT.meta(form.first()), Keyword.intern(null, "super-name"));
+// fn.superName = (String) RT.get(RT.meta(form.first()), Keyword.intern(null, "super-name"));
}
//fn.thisName = name;
String basename = enclosingMethod != null ?
- (enclosingMethod.fn.name + "$")
+ (enclosingMethod.objx.name + "$")
: //"clojure.fns." +
(munge(currentNS().name.name) + "$");
if(RT.second(form) instanceof Symbol)
name = ((Symbol) RT.second(form)).name;
- fn.simpleName = ((name != null ?
+ String simpleName = ((name != null ?
munge(name).replace(".", "_DOT_") : "fn")
+ "__" + RT.nextID());
- fn.name = basename + fn.simpleName;
+ fn.name = basename + simpleName;
fn.internalName = fn.name.replace('.', '/');
- fn.fntype = Type.getObjectType(fn.internalName);
+ fn.objtype = Type.getObjectType(fn.internalName);
try
{
Var.pushThreadBindings(
@@ -3052,14 +2685,120 @@ static public class FnExpr implements Expr{
{
Var.popThreadBindings();
}
- fn.compile();
+ fn.compile(fn.isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction",null,fn.onceOnly);
return fn;
}
+ public final ObjMethod variadicMethod(){
+ return variadicMethod;
+ }
+
boolean isVariadic(){
return variadicMethod != null;
}
+ public final IPersistentCollection methods(){
+ return methods;
+ }
+}
+
+static public class ObjExpr implements Expr{
+ static final String CONST_PREFIX = "const__";
+ String name;
+ //String simpleName;
+ String internalName;
+ String thisName;
+ Type objtype;
+ public final Object tag;
+ //localbinding->itself
+ IPersistentMap closes = PersistentHashMap.EMPTY;
+
+ //symbols
+ IPersistentSet volatiles = PersistentHashSet.EMPTY;
+
+ //Keyword->KeywordExpr
+ IPersistentMap keywords = PersistentHashMap.EMPTY;
+ IPersistentMap vars = PersistentHashMap.EMPTY;
+ Class compiledClass;
+ int line;
+ PersistentVector constants;
+ int constantsID;
+
+
+ final static Method voidctor = Method.getMethod("void <init>()");
+
+ public final String name(){
+ return name;
+ }
+
+// public final String simpleName(){
+// return simpleName;
+// }
+
+ public final String internalName(){
+ return internalName;
+ }
+
+ public final String thisName(){
+ return thisName;
+ }
+
+ public final Type objtype(){
+ return objtype;
+ }
+
+ public final IPersistentMap closes(){
+ return closes;
+ }
+
+ public final IPersistentMap keywords(){
+ return keywords;
+ }
+
+ public final IPersistentMap vars(){
+ return vars;
+ }
+
+ public final Class compiledClass(){
+ return compiledClass;
+ }
+
+ public final int line(){
+ return line;
+ }
+
+ public final PersistentVector constants(){
+ return constants;
+ }
+
+ public final int constantsID(){
+ return constantsID;
+ }
+
+ final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)");
+ final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)");
+ final static Method varintern =
+ Method.getMethod("clojure.lang.Var intern(clojure.lang.Symbol, clojure.lang.Symbol)");
+
+ final static Type DYNAMIC_CLASSLOADER_TYPE = Type.getType(DynamicClassLoader.class);
+ final static Method getClassMethod = Method.getMethod("Class getClass()");
+ final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()");
+ final static Method getConstantsMethod = Method.getMethod("Object[] getConstants(int)");
+ final static Method readStringMethod = Method.getMethod("Object readString(String)");
+ private DynamicClassLoader loader;
+ private byte[] bytecode;
+
+ public ObjExpr(Object tag){
+ this.tag = tag;
+ }
+
+ static String trimGenID(String name){
+ int i = name.lastIndexOf("__");
+ return i==-1?name:name.substring(0,i);
+ }
+
+
+
Type[] ctorTypes(){
if(closes.count() == 0)
return ARG_TYPES[0];
@@ -3078,7 +2817,7 @@ static public class FnExpr implements Expr{
return ret;
}
- private void compile() throws Exception{
+ void compile(String superName, String[] interfaceNames, boolean oneTimeUse) throws Exception{
//create bytecode for a class
//with name current_ns.defname[$letname]+
//anonymous fns get names fn__id
@@ -3088,9 +2827,9 @@ static public class FnExpr implements Expr{
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 + ACC_SUPER, internalName, null,
- superName != null ? superName :
- (isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction"), null);
+ cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, internalName, null,superName,interfaceNames);
+// superName != null ? superName :
+// (isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction"), null);
String source = (String) SOURCE.deref();
int lineBefore = (Integer) LINE_BEFORE.deref();
int lineAfter = (Integer) LINE_AFTER.deref() + 1;
@@ -3101,7 +2840,8 @@ static public class FnExpr implements Expr{
String smap = "SMAP\n" +
((source.lastIndexOf('.') > 0) ?
source.substring(0, source.lastIndexOf('.'))
- : simpleName)
+ :source)
+ // : simpleName)
+ ".java\n" +
"Clojure\n" +
"*S Clojure\n" +
@@ -3122,22 +2862,6 @@ static public class FnExpr implements Expr{
null, null);
}
-/*
- //static fields for keywords
- for(ISeq s = RT.keys(keywords); s != null; s = s.rest())
- {
- Keyword k = (Keyword) s.first();
- cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, munge(k.sym.toString()),
- KEYWORD_TYPE.getDescriptor(), null, null);
- }
- //static fields for vars
- for(ISeq s = RT.keys(vars); s != null; s = s.rest())
- {
- Var v = (Var) s.first();
- cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, munge(v.sym.toString()),
- VAR_TYPE.getDescriptor(), null, null);
- }
- */
//static init for constants, keywords and vars
GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
Method.getMethod("void <clinit> ()"),
@@ -3146,8 +2870,6 @@ static public class FnExpr implements Expr{
cv);
clinitgen.visitCode();
clinitgen.visitLineNumber(line, clinitgen.mark());
-// Label begin = clinitgen.newLabel();
-// Label end = clinitgen.newLabel();
if(constants.count() > 0)
{
@@ -3157,21 +2879,21 @@ static public class FnExpr implements Expr{
clinitgen.returnValue();
clinitgen.endMethod();
-// clinitgen.visitMaxs(1, 1);
//instance fields for closed-overs
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
LocalBinding lb = (LocalBinding) s.first();
+ //todo - only enable this non-private+writability for letfns where we need it
if(lb.getPrimitiveType() != null)
- cv.visitField(ACC_PUBLIC //+ ACC_FINAL
+// cv.visitField(ACC_PUBLIC + (isVolatile(lb) ? ACC_VOLATILE : ACC_FINAL)
+ cv.visitField(0 + (isVolatile(lb) ? ACC_VOLATILE : 0)
, lb.name, Type.getType(lb.getPrimitiveType()).getDescriptor(),
null, null);
else
- cv.visitField(ACC_PUBLIC //+ (onceOnly ? 0 : ACC_FINAL)
+ cv.visitField(0 //+ (oneTimeUse ? 0 : ACC_FINAL)
, lb.name, OBJECT_TYPE.getDescriptor(), null, null);
}
//ctor that takes closed-overs and inits base + fields
-// Method m = new Method("<init>", Type.VOID_TYPE, ARG_TYPES[closes.count()]);
Method m = new Method("<init>", Type.VOID_TYPE, ctorTypes());
GeneratorAdapter ctorgen = new GeneratorAdapter(ACC_PUBLIC,
m,
@@ -3184,15 +2906,15 @@ static public class FnExpr implements Expr{
ctorgen.visitLineNumber(line, ctorgen.mark());
ctorgen.visitLabel(start);
ctorgen.loadThis();
- if(superName != null)
- ctorgen.invokeConstructor(Type.getObjectType(superName), afnctor);
- else if(isVariadic()) //RestFn ctor takes reqArity arg
- {
- ctorgen.push(variadicMethod.reqParms.count());
- ctorgen.invokeConstructor(restFnType, restfnctor);
- }
- else
- ctorgen.invokeConstructor(aFnType, afnctor);
+// if(superName != null)
+ ctorgen.invokeConstructor(Type.getObjectType(superName), voidctor);
+// else if(isVariadic()) //RestFn ctor takes reqArity arg
+// {
+// ctorgen.push(variadicMethod.reqParms.count());
+// ctorgen.invokeConstructor(restFnType, restfnctor);
+// }
+// else
+// ctorgen.invokeConstructor(aFnType, voidctor);
int a = 1;
for(ISeq s = RT.keys(closes); s != null; s = s.next(), ++a)
{
@@ -3202,43 +2924,23 @@ static public class FnExpr implements Expr{
if(primc != null)
{
ctorgen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ILOAD), a);
- ctorgen.putField(fntype, lb.name, Type.getType(primc));
+ ctorgen.putField(objtype, lb.name, Type.getType(primc));
if(primc == Long.TYPE || primc == Double.TYPE)
++a;
}
else
{
ctorgen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ILOAD), a);
- ctorgen.putField(fntype, lb.name, OBJECT_TYPE);
+ ctorgen.putField(objtype, lb.name, OBJECT_TYPE);
}
}
ctorgen.visitLabel(end);
-// a = 1;
-// for(ISeq s = RT.keys(closes); s != null; s = s.rest(), ++a)
-// {
-// LocalBinding lb = (LocalBinding) s.first();
-// Class primc = lb.getPrimitiveType();
-// if(primc != null)
-// {
-// ctorgen.visitLocalVariable(lb.name, Type.getDescriptor(primc), null, start, end, a);
-// if(primc == Long.TYPE || primc == Double.TYPE)
-// ++a;
-// }
-// else
-// {
-// ctorgen.visitLocalVariable(lb.name, "Ljava/lang/Object;", null, start, end, a);
-// }
-// }
+
ctorgen.returnValue();
- // ctorgen.visitMaxs(1, 1);
ctorgen.endMethod();
- //override of invoke/doInvoke for each method
- for(ISeq s = RT.seq(methods); s != null; s = s.next())
- {
- FnMethod method = (FnMethod) s.first();
- method.emit(this, cv);
- }
+ emitMethods(cv);
+
//end of class
cv.visitEnd();
@@ -3249,6 +2951,9 @@ static public class FnExpr implements Expr{
// getCompiledClass();
}
+ protected void emitMethods(ClassVisitor gen){
+ }
+
void emitListAsObjectArray(Object value, GeneratorAdapter gen){
gen.push(((List) value).size());
gen.newArray(OBJECT_TYPE);
@@ -3406,7 +3111,7 @@ static public class FnExpr implements Expr{
{
emitValue(constants.nth(i), clinitgen);
clinitgen.checkCast(constantType(i));
- clinitgen.putStatic(fntype, constantName(i), constantType(i));
+ clinitgen.putStatic(objtype, constantName(i), constantType(i));
}
}
finally
@@ -3415,50 +3120,9 @@ static public class FnExpr implements Expr{
}
}
-// void emitConstants(GeneratorAdapter clinitgen){
-// try
-// {
-// Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T));
-//
-// for(int i = 0; i < constants.count(); i++)
-// {
-// Object o = constants.nth(i);
-// if(o instanceof String)
-// {
-// clinitgen.push((String) constants.nth(i));
-// }
-// else
-// {
-// String cs = null;
-// try
-// {
-// cs = RT.printString(o);
-// }
-// catch(Exception e)
-// {
-// throw new RuntimeException("Can't embed object in code, maybe print-dup not defined: "
-// + o);
-// }
-// if(cs.length() == 0)
-// throw new RuntimeException("Can't embed unreadable object in code: " + o);
-//
-// if(cs.startsWith("#<"))
-// throw new RuntimeException("Can't embed unreadable object in code: " + cs);
-// clinitgen.push(cs);
-// clinitgen.invokeStatic(RT_TYPE, readStringMethod);
-// clinitgen.checkCast(constantType(i));
-// }
-//// clinitgen.dup();
-//// clinitgen.push(i);
-//// clinitgen.arrayLoad(OBJECT_TYPE);
-// clinitgen.putStatic(fntype, constantName(i), constantType(i));
-// }
-// }
-// finally
-// {
-// Var.popThreadBindings();
-// }
-// }
+ boolean isVolatile(LocalBinding lb){
+ return closes.containsKey(lb) && volatiles.contains(lb.sym);
+ }
void emitClearCloses(GeneratorAdapter gen){
int a = 1;
@@ -3470,7 +3134,7 @@ static public class FnExpr implements Expr{
{
gen.loadThis();
gen.visitInsn(Opcodes.ACONST_NULL);
- gen.putField(fntype, lb.name, OBJECT_TYPE);
+ gen.putField(objtype, lb.name, OBJECT_TYPE);
}
}
}
@@ -3498,9 +3162,9 @@ static public class FnExpr implements Expr{
return getCompiledClass().newInstance();
}
- public void emitLetFnInits(GeneratorAdapter gen, FnExpr fn, IPersistentSet letFnLocals){
- //fn arg is enclosing fn, not this
- gen.checkCast(fntype);
+ public void emitLetFnInits(GeneratorAdapter gen, ObjExpr objx, IPersistentSet letFnLocals){
+ //objx arg is enclosing objx, not this
+ gen.checkCast(objtype);
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
@@ -3511,13 +3175,13 @@ static public class FnExpr implements Expr{
gen.dup();
if(primc != null)
{
- fn.emitUnboxedLocal(gen, lb);
- gen.putField(fntype, lb.name, Type.getType(primc));
+ objx.emitUnboxedLocal(gen, lb);
+ gen.putField(objtype, lb.name, Type.getType(primc));
}
else
{
- fn.emitLocal(gen, lb);
- gen.putField(fntype, lb.name, OBJECT_TYPE);
+ objx.emitLocal(gen, lb);
+ gen.putField(objtype, lb.name, OBJECT_TYPE);
}
}
}
@@ -3525,22 +3189,21 @@ static public class FnExpr implements Expr{
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
//emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
- //fn arg is enclosing fn, not this
+ //objx arg is enclosing objx, not this
getCompiledClass();
- gen.newInstance(fntype);
+ gen.newInstance(objtype);
gen.dup();
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
LocalBinding lb = (LocalBinding) s.first();
if(lb.getPrimitiveType() != null)
- fn.emitUnboxedLocal(gen, lb);
+ objx.emitUnboxedLocal(gen, lb);
else
- fn.emitLocal(gen, lb);
+ objx.emitLocal(gen, lb);
}
-// gen.invokeConstructor(fntype, new Method("<init>", Type.VOID_TYPE, ARG_TYPES[closes.count()]));
- gen.invokeConstructor(fntype, new Method("<init>", Type.VOID_TYPE, ctorTypes()));
+ gen.invokeConstructor(objtype, new Method("<init>", Type.VOID_TYPE, ctorTypes()));
if(context == C.STATEMENT)
{
gen.pop();
@@ -3555,6 +3218,26 @@ static public class FnExpr implements Expr{
return (tag != null) ? HostExpr.tagToClass(tag) : IFn.class;
}
+ public void emitAssignLocal(GeneratorAdapter gen, LocalBinding lb,Expr val){
+ if(!isVolatile(lb))
+ throw new IllegalArgumentException("Cannot assign to non-volatile: " + lb.name);
+ Class primc = lb.getPrimitiveType();
+ gen.loadThis();
+ if(primc != null)
+ {
+ MaybePrimitiveExpr me = (MaybePrimitiveExpr) val;
+ if(!me.canEmitPrimitive())
+ throw new IllegalArgumentException("Must assign primitive to primitive volatile: " + lb.name);
+ me.emitUnboxed(C.EXPRESSION, this, gen);
+ gen.putField(objtype, lb.name, Type.getType(primc));
+ }
+ else
+ {
+ val.emit(C.EXPRESSION, this, gen);
+ gen.putField(objtype, lb.name, OBJECT_TYPE);
+ }
+ }
+
private void emitLocal(GeneratorAdapter gen, LocalBinding lb){
if(closes.containsKey(lb))
{
@@ -3562,22 +3245,31 @@ static public class FnExpr implements Expr{
gen.loadThis();
if(primc != null)
{
- gen.getField(fntype, lb.name, Type.getType(primc));
+ gen.getField(objtype, lb.name, Type.getType(primc));
HostExpr.emitBoxReturn(this, gen, primc);
}
else
- gen.getField(fntype, lb.name, OBJECT_TYPE);
+ gen.getField(objtype, lb.name, OBJECT_TYPE);
}
else
{
Class primc = lb.getPrimitiveType();
- if(primc != null)
+ if(lb.isArg)
{
- gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ILOAD), lb.idx);
- HostExpr.emitBoxReturn(this, gen, primc);
+ gen.loadArg(lb.idx-1);
+ if(primc != null)
+ HostExpr.emitBoxReturn(this, gen, primc);
}
else
- gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ILOAD), lb.idx);
+ {
+ if(primc != null)
+ {
+ gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ILOAD), lb.idx);
+ HostExpr.emitBoxReturn(this, gen, primc);
+ }
+ else
+ gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ILOAD), lb.idx);
+ }
}
}
@@ -3586,8 +3278,10 @@ static public class FnExpr implements Expr{
if(closes.containsKey(lb))
{
gen.loadThis();
- gen.getField(fntype, lb.name, Type.getType(primc));
+ gen.getField(objtype, lb.name, Type.getType(primc));
}
+ else if(lb.isArg)
+ gen.loadArg(lb.idx-1);
else
gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ILOAD), lb.idx);
}
@@ -3605,7 +3299,7 @@ static public class FnExpr implements Expr{
}
public void emitConstant(GeneratorAdapter gen, int id){
- gen.getStatic(fntype, constantName(id), constantType(id));
+ gen.getStatic(objtype, constantName(id), constantType(id));
}
@@ -3640,77 +3334,22 @@ enum PSTATE{
REQ, REST, DONE
}
-
-public static class FnMethod{
- //when closures are defined inside other closures,
- //the closed over locals need to be propagated to the enclosing fn
- public final FnMethod parent;
- //localbinding->localbinding
- IPersistentMap locals = null;
- //num->localbinding
- IPersistentMap indexlocals = null;
+public static class FnMethod extends ObjMethod{
//localbinding->localbinding
PersistentVector reqParms = PersistentVector.EMPTY;
LocalBinding restParm = null;
- Expr body = null;
- FnExpr fn;
- PersistentVector argLocals;
- int maxLocal = 0;
- int line;
- PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY;
-
- public final IPersistentMap locals(){
- return locals;
- }
-
- public final PersistentVector reqParms(){
- return reqParms;
- }
-
- public final LocalBinding restParm(){
- return restParm;
- }
-
- public final Expr body(){
- return body;
- }
-
- public final FnExpr fn(){
- return fn;
- }
-
- public final PersistentVector argLocals(){
- return argLocals;
- }
-
- public final int maxLocal(){
- return maxLocal;
- }
- public final int line(){
- return line;
- }
-
- public FnMethod(FnExpr fn, FnMethod parent){
- this.parent = parent;
- this.fn = fn;
- }
-
- boolean isVariadic(){
- return restParm != null;
- }
-
- int numParams(){
- return reqParms.count() + (isVariadic() ? 1 : 0);
+ public FnMethod(ObjExpr objx, ObjMethod parent){
+ super(objx, parent);
}
- private static FnMethod parse(FnExpr fn, ISeq form) throws Exception{
+ static FnMethod parse(ObjExpr objx, ISeq form) throws Exception{
//([args] body...)
IPersistentVector parms = (IPersistentVector) RT.first(form);
ISeq body = RT.next(form);
try
{
- FnMethod method = new FnMethod(fn, (FnMethod) METHOD.deref());
+ FnMethod method = new FnMethod(objx, (ObjMethod) METHOD.deref());
method.line = (Integer) LINE.deref();
//register as the current method and set up a new env frame
Var.pushThreadBindings(
@@ -3722,7 +3361,7 @@ public static class FnMethod{
//register 'this' as local 0
//registerLocal(THISFN, null, null);
- registerLocal(Symbol.intern(fn.thisName != null ? fn.thisName : "fn__" + RT.nextID()), null, null);
+ registerLocal(Symbol.intern(objx.thisName != null ? objx.thisName : "fn__" + RT.nextID()), null, null,false);
PSTATE state = PSTATE.REQ;
PersistentVector argLocals = PersistentVector.EMPTY;
@@ -3743,7 +3382,7 @@ public static class FnMethod{
else
{
- LocalBinding lb = registerLocal(p, state == PSTATE.REST ? ISEQ : tagOf(p), null);
+ LocalBinding lb = registerLocal(p, state == PSTATE.REST ? ISEQ : tagOf(p), null,true);
argLocals = argLocals.cons(lb);
switch(state)
{
@@ -3773,13 +3412,118 @@ public static class FnMethod{
}
}
- public void emit(FnExpr fn, ClassVisitor cv){
- Method m = new Method(isVariadic() ? "doInvoke" : "invoke",
- OBJECT_TYPE, ARG_TYPES[numParams()]);
+ public final PersistentVector reqParms(){
+ return reqParms;
+ }
+
+ public final LocalBinding restParm(){
+ return restParm;
+ }
+
+ boolean isVariadic(){
+ return restParm != null;
+ }
+
+ int numParams(){
+ return reqParms.count() + (isVariadic() ? 1 : 0);
+ }
+
+ String getMethodName(){
+ return isVariadic()?"doInvoke":"invoke";
+ }
+
+ Type getReturnType(){
+ return OBJECT_TYPE;
+ }
+
+ Type[] getArgTypes(){
+ return ARG_TYPES[numParams()];
+ }
+
+ void emitClearLocals(GeneratorAdapter gen){
+ for(int i = 1; i < numParams() + 1; i++)
+ {
+ if(!localsUsedInCatchFinally.contains(i))
+ {
+ gen.visitInsn(Opcodes.ACONST_NULL);
+ gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), i);
+ }
+ }
+ for(int i = numParams() + 1; i < maxLocal + 1; i++)
+ {
+ if(!localsUsedInCatchFinally.contains(i))
+ {
+ LocalBinding b = (LocalBinding) RT.get(indexlocals, i);
+ if(b == null || maybePrimitiveType(b.init) == null)
+ {
+ gen.visitInsn(Opcodes.ACONST_NULL);
+ gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), i);
+ }
+ }
+ }
+ if(((FnExpr)objx).onceOnly)
+ {
+ objx.emitClearCloses(gen);
+ }
+ }
+}
+
+abstract public static class ObjMethod{
+ //when closures are defined inside other closures,
+ //the closed over locals need to be propagated to the enclosing objx
+ public final ObjMethod parent;
+ //localbinding->localbinding
+ IPersistentMap locals = null;
+ //num->localbinding
+ IPersistentMap indexlocals = null;
+ Expr body = null;
+ ObjExpr objx;
+ PersistentVector argLocals;
+ int maxLocal = 0;
+ int line;
+ PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY;
+
+ public final IPersistentMap locals(){
+ return locals;
+ }
+
+ public final Expr body(){
+ return body;
+ }
+
+ public final ObjExpr objx(){
+ return objx;
+ }
+
+ public final PersistentVector argLocals(){
+ return argLocals;
+ }
+
+ public final int maxLocal(){
+ return maxLocal;
+ }
+
+ public final int line(){
+ return line;
+ }
+
+ public ObjMethod(ObjExpr objx, ObjMethod parent){
+ this.parent = parent;
+ this.objx = objx;
+ }
+
+ abstract int numParams();
+ abstract String getMethodName();
+ abstract Type getReturnType();
+ abstract Type[] getArgTypes();
+
+ public void emit(ObjExpr fn, ClassVisitor cv){
+ Method m = new Method(getMethodName(), getReturnType(), getArgTypes());
GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC,
m,
null,
+ //todo don't hardwire this
EXCEPTION_TYPES,
cv);
gen.visitCode();
@@ -3808,16 +3552,24 @@ public static class FnMethod{
}
void emitClearLocals(GeneratorAdapter gen){
- //this seems shaky given primitive locals - revisit
- for(int i = 1; i < numParams() + 1; i++)
+ for(int i=0;i<argLocals.count();i++)
{
- if(!localsUsedInCatchFinally.contains(i))
+ LocalBinding lb = (LocalBinding) argLocals.nth(i);
+ if(!localsUsedInCatchFinally.contains(lb.idx) && lb.getPrimitiveType() == null)
{
gen.visitInsn(Opcodes.ACONST_NULL);
- gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), i);
-// gen.storeArg(i);
+ gen.storeArg(lb.idx - 1);
}
+
}
+// for(int i = 1; i < numParams() + 1; i++)
+// {
+// if(!localsUsedInCatchFinally.contains(i))
+// {
+// gen.visitInsn(Opcodes.ACONST_NULL);
+// gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), i);
+// }
+// }
for(int i = numParams() + 1; i < maxLocal + 1; i++)
{
if(!localsUsedInCatchFinally.contains(i))
@@ -3830,10 +3582,6 @@ public static class FnMethod{
}
}
}
- if(fn.onceOnly)
- {
- fn.emitClearCloses(gen);
- }
}
}
@@ -3843,14 +3591,16 @@ public static class LocalBinding{
public Expr init;
public final int idx;
public final String name;
+ public final boolean isArg;
- public LocalBinding(int num, Symbol sym, Symbol tag, Expr init) throws Exception{
+ public LocalBinding(int num, Symbol sym, Symbol tag, Expr init, boolean isArg) throws Exception{
if(maybePrimitiveType(init) != null && tag != null)
throw new UnsupportedOperationException("Can't type hint a local with a primitive initializer");
this.idx = num;
this.sym = sym;
this.tag = tag;
this.init = init;
+ this.isArg = isArg;
name = munge(sym.name);
}
@@ -3873,7 +3623,7 @@ public static class LocalBinding{
}
}
-public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
+public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr, AssignableExpr{
public final LocalBinding b;
public final Symbol tag;
@@ -3888,13 +3638,27 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
throw new UnsupportedOperationException("Can't eval locals");
}
- public void emitUnboxed(C context, FnExpr fn, GeneratorAdapter gen){
- fn.emitUnboxedLocal(gen, b);
+ public boolean canEmitPrimitive(){
+ return b.getPrimitiveType() != null;
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
+ objx.emitUnboxedLocal(gen, b);
+ }
+
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ if(context != C.STATEMENT)
+ objx.emitLocal(gen, b);
+ }
+
+ public Object evalAssign(Expr val) throws Exception{
+ throw new UnsupportedOperationException("Can't eval locals");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen, Expr val){
+ objx.emitAssignLocal(gen, b,val);
if(context != C.STATEMENT)
- fn.emitLocal(gen, b);
+ objx.emitLocal(gen, b);
}
public boolean hasJavaClass() throws Exception{
@@ -3910,7 +3674,7 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
}
-public static class BodyExpr implements Expr{
+public static class BodyExpr implements Expr, MaybePrimitiveExpr{
PersistentVector exprs;
public final PersistentVector exprs(){
@@ -3952,14 +3716,28 @@ public static class BodyExpr implements Expr{
return ret;
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public boolean canEmitPrimitive(){
+ return lastExpr() instanceof MaybePrimitiveExpr && ((MaybePrimitiveExpr)lastExpr()).canEmitPrimitive();
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
for(int i = 0; i < exprs.count() - 1; i++)
{
Expr e = (Expr) exprs.nth(i);
- e.emit(C.STATEMENT, fn, gen);
+ e.emit(C.STATEMENT, objx, gen);
+ }
+ MaybePrimitiveExpr last = (MaybePrimitiveExpr) exprs.nth(exprs.count() - 1);
+ last.emitUnboxed(context, objx, gen);
+ }
+
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ for(int i = 0; i < exprs.count() - 1; i++)
+ {
+ Expr e = (Expr) exprs.nth(i);
+ e.emit(C.STATEMENT, objx, gen);
}
Expr last = (Expr) exprs.nth(exprs.count() - 1);
- last.emit(context, fn, gen);
+ last.emit(context, objx, gen);
}
public boolean hasJavaClass() throws Exception{
@@ -4035,7 +3813,7 @@ public static class LetFnExpr implements Expr{
Symbol sym = (Symbol) bindings.nth(i);
if(sym.getNamespace() != null)
throw new Exception("Can't let qualified name: " + sym);
- LocalBinding lb = registerLocal(sym, tagOf(sym), null);
+ LocalBinding lb = registerLocal(sym, tagOf(sym), null,false);
lbs = lbs.cons(lb);
}
PersistentVector bindingInits = PersistentVector.EMPTY;
@@ -4061,7 +3839,7 @@ public static class LetFnExpr implements Expr{
throw new UnsupportedOperationException("Can't eval letfns");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
for(int i = 0; i < bindingInits.count(); i++)
{
BindingInit bi = (BindingInit) bindingInits.nth(i);
@@ -4075,21 +3853,21 @@ public static class LetFnExpr implements Expr{
{
BindingInit bi = (BindingInit) bindingInits.nth(i);
lbset = (IPersistentSet) lbset.cons(bi.binding);
- bi.init.emit(C.EXPRESSION, fn, gen);
+ bi.init.emit(C.EXPRESSION, objx, gen);
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), bi.binding.idx);
}
for(int i = 0; i < bindingInits.count(); i++)
{
BindingInit bi = (BindingInit) bindingInits.nth(i);
- FnExpr fe = (FnExpr) bi.init;
+ ObjExpr fe = (ObjExpr) bi.init;
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ILOAD), bi.binding.idx);
- fe.emitLetFnInits(gen, fn, lbset);
+ fe.emitLetFnInits(gen, objx, lbset);
}
Label loopLabel = gen.mark();
- body.emit(context, fn, gen);
+ body.emit(context, objx, gen);
Label end = gen.mark();
// gen.visitLocalVariable("this", "Ljava/lang/Object;", null, loopLabel, end, 0);
@@ -4167,7 +3945,7 @@ public static class LetExpr implements Expr{
throw new Exception("Can't let qualified name: " + sym);
Expr init = analyze(C.EXPRESSION, bindings.nth(i + 1), sym.name);
//sequential enhancement of env (like Lisp let*)
- LocalBinding lb = registerLocal(sym, tagOf(sym), init);
+ LocalBinding lb = registerLocal(sym, tagOf(sym), init,false);
BindingInit bi = new BindingInit(lb, init);
bindingInits = bindingInits.cons(bi);
@@ -4190,19 +3968,19 @@ public static class LetExpr implements Expr{
throw new UnsupportedOperationException("Can't eval let/loop");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
for(int i = 0; i < bindingInits.count(); i++)
{
BindingInit bi = (BindingInit) bindingInits.nth(i);
Class primc = maybePrimitiveType(bi.init);
if(primc != null)
{
- ((MaybePrimitiveExpr) bi.init).emitUnboxed(C.EXPRESSION, fn, gen);
+ ((MaybePrimitiveExpr) bi.init).emitUnboxed(C.EXPRESSION, objx, gen);
gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ISTORE), bi.binding.idx);
}
else
{
- bi.init.emit(C.EXPRESSION, fn, gen);
+ bi.init.emit(C.EXPRESSION, objx, gen);
gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), bi.binding.idx);
}
}
@@ -4212,7 +3990,7 @@ public static class LetExpr implements Expr{
try
{
Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel));
- body.emit(context, fn, gen);
+ body.emit(context, objx, gen);
}
finally
{
@@ -4220,7 +3998,7 @@ public static class LetExpr implements Expr{
}
}
else
- body.emit(context, fn, gen);
+ body.emit(context, objx, gen);
Label end = gen.mark();
// gen.visitLocalVariable("this", "Ljava/lang/Object;", null, loopLabel, end, 0);
for(ISeq bis = bindingInits.seq(); bis != null; bis = bis.next())
@@ -4260,7 +4038,7 @@ public static class RecurExpr implements Expr{
throw new UnsupportedOperationException("Can't eval recur");
}
- public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
Label loopLabel = (Label) LOOP_LABEL.deref();
if(loopLabel == null)
throw new IllegalStateException();
@@ -4281,11 +4059,11 @@ public static class RecurExpr implements Expr{
{
throw new RuntimeException(e);
}
- ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, fn, gen);
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
}
else
{
- arg.emit(C.EXPRESSION, fn, gen);
+ arg.emit(C.EXPRESSION, objx, gen);
}
}
@@ -4293,10 +4071,15 @@ public static class RecurExpr implements Expr{
{
LocalBinding lb = (LocalBinding) loopLocals.nth(i);
Class primc = lb.getPrimitiveType();
- if(primc != null)
- gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ISTORE), lb.idx);
+ if(lb.isArg)
+ gen.storeArg(lb.idx-1);
else
- gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), lb.idx);
+ {
+ if(primc != null)
+ gen.visitVarInsn(Type.getType(primc).getOpcode(Opcodes.ISTORE), lb.idx);
+ else
+ gen.visitVarInsn(OBJECT_TYPE.getOpcode(Opcodes.ISTORE), lb.idx);
+ }
}
gen.goTo(loopLabel);
@@ -4332,12 +4115,12 @@ public static class RecurExpr implements Expr{
}
}
-private static LocalBinding registerLocal(Symbol sym, Symbol tag, Expr init) throws Exception{
+private static LocalBinding registerLocal(Symbol sym, Symbol tag, Expr init, boolean isArg) throws Exception{
int num = getAndIncLocalNum();
- LocalBinding b = new LocalBinding(num, sym, tag, init);
+ LocalBinding b = new LocalBinding(num, sym, tag, init, isArg);
IPersistentMap localsMap = (IPersistentMap) LOCAL_ENV.deref();
LOCAL_ENV.set(RT.assoc(localsMap, b.sym, b));
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
method.locals = (IPersistentMap) RT.assoc(method.locals, b, b);
method.indexlocals = (IPersistentMap) RT.assoc(method.indexlocals, num, b);
return b;
@@ -4345,7 +4128,7 @@ private static LocalBinding registerLocal(Symbol sym, Symbol tag, Expr init) thr
private static int getAndIncLocalNum(){
int num = ((Number) NEXT_LOCAL_NUM.deref()).intValue();
- FnMethod m = (FnMethod) METHOD.deref();
+ ObjMethod m = (ObjMethod) METHOD.deref();
if(num > m.maxLocal)
m.maxLocal = num;
NEXT_LOCAL_NUM.set(num + 1);
@@ -4618,7 +4401,7 @@ public static Object eval(Object form) throws Exception{
&& !(RT.first(form) instanceof Symbol
&& ((Symbol) RT.first(form)).name.startsWith("def")))
{
- FnExpr fexpr = (FnExpr) analyze(C.EXPRESSION, RT.list(FN, PersistentVector.EMPTY, form), "eval");
+ ObjExpr fexpr = (ObjExpr) analyze(C.EXPRESSION, RT.list(FN, PersistentVector.EMPTY, form), "eval");
IFn fn = (IFn) fexpr.eval();
return fn.invoke();
}
@@ -4872,12 +4655,12 @@ static Namespace currentNS(){
return (Namespace) RT.CURRENT_NS.deref();
}
-static void closeOver(LocalBinding b, FnMethod method){
+static void closeOver(LocalBinding b, ObjMethod method){
if(b != null && method != null)
{
if(RT.get(method.locals, b) == null)
{
- method.fn.closes = (IPersistentMap) RT.assoc(method.fn.closes, b, b);
+ method.objx.closes = (IPersistentMap) RT.assoc(method.objx.closes, b, b);
closeOver(b, method.parent);
}
else if(IN_CATCH_FINALLY.deref() != null)
@@ -4894,7 +4677,7 @@ static LocalBinding referenceLocal(Symbol sym) throws Exception{
LocalBinding b = (LocalBinding) RT.get(LOCAL_ENV.deref(), sym);
if(b != null)
{
- FnMethod method = (FnMethod) METHOD.deref();
+ ObjMethod method = (ObjMethod) METHOD.deref();
closeOver(b, method);
}
return b;
@@ -4997,7 +4780,7 @@ public static void pushNS(){
Symbol.create("*ns*")), null));
}
-static void compile1(GeneratorAdapter gen, FnExpr fn, Object form) throws Exception{
+static void compile1(GeneratorAdapter gen, ObjExpr objx, Object form) throws Exception{
Integer line = (Integer) LINE.deref();
if(RT.meta(form) != null && RT.meta(form).containsKey(RT.LINE_KEY))
line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);
@@ -5010,16 +4793,16 @@ static void compile1(GeneratorAdapter gen, FnExpr fn, Object form) throws Except
{
for(ISeq s = RT.next(form); s != null; s = RT.next(s))
{
- compile1(gen, fn, RT.first(s));
+ compile1(gen, objx, RT.first(s));
}
}
else
{
Expr expr = analyze(C.EVAL, form);
- fn.keywords = (IPersistentMap) KEYWORDS.deref();
- fn.vars = (IPersistentMap) VARS.deref();
- fn.constants = (PersistentVector) CONSTANTS.deref();
- expr.emit(C.EXPRESSION, fn, gen);
+ objx.keywords = (IPersistentMap) KEYWORDS.deref();
+ objx.vars = (IPersistentMap) VARS.deref();
+ objx.constants = (PersistentVector) CONSTANTS.deref();
+ expr.emit(C.EXPRESSION, objx, gen);
expr.eval();
}
}
@@ -5052,14 +4835,14 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
try
{
//generate loader class
- FnExpr fn = new FnExpr(null);
- fn.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.'))
+ ObjExpr objx = new ObjExpr(null);
+ objx.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.'))
+ RT.LOADER_SUFFIX;
- fn.fntype = Type.getObjectType(fn.internalName);
+ objx.objtype = Type.getObjectType(objx.internalName);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = cw;
- cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, fn.internalName, null, "java/lang/Object", null);
+ cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, objx.internalName, null, "java/lang/Object", null);
//static load method
GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
@@ -5073,7 +4856,7 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
r = LispReader.read(pushbackReader, false, EOF, false))
{
LINE_AFTER.set(pushbackReader.getLineNumber());
- compile1(gen, fn, r);
+ compile1(gen, objx, r);
LINE_BEFORE.set(pushbackReader.getLineNumber());
}
//end of load
@@ -5081,9 +4864,9 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
gen.endMethod();
//static fields for constants
- for(int i = 0; i < fn.constants.count(); i++)
+ for(int i = 0; i < objx.constants.count(); i++)
{
- cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, fn.constantName(i), fn.constantType(i).getDescriptor(),
+ cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, objx.constantName(i), objx.constantType(i).getDescriptor(),
null, null);
}
@@ -5099,13 +4882,13 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
Label end = clinitgen.newLabel();
Label finallyLabel = clinitgen.newLabel();
- if(fn.constants.count() > 0)
+ if(objx.constants.count() > 0)
{
- fn.emitConstants(clinitgen);
+ objx.emitConstants(clinitgen);
}
clinitgen.invokeStatic(Type.getType(Compiler.class), Method.getMethod("void pushNS()"));
clinitgen.mark(startTry);
- clinitgen.invokeStatic(fn.fntype, Method.getMethod("void load()"));
+ clinitgen.invokeStatic(objx.objtype, Method.getMethod("void load()"));
clinitgen.mark(endTry);
clinitgen.invokeStatic(VAR_TYPE, Method.getMethod("void popThreadBindings()"));
clinitgen.goTo(end);
@@ -5124,7 +4907,7 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
//end of class
cv.visitEnd();
- writeClassFile(fn.internalName, cw.toByteArray());
+ writeClassFile(objx.internalName, cw.toByteArray());
}
catch(LispReader.ReaderException e)
{
@@ -5137,4 +4920,452 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
return ret;
}
+
+static public class NewInstanceExpr extends ObjExpr{
+ IPersistentMap optionsMap = PersistentArrayMap.EMPTY;
+ IPersistentCollection methods;
+
+ public NewInstanceExpr(Object tag){
+ super(tag);
+ }
+
+ static Expr parse(C context, ISeq form) throws Exception{
+ //(new [super then interfaces] this-name? {options}? (method-name [args] body)*)
+
+ NewInstanceExpr ret = new NewInstanceExpr(null);
+ ObjMethod enclosingMethod = (ObjMethod) METHOD.deref();
+ String basename = enclosingMethod != null ?
+ (trimGenID(enclosingMethod.objx.name) + "$")
+ : (munge(currentNS().name.name) + "$");
+ String simpleName = "obj__" + RT.nextID();
+ ret.name = basename + simpleName;
+ ret.internalName = ret.name.replace('.', '/');
+ ret.objtype = Type.getObjectType(ret.internalName);
+
+ PersistentVector v = PersistentVector.EMPTY;
+ for(ISeq s = RT.seq(RT.second(form));s!=null;s = s.next())
+ {
+ Class c = (Class) resolve((Symbol) s.first());
+ if(!c.isInterface() && v.count() > 0)
+ throw new IllegalArgumentException("superclass must be first");
+ v = v.cons(c);
+ }
+ ISeq superAndInterfaces = RT.seq(v);
+ Class superClass = (Class) RT.first(superAndInterfaces);
+ if(superClass == null || superClass.isInterface())
+ {
+ superClass = Object.class;
+ superAndInterfaces = RT.cons(superClass, superAndInterfaces);
+ }
+ ISeq interfaces = RT.next(superAndInterfaces);
+ Map[] mc = gatherMethods(superClass,interfaces);
+ Map overrideables = mc[0];
+ Map allmethods = mc[1];
+
+ ISeq rform = RT.next(RT.next(form));
+
+ //supers might be followed by symbol naming this
+ if(RT.first(rform) instanceof Symbol)
+ {
+ ret.thisName = ((Symbol) RT.first(rform)).name;
+ rform = RT.next(rform);
+ }
+
+ //might be followed by map of options
+ if(RT.first(rform) instanceof IPersistentMap)
+ {
+ ret.optionsMap = ((IPersistentMap) RT.first(rform));
+ rform = RT.next(rform);
+ }
+
+ if(RT.get(ret.optionsMap, volatileKey) != null)
+ {
+ ret.volatiles = PersistentHashSet.create(RT.seq(RT.get(ret.optionsMap, volatileKey)));
+ }
+
+ try
+ {
+ Var.pushThreadBindings(
+ RT.map(CONSTANTS, PersistentVector.EMPTY,
+ KEYWORDS, PersistentHashMap.EMPTY,
+ VARS, PersistentHashMap.EMPTY));
+
+ //now (methodname [args] body)*
+ ret.line = (Integer) LINE.deref();
+ IPersistentCollection methods = null;
+ for(ISeq s = rform; s != null; s = RT.next(s))
+ {
+ NewInstanceMethod m = NewInstanceMethod.parse(ret, (ISeq) RT.first(s),overrideables, allmethods);
+ methods = RT.conj(methods, m);
+ }
+
+
+ ret.methods = methods;
+ ret.keywords = (IPersistentMap) KEYWORDS.deref();
+ ret.vars = (IPersistentMap) VARS.deref();
+ ret.constants = (PersistentVector) CONSTANTS.deref();
+ ret.constantsID = RT.nextID();
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+
+ int icnt = RT.count(RT.next(superAndInterfaces));
+ String[] inames = icnt > 0 ? new String[icnt] : null;
+ for(int i=0;i<icnt;i++)
+ inames[i] = slashname((Class) RT.nth(RT.next(superAndInterfaces), i));
+ ret.compile(slashname(superClass),inames,false);
+ return ret;
+ }
+
+ static String slashname(Class c){
+ return c.getName().replace('.', '/');
+ }
+
+
+ protected void emitMethods(ClassVisitor cv){
+ for(ISeq s = RT.seq(methods); s != null; s = s.next())
+ {
+ ObjMethod method = (ObjMethod) s.first();
+ method.emit(this, cv);
+ }
+ }
+
+ static public IPersistentVector msig(java.lang.reflect.Method m){
+ return RT.vector(m.getName(), RT.seq(m.getParameterTypes()));
+ }
+
+ static void considerMethod(java.lang.reflect.Method m, Map mm, Map considered){
+ IPersistentVector mk = msig(m);
+ int mods = m.getModifiers();
+
+ if(considered.containsKey(mk)
+ || !(Modifier.isPublic(mods) || Modifier.isProtected(mods))
+ || Modifier.isStatic(mods)
+ || Modifier.isFinal(mods))
+ {
+ if(!Modifier.isStatic(mods))
+ considered.put(mk, m);
+ }
+ else
+ {
+ considered.put(mk, m);
+ mm.put(mk, m);
+ }
+ }
+
+ static void gatherMethods(Class c, Map mm, Map considered){
+ for(; c != null; c = c.getSuperclass())
+ {
+ for(java.lang.reflect.Method m : c.getDeclaredMethods())
+ considerMethod(m, mm, considered);
+ for(java.lang.reflect.Method m : c.getMethods())
+ considerMethod(m, mm, considered);
+ }
+ }
+
+ static public Map[] gatherMethods(Class sc, ISeq interfaces){
+ Map mm = new HashMap();
+ Map considered = new HashMap();
+ gatherMethods(sc, mm, considered);
+ for(; interfaces != null; interfaces = interfaces.next())
+ gatherMethods((Class) interfaces.first(), mm, considered);
+ return new Map[]{mm, considered};
+ }
+}
+
+public static class NewInstanceMethod extends ObjMethod{
+ String name;
+ Type[] argTypes;
+ Type retType;
+ Class retClass;
+
+ public NewInstanceMethod(ObjExpr objx, ObjMethod parent){
+ super(objx, parent);
+ }
+
+ int numParams(){
+ return argLocals.count();
+ }
+
+ String getMethodName(){
+ return name;
+ }
+
+ Type getReturnType(){
+ return retType;
+ }
+
+ Type[] getArgTypes(){
+ return argTypes;
+ }
+
+ static Class primClass(Symbol sym){
+ if(sym == null)
+ return null;
+ Class c = null;
+ if(sym.name.equals("int"))
+ c = int.class;
+ else if(sym.name.equals("long"))
+ c = long.class;
+ else if(sym.name.equals("float"))
+ c = float.class;
+ else if(sym.name.equals("double"))
+ c = double.class;
+ else if(sym.name.equals("char"))
+ c = char.class;
+ else if(sym.name.equals("short"))
+ c = short.class;
+ else if(sym.name.equals("byte"))
+ c = byte.class;
+ else if(sym.name.equals("boolean"))
+ c = boolean.class;
+ else if(sym.name.equals("void"))
+ c = void.class;
+ return c;
+ }
+
+ static Class tagClass(Object tag) throws Exception{
+ if(tag == null)
+ return Object.class;
+ Class c = null;
+ if(tag instanceof Symbol)
+ c = primClass((Symbol) tag);
+ if(c == null)
+ c = HostExpr.tagToClass(tag);
+ return c;
+ }
+
+ static public IPersistentVector msig(String name,Class[] paramTypes){
+ return RT.vector(name,RT.seq(paramTypes));
+ }
+
+ static NewInstanceMethod parse(ObjExpr objx, ISeq form, Map overrideables, Map allmethods) throws Exception{
+ //(methodname [args] body...)
+ NewInstanceMethod method = new NewInstanceMethod(objx, (ObjMethod) METHOD.deref());
+ Symbol name = (Symbol)RT.first(form);
+ IPersistentVector parms = (IPersistentVector) RT.second(form);
+ ISeq body = RT.next(RT.next(form));
+ try
+ {
+ method.line = (Integer) LINE.deref();
+ //register as the current method and set up a new env frame
+ Var.pushThreadBindings(
+ RT.map(
+ METHOD, method,
+ LOCAL_ENV, LOCAL_ENV.deref(),
+ LOOP_LOCALS, null,
+ NEXT_LOCAL_NUM, 0));
+
+ //register 'this' as local 0
+ registerLocal(Symbol.intern(objx.thisName != null ? objx.thisName : "obj__" + RT.nextID()),
+ null, null,false);
+
+ PersistentVector argLocals = PersistentVector.EMPTY;
+ method.retClass = tagClass(tagOf(name));
+ method.argTypes = new Type[parms.count()];
+ boolean hinted = tagOf(name) != null;
+ Class[] pclasses = new Class[parms.count()];
+ Symbol[] psyms = new Symbol[parms.count()];
+
+ for(int i = 0; i < parms.count(); i++)
+ {
+ if(!(parms.nth(i) instanceof Symbol))
+ throw new IllegalArgumentException("params must be Symbols");
+ Symbol p = (Symbol) parms.nth(i);
+ Object tag = tagOf(p);
+ if(tag != null)
+ hinted = true;
+ if(p.getNamespace() != null)
+ p = Symbol.create(p.name);
+ Class pclass = tagClass(tag);
+ pclasses[i] = pclass;
+ psyms[i] = p;
+ }
+ Map matches = findMethodsWithNameAndArity(name.name, parms.count(), overrideables);
+ Object mk = msig(name.name, pclasses);
+ if(matches.size() > 0)
+ {
+ //multiple methods
+ if(matches.size() > 1)
+ {
+ //must be hinted and match one method
+ if(!hinted)
+ throw new IllegalArgumentException("Must hint overloaded method: " + name.name);
+ java.lang.reflect.Method m = (java.lang.reflect.Method) matches.get(mk);
+ if(m == null)
+ throw new IllegalArgumentException("Can't find matching overloaded method: " + name.name);
+ if(m.getReturnType() != method.retClass)
+ throw new IllegalArgumentException("Mismatched return type: " + name.name +
+ ", expected: " + m.getReturnType().getName() + ", had: " + method.retClass.getName());
+ }
+ else //one match
+ {
+ //if hinted, validate match,
+ if(hinted)
+ {
+ java.lang.reflect.Method m = (java.lang.reflect.Method) matches.get(mk);
+ if(m == null)
+ throw new IllegalArgumentException("Can't find matching method: " + name.name +
+ ", leave off hints for auto match.");
+ if(m.getReturnType() != method.retClass)
+ throw new IllegalArgumentException("Mismatched return type: " + name.name +
+ ", expected: " + m.getReturnType().getName() + ", had: " + method.retClass.getName());
+ }
+ else //adopt found method sig
+ {
+ java.lang.reflect.Method m = (java.lang.reflect.Method) matches.values().iterator().next();
+ method.retClass = m.getReturnType();
+ pclasses = m.getParameterTypes();
+ }
+ }
+ }
+ else if(findMethodsWithName(name.name,allmethods).size()>0)
+ throw new IllegalArgumentException("Can't override/overload method: " + name.name);
+ //todo
+ //else
+ //validate unque name+arity among additional methods
+
+ method.retType = Type.getType(method.retClass);
+
+ for(int i = 0; i < parms.count(); i++)
+ {
+ LocalBinding lb = registerLocal(psyms[i], null, new MethodParamExpr(pclasses[i]),true);
+ argLocals = argLocals.assocN(i,lb);
+ method.argTypes[i] = Type.getType(pclasses[i]);
+ }
+ for(int i = 0; i < parms.count(); i++)
+ {
+ if(pclasses[i] == long.class || pclasses[i] == double.class)
+ getAndIncLocalNum();
+ }
+ LOOP_LOCALS.set(argLocals);
+ method.name = name.name;
+ method.argLocals = argLocals;
+ method.body = (new BodyExpr.Parser()).parse(C.RETURN, body);
+ return method;
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+ }
+
+ private static Map findMethodsWithNameAndArity(String name, int arity, Map mm){
+ Map ret = new HashMap();
+ for(Object o : mm.entrySet())
+ {
+ Map.Entry e = (Map.Entry) o;
+ java.lang.reflect.Method m = (java.lang.reflect.Method) e.getValue();
+ if(name.equals(m.getName()) && m.getParameterTypes().length == arity)
+ ret.put(e.getKey(), e.getValue());
+ }
+ return ret;
+ }
+
+ private static Map findMethodsWithName(String name, Map mm){
+ Map ret = new HashMap();
+ for(Object o : mm.entrySet())
+ {
+ Map.Entry e = (Map.Entry) o;
+ java.lang.reflect.Method m = (java.lang.reflect.Method) e.getValue();
+ if(name.equals(m.getName()))
+ ret.put(e.getKey(), e.getValue());
+ }
+ return ret;
+ }
+
+ public void emit(ObjExpr obj, ClassVisitor cv){
+ Method m = new Method(getMethodName(), getReturnType(), getArgTypes());
+
+ GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC,
+ m,
+ null,
+ //todo don't hardwire this
+ EXCEPTION_TYPES,
+ cv);
+ gen.visitCode();
+ Label loopLabel = gen.mark();
+ gen.visitLineNumber(line, loopLabel);
+ try
+ {
+ Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel, METHOD, this));
+ MaybePrimitiveExpr be = (MaybePrimitiveExpr) body;
+ if(Util.isPrimitive(retClass) && be.canEmitPrimitive())
+ {
+ if(be.getJavaClass() == retClass)
+ be.emitUnboxed(C.RETURN,obj,gen);
+ //todo - support the standard widening conversions
+ else
+ throw new IllegalArgumentException("Mismatched primitive return, expected: "
+ + retClass + ", had: " + be.getJavaClass());
+ }
+ else
+ {
+ body.emit(C.RETURN, obj, gen);
+ if(retClass == void.class)
+ {
+ gen.pop();
+ }
+ else
+ gen.unbox(retType);
+ }
+
+ Label end = gen.mark();
+ gen.visitLocalVariable("this", obj.objtype.getDescriptor(), null, loopLabel, end, 0);
+ for(ISeq lbs = argLocals.seq(); lbs != null; lbs = lbs.next())
+ {
+ LocalBinding lb = (LocalBinding) lbs.first();
+ gen.visitLocalVariable(lb.name, argTypes[lb.idx-1].getDescriptor(), null, loopLabel, end, lb.idx);
+ }
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+
+ gen.returnValue();
+ //gen.visitMaxs(1, 1);
+ gen.endMethod();
+ }
+}
+
+static public class MethodParamExpr implements Expr, MaybePrimitiveExpr{
+ final Class c;
+
+ public MethodParamExpr(Class c){
+ this.c = c;
+ }
+
+ public Object eval() throws Exception{
+ throw new Exception("Can't eval");
+ }
+
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ throw new RuntimeException("Can't emit");
+ }
+
+ public boolean hasJavaClass() throws Exception{
+ return c != null;
+ }
+
+ public Class getJavaClass() throws Exception{
+ return c;
+ }
+
+ public boolean canEmitPrimitive(){
+ return Util.isPrimitive(c);
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
+ throw new RuntimeException("Can't emit");
+ }
+}
+
+
}
diff --git a/src/jvm/clojure/lang/PersistentList.java b/src/jvm/clojure/lang/PersistentList.java
index cc4f5ec4..912d2f8d 100644
--- a/src/jvm/clojure/lang/PersistentList.java
+++ b/src/jvm/clojure/lang/PersistentList.java
@@ -18,8 +18,12 @@ private final Object _first;
private final IPersistentList _rest;
private final int _count;
-public static IFn creator = new RestFn(0){
- protected Object doInvoke(Object args) throws Exception{
+public static IFn creator = new RestFn(){
+ final public int getRequiredArity(){
+ return 0;
+ }
+
+ final protected Object doInvoke(Object args) throws Exception{
if(args instanceof ArraySeq)
{
Object[] argsarray = (Object[]) ((ArraySeq) args).array;
diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java
index 4a7061f4..12d58018 100644
--- a/src/jvm/clojure/lang/Reflector.java
+++ b/src/jvm/clojure/lang/Reflector.java
@@ -382,7 +382,8 @@ static Object boxArg(Class paramType, Object arg){
else if(paramType == byte.class)
return n.byteValue();
}
- throw new IllegalArgumentException("Unexpected param type");
+ throw new IllegalArgumentException("Unexpected param type, expected: " + paramType +
+ ", given: " + arg.getClass().getName());
}
static Object[] boxArgs(Class[] params, Object[] args){
diff --git a/src/jvm/clojure/lang/RestFn.java b/src/jvm/clojure/lang/RestFn.java
index 4e15f799..c0ba6262 100644
--- a/src/jvm/clojure/lang/RestFn.java
+++ b/src/jvm/clojure/lang/RestFn.java
@@ -11,11 +11,7 @@ package clojure.lang;
public abstract class RestFn extends AFunction{
-protected int reqArity;
-
-public RestFn(int reqArity){
- this.reqArity = reqArity;
-}
+abstract public int getRequiredArity();
protected Object doInvoke(Object args) throws Exception{
return null;
@@ -132,11 +128,11 @@ protected Object doInvoke(Object arg1, Object arg2, Object arg3, Object arg4, Ob
public Object applyTo(ISeq args) throws Exception{
- if(RT.boundedLength(args, reqArity) <= reqArity)
+ if(RT.boundedLength(args, getRequiredArity()) <= getRequiredArity())
{
return AFn.applyToHelper(this, args);
}
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(args);
@@ -396,7 +392,7 @@ public Object applyTo(ISeq args) throws Exception{
}
public Object invoke() throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(null);
@@ -407,7 +403,7 @@ public Object invoke() throws Exception{
}
public Object invoke(Object arg1) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1));
@@ -420,7 +416,7 @@ public Object invoke(Object arg1) throws Exception{
}
public Object invoke(Object arg1, Object arg2) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2));
@@ -435,7 +431,7 @@ public Object invoke(Object arg1, Object arg2) throws Exception{
}
public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3));
@@ -452,7 +448,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{
}
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4));
@@ -471,7 +467,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws
}
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5));
@@ -492,7 +488,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
}
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6));
@@ -516,7 +512,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7)
throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7));
@@ -542,7 +538,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
@@ -570,7 +566,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9));
@@ -600,7 +596,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10));
@@ -632,7 +628,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11));
@@ -666,7 +662,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12));
@@ -703,7 +699,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13)
throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(
@@ -755,7 +751,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14)
throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -811,7 +807,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -870,7 +866,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -932,7 +928,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16, Object arg17) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -997,7 +993,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16, Object arg17, Object arg18) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -1066,7 +1062,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -1142,7 +1138,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20)
throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ArraySeq.create(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12,
@@ -1225,7 +1221,7 @@ public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object
Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, Object... args)
throws Exception{
- switch(reqArity)
+ switch(getRequiredArity())
{
case 0:
return doInvoke(ontoArrayPrepend(args, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11,
@@ -1331,5 +1327,6 @@ protected static ISeq findKey(Object key, ISeq args){
return null;
}
+
}