Fix recusrive calls in infix and prefix form

The infamous invokeOperation() method removed
This commit is contained in:
Andrey Breslav
2013-11-28 20:09:37 +04:00
parent db4b73189a
commit 93160431f9
6 changed files with 81 additions and 34 deletions
@@ -2638,7 +2638,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, StackValue receiver) {
IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
JetSimpleNameExpression reference = expression.getOperationReference();
IElementType opToken = reference.getReferencedNameElementType();
if (opToken == JetTokens.EQ) {
return generateAssignmentExpression(expression);
}
@@ -2657,7 +2658,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ ||
opToken == JetTokens.GT || opToken == JetTokens.GTEQ) {
return generateComparison(expression);
return generateComparison(expression, receiver);
}
else if (opToken == JetTokens.ELVIS) {
return generateElvis(expression);
@@ -2666,7 +2667,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return generateIn(expression);
}
else {
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference);
Call call = bindingContext.get(BindingContext.CALL, reference);
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, reference);
assert op instanceof FunctionDescriptor : String.valueOf(op);
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
if (callable instanceof IntrinsicMethod) {
@@ -2675,7 +2679,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
Arrays.asList(expression.getLeft(), expression.getRight()), receiver, state);
}
else {
return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable);
return invokeFunction(call, receiver, resolvedCall);
}
}
}
@@ -2856,7 +2860,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.onStack(exprType);
}
private StackValue generateComparison(JetBinaryExpression expression) {
private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) {
DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target;
FunctionDescriptor descriptor = (FunctionDescriptor) target;
@@ -2869,13 +2873,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (callable instanceof IntrinsicMethod) {
// Compare two primitive values
type = comparisonOperandType(expressionType(left), expressionType(right));
StackValue receiver = gen(left);
receiver.put(type, v);
StackValue recv = gen(left);
recv.put(type, v);
gen(right, type);
}
else {
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference());
StackValue result = invokeFunction(call, receiver, resolvedCall);
type = Type.INT_TYPE;
StackValue result = invokeOperation(expression, descriptor, (CallableMethod) callable);
result.put(type, v);
v.iconst(0);
}
@@ -3009,14 +3016,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
else {
DeclarationDescriptor cls = op.getContainingDeclaration();
CallableMethod callableMethod = (CallableMethod) callable;
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null;
if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) {
return invokeOperation(expression, (FunctionDescriptor) op, callableMethod);
Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference());
return invokeFunction(call, receiver, resolvedCall);
}
else {
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null;
CallableMethod callableMethod = (CallableMethod) callable;
StackValue value = gen(expression.getBaseExpression());
value.dupReceiver(v);
@@ -3033,27 +3042,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) {
//TODO: similar logic exists in visitSimpleNameExpression - extract common logic
int functionLocalIndex = lookupLocalIndex(op);
if (functionLocalIndex >= 0) {
stackValueForLocal(op, functionLocalIndex).put(callable.getOwner(), v);
} else {
StackValue stackValue = context.lookupInContext(op, StackValue.local(0, OBJECT_TYPE), state, true);
if (stackValue != null) {
stackValue.put(callable.getOwner(), v);
}
}
ResolvedCall<? extends CallableDescriptor> resolvedCall =
bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
assert resolvedCall != null;
genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable);
pushArgumentsAndInvoke(resolvedCall, callable);
return returnValueAsStackValue(op, callable.getSignature().getAsmMethod().getReturnType());
}
@Override
public StackValue visitPostfixExpression(@NotNull JetPostfixExpression expression, StackValue receiver) {
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) {
@@ -0,0 +1,8 @@
fun Int.test(x : Int) : Int {
if (this > 1) {
return (this - 1) test x
}
return this
}
fun box() : String = if (10.test(10) == 1) "OK" else "FAIL"
@@ -0,0 +1,8 @@
fun String.plus() : String {
if (this == "") {
return "done"
}
return +""
}
fun box() : String = if (+"11" == "done") "OK" else "FAIL"
@@ -0,0 +1,11 @@
class C
fun C.compareTo(o: C) : Int {
if (this == o) return 0
if (o >= o) {
return 1
}
return -1
}
fun box() : String = if (C() > C()) "OK" else "FAIL"
@@ -0,0 +1,12 @@
fun String.inc() : String {
if (this == "") {
return "done"
}
var s = ""
return ++s
}
fun box() : String {
var s = "11test"
return if (++s == "done") "OK" else "FAIL"
}
@@ -2407,6 +2407,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/functions/functionNtoString.kt");
}
@TestMetadata("infixRecursiveCall.kt")
public void testInfixRecursiveCall() throws Exception {
doTest("compiler/testData/codegen/box/functions/infixRecursiveCall.kt");
}
@TestMetadata("kt1038.kt")
public void testKt1038() throws Exception {
doTest("compiler/testData/codegen/box/functions/kt1038.kt");
@@ -2512,6 +2517,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt");
}
@TestMetadata("prefixRecursiveCall.kt")
public void testPrefixRecursiveCall() throws Exception {
doTest("compiler/testData/codegen/box/functions/prefixRecursiveCall.kt");
}
@TestMetadata("recursiveCompareTo.kt")
public void testRecursiveCompareTo() throws Exception {
doTest("compiler/testData/codegen/box/functions/recursiveCompareTo.kt");
}
@TestMetadata("recursiveIncrementCall.kt")
public void testRecursiveIncrementCall() throws Exception {
doTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt");
}
@TestMetadata("compiler/testData/codegen/box/functions/invoke")
public static class Invoke extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInInvoke() throws Exception {