Record compile time constants to trace

This commit is contained in:
Natalia Ukhorskaya
2013-11-13 11:16:08 +04:00
parent 1bd63fefa4
commit e23ef2dc98
2 changed files with 59 additions and 62 deletions
@@ -42,39 +42,61 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.COMPILE_TIME_INITIAL
@SuppressWarnings("StaticMethodReferencedViaSubclass") @SuppressWarnings("StaticMethodReferencedViaSubclass")
public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<?>, Void> { public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<?>, Void> {
@NotNull private final BindingTrace trace; private final BindingTrace trace;
@NotNull private final JetType expectedType; private final JetType expectedType;
public ConstantExpressionEvaluator(@NotNull BindingTrace trace, @NotNull JetType expectedType) { private ConstantExpressionEvaluator(@NotNull BindingTrace trace, @NotNull JetType expectedType) {
this.trace = trace; this.trace = trace;
this.expectedType = expectedType; this.expectedType = expectedType;
} }
@Nullable
public static CompileTimeConstant<?> evaluate(@NotNull JetExpression expression, @NotNull BindingTrace trace, @NotNull JetType expectedType) {
ConstantExpressionEvaluator evaluator = new ConstantExpressionEvaluator(trace, expectedType);
return evaluator.evaluate(expression);
}
@Nullable
public CompileTimeConstant<?> evaluate(@NotNull JetExpression expression) {
CompileTimeConstant<?> recordedCompileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
if (recordedCompileTimeConstant != null) {
return recordedCompileTimeConstant;
}
CompileTimeConstant<?> compileTimeConstant = expression.accept(this, null);
if (compileTimeConstant != null) {
trace.record(BindingContext.COMPILE_TIME_VALUE, expression, compileTimeConstant);
return compileTimeConstant;
}
return null;
}
@Override @Override
public CompileTimeConstant<?> visitConstantExpression(@NotNull JetConstantExpression expression, Void nothing) { public CompileTimeConstant<?> visitConstantExpression(@NotNull JetConstantExpression expression, Void data) {
return trace.get(BindingContext.COMPILE_TIME_VALUE, expression); return trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
} }
@Override @Override
public CompileTimeConstant<?> visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void nothing) { public CompileTimeConstant<?> visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, Void data) {
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression, nothing); JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression);
if (deparenthesizedExpression != null) { if (deparenthesizedExpression != null) {
return deparenthesizedExpression.accept(this, nothing); return evaluate(deparenthesizedExpression);
} }
return super.visitParenthesizedExpression(expression, nothing); return null;
} }
@Override @Override
public CompileTimeConstant<?> visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) { public CompileTimeConstant<?> visitPrefixExpression(@NotNull JetPrefixExpression expression, Void data) {
JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression, data); JetExpression deparenthesizedExpression = getDeparenthesizedExpression(expression);
if (deparenthesizedExpression != null) { if (deparenthesizedExpression != null) {
return deparenthesizedExpression.accept(this, data); return evaluate(deparenthesizedExpression);
} }
return super.visitPrefixExpression(expression, data); return null;
} }
@Nullable @Nullable
private JetExpression getDeparenthesizedExpression(JetExpression expression, Void data) { private static JetExpression getDeparenthesizedExpression(JetExpression expression) {
JetExpression deparenthesizedExpr = JetPsiUtil.deparenthesize(expression); JetExpression deparenthesizedExpr = JetPsiUtil.deparenthesize(expression);
if (deparenthesizedExpr == expression) { if (deparenthesizedExpr == expression) {
return null; return null;
@@ -83,29 +105,26 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
} }
@Override @Override
public CompileTimeConstant<?> visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void nothing) { public CompileTimeConstant<?> visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, Void data) {
CompileTimeConstant<?> compileTimeConstant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
if (compileTimeConstant != null) {
return compileTimeConstant;
}
JetStringTemplateEntry[] stringTemplateEntries = expression.getEntries(); JetStringTemplateEntry[] stringTemplateEntries = expression.getEntries();
if (stringTemplateEntries.length == 1) { if (stringTemplateEntries.length == 1) {
CompileTimeConstant singleEntry = stringTemplateEntries[0].accept(this, nothing); CompileTimeConstant singleEntry = stringTemplateEntries[0].accept(this, null);
if (!(singleEntry instanceof StringValue) && singleEntry != null) { if (!(singleEntry instanceof StringValue) && singleEntry != null) {
return new StringValue(singleEntry.getValue().toString()); return new StringValue(singleEntry.getValue().toString());
} }
return singleEntry; else {
return singleEntry;
}
} }
else if (stringTemplateEntries.length > 1) { else if (stringTemplateEntries.length > 1) {
CompileTimeConstant<?> first = stringTemplateEntries[0].accept(this, nothing); CompileTimeConstant<?> first = stringTemplateEntries[0].accept(this, null);
if (first == null) { if (first == null) {
return null; return null;
} }
CompileTimeConstant<?> second; CompileTimeConstant<?> second;
String tmpResult = null; String tmpResult = null;
for (int i = 1; i < stringTemplateEntries.length; i++) { for (int i = 1; i < stringTemplateEntries.length; i++) {
second = stringTemplateEntries[i].accept(this, nothing); second = stringTemplateEntries[i].accept(this, null);
if (second == null) { if (second == null) {
return null; return null;
} }
@@ -125,12 +144,12 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
} }
@Override @Override
public CompileTimeConstant<?> visitBlockStringTemplateEntry(@NotNull JetBlockStringTemplateEntry entry, Void data) { public CompileTimeConstant<?> visitStringTemplateEntryWithExpression(@NotNull JetStringTemplateEntryWithExpression entry, Void data) {
JetExpression expression = entry.getExpression(); JetExpression expression = entry.getExpression();
if (expression != null) { if (expression != null) {
return expression.accept(this, data); return evaluate(expression);
} }
return super.visitBlockStringTemplateEntry(entry, data); return null;
} }
@Override @Override
@@ -138,15 +157,6 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
return new StringValue(entry.getText()); return new StringValue(entry.getText());
} }
@Override
public CompileTimeConstant<?> visitSimpleNameStringTemplateEntry(@NotNull JetSimpleNameStringTemplateEntry entry, Void data) {
JetExpression expression = entry.getExpression();
if (expression != null) {
return expression.accept(this, data);
}
return super.visitSimpleNameStringTemplateEntry(entry, data);
}
@Override @Override
public CompileTimeConstant<?> visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry, Void data) { public CompileTimeConstant<?> visitEscapeStringTemplateEntry(@NotNull JetEscapeStringTemplateEntry entry, Void data) {
return new StringValue(entry.getUnescapedValue()); return new StringValue(entry.getUnescapedValue());
@@ -162,7 +172,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
IElementType operationToken = expression.getOperationToken(); IElementType operationToken = expression.getOperationToken();
if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) { if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationToken)) {
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType(); JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
CompileTimeConstant<?> leftConstant = leftExpression.accept(new ConstantExpressionEvaluator(trace, booleanType), null); CompileTimeConstant<?> leftConstant = evaluate(leftExpression, trace, booleanType);
if (leftConstant == null) { if (leftConstant == null) {
return null; return null;
} }
@@ -170,23 +180,17 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
if (rightExpression == null) { if (rightExpression == null) {
return null; return null;
} }
CompileTimeConstant<?> rightConstant = rightExpression.accept(new ConstantExpressionEvaluator(trace, booleanType), null); CompileTimeConstant<?> rightConstant = evaluate(rightExpression, trace, booleanType);
if (rightConstant == null) { if (rightConstant == null) {
return null; return null;
} }
Name operationName = operationToken == JetTokens.ANDAND ? Name.identifier("andand") : Name.identifier("oror"); Name operationName = operationToken == JetTokens.ANDAND ? Name.identifier("andand") : Name.identifier("oror");
Object result = EvaluatePackage.evaluateBinaryExpression(leftConstant, rightConstant, operationName); Object result = EvaluatePackage.evaluateBinaryExpression(leftConstant, rightConstant, operationName);
if (result == null) {
return null;
}
return createCompileTimeConstant(result, expectedType); return createCompileTimeConstant(result, expectedType);
} }
else { else {
Object result = evaluateCall(expression.getOperationReference(), leftExpression); Object result = evaluateCall(expression.getOperationReference(), leftExpression);
if (result == null) {
return null;
}
if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken)) { if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationToken)) {
return createCompileTimeConstantForCompareTo(result, operationToken); return createCompileTimeConstantForCompareTo(result, operationToken);
} }
@@ -231,7 +235,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
@Nullable @Nullable
private static CompileTimeConstant<?> createCompileTimeConstantForEquals( private static CompileTimeConstant<?> createCompileTimeConstantForEquals(
@NotNull Object result, @Nullable Object result,
@NotNull IElementType operationToken @NotNull IElementType operationToken
) { ) {
if (result instanceof Boolean) { if (result instanceof Boolean) {
@@ -248,7 +252,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
@Nullable @Nullable
private static CompileTimeConstant<?> createCompileTimeConstantForCompareTo( private static CompileTimeConstant<?> createCompileTimeConstantForCompareTo(
@NotNull Object result, @Nullable Object result,
@NotNull IElementType operationToken @NotNull IElementType operationToken
) { ) {
if (result instanceof Integer) { if (result instanceof Integer) {
@@ -292,14 +296,15 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
return null; return null;
} }
Object result = evaluateCall(expression.getOperationReference(), leftExpression); Object result = evaluateCall(expression.getOperationReference(), leftExpression);
if (result == null) {
return null;
}
return createCompileTimeConstant(result, expectedType); return createCompileTimeConstant(result, expectedType);
} }
public static CompileTimeConstant<?> createCompileTimeConstant(@NotNull Object value, @NotNull JetType expectedType) { @Nullable
if (value instanceof Integer) { public static CompileTimeConstant<?> createCompileTimeConstant(@Nullable Object value, @NotNull JetType expectedType) {
if (value == null) {
return null;
}
else if (value instanceof Integer) {
return getIntegerValue(((Integer) value).longValue(), expectedType); return getIntegerValue(((Integer) value).longValue(), expectedType);
} }
else if (value instanceof Byte) { else if (value instanceof Byte) {
@@ -399,11 +404,6 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
/* 1.toInt(); 1.plus(1); MyEnum.A */ /* 1.toInt(); 1.plus(1); MyEnum.A */
@Override @Override
public CompileTimeConstant<?> visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) { public CompileTimeConstant<?> visitQualifiedExpression(@NotNull JetQualifiedExpression expression, Void data) {
CompileTimeConstant wholeExpressionValue = trace.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, expression);
if (wholeExpressionValue != null) {
return wholeExpressionValue;
}
JetExpression receiverExpression = expression.getReceiverExpression(); JetExpression receiverExpression = expression.getReceiverExpression();
JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression selectorExpression = expression.getSelectorExpression();
@@ -416,17 +416,14 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
if (((JetCallExpression) selectorExpression).getValueArguments().size() < 2) { if (((JetCallExpression) selectorExpression).getValueArguments().size() < 2) {
Object result = evaluateCall(calleeExpression, receiverExpression); Object result = evaluateCall(calleeExpression, receiverExpression);
if (result == null) {
return null;
}
return createCompileTimeConstant(result, expectedType); return createCompileTimeConstant(result, expectedType);
} }
} }
if (selectorExpression != null) { if (selectorExpression != null) {
return selectorExpression.accept(this, null); return evaluate(selectorExpression);
} }
return super.visitQualifiedExpression(expression, data); return null;
} }
@Nullable @Nullable
@@ -483,7 +480,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
for (ValueArgument argument : valueArguments) { for (ValueArgument argument : valueArguments) {
JetExpression argumentExpression = argument.getArgumentExpression(); JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) { if (argumentExpression != null) {
CompileTimeConstant<?> constant = argumentExpression.accept(new ConstantExpressionEvaluator(trace, expectedType), null); CompileTimeConstant<?> constant = evaluate(argumentExpression, trace, expectedType);
if (constant != null) { if (constant != null) {
constants.add(constant); constants.add(constant);
} }
@@ -493,7 +490,7 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
} }
@Override @Override
public CompileTimeConstant<?> visitJetElement(@NotNull JetElement element, Void nothing) { public CompileTimeConstant<?> visitJetElement(@NotNull JetElement element, Void data) {
return null; return null;
} }
} }
@@ -257,7 +257,7 @@ public class AnnotationResolver {
@NotNull JetType expectedType, @NotNull JetType expectedType,
@NotNull BindingTrace trace @NotNull BindingTrace trace
) { ) {
return expression.accept(new ConstantExpressionEvaluator(trace, expectedType), null); return ConstantExpressionEvaluator.evaluate(expression, trace, expectedType);
} }
@NotNull @NotNull