generate checkcast instruction for 'as' calls; use accessors for accessing fields of other instances of the same class

This commit is contained in:
Dmitry Jemerov
2011-06-17 13:36:51 +02:00
parent 6d1823ac2a
commit 54d2f25d75
5 changed files with 39 additions and 9 deletions
@@ -608,7 +608,9 @@ public class ExpressionCodegen extends JetVisitor {
else { else {
boolean isStatic = container instanceof NamespaceDescriptorImpl; boolean isStatic = container instanceof NamespaceDescriptorImpl;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField); JetExpression receiver = getReceiverForSelector(expression);
final boolean forceInterface = receiver != null && !(receiver instanceof JetThisExpression);
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface);
if (!isStatic) { if (!isStatic) {
ensureReceiverOnStack(expression, container instanceof ClassDescriptor ? (ClassDescriptor) container : null); ensureReceiverOnStack(expression, container instanceof ClassDescriptor ? (ClassDescriptor) container : null);
} }
@@ -621,14 +623,14 @@ public class ExpressionCodegen extends JetVisitor {
} }
} }
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) { public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
final JetType outType = propertyDescriptor.getOutType(); final JetType outType = propertyDescriptor.getOutType();
boolean isInsideClass = containingDeclaration == contextType; boolean isInsideClass = !forceInterface && containingDeclaration == contextType;
Method getter; Method getter;
Method setter; Method setter;
if (directToField) { if (forceField) {
getter = null; getter = null;
setter = null; setter = null;
} }
@@ -771,13 +773,21 @@ public class ExpressionCodegen extends JetVisitor {
} }
} }
private void ensureReceiverOnStack(JetElement expression, @Nullable ClassDescriptor calleeContainingClass) { private JetExpression getReceiverForSelector(JetElement expression) {
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
if (!resolvesToClassOrPackage(parent.getReceiverExpression())) { return parent.getReceiverExpression();
}
return null;
}
private void ensureReceiverOnStack(JetElement expression, @Nullable ClassDescriptor calleeContainingClass) {
JetExpression receiver = getReceiverForSelector(expression);
if (receiver != null) {
if (!resolvesToClassOrPackage(receiver)) {
// we have a receiver on stack // we have a receiver on stack
if (myStack.isEmpty()) { if (myStack.isEmpty()) {
throw new IllegalStateException("expected receiver on stack but it's not there: " + parent.getReceiverExpression().getText()); throw new IllegalStateException("expected receiver on stack but it's not there: " + receiver.getText());
} }
myStack.pop().put(JetTypeMapper.TYPE_OBJECT, v); myStack.pop().put(JetTypeMapper.TYPE_OBJECT, v);
} }
@@ -1551,6 +1561,7 @@ public class ExpressionCodegen extends JetVisitor {
throwNewException(CLASS_TYPE_CAST_EXCEPTION); throwNewException(CLASS_TYPE_CAST_EXCEPTION);
} }
v.mark(isInstance); v.mark(isInstance);
v.checkcast(type);
myStack.push(StackValue.onStack(type)); myStack.push(StackValue.onStack(type));
} }
} }
@@ -298,7 +298,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (initializer != null) { if (initializer != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
codegen.genToJVMStack(initializer); codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(propertyDescriptor, false).store(iv); codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
} }
} }
@@ -89,7 +89,7 @@ public class NamespaceCodegen {
if (initializer != null && !(initializer instanceof JetConstantExpression)) { if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
codegen.genToJVMStack(initializer); codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, false).store(new InstructionAdapter(mv)); codegen.intermediateValueForProperty(descriptor, false, false).store(new InstructionAdapter(mv));
} }
} }
} }
+15
View File
@@ -0,0 +1,15 @@
class C(val x: Int) {
fun equals(rhs: Any?): Boolean {
if (rhs is C) {
val rhsC = rhs as C
return rhsC.x == x
}
return false
}
}
fun box(): String {
val c1 = C(10)
val c2 = C(10)
return if (c1 == c2) "OK" else "fail"
}
@@ -404,4 +404,8 @@ public class NamespaceGenTest extends CodegenTestCase {
public void testNamespaceQualifiedMethod() throws Exception { public void testNamespaceQualifiedMethod() throws Exception {
blackBoxFile("namespaceQualifiedMethod.jet"); blackBoxFile("namespaceQualifiedMethod.jet");
} }
public void testCheckCast() throws Exception {
blackBoxFile("checkCast.jet");
}
} }