diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-07-30 13:00:51 -0400 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-07-30 13:00:51 -0400 |
commit | c7347544a9f192d98c05981ceab3afb3f237b3c2 (patch) | |
tree | 1953fd21508b9d64e38673af2618e57e5f4d2b93 /src | |
parent | 48f4803d942721e15a0b1b1c1a7610eba345a688 (diff) |
allow primitive to flow out of body
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 798316a7..4a483c82 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -579,7 +579,8 @@ static interface AssignableExpr{ void emitAssign(C context, ObjExpr objx, GeneratorAdapter gen, Expr val); } -static public interface MaybePrimitiveExpr{ +static public interface MaybePrimitiveExpr extends Expr{ + public boolean canEmitPrimitive(); public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen); } @@ -871,6 +872,11 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ return Reflector.invokeNoArgInstanceMember(target.eval(), fieldName); } + 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) @@ -965,6 +971,10 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ return Reflector.getStaticField(c, fieldName); } + 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())); @@ -1154,6 +1164,10 @@ static class InstanceMethodExpr extends MethodExpr{ } } + 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) @@ -1296,6 +1310,10 @@ static class StaticMethodExpr extends MethodExpr{ } } + 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) @@ -3544,6 +3562,10 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{ throw new UnsupportedOperationException("Can't eval locals"); } + public boolean canEmitPrimitive(){ + return b.getPrimitiveType() != null; + } + public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){ objx.emitUnboxedLocal(gen, b); } @@ -3566,7 +3588,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(){ @@ -3608,6 +3630,20 @@ public static class BodyExpr implements Expr{ return ret; } + 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, 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++) { @@ -5022,14 +5058,27 @@ public static class NewInstanceMethod extends ObjMethod{ try { Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel, METHOD, this)); - body.emit(C.RETURN, obj, gen); - if(retClass == void.class) + MaybePrimitiveExpr be = (MaybePrimitiveExpr) body; + if(Util.isPrimitive(retClass) && be.canEmitPrimitive()) { - gen.pop(); + 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 if(retClass.isPrimitive()) - gen.unbox(retType); - + else + { + body.emit(C.RETURN, obj, gen); + if(retClass == void.class) + { + gen.pop(); + } + else if(retClass.isPrimitive()) + 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()) @@ -5038,6 +5087,10 @@ public static class NewInstanceMethod extends ObjMethod{ gen.visitLocalVariable(lb.name, argTypes[lb.idx-1].getDescriptor(), null, loopLabel, end, lb.idx); } } + catch(Exception e) + { + throw new RuntimeException(e); + } finally { Var.popThreadBindings(); @@ -5072,6 +5125,10 @@ static public class MethodParamExpr implements Expr, MaybePrimitiveExpr{ return c; } + public boolean canEmitPrimitive(){ + return Util.isPrimitive(c); + } + public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){ throw new RuntimeException("Can't emit"); } |