augmented assignments for arrays; replace the hack of "value before receiver" with a lesser hack of dupReceiver()

This commit is contained in:
Dmitry Jemerov
2011-04-15 19:46:33 +02:00
parent f13da41f43
commit 009c58f680
3 changed files with 31 additions and 14 deletions
@@ -781,7 +781,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateAssignmentExpression(JetBinaryExpression expression) {
StackValue stackValue = generateIntermediateValue(expression.getLeft());
genToJVMStack(expression.getRight());
stackValue.store(v, false);
stackValue.store(v);
}
private void generateAugmentedAssignment(JetBinaryExpression expression) {
@@ -789,11 +789,11 @@ public class ExpressionCodegen extends JetVisitor {
final JetExpression lhs = expression.getLeft();
Type asmType = expressionType(lhs);
StackValue value = generateIntermediateValue(lhs);
value.dupReceiver(v);
value.put(asmType, v);
genToJVMStack(expression.getRight());
v.visitInsn(asmType.getOpcode(opcodeForMethod(op.getName())));
value = generateIntermediateValue(lhs);
value.store(v, true);
value.store(v);
}
private void generateConcatenation(JetBinaryExpression expression) {
@@ -896,6 +896,7 @@ public class ExpressionCodegen extends JetVisitor {
}
}
StackValue value = generateIntermediateValue(operand);
value.dupReceiver(v);
value.put(asmType, v);
if (asmType == Type.LONG_TYPE) {
v.aconst(Long.valueOf(increment));
@@ -910,8 +911,7 @@ public class ExpressionCodegen extends JetVisitor {
v.aconst(increment);
}
v.add(asmType);
value = generateIntermediateValue(operand);
value.store(v, true);
value.store(v);
return value;
}
@@ -19,10 +19,13 @@ public abstract class StackValue {
public abstract void put(Type type, InstructionAdapter v);
public void store(InstructionAdapter v, boolean valueBeforeReceiver) {
public void store(InstructionAdapter v) {
throw new UnsupportedOperationException("cannot store to value " + this);
}
public void dupReceiver(InstructionAdapter v) {
}
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
if (this.type == Type.BOOLEAN_TYPE) {
put(Type.BOOLEAN_TYPE, v);
@@ -160,7 +163,7 @@ public abstract class StackValue {
}
@Override
public void store(InstructionAdapter v, boolean valueBeforeReceiver) {
public void store(InstructionAdapter v) {
v.store(index, this.type);
}
}
@@ -328,9 +331,14 @@ public abstract class StackValue {
}
@Override
public void store(InstructionAdapter v, boolean valueBeforeReceiver) {
public void store(InstructionAdapter v) {
v.astore(type); // assumes array and index are on the stack
}
@Override
public void dupReceiver(InstructionAdapter v) {
v.dup2(); // array and index
}
}
private static class Field extends StackValue {
@@ -351,11 +359,12 @@ public abstract class StackValue {
}
@Override
public void store(InstructionAdapter v, boolean valueBeforeReceiver) {
// HACK should find some way to avoid this swap
if (valueBeforeReceiver && !isStatic) {
v.swap();
}
public void dupReceiver(InstructionAdapter v) {
if (!isStatic) v.dup();
}
@Override
public void store(InstructionAdapter v) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
}
}
@@ -338,10 +338,18 @@ public class NamespaceGenTest extends CodegenTestCase {
public void testArrayWrite() throws Exception {
loadText("fun foo(c: Array<String>) { c[0] = \"jet\"; }");
System.out.println(generateToText());
final Method main = generateFunction();
String[] array = new String[] { null };
main.invoke(null, new Object[] { array });
assertEquals("jet", array[0]);
}
public void testArrayAugAssign() throws Exception {
loadText("fun foo(c: Array<Int>) { c[0] *= 2 }");
System.out.println(generateToText());
final Method main = generateFunction();
int[] data = new int[] { 5 };
main.invoke(null, new Object[] { data });
assertEquals(10, data[0]);
}
}