generate checkcast instruction for 'as' calls; use accessors for accessing fields of other instances of the same class
This commit is contained in:
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user