From b054ccefdbc123a226ab7c54444c86c302cc638e Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Fri, 18 Nov 2011 12:10:08 +0200 Subject: [PATCH] KT-518 - array like expression via intrinsic method --- .../jet/codegen/ExpressionCodegen.java | 16 ++++++++-- .../org/jetbrains/jet/codegen/StackValue.java | 19 ++++++++---- .../codegen/intrinsics/IntrinsicMethods.java | 1 + .../jet/codegen/intrinsics/StringGetChar.java | 30 +++++++++++++++++++ .../testData/codegen/regressions/kt518.jet | 15 ++++++++++ .../jet/codegen/PrimitiveTypesTest.java | 4 +++ 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.java create mode 100644 compiler/testData/codegen/regressions/kt518.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 2f693489f49..52922709fcf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1130,7 +1130,7 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.none(); } - private Callable resolveToCallable(DeclarationDescriptor fd, boolean superCall) { + Callable resolveToCallable(DeclarationDescriptor fd, boolean superCall) { final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd); if (intrinsic != null) { return intrinsic; @@ -2099,11 +2099,11 @@ public class ExpressionCodegen extends JetVisitor { final JetExpression array = expression.getArrayExpression(); JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type); - gen(array, arrayType); final List indices = expression.getIndexExpressions(); FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); assert operationDescriptor != null; if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) { + gen(array, arrayType); for (JetExpression index : indices) { gen(index, Type.INT_TYPE); } @@ -2132,6 +2132,12 @@ public class ExpressionCodegen extends JetVisitor { Type[] argumentTypes = accessor.getSignature().getArgumentTypes(); int index = 0; if(isGetter) { + Callable callable = resolveToCallable(getterDescriptor, false); + if(callable instanceof CallableMethod) + genThisAndReceiverFromResolvedCall((CallableMethod) callable, receiver, resolvedGetCall); + else + gen(array, typeMapper.mapType(((ClassDescriptor)getterDescriptor.getContainingDeclaration()).getDefaultType())); + assert getterDescriptor != null; if(getterDescriptor.getReceiverParameter().exists()) { index++; @@ -2145,6 +2151,12 @@ public class ExpressionCodegen extends JetVisitor { asmType = accessor.getSignature().getReturnType(); } else { + Callable callable = resolveToCallable(resolvedSetCall.getResultingDescriptor(), false); + if(callable instanceof CallableMethod) + genThisAndReceiverFromResolvedCall((CallableMethod) callable, receiver, resolvedSetCall); + else + gen(array, arrayType); + assert setterDescriptor != null; if(setterDescriptor.getReceiverParameter().exists()) { index++; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 3239cb8b343..bf370dc3bf2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.tree.IElementType; +import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; @@ -482,8 +483,8 @@ public abstract class StackValue { } private static class CollectionElement extends StackValue { - private final CallableMethod getter; - private final CallableMethod setter; + private final Callable getter; + private final Callable setter; private final ExpressionCodegen codegen; private final FrameMap frame; private final ResolvedCall resolvedGetCall; @@ -497,8 +498,8 @@ public abstract class StackValue { this.resolvedSetCall = resolvedSetCall; this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor(); this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor(); - this.setter = resolvedSetCall == null ? null : codegen.typeMapper.mapToCallableMethod(setterDescriptor, false, OwnerKind.IMPLEMENTATION); - this.getter = resolvedGetCall == null ? null : codegen.typeMapper.mapToCallableMethod(getterDescriptor, false, OwnerKind.IMPLEMENTATION); + this.setter = resolvedSetCall == null ? null : codegen.resolveToCallable(setterDescriptor, false); + this.getter = resolvedGetCall == null ? null : codegen.resolveToCallable(getterDescriptor, false); this.codegen = codegen; this.frame = codegen.myFrameMap; } @@ -508,7 +509,10 @@ public abstract class StackValue { if (getter == null) { throw new UnsupportedOperationException("no getter specified"); } - getter.invoke(v); + if(getter instanceof CallableMethod) + ((CallableMethod)getter).invoke(v); + else + ((IntrinsicMethod)getter).generate(codegen, v, null, null, null, null); coerce(type, v); } @@ -517,7 +521,10 @@ public abstract class StackValue { if (setter == null) { throw new UnsupportedOperationException("no setter specified"); } - setter.invoke(v); + if(setter instanceof CallableMethod) + ((CallableMethod)setter).invoke(v); + else + ((IntrinsicMethod)setter).generate(codegen, v, null, null, null, null); } @Override diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 3ffd1f319ff..5ea6dc9faed 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -76,6 +76,7 @@ public class IntrinsicMethods { declareIntrinsicFunction("Boolean", "not", 0, new Not()); declareIntrinsicFunction("String", "plus", 1, new Concat()); + declareIntrinsicFunction("String", "get", 1, new StringGetChar()); declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString()); declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.java new file mode 100644 index 00000000000..4c39b0c1260 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StringGetChar.java @@ -0,0 +1,30 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lexer.JetTokens; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class StringGetChar implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + if(receiver != null) + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + if(arguments != null) + codegen.gen(arguments.get(0)).put(Type.INT_TYPE, v); + v.invokevirtual("java/lang/String", "charAt", "(I)C"); + return StackValue.onStack(Type.CHAR_TYPE); + } +} diff --git a/compiler/testData/codegen/regressions/kt518.jet b/compiler/testData/codegen/regressions/kt518.jet new file mode 100644 index 00000000000..9b9ab40dc24 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt518.jet @@ -0,0 +1,15 @@ + +fun foo(i : Int?, a : Any?) { + i?.plus(1) + if (i != null) { + i + 1 + if (a is String) { + a[0] + } + } +} + +fun box () : String { + foo(2, "239") + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index d58093ab056..0a7b11175ea 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -280,4 +280,8 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testKt446 () throws Exception { blackBoxFile("regressions/kt446.jet"); } + + public void testKt518 () throws Exception { + blackBoxFile("regressions/kt518.jet"); + } } -- GitLab