Using invokeFunction() instead of invokeFunctionWithNoParams() when generating when() conditions
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -45,15 +46,17 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibraryNames;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.codegen.JetTypeMapper.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -80,6 +83,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
||||
private final Collection<String> localVariableNames = new HashSet<String>();
|
||||
|
||||
/*
|
||||
* When we create a temporary variable to hold some value not to compute it many times
|
||||
* we put it into this map to emit access to that variable instead of evaluating the whole expression
|
||||
*/
|
||||
private final Map<JetElement, StackValue.Local> tempVariables = Maps.newHashMap();
|
||||
|
||||
static class BlockStackElement {
|
||||
}
|
||||
|
||||
@@ -157,6 +166,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
public StackValue genQualified(StackValue receiver, JetElement selector) {
|
||||
if (tempVariables.containsKey(selector)) {
|
||||
throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector");
|
||||
}
|
||||
if (!(selector instanceof JetBlockExpression)) {
|
||||
markLineNumber(selector);
|
||||
}
|
||||
@@ -176,6 +188,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
public StackValue gen(JetElement expr) {
|
||||
StackValue tempVar = tempVariables.get(expr);
|
||||
if (tempVar != null) {
|
||||
return tempVar;
|
||||
}
|
||||
if (expr instanceof JetExpression) {
|
||||
JetExpression expression = (JetExpression) expr;
|
||||
CompileTimeConstant<?> constant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
@@ -3252,6 +3268,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
final int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
if (subjectLocal != -1) {
|
||||
gen(expr, subjectType);
|
||||
tempVariables.put(expr, StackValue.local(subjectLocal, subjectType));
|
||||
v.store(subjectLocal, subjectType);
|
||||
}
|
||||
|
||||
@@ -3301,6 +3318,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
v.mark(end);
|
||||
|
||||
myFrameMap.leaveTemp(subjectType);
|
||||
tempVariables.remove(expr);
|
||||
return StackValue.onStack(resultType);
|
||||
}
|
||||
|
||||
@@ -3319,12 +3337,15 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted);
|
||||
}
|
||||
else {
|
||||
FunctionDescriptor op =
|
||||
(FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference());
|
||||
genToJVMStack(rangeExpression);
|
||||
new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v);
|
||||
invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
|
||||
|
||||
//FunctionDescriptor op =
|
||||
// (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference());
|
||||
//genToJVMStack(rangeExpression);
|
||||
//new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v);
|
||||
//invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall =
|
||||
bindingContext.get(RESOLVED_CALL, conditionInRange.getOperationReference());
|
||||
Call call = bindingContext.get(CALL, conditionInRange.getOperationReference());
|
||||
invokeFunction(call, StackValue.none(), resolvedCall);
|
||||
if (inverted) {
|
||||
invertBoolean();
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static StackValue local(int index, Type type) {
|
||||
public static Local local(int index, Type type) {
|
||||
return new Local(index, type);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,3 +9,21 @@ fun isDigit(a: Int) : String {
|
||||
else -> "something"
|
||||
}
|
||||
}
|
||||
|
||||
fun assertDigit(i: Int, expected: String): String {
|
||||
val result = isDigit(i)
|
||||
return if (result == expected) "" else "fail: isDigit($i) = \"$result\""
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val result =
|
||||
assertDigit(239, "array list") +
|
||||
assertDigit(0, "digit") +
|
||||
assertDigit(9, "digit") +
|
||||
assertDigit(5, "digit") +
|
||||
assertDigit(19, "something") +
|
||||
assertDigit(190, "not small")
|
||||
|
||||
if (result == "") return "OK"
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
var x = 0
|
||||
fun inc(): Int {
|
||||
x++
|
||||
return 0
|
||||
}
|
||||
fun box(): String {
|
||||
val al = java.util.ArrayList<Int>()
|
||||
when (inc()) {
|
||||
in al -> return "fail 1"
|
||||
else -> {}
|
||||
}
|
||||
return if (x == 1) "OK" else "fail 2"
|
||||
}
|
||||
@@ -77,15 +77,11 @@ public class PatternMatchingTest extends CodegenTestCase {
|
||||
}
|
||||
|
||||
public void testRange() throws Exception {
|
||||
loadFile();
|
||||
// System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
assertEquals("array list", foo.invoke(null, 239));
|
||||
assertEquals("digit", foo.invoke(null, 0));
|
||||
assertEquals("digit", foo.invoke(null, 9));
|
||||
assertEquals("digit", foo.invoke(null, 5));
|
||||
assertEquals("something", foo.invoke(null, 19));
|
||||
assertEquals("not small", foo.invoke(null, 190));
|
||||
blackBoxFile("patternMatching/range.jet");
|
||||
}
|
||||
|
||||
public void testWhenArgumentIsEvaluatedOnlyOnce() throws Exception {
|
||||
blackBoxFile("patternMatching/whenArgumentIsEvaluatedOnlyOnce.kt");
|
||||
}
|
||||
|
||||
public void testRangeChar() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user