KT-518 - array like expression via intrinsic method
This commit is contained in:
@@ -1130,7 +1130,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Callable resolveToCallable(DeclarationDescriptor fd, boolean superCall) {
|
Callable resolveToCallable(DeclarationDescriptor fd, boolean superCall) {
|
||||||
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd);
|
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd);
|
||||||
if (intrinsic != null) {
|
if (intrinsic != null) {
|
||||||
return intrinsic;
|
return intrinsic;
|
||||||
@@ -2099,11 +2099,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
final JetExpression array = expression.getArrayExpression();
|
final JetExpression array = expression.getArrayExpression();
|
||||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
|
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
|
||||||
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
|
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
|
||||||
gen(array, arrayType);
|
|
||||||
final List<JetExpression> indices = expression.getIndexExpressions();
|
final List<JetExpression> indices = expression.getIndexExpressions();
|
||||||
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
||||||
assert operationDescriptor != null;
|
assert operationDescriptor != null;
|
||||||
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
|
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
|
||||||
|
gen(array, arrayType);
|
||||||
for (JetExpression index : indices) {
|
for (JetExpression index : indices) {
|
||||||
gen(index, Type.INT_TYPE);
|
gen(index, Type.INT_TYPE);
|
||||||
}
|
}
|
||||||
@@ -2132,6 +2132,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
|
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if(isGetter) {
|
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;
|
assert getterDescriptor != null;
|
||||||
if(getterDescriptor.getReceiverParameter().exists()) {
|
if(getterDescriptor.getReceiverParameter().exists()) {
|
||||||
index++;
|
index++;
|
||||||
@@ -2145,6 +2151,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
asmType = accessor.getSignature().getReturnType();
|
asmType = accessor.getSignature().getReturnType();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Callable callable = resolveToCallable(resolvedSetCall.getResultingDescriptor(), false);
|
||||||
|
if(callable instanceof CallableMethod)
|
||||||
|
genThisAndReceiverFromResolvedCall((CallableMethod) callable, receiver, resolvedSetCall);
|
||||||
|
else
|
||||||
|
gen(array, arrayType);
|
||||||
|
|
||||||
assert setterDescriptor != null;
|
assert setterDescriptor != null;
|
||||||
if(setterDescriptor.getReceiverParameter().exists()) {
|
if(setterDescriptor.getReceiverParameter().exists()) {
|
||||||
index++;
|
index++;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.tree.IElementType;
|
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.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
@@ -482,8 +483,8 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class CollectionElement extends StackValue {
|
private static class CollectionElement extends StackValue {
|
||||||
private final CallableMethod getter;
|
private final Callable getter;
|
||||||
private final CallableMethod setter;
|
private final Callable setter;
|
||||||
private final ExpressionCodegen codegen;
|
private final ExpressionCodegen codegen;
|
||||||
private final FrameMap frame;
|
private final FrameMap frame;
|
||||||
private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
|
private final ResolvedCall<FunctionDescriptor> resolvedGetCall;
|
||||||
@@ -497,8 +498,8 @@ public abstract class StackValue {
|
|||||||
this.resolvedSetCall = resolvedSetCall;
|
this.resolvedSetCall = resolvedSetCall;
|
||||||
this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
|
this.setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
|
||||||
this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
|
this.getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
|
||||||
this.setter = resolvedSetCall == null ? null : codegen.typeMapper.mapToCallableMethod(setterDescriptor, false, OwnerKind.IMPLEMENTATION);
|
this.setter = resolvedSetCall == null ? null : codegen.resolveToCallable(setterDescriptor, false);
|
||||||
this.getter = resolvedGetCall == null ? null : codegen.typeMapper.mapToCallableMethod(getterDescriptor, false, OwnerKind.IMPLEMENTATION);
|
this.getter = resolvedGetCall == null ? null : codegen.resolveToCallable(getterDescriptor, false);
|
||||||
this.codegen = codegen;
|
this.codegen = codegen;
|
||||||
this.frame = codegen.myFrameMap;
|
this.frame = codegen.myFrameMap;
|
||||||
}
|
}
|
||||||
@@ -508,7 +509,10 @@ public abstract class StackValue {
|
|||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
throw new UnsupportedOperationException("no getter specified");
|
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);
|
coerce(type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +521,10 @@ public abstract class StackValue {
|
|||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
throw new UnsupportedOperationException("no setter specified");
|
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
|
@Override
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ public class IntrinsicMethods {
|
|||||||
declareIntrinsicFunction("Boolean", "not", 0, new Not());
|
declareIntrinsicFunction("Boolean", "not", 0, new Not());
|
||||||
|
|
||||||
declareIntrinsicFunction("String", "plus", 1, new Concat());
|
declareIntrinsicFunction("String", "plus", 1, new Concat());
|
||||||
|
declareIntrinsicFunction("String", "get", 1, new StringGetChar());
|
||||||
|
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString());
|
declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString());
|
||||||
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS);
|
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS);
|
||||||
|
|||||||
@@ -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<JetExpression> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -280,4 +280,8 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
|||||||
public void testKt446 () throws Exception {
|
public void testKt446 () throws Exception {
|
||||||
blackBoxFile("regressions/kt446.jet");
|
blackBoxFile("regressions/kt446.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt518 () throws Exception {
|
||||||
|
blackBoxFile("regressions/kt518.jet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user