Index: pkg/compiler/lib/src/constants/expressions.dart |
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart |
index 5aeb27b8665ee030ea7e311c7dc652288e461581..291babc6687d42ac808a22ef28115b80c986b922 100644 |
--- a/pkg/compiler/lib/src/constants/expressions.dart |
+++ b/pkg/compiler/lib/src/constants/expressions.dart |
@@ -4,7 +4,8 @@ |
library dart2js.constants.expressions; |
-import '../dart2jslib.dart' show assertDebugMode; |
+import '../constants/constant_system.dart'; |
+import '../dart2jslib.dart' show assertDebugMode, Compiler; |
import '../dart_types.dart'; |
import '../elements/elements.dart' show |
ConstructorElement, |
@@ -13,6 +14,7 @@ import '../elements/elements.dart' show |
FunctionElement, |
VariableElement; |
import '../resolution/operators.dart'; |
+import '../tree/tree.dart' show DartString; |
import '../universe/universe.dart' show CallStructure; |
import 'values.dart'; |
@@ -43,6 +45,15 @@ enum ConstantExpressionKind { |
NAMED_REFERENCE, |
} |
+/// Environment used for evaluating constant expressions. |
+abstract class Environment { |
+ // TODO(johnniwinther): Replace this with [CoreTypes] and maybe [Backend]. |
+ Compiler get compiler; |
+ |
+ /// Read environments string passed in using the '-Dname=value' option. |
+ String readFromEnvironment(String name); |
+} |
+ |
/// The normalized arguments passed to a const constructor computed from the |
/// actual [arguments] and the [defaultValues] of the called construrctor. |
class Arguments { |
@@ -198,7 +209,7 @@ class RedirectingFactoryConstantConstructor implements ConstantConstructor { |
RedirectingFactoryConstantConstructor(this.constructorInvocation); |
ConstantConstructorKind get kind { |
- return ConstantConstructorKind.REDIRECTING_GENERATIVE; |
+ return ConstantConstructorKind.REDIRECTING_FACTORY; |
} |
InterfaceType computeInstanceType(InterfaceType newType) { |
@@ -250,6 +261,11 @@ abstract class ConstantExpression { |
/// Substitute free variables using arguments. |
ConstantExpression apply(Arguments arguments) => this; |
+ /// Compute the [ConstantValue] for this expression using the [environment] |
+ /// and the [constantSystem]. |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem); |
+ |
String getText() { |
ConstExpPrinter printer = new ConstExpPrinter(); |
accept(printer); |
@@ -293,6 +309,13 @@ class ErroneousConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ // TODO(johnniwinther): Use non-constant values for errors. |
+ return value; |
+ } |
+ |
+ @override |
int _computeHashCode() => 13; |
@override |
@@ -323,6 +346,12 @@ class BoolConstantExpression extends PrimitiveConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createBool(primitiveValue); |
+ } |
+ |
+ @override |
int _computeHashCode() => 13 * primitiveValue.hashCode; |
@override |
@@ -345,6 +374,12 @@ class IntConstantExpression extends PrimitiveConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createInt(primitiveValue); |
+ } |
+ |
+ @override |
int _computeHashCode() => 17 * primitiveValue.hashCode; |
@override |
@@ -367,6 +402,12 @@ class DoubleConstantExpression extends PrimitiveConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createDouble(primitiveValue); |
+ } |
+ |
+ @override |
int _computeHashCode() => 19 * primitiveValue.hashCode; |
@override |
@@ -389,6 +430,12 @@ class StringConstantExpression extends PrimitiveConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createString(new DartString.literal(primitiveValue)); |
+ } |
+ |
+ @override |
int _computeHashCode() => 23 * primitiveValue.hashCode; |
@override |
@@ -407,6 +454,12 @@ class NullConstantExpression extends PrimitiveConstantExpression { |
return visitor.visitNull(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createNull(); |
+ } |
+ |
get primitiveValue => null; |
@override |
@@ -431,11 +484,18 @@ class ListConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createList(type, |
+ values.map((v) => v.evaluate(environment, constantSystem)).toList()); |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new ListConstantExpression(null, type, |
values.map((v) => v.apply(arguments)).toList()); |
} |
+ @override |
int _computeHashCode() { |
int hashCode = 13 * type.hashCode + 17 * values.length; |
for (ConstantExpression value in values) { |
@@ -471,12 +531,21 @@ class MapConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createMap(environment.compiler, |
+ type, |
+ keys.map((k) => k.evaluate(environment, constantSystem)).toList(), |
+ values.map((v) => v.evaluate(environment, constantSystem)).toList()); |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new MapConstantExpression(null, type, |
keys.map((k) => k.apply(arguments)).toList(), |
values.map((v) => v.apply(arguments)).toList()); |
} |
+ @override |
int _computeHashCode() { |
int hashCode = 13 * type.hashCode + 17 * values.length; |
for (ConstantExpression value in values) { |
@@ -536,6 +605,19 @@ class ConstructedConstantExpression extends ConstantExpression { |
this.arguments.map((a) => a.apply(arguments)).toList()); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ Map<FieldElement, ConstantValue> fieldValues = |
+ <FieldElement, ConstantValue>{}; |
+ computeInstanceFields().forEach( |
+ (FieldElement field, ConstantExpression constant) { |
+ fieldValues[field] = constant.evaluate(environment, constantSystem); |
+ }); |
+ return new ConstructedConstantValue(computeInstanceType(), fieldValues); |
+ } |
+ |
+ @override |
int _computeHashCode() { |
int hashCode = |
13 * type.hashCode + |
@@ -578,6 +660,34 @@ class ConcatenateConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ DartString accumulator; |
+ for (ConstantExpression expression in expressions) { |
+ ConstantValue value = expression.evaluate(environment, constantSystem); |
+ DartString valueString; |
+ if (value.isNum || value.isBool) { |
+ PrimitiveConstantValue primitive = value; |
+ valueString = |
+ new DartString.literal(primitive.primitiveValue.toString()); |
+ } else if (value.isString) { |
+ PrimitiveConstantValue primitive = value; |
+ valueString = primitive.primitiveValue; |
+ } else { |
+ // TODO(johnniwinther): Specialize message to indicated that the problem |
+ // is not constness but the types of the const expressions. |
+ return new NonConstantValue(); |
+ } |
+ if (accumulator == null) { |
+ accumulator = valueString; |
+ } else { |
+ accumulator = new DartString.concat(accumulator, valueString); |
+ } |
+ } |
+ return constantSystem.createString(accumulator); |
+ } |
+ |
+ @override |
int _computeHashCode() { |
int hashCode = 17 * expressions.length; |
for (ConstantExpression value in expressions) { |
@@ -616,6 +726,13 @@ class SymbolConstantExpression extends ConstantExpression { |
bool _equals(SymbolConstantExpression other) { |
return name == other.name; |
} |
+ |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ // TODO(johnniwinther): Implement this. |
+ throw new UnsupportedError('SymbolConstantExpression.evaluate'); |
+ } |
} |
/// Type literal. |
@@ -635,6 +752,12 @@ class TypeConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.createType(environment.compiler, type); |
+ } |
+ |
+ @override |
int _computeHashCode() => 13 * type.hashCode; |
@override |
@@ -657,6 +780,12 @@ class VariableConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return element.constant.evaluate(environment, constantSystem); |
+ } |
+ |
+ @override |
int _computeHashCode() => 13 * element.hashCode; |
@override |
@@ -679,6 +808,12 @@ class FunctionConstantExpression extends ConstantExpression { |
} |
@override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return new FunctionConstantValue(element); |
+ } |
+ |
+ @override |
int _computeHashCode() => 13 * element.hashCode; |
@override |
@@ -704,6 +839,14 @@ class BinaryConstantExpression extends ConstantExpression { |
return visitor.visitBinary(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.lookupBinary(operator).fold( |
+ left.evaluate(environment, constantSystem), |
+ right.evaluate(environment, constantSystem)); |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new BinaryConstantExpression( |
value, |
@@ -765,6 +908,14 @@ class IdenticalConstantExpression extends ConstantExpression { |
return visitor.visitIdentical(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.identity.fold( |
+ left.evaluate(environment, constantSystem), |
+ right.evaluate(environment, constantSystem)); |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new IdenticalConstantExpression( |
value, |
@@ -803,6 +954,13 @@ class UnaryConstantExpression extends ConstantExpression { |
return visitor.visitUnary(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ return constantSystem.lookupUnary(operator).fold( |
+ expression.evaluate(environment, constantSystem)); |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new UnaryConstantExpression( |
value, |
@@ -872,6 +1030,24 @@ class ConditionalConstantExpression extends ConstantExpression { |
trueExp == other.trueExp && |
falseExp == other.falseExp; |
} |
+ |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ ConstantValue conditionValue = |
+ condition.evaluate(environment, constantSystem); |
+ ConstantValue trueValue = |
+ trueExp.evaluate(environment, constantSystem); |
+ ConstantValue falseValue = |
+ falseExp.evaluate(environment, constantSystem); |
+ if (conditionValue.isTrue) { |
+ return trueValue; |
+ } else if (conditionValue.isFalse) { |
+ return falseValue; |
+ } else { |
+ return new NonConstantValue(); |
+ } |
+ } |
} |
/// A reference to a position parameter. |
@@ -901,6 +1077,12 @@ class PositionalArgumentReference extends ConstantExpression { |
@override |
bool _equals(PositionalArgumentReference other) => index == other.index; |
+ |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ throw new UnsupportedError('PositionalArgumentReference.evaluate'); |
+ } |
} |
/// A reference to a named parameter. |
@@ -930,6 +1112,12 @@ class NamedArgumentReference extends ConstantExpression { |
@override |
bool _equals(NamedArgumentReference other) => name == other.name; |
+ |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ throw new UnsupportedError('NamedArgumentReference.evaluate'); |
+ } |
} |
abstract class FromEnvironmentConstantExpression extends ConstantExpression { |
@@ -970,6 +1158,19 @@ class BoolFromEnvironmentConstantExpression |
return visitor.visitBoolFromEnvironment(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ String text = environment.readFromEnvironment(name); |
+ if (text == 'true') { |
+ return constantSystem.createBool(true); |
+ } else if (text == 'false') { |
+ return constantSystem.createBool(false); |
+ } else { |
+ return defaultValue.evaluate(environment, constantSystem); |
+ } |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new BoolFromEnvironmentConstantExpression( |
null, name, defaultValue.apply(arguments)); |
@@ -994,6 +1195,21 @@ class IntFromEnvironmentConstantExpression |
return visitor.visitIntFromEnvironment(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ int value; |
+ String text = environment.readFromEnvironment(name); |
+ if (text != null) { |
+ value = int.parse(text, onError: (_) => null); |
+ } |
+ if (value == null) { |
+ return defaultValue.evaluate(environment, constantSystem); |
+ } else { |
+ return constantSystem.createInt(value); |
+ } |
+ } |
+ |
ConstantExpression apply(Arguments arguments) { |
return new IntFromEnvironmentConstantExpression( |
null, name, defaultValue.apply(arguments)); |
@@ -1018,6 +1234,16 @@ class StringFromEnvironmentConstantExpression |
return visitor.visitStringFromEnvironment(this, context); |
} |
+ @override |
+ ConstantValue evaluate(Environment environment, |
+ ConstantSystem constantSystem) { |
+ String text = environment.readFromEnvironment(name); |
+ if (text == null) { |
+ return defaultValue.evaluate(environment, constantSystem); |
+ } else { |
+ return constantSystem.createString(new DartString.literal(text)); |
+ } |
+ } |
ConstantExpression apply(Arguments arguments) { |
return new StringFromEnvironmentConstantExpression( |