summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-07-30 13:00:51 -0400
committerRich Hickey <richhickey@gmail.com>2009-07-30 13:00:51 -0400
commitc7347544a9f192d98c05981ceab3afb3f237b3c2 (patch)
tree1953fd21508b9d64e38673af2618e57e5f4d2b93
parent48f4803d942721e15a0b1b1c1a7610eba345a688 (diff)
allow primitive to flow out of body
-rw-r--r--src/jvm/clojure/lang/Compiler.java73
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");
}