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 {
boolean isStatic = container instanceof NamespaceDescriptorImpl;
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) {
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();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
final JetType outType = propertyDescriptor.getOutType();
boolean isInsideClass = containingDeclaration == contextType;
boolean isInsideClass = !forceInterface && containingDeclaration == contextType;
Method getter;
Method setter;
if (directToField) {
if (forceField) {
getter = 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)) {
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
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);
}
@@ -1551,6 +1561,7 @@ public class ExpressionCodegen extends JetVisitor {
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
}
v.mark(isInstance);
v.checkcast(type);
myStack.push(StackValue.onStack(type));
}
}
@@ -298,7 +298,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (initializer != null) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
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)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
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 {
blackBoxFile("namespaceQualifiedMethod.jet");
}
public void testCheckCast() throws Exception {
blackBoxFile("checkCast.jet");
}
}