Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1025)

Unified Diff: pkg/compiler/lib/src/kernel/element_map.dart

Issue 2916393002: Compute constants from IR nodes (Closed)
Patch Set: Updated cf. comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/kernel/element_map.dart
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index cec38f80eb658788f7f65f0f993ae17c46105798..09cfd9a351c157d34e9fa818e52112f28c4988ce 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -147,7 +147,8 @@ abstract class KernelToElementMap {
InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node);
/// Computes the [ConstantValue] for the constant [expression].
- ConstantValue getConstantValue(ir.Expression expression);
+ ConstantValue getConstantValue(ir.Expression expression,
+ {bool requireConstant: true});
/// Returns the `noSuchMethod` [FunctionEntity] call from a
/// `super.noSuchMethod` invocation within [cls].
@@ -170,7 +171,8 @@ enum ForeignKind {
abstract class KernelToElementMapMixin implements KernelToElementMap {
DiagnosticReporter get reporter;
native.BehaviorBuilder get nativeBehaviorBuilder;
- ConstantValue computeConstantValue(ConstantExpression constant);
+ ConstantValue computeConstantValue(ConstantExpression constant,
+ {bool requireConstant: true});
@override
Name getName(ir.Name name) {
@@ -240,13 +242,18 @@ abstract class KernelToElementMapMixin implements KernelToElementMap {
return new Selector.setter(name);
}
- ConstantValue getConstantValue(ir.Expression node) {
- ConstantExpression constant = new Constantifier(this).visit(node);
+ ConstantValue getConstantValue(ir.Expression node,
+ {bool requireConstant: true}) {
+ ConstantExpression constant =
+ new Constantifier(this, requireConstant: requireConstant).visit(node);
if (constant == null) {
- throw new UnsupportedError(
- 'No constant for ${DebugPrinter.prettyPrint(node)}');
+ if (requireConstant) {
+ throw new UnsupportedError(
+ 'No constant for ${DebugPrinter.prettyPrint(node)}');
+ }
+ return null;
}
- return computeConstantValue(constant);
+ return computeConstantValue(constant, requireConstant: requireConstant);
}
/// Converts [annotations] into a list of [ConstantValue]s.
@@ -550,8 +557,11 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
}
ConstantExpression defaultExpression(ir.Expression node) {
- throw new UnimplementedError(
- 'Unimplemented constant expression $node (${node.runtimeType})');
+ if (requireConstant) {
+ throw new UnimplementedError(
+ 'Unimplemented constant expression $node (${node.runtimeType})');
+ }
+ return null;
}
List<ConstantExpression> _computeList(List<ir.Expression> expressions) {
@@ -581,12 +591,14 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
ConstructedConstantExpression _computeConstructorInvocation(
ir.Constructor target, ir.Arguments arguments) {
+ List<ConstantExpression> expressions = _computeArguments(arguments);
+ if (expressions == null) return null;
return new ConstructedConstantExpression(
elementAdapter.createInterfaceType(
target.enclosingClass, arguments.types),
elementAdapter.getConstructor(target),
elementAdapter.getCallStructure(arguments),
- _computeArguments(arguments));
+ expressions);
}
@override
@@ -605,22 +617,23 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
assert(function.namedParameters.contains(node.variable));
return new NamedArgumentReference(node.variable.name);
}
+ } else if (node.variable.isConst) {
+ return visit(node.variable.initializer);
}
- throw new UnimplementedError(
- 'Unimplemented constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
@override
ConstantExpression visitStaticGet(ir.StaticGet node) {
- if (node.target is ir.Field) {
+ ir.Member target = node.target;
+ if (target is ir.Field && target.isConst) {
return new FieldConstantExpression(elementAdapter.getField(node.target));
} else if (node.target is ir.Procedure) {
FunctionEntity function = elementAdapter.getMethod(node.target);
DartType type = elementAdapter.getFunctionType(node.target.function);
return new FunctionConstantExpression(function, type);
}
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
@override
@@ -655,22 +668,27 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
@override
ConstantExpression visitStringConcatenation(ir.StringConcatenation node) {
- return new ConcatenateConstantExpression(_computeList(node.expressions));
+ List<ConstantExpression> expressions = _computeList(node.expressions);
+ if (expressions == null) return null;
+ return new ConcatenateConstantExpression(expressions);
}
@override
ConstantExpression visitMapLiteral(ir.MapLiteral node) {
if (!node.isConst) {
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
DartType keyType = elementAdapter.getDartType(node.keyType);
DartType valueType = elementAdapter.getDartType(node.valueType);
List<ConstantExpression> keys = <ConstantExpression>[];
List<ConstantExpression> values = <ConstantExpression>[];
for (ir.MapEntry entry in node.entries) {
- keys.add(visit(entry.key));
- values.add(visit(entry.value));
+ ConstantExpression key = visit(entry.key);
+ if (key == null) return null;
+ keys.add(key);
+ ConstantExpression value = visit(entry.value);
+ if (value == null) return null;
+ values.add(value);
}
return new MapConstantExpression(
_commonElements.mapType(keyType, valueType), keys, values);
@@ -679,23 +697,52 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
@override
ConstantExpression visitListLiteral(ir.ListLiteral node) {
if (!node.isConst) {
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
DartType elementType = elementAdapter.getDartType(node.typeArgument);
List<ConstantExpression> values = <ConstantExpression>[];
- for (ir.Expression value in node.expressions) {
- values.add(visit(value));
+ for (ir.Expression expression in node.expressions) {
+ ConstantExpression value = visit(expression);
+ if (value == null) return null;
+ values.add(value);
}
return new ListConstantExpression(
_commonElements.listType(elementType), values);
}
@override
+ ConstantExpression visitTypeLiteral(ir.TypeLiteral node) {
+ DartType type = elementAdapter.getDartType(node.type);
+ String name;
+ if (type.isDynamic) {
+ name = 'dynamic';
+ } else if (type is InterfaceType) {
+ name = type.element.name;
+ } else if (type.isFunctionType || type.isTypedef) {
+ // TODO(johnniwinther): Compute a name for the type literal? It is only
+ // used in error messages in the old SSA builder.
+ name = '?';
+ } else {
+ return defaultExpression(node);
+ }
+ return new TypeConstantExpression(type, name);
+ }
+
+ @override
+ ConstantExpression visitNot(ir.Not node) {
+ ConstantExpression expression = visit(node.operand);
+ if (expression == null) return null;
+ return new UnaryConstantExpression(UnaryOperator.NOT, expression);
+ }
+
+ @override
ConstantExpression visitConditionalExpression(ir.ConditionalExpression node) {
ConstantExpression condition = visit(node.condition);
+ if (condition == null) return null;
ConstantExpression trueExp = visit(node.then);
+ if (trueExp == null) return null;
ConstantExpression falseExp = visit(node.otherwise);
+ if (falseExp == null) return null;
return new ConditionalConstantExpression(condition, trueExp, falseExp);
}
@@ -706,6 +753,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
'Unexpected constant expression $node (${node.runtimeType})');
}
ConstantExpression receiver = visit(node.receiver);
+ if (receiver == null) return null;
return new StringLengthConstantExpression(receiver);
}
@@ -714,8 +762,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
// Method invocations are generally not constant expressions but unary
// and binary expressions are encoded as method invocations in kernel.
if (node.arguments.named.isNotEmpty) {
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
if (node.arguments.positional.length == 0) {
UnaryOperator operator;
@@ -726,6 +773,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
}
if (operator != null) {
ConstantExpression expression = visit(node.receiver);
+ if (expression == null) return null;
return new UnaryConstantExpression(operator, expression);
}
}
@@ -733,12 +781,13 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
BinaryOperator operator = BinaryOperator.parse(node.name.name);
if (operator != null) {
ConstantExpression left = visit(node.receiver);
+ if (left == null) return null;
ConstantExpression right = visit(node.arguments.positional.single);
+ if (right == null) return null;
return new BinaryConstantExpression(left, operator, right);
}
}
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
@override
@@ -748,19 +797,22 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
if (node.arguments.positional.length == 2 &&
node.arguments.named.isEmpty) {
ConstantExpression left = visit(node.arguments.positional[0]);
+ if (left == null) return null;
ConstantExpression right = visit(node.arguments.positional[1]);
+ if (right == null) return null;
return new IdenticalConstantExpression(left, right);
}
} else if (member.name == 'fromEnvironment' &&
node.arguments.positional.length == 1) {
ConstantExpression name = visit(node.arguments.positional.single);
+ if (name == null) return null;
ConstantExpression defaultValue;
if (node.arguments.named.length == 1) {
if (node.arguments.named.single.name != 'defaultValue') {
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
defaultValue = visit(node.arguments.named.single.value);
+ if (defaultValue == null) return null;
}
if (member.enclosingClass == _commonElements.boolClass) {
return new BoolFromEnvironmentConstantExpression(name, defaultValue);
@@ -770,8 +822,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
return new StringFromEnvironmentConstantExpression(name, defaultValue);
}
}
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
@override
@@ -779,11 +830,12 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
BinaryOperator operator = BinaryOperator.parse(node.operator);
if (operator != null) {
ConstantExpression left = visit(node.left);
+ if (left == null) return null;
ConstantExpression right = visit(node.right);
+ if (right == null) return null;
return new BinaryConstantExpression(left, operator, right);
}
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
@override
@@ -803,7 +855,9 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
// We have <left> ?? <right> encoded as:
// let #1 = <left> in #1 == null ? <right> : #1
ConstantExpression left = visit(node.variable.initializer);
+ if (left == null) return null;
ConstantExpression right = visit(body.then);
+ if (right == null) return null;
// TODO(johnniwinther): Remove [IF_NULL] binary constant expression
// when the resolver is removed; then we no longer need the
// expressions to be structurally equivalence for equivalence
@@ -814,8 +868,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
}
}
}
- throw new UnimplementedError(
- 'Unexpected constant expression $node (${node.runtimeType})');
+ return defaultExpression(node);
}
/// Compute the [ConstantConstructor] corresponding to the const constructor
@@ -829,20 +882,25 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
Map<dynamic, ConstantExpression> defaultValues =
<dynamic, ConstantExpression>{};
int parameterIndex = 0;
- node.function.positionalParameters
- .forEach((ir.VariableDeclaration parameter) {
+ for (ir.VariableDeclaration parameter
+ in node.function.positionalParameters) {
if (parameterIndex >= node.function.requiredParameterCount) {
+ ConstantExpression defaultValue;
if (parameter.initializer != null) {
- defaultValues[parameterIndex] = parameter.initializer.accept(this);
+ defaultValue = parameter.initializer.accept(this);
} else {
- defaultValues[parameterIndex] = new NullConstantExpression();
+ defaultValue = new NullConstantExpression();
}
+ if (defaultValue == null) return null;
+ defaultValues[parameterIndex] = defaultValue;
}
parameterIndex++;
- });
- node.function.namedParameters.forEach((ir.VariableDeclaration parameter) {
- defaultValues[parameter.name] = parameter.initializer.accept(this);
- });
+ }
+ for (ir.VariableDeclaration parameter in node.function.namedParameters) {
+ ConstantExpression defaultValue = parameter.initializer.accept(this);
+ if (defaultValue == null) return null;
+ defaultValues[parameter.name] = defaultValue;
+ }
bool isRedirecting = node.initializers.length == 1 &&
node.initializers.single is ir.RedirectingInitializer;
« no previous file with comments | « pkg/compiler/lib/src/js_backend/runtime_types.dart ('k') | pkg/compiler/lib/src/kernel/element_map_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698