diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9e8207cb18a..f9873af4c82 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2638,7 +2638,8 @@ public class ExpressionCodegen extends JetVisitor 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 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 implem return generateIn(expression); } else { - DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); + ResolvedCall 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 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 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 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 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 implem } else { DeclarationDescriptor cls = op.getContainingDeclaration(); - CallableMethod callableMethod = (CallableMethod) callable; + ResolvedCall 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 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 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 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) { diff --git a/compiler/testData/codegen/box/functions/infixRecursiveCall.kt b/compiler/testData/codegen/box/functions/infixRecursiveCall.kt new file mode 100644 index 00000000000..72c3f985204 --- /dev/null +++ b/compiler/testData/codegen/box/functions/infixRecursiveCall.kt @@ -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" \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/prefixRecursiveCall.kt b/compiler/testData/codegen/box/functions/prefixRecursiveCall.kt new file mode 100644 index 00000000000..9fe7c720e05 --- /dev/null +++ b/compiler/testData/codegen/box/functions/prefixRecursiveCall.kt @@ -0,0 +1,8 @@ +fun String.plus() : String { + if (this == "") { + return "done" + } + return +"" +} + +fun box() : String = if (+"11" == "done") "OK" else "FAIL" \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/recursiveCompareTo.kt b/compiler/testData/codegen/box/functions/recursiveCompareTo.kt new file mode 100644 index 00000000000..2feebcc715d --- /dev/null +++ b/compiler/testData/codegen/box/functions/recursiveCompareTo.kt @@ -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" \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/recursiveIncrementCall.kt b/compiler/testData/codegen/box/functions/recursiveIncrementCall.kt new file mode 100644 index 00000000000..cf09fc54cc7 --- /dev/null +++ b/compiler/testData/codegen/box/functions/recursiveIncrementCall.kt @@ -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" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index d59efbbf6f5..069372d3ce2 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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 {