Using invokeFunction() instead of invokeFunctionWithNoParams() when generating when() conditions
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.openapi.editor.Document;
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
import com.intellij.openapi.util.Pair;
|
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.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
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.JetStandardClasses;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibraryNames;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibraryNames;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.JetTypeMapper.*;
|
import static org.jetbrains.jet.codegen.JetTypeMapper.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.CALL;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
|
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
@@ -80,6 +83,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
|
||||||
private final Collection<String> localVariableNames = new HashSet<String>();
|
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 {
|
static class BlockStackElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +166,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackValue genQualified(StackValue receiver, JetElement selector) {
|
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)) {
|
if (!(selector instanceof JetBlockExpression)) {
|
||||||
markLineNumber(selector);
|
markLineNumber(selector);
|
||||||
}
|
}
|
||||||
@@ -176,6 +188,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StackValue gen(JetElement expr) {
|
public StackValue gen(JetElement expr) {
|
||||||
|
StackValue tempVar = tempVariables.get(expr);
|
||||||
|
if (tempVar != null) {
|
||||||
|
return tempVar;
|
||||||
|
}
|
||||||
if (expr instanceof JetExpression) {
|
if (expr instanceof JetExpression) {
|
||||||
JetExpression expression = (JetExpression) expr;
|
JetExpression expression = (JetExpression) expr;
|
||||||
CompileTimeConstant<?> constant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
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;
|
final int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||||
if (subjectLocal != -1) {
|
if (subjectLocal != -1) {
|
||||||
gen(expr, subjectType);
|
gen(expr, subjectType);
|
||||||
|
tempVariables.put(expr, StackValue.local(subjectLocal, subjectType));
|
||||||
v.store(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);
|
v.mark(end);
|
||||||
|
|
||||||
myFrameMap.leaveTemp(subjectType);
|
myFrameMap.leaveTemp(subjectType);
|
||||||
|
tempVariables.remove(expr);
|
||||||
return StackValue.onStack(resultType);
|
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);
|
getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FunctionDescriptor op =
|
//FunctionDescriptor op =
|
||||||
(FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference());
|
// (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference());
|
||||||
genToJVMStack(rangeExpression);
|
//genToJVMStack(rangeExpression);
|
||||||
new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v);
|
//new StackValue.Local(subjectLocal, subjectType).put(TYPE_OBJECT, v);
|
||||||
invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, 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) {
|
if (inverted) {
|
||||||
invertBoolean();
|
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);
|
return new Local(index, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,3 +9,21 @@ fun isDigit(a: Int) : String {
|
|||||||
else -> "something"
|
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 {
|
public void testRange() throws Exception {
|
||||||
loadFile();
|
blackBoxFile("patternMatching/range.jet");
|
||||||
// System.out.println(generateToText());
|
}
|
||||||
Method foo = generateFunction();
|
|
||||||
assertEquals("array list", foo.invoke(null, 239));
|
public void testWhenArgumentIsEvaluatedOnlyOnce() throws Exception {
|
||||||
assertEquals("digit", foo.invoke(null, 0));
|
blackBoxFile("patternMatching/whenArgumentIsEvaluatedOnlyOnce.kt");
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRangeChar() throws Exception {
|
public void testRangeChar() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user