correctly handle ensureReceiverOnStack() when the expression is itself a receiver; use correct type when putting/storing fields

This commit is contained in:
Dmitry Jemerov
2011-05-27 19:03:11 +04:00
parent 9969b8d7a4
commit 78247520c7
5 changed files with 39 additions and 10 deletions
@@ -353,7 +353,11 @@ public class ClassCodegen {
propertyCodegen.gen((JetProperty) declaration, kind);
}
else if (declaration instanceof JetFunction) {
functionCodegen.gen((JetFunction) declaration, kind);
try {
functionCodegen.gen((JetFunction) declaration, kind);
} catch (RuntimeException e) {
throw new RuntimeException("Error generating method "+ aClass.getName() + "." + declaration.getName(), e);
}
}
}
@@ -757,10 +757,13 @@ public class ExpressionCodegen extends JetVisitor {
}
private void ensureReceiverOnStack(JetElement expression) {
if (expression.getParent() instanceof JetDotQualifiedExpression) {
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
if (!resolvesToClassOrPackage(parent.getReceiverExpression())) {
// we have a receiver on stack
if (myStack.isEmpty()) {
throw new IllegalStateException("expected receiver on stack but it's not there: " + parent.getReceiverExpression().getText());
}
myStack.pop().put(JetTypeMapper.TYPE_OBJECT, v);
}
}
@@ -769,6 +772,15 @@ public class ExpressionCodegen extends JetVisitor {
}
}
private static boolean isReceiver(JetElement expression) {
final PsiElement parent = expression.getParent();
if (parent instanceof JetQualifiedExpression) {
final JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression();
return expression == receiverExpression;
}
return false;
}
private void pushMethodArguments(JetCall expression, Method method) {
final Type[] argTypes = method.getArgumentTypes();
List<JetArgument> args = expression.getValueArguments();
@@ -408,7 +408,7 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, fieldOwner, name, type.getDescriptor());
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, fieldOwner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, getter.getName(), getter.getDescriptor());
@@ -418,7 +418,7 @@ public abstract class StackValue {
@Override
public void store(InstructionAdapter v) {
if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, fieldOwner, name, type.getDescriptor());
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, fieldOwner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, setter.getName(), setter.getDescriptor());
@@ -0,0 +1,6 @@
class Evaluator(val expr: StringBuilder) {
fun evaluateArg(): Int {
return expr.length()
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -15,7 +16,6 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivateVal() throws Exception {
loadFile();
System.out.println(generateToText());
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVal");
final Field[] fields = aClass.getDeclaredFields();
assertEquals(2, fields.length); // $typeInfo, prop
@@ -25,7 +25,6 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivateVar() throws Exception {
loadFile();
System.out.println(generateToText());
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setValueOfX");
@@ -36,7 +35,6 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPublicVar() throws Exception {
loadText("class PublicVar() { public var foo = 0; }");
System.out.println(generateToText());
final Class aClass = loadImplementationClass(generateClassesInFile(), "PublicVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setFoo");
@@ -79,7 +77,6 @@ public class PropertyGenTest extends CodegenTestCase {
public void testFieldSetter() throws Exception {
loadFile();
System.out.println(generateToText());
final Method method = generateFunction("append");
method.invoke(null, "IntelliJ ");
String value = (String) method.invoke(null, "IDEA");
@@ -88,7 +85,6 @@ public class PropertyGenTest extends CodegenTestCase {
public void testFieldSetterPlusEq() throws Exception {
loadFile();
System.out.println(generateToText());
final Method method = generateFunction("append");
method.invoke(null, "IntelliJ ");
String value = (String) method.invoke(null, "IDEA");
@@ -109,8 +105,19 @@ public class PropertyGenTest extends CodegenTestCase {
public void testInitializersForNamespaceProperties() throws Exception {
loadText("public val x = System.currentTimeMillis()");
System.out.println(generateToText());
final Method method = generateFunction("getX");
assertIsCurrentTime((Long) method.invoke(null));
}
public void testPropertyReceiverOnStack() throws Exception {
loadFile();
System.out.println(generateToText());
final Class aClass = loadImplementationClass(generateClassesInFile(), "Evaluator");
final Constructor constructor = aClass.getConstructor(StringBuilder.class);
StringBuilder sb = new StringBuilder("xyzzy");
final Object instance = constructor.newInstance(sb);
final Method method = aClass.getMethod("evaluateArg");
Integer result = (Integer) method.invoke(instance);
assertEquals(5, result.intValue());
}
}