mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 17:15:02 +00:00
Add StringLengthConstantExpression
... and make .fromEnvironment name a ConstantExpression. BUG= R=karlklose@google.com Review URL: https://codereview.chromium.org//1166723002
This commit is contained in:
parent
411246ccc7
commit
3250c8fd91
|
@ -535,7 +535,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|||
StringConstantValue stringConstantValue = left.value;
|
||||
DartString string = stringConstantValue.primitiveValue;
|
||||
IntConstantValue length = constantSystem.createInt(string.length);
|
||||
result = new VariableConstantExpression(length, element);
|
||||
result =
|
||||
new StringLengthConstantExpression(length, left.expression);
|
||||
}
|
||||
}
|
||||
// Fall through to error handling.
|
||||
|
@ -880,15 +881,20 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|||
AstConstant createEvaluatedConstant(ConstantValue value) {
|
||||
|
||||
ConstantExpression expression;
|
||||
ConstantExpression name = concreteArguments[0].expression;
|
||||
ConstantExpression defaultValue;
|
||||
if (concreteArguments.length > 1) {
|
||||
defaultValue = concreteArguments[1].expression;
|
||||
}
|
||||
if (constructor == compiler.intEnvironment) {
|
||||
expression = new IntFromEnvironmentConstantExpression(
|
||||
value, name, normalizedArguments[1].expression);
|
||||
value, name, defaultValue);
|
||||
} else if (constructor == compiler.boolEnvironment) {
|
||||
expression = new BoolFromEnvironmentConstantExpression(
|
||||
value, name, normalizedArguments[1].expression);
|
||||
value, name, defaultValue);
|
||||
} else if (constructor == compiler.stringEnvironment) {
|
||||
expression = new StringFromEnvironmentConstantExpression(
|
||||
value, name, normalizedArguments[1].expression);
|
||||
value, name, defaultValue);
|
||||
}
|
||||
return new AstConstant(context, node, expression);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ enum ConstantExpressionKind {
|
|||
NULL,
|
||||
STRING,
|
||||
STRING_FROM_ENVIRONMENT,
|
||||
STRING_LENGTH,
|
||||
SYMBOL,
|
||||
TYPE,
|
||||
UNARY,
|
||||
|
@ -1002,6 +1003,50 @@ class UnaryConstantExpression extends ConstantExpression {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
/// A string length constant expression like `a.length`.
|
||||
class StringLengthConstantExpression extends ConstantExpression {
|
||||
final ConstantValue value;
|
||||
final ConstantExpression expression;
|
||||
|
||||
StringLengthConstantExpression(this.value, this.expression);
|
||||
|
||||
ConstantExpressionKind get kind => ConstantExpressionKind.STRING_LENGTH;
|
||||
|
||||
accept(ConstantExpressionVisitor visitor, [context]) {
|
||||
return visitor.visitStringLength(this, context);
|
||||
}
|
||||
|
||||
@override
|
||||
ConstantValue evaluate(Environment environment,
|
||||
ConstantSystem constantSystem) {
|
||||
ConstantValue value = expression.evaluate(environment, constantSystem);
|
||||
if (value.isString) {
|
||||
StringConstantValue stringValue = value;
|
||||
return constantSystem.createInt(stringValue.primitiveValue.length);
|
||||
}
|
||||
return new NonConstantValue();
|
||||
}
|
||||
|
||||
ConstantExpression apply(NormalizedArguments arguments) {
|
||||
return new StringLengthConstantExpression(
|
||||
value,
|
||||
expression.apply(arguments));
|
||||
}
|
||||
|
||||
int get precedence => 15;
|
||||
|
||||
@override
|
||||
int _computeHashCode() {
|
||||
return 23 * expression.hashCode;
|
||||
}
|
||||
|
||||
@override
|
||||
bool _equals(StringLengthConstantExpression other) {
|
||||
return expression == other.expression;
|
||||
}
|
||||
}
|
||||
|
||||
/// A constant conditional expression like `a ? b : c`.
|
||||
class ConditionalConstantExpression extends ConstantExpression {
|
||||
final ConstantValue value;
|
||||
|
@ -1135,7 +1180,7 @@ class NamedArgumentReference extends ConstantExpression {
|
|||
|
||||
abstract class FromEnvironmentConstantExpression extends ConstantExpression {
|
||||
final ConstantValue value;
|
||||
final String name;
|
||||
final ConstantExpression name;
|
||||
final ConstantExpression defaultValue;
|
||||
|
||||
FromEnvironmentConstantExpression(this.value, this.name, this.defaultValue);
|
||||
|
@ -1159,7 +1204,7 @@ class BoolFromEnvironmentConstantExpression
|
|||
|
||||
BoolFromEnvironmentConstantExpression(
|
||||
ConstantValue value,
|
||||
String name,
|
||||
ConstantExpression name,
|
||||
ConstantExpression defaultValue)
|
||||
: super(value, name, defaultValue);
|
||||
|
||||
|
@ -1174,19 +1219,35 @@ class BoolFromEnvironmentConstantExpression
|
|||
@override
|
||||
ConstantValue evaluate(Environment environment,
|
||||
ConstantSystem constantSystem) {
|
||||
String text = environment.readFromEnvironment(name);
|
||||
ConstantValue nameConstantValue =
|
||||
name.evaluate(environment, constantSystem);
|
||||
ConstantValue defaultConstantValue;
|
||||
if (defaultValue != null) {
|
||||
defaultConstantValue =
|
||||
defaultValue.evaluate(environment, constantSystem);
|
||||
} else {
|
||||
defaultConstantValue = constantSystem.createBool(false);
|
||||
}
|
||||
if (!nameConstantValue.isString) {
|
||||
return new NonConstantValue();
|
||||
}
|
||||
StringConstantValue nameStringConstantValue = nameConstantValue;
|
||||
String text = environment.readFromEnvironment(
|
||||
nameStringConstantValue.primitiveValue.slowToString());
|
||||
if (text == 'true') {
|
||||
return constantSystem.createBool(true);
|
||||
} else if (text == 'false') {
|
||||
return constantSystem.createBool(false);
|
||||
} else {
|
||||
return defaultValue.evaluate(environment, constantSystem);
|
||||
return defaultConstantValue;
|
||||
}
|
||||
}
|
||||
|
||||
ConstantExpression apply(NormalizedArguments arguments) {
|
||||
return new BoolFromEnvironmentConstantExpression(
|
||||
null, name, defaultValue.apply(arguments));
|
||||
null,
|
||||
name.apply(arguments),
|
||||
defaultValue != null ? defaultValue.apply(arguments) : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,7 +1257,7 @@ class IntFromEnvironmentConstantExpression
|
|||
|
||||
IntFromEnvironmentConstantExpression(
|
||||
ConstantValue value,
|
||||
String name,
|
||||
ConstantExpression name,
|
||||
ConstantExpression defaultValue)
|
||||
: super(value, name, defaultValue);
|
||||
|
||||
|
@ -1211,13 +1272,27 @@ class IntFromEnvironmentConstantExpression
|
|||
@override
|
||||
ConstantValue evaluate(Environment environment,
|
||||
ConstantSystem constantSystem) {
|
||||
ConstantValue nameConstantValue =
|
||||
name.evaluate(environment, constantSystem);
|
||||
ConstantValue defaultConstantValue;
|
||||
if (defaultValue != null) {
|
||||
defaultConstantValue =
|
||||
defaultValue.evaluate(environment, constantSystem);
|
||||
} else {
|
||||
defaultConstantValue = constantSystem.createNull();
|
||||
}
|
||||
if (!nameConstantValue.isString) {
|
||||
return new NonConstantValue();
|
||||
}
|
||||
StringConstantValue nameStringConstantValue = nameConstantValue;
|
||||
String text = environment.readFromEnvironment(
|
||||
nameStringConstantValue.primitiveValue.slowToString());
|
||||
int value;
|
||||
String text = environment.readFromEnvironment(name);
|
||||
if (text != null) {
|
||||
value = int.parse(text, onError: (_) => null);
|
||||
}
|
||||
if (value == null) {
|
||||
return defaultValue.evaluate(environment, constantSystem);
|
||||
return defaultConstantValue;
|
||||
} else {
|
||||
return constantSystem.createInt(value);
|
||||
}
|
||||
|
@ -1225,7 +1300,9 @@ class IntFromEnvironmentConstantExpression
|
|||
|
||||
ConstantExpression apply(NormalizedArguments arguments) {
|
||||
return new IntFromEnvironmentConstantExpression(
|
||||
null, name, defaultValue.apply(arguments));
|
||||
null,
|
||||
name.apply(arguments),
|
||||
defaultValue != null ? defaultValue.apply(arguments) : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1235,7 +1312,7 @@ class StringFromEnvironmentConstantExpression
|
|||
|
||||
StringFromEnvironmentConstantExpression(
|
||||
ConstantValue value,
|
||||
String name,
|
||||
ConstantExpression name,
|
||||
ConstantExpression defaultValue)
|
||||
: super(value, name, defaultValue);
|
||||
|
||||
|
@ -1250,9 +1327,23 @@ class StringFromEnvironmentConstantExpression
|
|||
@override
|
||||
ConstantValue evaluate(Environment environment,
|
||||
ConstantSystem constantSystem) {
|
||||
String text = environment.readFromEnvironment(name);
|
||||
ConstantValue nameConstantValue =
|
||||
name.evaluate(environment, constantSystem);
|
||||
ConstantValue defaultConstantValue;
|
||||
if (defaultValue != null) {
|
||||
defaultConstantValue =
|
||||
defaultValue.evaluate(environment, constantSystem);
|
||||
} else {
|
||||
defaultConstantValue = constantSystem.createNull();
|
||||
}
|
||||
if (!nameConstantValue.isString) {
|
||||
return new NonConstantValue();
|
||||
}
|
||||
StringConstantValue nameStringConstantValue = nameConstantValue;
|
||||
String text = environment.readFromEnvironment(
|
||||
nameStringConstantValue.primitiveValue.slowToString());
|
||||
if (text == null) {
|
||||
return defaultValue.evaluate(environment, constantSystem);
|
||||
return defaultConstantValue;
|
||||
} else {
|
||||
return constantSystem.createString(new DartString.literal(text));
|
||||
}
|
||||
|
@ -1260,7 +1351,9 @@ class StringFromEnvironmentConstantExpression
|
|||
|
||||
ConstantExpression apply(NormalizedArguments arguments) {
|
||||
return new StringFromEnvironmentConstantExpression(
|
||||
null, name, defaultValue.apply(arguments));
|
||||
null,
|
||||
name.apply(arguments),
|
||||
defaultValue != null ? defaultValue.apply(arguments) : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,6 +1379,11 @@ class DeferredConstantExpression extends ConstantExpression {
|
|||
return 13 * expression.hashCode;
|
||||
}
|
||||
|
||||
ConstantExpression apply(NormalizedArguments arguments) {
|
||||
return new DeferredConstantExpression(
|
||||
value, expression.apply(arguments), prefix);
|
||||
}
|
||||
|
||||
@override
|
||||
bool _equals(DeferredConstantExpression other) {
|
||||
return expression == other.expression;
|
||||
|
@ -1320,6 +1418,7 @@ abstract class ConstantExpressionVisitor<R, A> {
|
|||
R visitBinary(BinaryConstantExpression exp, A context);
|
||||
R visitIdentical(IdenticalConstantExpression exp, A context);
|
||||
R visitUnary(UnaryConstantExpression exp, A context);
|
||||
R visitStringLength(StringLengthConstantExpression exp, A context);
|
||||
R visitConditional(ConditionalConstantExpression exp, A context);
|
||||
R visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
|
||||
A context);
|
||||
|
@ -1346,8 +1445,8 @@ class ConstExpPrinter extends ConstantExpressionVisitor {
|
|||
final StringBuffer sb = new StringBuffer();
|
||||
|
||||
void write(ConstantExpression parent,
|
||||
ConstantExpression child,
|
||||
{bool leftAssociative: true}) {
|
||||
ConstantExpression child,
|
||||
{bool leftAssociative: true}) {
|
||||
if (child.precedence < parent.precedence ||
|
||||
!leftAssociative && child.precedence == parent.precedence) {
|
||||
sb.write('(');
|
||||
|
@ -1443,11 +1542,11 @@ class ConstExpPrinter extends ConstantExpressionVisitor {
|
|||
void visitConstructed(ConstructedConstantExpression exp, [_]) {
|
||||
sb.write('const ');
|
||||
sb.write(exp.target.enclosingClass.name);
|
||||
writeTypeArguments(exp.type);
|
||||
if (exp.target.name != '') {
|
||||
sb.write('.');
|
||||
sb.write(exp.target.name);
|
||||
}
|
||||
writeTypeArguments(exp.type);
|
||||
sb.write('(');
|
||||
bool needsComma = false;
|
||||
|
||||
|
@ -1529,6 +1628,12 @@ class ConstExpPrinter extends ConstantExpressionVisitor {
|
|||
write(exp, exp.expression);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitStringLength(StringLengthConstantExpression exp, [_]) {
|
||||
write(exp, exp.expression, leftAssociative: false);
|
||||
sb.write('.length');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConditional(ConditionalConstantExpression exp, [_]) {
|
||||
write(exp, exp.condition, leftAssociative: false);
|
||||
|
@ -1560,23 +1665,35 @@ class ConstExpPrinter extends ConstantExpressionVisitor {
|
|||
@override
|
||||
void visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
|
||||
[_]) {
|
||||
sb.write('const bool.fromEnvironment("${exp.name}", defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
sb.write('const bool.fromEnvironment(');
|
||||
visit(exp.name);
|
||||
if (exp.defaultValue != null) {
|
||||
sb.write(', defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
}
|
||||
sb.write(')');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp, [_]) {
|
||||
sb.write('const int.fromEnvironment("${exp.name}", defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
sb.write('const int.fromEnvironment(');
|
||||
visit(exp.name);
|
||||
if (exp.defaultValue != null) {
|
||||
sb.write(', defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
}
|
||||
sb.write(')');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
|
||||
[_]) {
|
||||
sb.write('const String.fromEnvironment("${exp.name}", defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
sb.write('const String.fromEnvironment(');
|
||||
visit(exp.name);
|
||||
if (exp.defaultValue != null) {
|
||||
sb.write(', defaultValue: ');
|
||||
visit(exp.defaultValue);
|
||||
}
|
||||
sb.write(')');
|
||||
}
|
||||
|
||||
|
|
|
@ -228,6 +228,12 @@ class AnnotationCreator
|
|||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Annotation visitStringLength(StringLengthConstantExpression exp,
|
||||
AnnotationInfo context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Annotation visitDeferred(DeferredConstantExpression exp,
|
||||
AnnotationInfo context) {
|
||||
|
|
|
@ -38,7 +38,8 @@ class MemoryEnvironment implements Environment {
|
|||
final Compiler compiler;
|
||||
final Map<String, String> env;
|
||||
|
||||
MemoryEnvironment(this.compiler, [this.env = const <String, String>{}]);
|
||||
MemoryEnvironment(this.compiler,
|
||||
[this.env = const <String, String>{}]);
|
||||
|
||||
@override
|
||||
String readFromEnvironment(String name) => env[name];
|
||||
|
@ -54,6 +55,7 @@ const List<TestData> DATA = const [
|
|||
const ConstantData('"foo"', const { const {} : 'StringConstant("foo")' }),
|
||||
const ConstantData('1 + 2', const { const {} : 'IntConstant(3)' }),
|
||||
const ConstantData('-(1)', const { const {} : 'IntConstant(-1)' }),
|
||||
const ConstantData('"foo".length', const { const {} : 'IntConstant(3)' }),
|
||||
const ConstantData('identical(0, 1)',
|
||||
const { const {} : 'BoolConstant(false)' }),
|
||||
const ConstantData('"a" "b"', const { const {} : 'StringConstant("ab")' }),
|
||||
|
@ -144,9 +146,7 @@ class A<T> implements B {
|
|||
}
|
||||
class B<S> implements C {
|
||||
const factory B({field1}) = A<B<S>>;
|
||||
// TODO(johnniwinther): Enable this when the constructor evaluator doesn't
|
||||
// crash:
|
||||
/*const factory B.named() = A<S>;*/
|
||||
const factory B.named() = A<S>;
|
||||
}
|
||||
class C<U> {
|
||||
const factory C({field1}) = A<B<double>>;
|
||||
|
@ -170,11 +170,9 @@ class C<U> {
|
|||
const ConstantData('const C<int>(field1: 87)',
|
||||
const { const {} :
|
||||
'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))' }),
|
||||
// TODO(johnniwinther): Enable this when the constructor evaluator doesn't
|
||||
// crash:
|
||||
/*const ConstantData('const B<int>.named()',
|
||||
const ConstantData('const B<int>.named()',
|
||||
const { const {} :
|
||||
'ConstructedConstant(A<int>(field1=IntConstant(42)))' }),*/
|
||||
'ConstructedConstant(A<int>(field1=IntConstant(42)))' }),
|
||||
]),
|
||||
const TestData('''
|
||||
const c = const int.fromEnvironment("foo", defaultValue: 5);
|
||||
|
|
|
@ -52,6 +52,7 @@ const List<TestData> DATA = const [
|
|||
const ConstantData('"foo"', ConstantExpressionKind.STRING),
|
||||
const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
|
||||
const ConstantData('-(1)', ConstantExpressionKind.UNARY, text: '-1'),
|
||||
const ConstantData('"foo".length', ConstantExpressionKind.STRING_LENGTH),
|
||||
const ConstantData('identical(0, 1)', ConstantExpressionKind.IDENTICAL),
|
||||
const ConstantData('"a" "b"', ConstantExpressionKind.CONCATENATE,
|
||||
text: '"ab"'),
|
||||
|
@ -148,7 +149,7 @@ class B<S> implements C {
|
|||
const factory B({field1}) = A<B<S>>;
|
||||
// TODO(johnniwinther): Enable this when the constructor evaluator doesn't
|
||||
// crash:
|
||||
/*const factory B.named() = A<S>;*/
|
||||
const factory B.named() = A<S>;
|
||||
}
|
||||
class C<U> {
|
||||
const factory C({field1}) = A<B<double>>;
|
||||
|
@ -183,14 +184,12 @@ class C<U> {
|
|||
fields: const {
|
||||
'field(A#field1)': '87',
|
||||
}),
|
||||
// TODO(johnniwinther): Enable this when the constructor evaluator doesn't
|
||||
// crash:
|
||||
/*const ConstantData('const B<int>.named()',
|
||||
const ConstantData('const B<int>.named()',
|
||||
ConstantExpressionKind.CONSTRUCTED,
|
||||
type: 'A<int>',
|
||||
fields: const {
|
||||
'field(A#field1)': '42',
|
||||
}),*/
|
||||
}),
|
||||
]),
|
||||
];
|
||||
|
||||
|
|
|
@ -3093,7 +3093,7 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
|||
''',
|
||||
const Visit(VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
|
||||
constant:
|
||||
'const bool.fromEnvironment("foo", defaultValue: false)')),
|
||||
'const bool.fromEnvironment("foo")')),
|
||||
const Test(
|
||||
'''
|
||||
m() => const bool.fromEnvironment('foo', defaultValue: true);
|
||||
|
@ -3105,14 +3105,14 @@ const Map<String, List<Test>> SEND_TESTS = const {
|
|||
m() => const int.fromEnvironment('foo');
|
||||
''',
|
||||
const Visit(VisitKind.VISIT_INT_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
|
||||
constant: 'const int.fromEnvironment("foo", defaultValue: null)')),
|
||||
constant: 'const int.fromEnvironment("foo")')),
|
||||
const Test(
|
||||
'''
|
||||
m() => const String.fromEnvironment('foo');
|
||||
''',
|
||||
const Visit(VisitKind.VISIT_STRING_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
|
||||
constant:
|
||||
'const String.fromEnvironment("foo", defaultValue: null)')),
|
||||
'const String.fromEnvironment("foo")')),
|
||||
const Test(
|
||||
'''
|
||||
class Class {
|
||||
|
|
Loading…
Reference in a new issue