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

Side by Side Diff: pkg/compiler/lib/src/constants/expressions.dart

Issue 1115183002: Add ConstantConstructor to ConstantExpression system. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add test. Created 5 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.constants.expressions; 5 library dart2js.constants.expressions;
6 6
7 import '../dart2jslib.dart' show assertDebugMode; 7 import '../dart2jslib.dart' show assertDebugMode;
8 import '../dart_types.dart'; 8 import '../dart_types.dart';
9 import '../elements/elements.dart' show 9 import '../elements/elements.dart' show
10 ConstructorElement, 10 ConstructorElement,
11 Element, 11 Element,
12 FieldElement,
12 FunctionElement, 13 FunctionElement,
13 VariableElement; 14 VariableElement;
14 import '../resolution/operators.dart'; 15 import '../resolution/operators.dart';
15 import '../universe/universe.dart' show CallStructure; 16 import '../universe/universe.dart' show CallStructure;
16 import 'values.dart'; 17 import 'values.dart';
17 18
18 enum ConstantExpressionKind { 19 enum ConstantExpressionKind {
19 BINARY, 20 BINARY,
20 BOOL, 21 BOOL,
22 BOOL_FROM_ENVIRONMENT,
21 CONCATENATE, 23 CONCATENATE,
22 CONDITIONAL, 24 CONDITIONAL,
23 CONSTRUCTED, 25 CONSTRUCTED,
24 DOUBLE, 26 DOUBLE,
25 ERRONEOUS, 27 ERRONEOUS,
26 FUNCTION, 28 FUNCTION,
27 IDENTICAL, 29 IDENTICAL,
28 INT, 30 INT,
31 INT_FROM_ENVIRONMENT,
29 LIST, 32 LIST,
30 MAP, 33 MAP,
31 NULL, 34 NULL,
32 STRING, 35 STRING,
36 STRING_FROM_ENVIRONMENT,
33 SYMBOL, 37 SYMBOL,
34 TYPE, 38 TYPE,
35 UNARY, 39 UNARY,
36 VARIABLE, 40 VARIABLE,
41
42 POSITIONAL_REFERENCE,
43 NAMED_REFERENCE,
44 }
45
46 /// The normalized arguments passed to a const constructor computed from the
47 /// actual [arguments] and the [defaultValues] of the called construrctor.
48 class Arguments {
karlklose 2015/05/11 10:23:18 This class should have a more specific name like,
Johnni Winther 2015/05/11 12:24:57 NormalizedArguments it is.
49 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues;
karlklose 2015/05/11 10:23:18 In the emitter code modell we used 'var /*Map|List
Johnni Winther 2015/05/11 12:24:57 A list is annoying is the indices are absolute and
50 final CallStructure callStructure;
51 final List<ConstantExpression> arguments;
52
53 Arguments(this.defaultValues, this.callStructure, this.arguments);
54
55 /// Returns the normalized named argument [name].
56 ConstantExpression getNamedArgument(String name) {
57 int index = callStructure.namedArguments.indexOf(name);
58 if (index == -1) {
59 // The named argument is not provided.
60 return defaultValues[name];
61 }
62 return arguments[index + callStructure.positionalArgumentCount];
63 }
64
65 /// Returns the normalized [index]th positional argument.
66 ConstantExpression getPositionalArgument(int index) {
67 if (index >= callStructure.positionalArgumentCount) {
68 // The positional argument is not provided.
69 return defaultValues[index];
70 }
71 return arguments[index];
72 }
73 }
74
75 enum ConstantConstructorKind {
76 GENERATIVE,
77 REDIRECTING_GENERATIVE,
78 REDIRECTING_FACTORY,
79 }
80
81 /// Definition of a constant constructor.
82 abstract class ConstantConstructor {
83 ConstantConstructorKind get kind;
84
85 /// Computes the type of the instance created in a const constructor
86 /// invocation with type [newType].
87 InterfaceType computeInstanceType(InterfaceType newType);
88
89 /// Computes the constant expressions of the fields of the created instance
90 /// in a const constructor invocation with [arguments].
91 Map<FieldElement, ConstantExpression> computeInstanceFields(
92 List<ConstantExpression> arguments,
93 CallStructure callStructure);
94 }
95
96 /// A generative constant constructor.
97 class GenerativeConstantConstructor implements ConstantConstructor{
98 final InterfaceType type;
99 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues;
100 final Map<FieldElement, ConstantExpression> fieldMap;
101 final ConstructedConstantExpression constructorInvocation;
karlklose 2015/05/11 10:23:19 'constructorInvocation' -> 'superConstructor[Invoc
Johnni Winther 2015/05/11 12:24:57 Done.
102
103 GenerativeConstantConstructor(
104 this.type,
105 this.defaultValues,
106 this.fieldMap,
107 this.constructorInvocation);
108
109 ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE;
110
111 InterfaceType computeInstanceType(InterfaceType newType) {
112 return type.substByContext(newType);
113 }
114
115 Map<FieldElement, ConstantExpression> computeInstanceFields(
116 List<ConstantExpression> arguments,
117 CallStructure callStructure) {
118 Arguments args = new Arguments(defaultValues, callStructure, arguments);
karlklose 2015/05/11 10:23:19 Lines 118-127 could be shared with ll. 171-178 in
Johnni Winther 2015/05/11 12:24:57 Done.
119 Map<FieldElement, ConstantExpression> appliedFieldMap =
120 <FieldElement, ConstantExpression>{};
121 if (constructorInvocation != null) {
122 Map<FieldElement, ConstantExpression> superFieldMap =
123 constructorInvocation.computeInstanceFields();
124 superFieldMap.forEach((FieldElement field, ConstantExpression constant) {
125 appliedFieldMap[field] = constant.apply(args);
126 });
127 }
128 fieldMap.forEach((FieldElement field, ConstantExpression constant) {
129 appliedFieldMap[field] = constant.apply(args);
130 });
131 return appliedFieldMap;
132 }
133
134 String toString() {
135 StringBuffer sb = new StringBuffer();
136 sb.write("{'type': $type");
karlklose 2015/05/11 10:23:19 Do we have a JSON library that could do this conve
Johnni Winther 2015/05/11 12:24:57 JSON isn't imported, just wanted it readable.
137 defaultValues.forEach((key, ConstantExpression expression) {
138 sb.write(",\n 'default:${key}': ${expression.getText()}");
139 });
140 fieldMap.forEach((FieldElement field, ConstantExpression expression) {
141 sb.write(",\n 'field:${field}': ${expression.getText()}");
142 });
143 if (constructorInvocation != null) {
144 sb.write(",\n 'constructor: ${constructorInvocation.getText()}");
145 }
146 sb.write("}");
147 return sb.toString();
148 }
149 }
150
151 /// A redirecting generative constant constructor.
152 class RedirectingGenerativeConstantConstructor implements ConstantConstructor {
153 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues;
154 final ConstructedConstantExpression constructorInvocation;
155
156 RedirectingGenerativeConstantConstructor(
157 this.defaultValues,
158 this.constructorInvocation);
159
160 ConstantConstructorKind get kind {
161 return ConstantConstructorKind.REDIRECTING_GENERATIVE;
162 }
163
164 InterfaceType computeInstanceType(InterfaceType newType) {
165 return constructorInvocation.computeInstanceType().substByContext(newType);
166 }
167
168 Map<FieldElement, ConstantExpression> computeInstanceFields(
169 List<ConstantExpression> arguments,
170 CallStructure callStructure) {
171 Arguments args = new Arguments(defaultValues, callStructure, arguments);
172 Map<FieldElement, ConstantExpression> appliedFieldMap =
173 <FieldElement, ConstantExpression>{};
174 Map<FieldElement, ConstantExpression> fieldMap =
175 constructorInvocation.computeInstanceFields();
176 fieldMap.forEach((FieldElement field, ConstantExpression constant) {
177 appliedFieldMap[field] = constant.apply(args);
178 });
179 return appliedFieldMap;
180 }
181
182 String toString() {
183 StringBuffer sb = new StringBuffer();
184 sb.write("{'type': ${constructorInvocation.type}");
185 defaultValues.forEach((key, ConstantExpression expression) {
186 sb.write(",\n 'default:${key}': ${expression.getText()}");
187 });
188 sb.write(",\n 'constructor': ${constructorInvocation.getText()}");
189 sb.write("}");
190 return sb.toString();
191 }
192 }
193
194 /// A redirecting factory constant constructor.
195 class RedirectingFactoryConstantConstructor implements ConstantConstructor {
196 final ConstructedConstantExpression constructorInvocation;
karlklose 2015/05/11 10:23:19 'targetConstructorInvocation'?
Johnni Winther 2015/05/11 12:24:57 Done.
197
198 RedirectingFactoryConstantConstructor(this.constructorInvocation);
199
200 ConstantConstructorKind get kind {
201 return ConstantConstructorKind.REDIRECTING_FACTORY;
202 }
203
204 InterfaceType computeInstanceType(InterfaceType newType) {
205 return constructorInvocation.computeInstanceType().substByContext(newType);
206 }
207
208 Map<FieldElement, ConstantExpression> computeInstanceFields(
209 List<ConstantExpression> arguments,
210 CallStructure callStructure) {
211 ConstantConstructor constantConstructor =
212 constructorInvocation.target.constantConstructor;
213 return constantConstructor.computeInstanceFields(arguments, callStructure);
214 }
215
216 String toString() {
217 StringBuffer sb = new StringBuffer();
218 sb.write("{");
219 sb.write("'constructor': ${constructorInvocation.getText()}");
220 sb.write("}");
221 return sb.toString();
222 }
37 } 223 }
38 224
39 /// An expression that is a compile-time constant. 225 /// An expression that is a compile-time constant.
40 /// 226 ///
41 /// Whereas [ConstantValue] represent a compile-time value, a 227 /// Whereas [ConstantValue] represent a compile-time value, a
42 /// [ConstantExpression] represents an expression for creating a constant. 228 /// [ConstantExpression] represents an expression for creating a constant.
43 /// 229 ///
44 /// There is no one-to-one mapping between [ConstantExpression] and 230 /// There is no one-to-one mapping between [ConstantExpression] and
45 /// [ConstantValue], because different expressions can denote the same constant. 231 /// [ConstantValue], because different expressions can denote the same constant.
46 /// For instance, multiple `const` constructors may be used to create the same 232 /// For instance, multiple `const` constructors may be used to create the same
47 /// object, and different `const` variables may hold the same value. 233 /// object, and different `const` variables may hold the same value.
48 abstract class ConstantExpression { 234 abstract class ConstantExpression {
49 int _hashCode; 235 int _hashCode;
50 236
51 ConstantExpressionKind get kind; 237 ConstantExpressionKind get kind;
52 238
53 /// Returns the value of this constant expression. 239 /// Returns the value of this constant expression.
240 // TODO(johnniwinther): Replace this with an evaluation method that takes
241 // a constant system and an environment.
54 ConstantValue get value; 242 ConstantValue get value;
55 243
56 // TODO(johnniwinther): Unify precedence handled between constants, front-end 244 // TODO(johnniwinther): Unify precedence handled between constants, front-end
57 // and back-end. 245 // and back-end.
58 int get precedence => 16; 246 int get precedence => 16;
59 247
60 accept(ConstantExpressionVisitor visitor, [context]); 248 accept(ConstantExpressionVisitor visitor, [context]);
61 249
250 /// Substitute free variables using arguments.
251 ConstantExpression apply(Arguments arguments) => this;
252
62 String getText() { 253 String getText() {
63 ConstExpPrinter printer = new ConstExpPrinter(); 254 ConstExpPrinter printer = new ConstExpPrinter();
64 accept(printer); 255 accept(printer);
65 return printer.toString(); 256 return printer.toString();
66 } 257 }
67 258
68 int _computeHashCode(); 259 int _computeHashCode();
69 260
70 int get hashCode { 261 int get hashCode {
71 if (_hashCode == null) { 262 if (_hashCode == null) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 300 }
110 301
111 /// A boolean, int, double, string, or null constant. 302 /// A boolean, int, double, string, or null constant.
112 abstract class PrimitiveConstantExpression extends ConstantExpression { 303 abstract class PrimitiveConstantExpression extends ConstantExpression {
113 final PrimitiveConstantValue value; 304 final PrimitiveConstantValue value;
114 305
115 PrimitiveConstantExpression(this.value); 306 PrimitiveConstantExpression(this.value);
116 307
117 /// The primitive value of this contant expression. 308 /// The primitive value of this contant expression.
118 get primitiveValue; 309 get primitiveValue;
119
120 accept(ConstantExpressionVisitor visitor, [context]) {
121 return visitor.visitPrimitive(this, context);
122 }
123 } 310 }
124 311
125 /// Boolean literal constant. 312 /// Boolean literal constant.
126 class BoolConstantExpression extends PrimitiveConstantExpression { 313 class BoolConstantExpression extends PrimitiveConstantExpression {
127 final bool primitiveValue; 314 final bool primitiveValue;
128 315
129 BoolConstantExpression(this.primitiveValue, 316 BoolConstantExpression(this.primitiveValue,
130 PrimitiveConstantValue value) : super(value); 317 PrimitiveConstantValue value) : super(value);
131 318
132 ConstantExpressionKind get kind => ConstantExpressionKind.BOOL; 319 ConstantExpressionKind get kind => ConstantExpressionKind.BOOL;
133 320
321 accept(ConstantExpressionVisitor visitor, [context]) {
322 return visitor.visitBool(this, context);
323 }
324
134 @override 325 @override
135 int _computeHashCode() => 13 * primitiveValue.hashCode; 326 int _computeHashCode() => 13 * primitiveValue.hashCode;
136 327
137 @override 328 @override
138 bool _equals(BoolConstantExpression other) { 329 bool _equals(BoolConstantExpression other) {
139 return primitiveValue == other.primitiveValue; 330 return primitiveValue == other.primitiveValue;
140 } 331 }
141 } 332 }
142 333
143 /// Integer literal constant. 334 /// Integer literal constant.
144 class IntConstantExpression extends PrimitiveConstantExpression { 335 class IntConstantExpression extends PrimitiveConstantExpression {
145 final int primitiveValue; 336 final int primitiveValue;
146 337
147 IntConstantExpression(this.primitiveValue, 338 IntConstantExpression(this.primitiveValue,
148 PrimitiveConstantValue value) : super(value); 339 PrimitiveConstantValue value) : super(value);
149 340
150 ConstantExpressionKind get kind => ConstantExpressionKind.INT; 341 ConstantExpressionKind get kind => ConstantExpressionKind.INT;
151 342
343 accept(ConstantExpressionVisitor visitor, [context]) {
344 return visitor.visitInt(this, context);
345 }
346
152 @override 347 @override
153 int _computeHashCode() => 17 * primitiveValue.hashCode; 348 int _computeHashCode() => 17 * primitiveValue.hashCode;
154 349
155 @override 350 @override
156 bool _equals(IntConstantExpression other) { 351 bool _equals(IntConstantExpression other) {
157 return primitiveValue == other.primitiveValue; 352 return primitiveValue == other.primitiveValue;
158 } 353 }
159 } 354 }
160 355
161 /// Double literal constant. 356 /// Double literal constant.
162 class DoubleConstantExpression extends PrimitiveConstantExpression { 357 class DoubleConstantExpression extends PrimitiveConstantExpression {
163 final double primitiveValue; 358 final double primitiveValue;
164 359
165 DoubleConstantExpression(this.primitiveValue, 360 DoubleConstantExpression(this.primitiveValue,
166 PrimitiveConstantValue value) : super(value); 361 PrimitiveConstantValue value) : super(value);
167 362
168 ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE; 363 ConstantExpressionKind get kind => ConstantExpressionKind.DOUBLE;
169 364
365 accept(ConstantExpressionVisitor visitor, [context]) {
366 return visitor.visitDouble(this, context);
367 }
368
170 @override 369 @override
171 int _computeHashCode() => 19 * primitiveValue.hashCode; 370 int _computeHashCode() => 19 * primitiveValue.hashCode;
172 371
173 @override 372 @override
174 bool _equals(DoubleConstantExpression other) { 373 bool _equals(DoubleConstantExpression other) {
175 return primitiveValue == other.primitiveValue; 374 return primitiveValue == other.primitiveValue;
176 } 375 }
177 } 376 }
178 377
179 /// String literal constant. 378 /// String literal constant.
180 class StringConstantExpression extends PrimitiveConstantExpression { 379 class StringConstantExpression extends PrimitiveConstantExpression {
181 final String primitiveValue; 380 final String primitiveValue;
182 381
183 StringConstantExpression(this.primitiveValue, 382 StringConstantExpression(this.primitiveValue,
184 PrimitiveConstantValue value) : super(value); 383 PrimitiveConstantValue value) : super(value);
185 384
186 ConstantExpressionKind get kind => ConstantExpressionKind.STRING; 385 ConstantExpressionKind get kind => ConstantExpressionKind.STRING;
187 386
387 accept(ConstantExpressionVisitor visitor, [context]) {
388 return visitor.visitString(this, context);
389 }
390
188 @override 391 @override
189 int _computeHashCode() => 23 * primitiveValue.hashCode; 392 int _computeHashCode() => 23 * primitiveValue.hashCode;
190 393
191 @override 394 @override
192 bool _equals(StringConstantExpression other) { 395 bool _equals(StringConstantExpression other) {
193 return primitiveValue == other.primitiveValue; 396 return primitiveValue == other.primitiveValue;
194 } 397 }
195 } 398 }
196 399
197 /// Null literal constant. 400 /// Null literal constant.
198 class NullConstantExpression extends PrimitiveConstantExpression { 401 class NullConstantExpression extends PrimitiveConstantExpression {
199 NullConstantExpression(PrimitiveConstantValue value) : super(value); 402 NullConstantExpression(PrimitiveConstantValue value) : super(value);
200 403
201 ConstantExpressionKind get kind => ConstantExpressionKind.NULL; 404 ConstantExpressionKind get kind => ConstantExpressionKind.NULL;
202 405
406 accept(ConstantExpressionVisitor visitor, [context]) {
407 return visitor.visitNull(this, context);
408 }
409
203 get primitiveValue => null; 410 get primitiveValue => null;
204 411
205 @override 412 @override
206 int _computeHashCode() => 29; 413 int _computeHashCode() => 29;
207 414
208 @override 415 @override
209 bool _equals(NullConstantExpression other) => true; 416 bool _equals(NullConstantExpression other) => true;
210 } 417 }
211 418
212 /// Literal list constant. 419 /// Literal list constant.
213 class ListConstantExpression extends ConstantExpression { 420 class ListConstantExpression extends ConstantExpression {
214 final ListConstantValue value; 421 final ListConstantValue value;
215 final InterfaceType type; 422 final InterfaceType type;
216 final List<ConstantExpression> values; 423 final List<ConstantExpression> values;
217 424
218 ListConstantExpression(this.value, this.type, this.values); 425 ListConstantExpression(this.value, this.type, this.values);
219 426
220 ConstantExpressionKind get kind => ConstantExpressionKind.LIST; 427 ConstantExpressionKind get kind => ConstantExpressionKind.LIST;
221 428
222 accept(ConstantExpressionVisitor visitor, [context]) { 429 accept(ConstantExpressionVisitor visitor, [context]) {
223 return visitor.visitList(this, context); 430 return visitor.visitList(this, context);
224 } 431 }
225 432
226 @override 433 @override
434 ConstantExpression apply(Arguments arguments) {
435 return new ListConstantExpression(null, type,
436 values.map((v) => v.apply(arguments)).toList());
437 }
438
227 int _computeHashCode() { 439 int _computeHashCode() {
228 int hashCode = 13 * type.hashCode + 17 * values.length; 440 int hashCode = 13 * type.hashCode + 17 * values.length;
229 for (ConstantExpression value in values) { 441 for (ConstantExpression value in values) {
230 hashCode ^= 19 * value.hashCode; 442 hashCode ^= 19 * value.hashCode;
231 } 443 }
232 return hashCode; 444 return hashCode;
233 } 445 }
234 446
235 @override 447 @override
236 bool _equals(ListConstantExpression other) { 448 bool _equals(ListConstantExpression other) {
(...skipping 15 matching lines...) Expand all
252 464
253 MapConstantExpression(this.value, this.type, this.keys, this.values); 465 MapConstantExpression(this.value, this.type, this.keys, this.values);
254 466
255 ConstantExpressionKind get kind => ConstantExpressionKind.MAP; 467 ConstantExpressionKind get kind => ConstantExpressionKind.MAP;
256 468
257 accept(ConstantExpressionVisitor visitor, [context]) { 469 accept(ConstantExpressionVisitor visitor, [context]) {
258 return visitor.visitMap(this, context); 470 return visitor.visitMap(this, context);
259 } 471 }
260 472
261 @override 473 @override
474 ConstantExpression apply(Arguments arguments) {
475 return new MapConstantExpression(null, type,
476 keys.map((k) => k.apply(arguments)).toList(),
477 values.map((v) => v.apply(arguments)).toList());
478 }
479
262 int _computeHashCode() { 480 int _computeHashCode() {
263 int hashCode = 13 * type.hashCode + 17 * values.length; 481 int hashCode = 13 * type.hashCode + 17 * values.length;
264 for (ConstantExpression value in values) { 482 for (ConstantExpression value in values) {
265 hashCode ^= 19 * value.hashCode; 483 hashCode ^= 19 * value.hashCode;
266 } 484 }
267 return hashCode; 485 return hashCode;
268 } 486 }
269 487
270 @override 488 @override
271 bool _equals(MapConstantExpression other) { 489 bool _equals(MapConstantExpression other) {
(...skipping 15 matching lines...) Expand all
287 final CallStructure callStructure; 505 final CallStructure callStructure;
288 final List<ConstantExpression> arguments; 506 final List<ConstantExpression> arguments;
289 507
290 ConstructedConstantExpression( 508 ConstructedConstantExpression(
291 this.value, 509 this.value,
292 this.type, 510 this.type,
293 this.target, 511 this.target,
294 this.callStructure, 512 this.callStructure,
295 this.arguments) { 513 this.arguments) {
296 assert(type.element == target.enclosingClass); 514 assert(type.element == target.enclosingClass);
515 assert(!arguments.contains(null));
297 } 516 }
298 517
299 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED; 518 ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
300 519
301 accept(ConstantExpressionVisitor visitor, [context]) { 520 accept(ConstantExpressionVisitor visitor, [context]) {
302 return visitor.visitConstructed(this, context); 521 return visitor.visitConstructed(this, context);
303 } 522 }
304 523
305 @override 524 Map<FieldElement, ConstantExpression> computeInstanceFields() {
karlklose 2015/05/11 10:23:19 Restore '@override'?
Johnni Winther 2015/05/11 12:24:57 Done.
525 return target.constantConstructor.computeInstanceFields(
526 arguments, callStructure);
527 }
528
529 InterfaceType computeInstanceType() {
530 return target.constantConstructor.computeInstanceType(type);
531 }
532
533 ConstructedConstantExpression apply(Arguments arguments) {
534 return new ConstructedConstantExpression(null,
535 type, target, callStructure,
536 this.arguments.map((a) => a.apply(arguments)).toList());
537 }
538
306 int _computeHashCode() { 539 int _computeHashCode() {
307 int hashCode = 540 int hashCode =
308 13 * type.hashCode + 541 13 * type.hashCode +
309 17 * target.hashCode + 542 17 * target.hashCode +
310 19 * callStructure.hashCode; 543 19 * callStructure.hashCode;
311 for (ConstantExpression value in arguments) { 544 for (ConstantExpression value in arguments) {
312 hashCode ^= 23 * value.hashCode; 545 hashCode ^= 23 * value.hashCode;
313 } 546 }
314 return hashCode; 547 return hashCode;
315 } 548 }
316 549
317 @override 550 @override
318 bool _equals(ConstructedConstantExpression other) { 551 bool _equals(ConstructedConstantExpression other) {
319 if (type != other.type) return false; 552 if (type != other.type) return false;
320 if (target != other.target) return false; 553 if (target != other.target) return false;
321 if (callStructure != other.callStructure) return false; 554 if (callStructure != other.callStructure) return false;
322 for (int i = 0; i < arguments.length; i++) { 555 for (int i = 0; i < arguments.length; i++) {
323 if (arguments[i] != other.arguments[i]) return false; 556 if (arguments[i] != other.arguments[i]) return false;
324 } 557 }
325 return true; 558 return true;
326 } 559 }
327 } 560 }
328 561
329 /// String literal with juxtaposition and/or interpolations. 562 /// String literal with juxtaposition and/or interpolations.
330 class ConcatenateConstantExpression extends ConstantExpression { 563 class ConcatenateConstantExpression extends ConstantExpression {
331 final StringConstantValue value; 564 final StringConstantValue value;
332 final List<ConstantExpression> arguments; 565 final List<ConstantExpression> expressions;
333 566
334 ConcatenateConstantExpression(this.value, this.arguments); 567 ConcatenateConstantExpression(this.value, this.expressions);
335 568
336 ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE; 569 ConstantExpressionKind get kind => ConstantExpressionKind.CONCATENATE;
337 570
338 accept(ConstantExpressionVisitor visitor, [context]) { 571 accept(ConstantExpressionVisitor visitor, [context]) {
339 return visitor.visitConcatenate(this, context); 572 return visitor.visitConcatenate(this, context);
340 } 573 }
341 574
575 ConstantExpression apply(Arguments arguments) {
576 return new ConcatenateConstantExpression(null,
577 expressions.map((a) => a.apply(arguments)).toList());
578 }
579
342 @override 580 @override
343 int _computeHashCode() { 581 int _computeHashCode() {
344 int hashCode = 17 * arguments.length; 582 int hashCode = 17 * expressions.length;
345 for (ConstantExpression value in arguments) { 583 for (ConstantExpression value in expressions) {
346 hashCode ^= 19 * value.hashCode; 584 hashCode ^= 19 * value.hashCode;
347 } 585 }
348 return hashCode; 586 return hashCode;
349 } 587 }
350 588
351 @override 589 @override
352 bool _equals(ConcatenateConstantExpression other) { 590 bool _equals(ConcatenateConstantExpression other) {
353 if (arguments.length != other.arguments.length) return false; 591 if (expressions.length != other.expressions.length) return false;
354 for (int i = 0; i < arguments.length; i++) { 592 for (int i = 0; i < expressions.length; i++) {
355 if (arguments[i] != other.arguments[i]) return false; 593 if (expressions[i] != other.expressions[i]) return false;
356 } 594 }
357 return true; 595 return true;
358 } 596 }
359 } 597 }
360 598
361 /// Symbol literal. 599 /// Symbol literal.
362 class SymbolConstantExpression extends ConstantExpression { 600 class SymbolConstantExpression extends ConstantExpression {
363 final ConstructedConstantValue value; 601 final ConstructedConstantValue value;
364 final String name; 602 final String name;
365 603
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 BinaryConstantExpression(this.value, this.left, this.operator, this.right) { 697 BinaryConstantExpression(this.value, this.left, this.operator, this.right) {
460 assert(PRECEDENCE_MAP[operator.kind] != null); 698 assert(PRECEDENCE_MAP[operator.kind] != null);
461 } 699 }
462 700
463 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY; 701 ConstantExpressionKind get kind => ConstantExpressionKind.BINARY;
464 702
465 accept(ConstantExpressionVisitor visitor, [context]) { 703 accept(ConstantExpressionVisitor visitor, [context]) {
466 return visitor.visitBinary(this, context); 704 return visitor.visitBinary(this, context);
467 } 705 }
468 706
707 ConstantExpression apply(Arguments arguments) {
708 return new BinaryConstantExpression(
709 value,
710 left.apply(arguments),
711 operator,
712 right.apply(arguments));
713 }
714
469 int get precedence => PRECEDENCE_MAP[operator.kind]; 715 int get precedence => PRECEDENCE_MAP[operator.kind];
470 716
471 @override 717 @override
472 int _computeHashCode() { 718 int _computeHashCode() {
473 return 13 * operator.hashCode + 719 return 13 * operator.hashCode +
474 17 * left.hashCode + 720 17 * left.hashCode +
475 19 * right.hashCode; 721 19 * right.hashCode;
476 } 722 }
477 723
478 @override 724 @override
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 final ConstantExpression right; 758 final ConstantExpression right;
513 759
514 IdenticalConstantExpression(this.value, this.left, this.right); 760 IdenticalConstantExpression(this.value, this.left, this.right);
515 761
516 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL; 762 ConstantExpressionKind get kind => ConstantExpressionKind.IDENTICAL;
517 763
518 accept(ConstantExpressionVisitor visitor, [context]) { 764 accept(ConstantExpressionVisitor visitor, [context]) {
519 return visitor.visitIdentical(this, context); 765 return visitor.visitIdentical(this, context);
520 } 766 }
521 767
768 ConstantExpression apply(Arguments arguments) {
769 return new IdenticalConstantExpression(
770 value,
771 left.apply(arguments),
772 right.apply(arguments));
773 }
774
522 int get precedence => 15; 775 int get precedence => 15;
523 776
524 @override 777 @override
525 int _computeHashCode() { 778 int _computeHashCode() {
526 return 17 * left.hashCode + 779 return 17 * left.hashCode +
527 19 * right.hashCode; 780 19 * right.hashCode;
528 } 781 }
529 782
530 @override 783 @override
531 bool _equals(IdenticalConstantExpression other) { 784 bool _equals(IdenticalConstantExpression other) {
(...skipping 11 matching lines...) Expand all
543 UnaryConstantExpression(this.value, this.operator, this.expression) { 796 UnaryConstantExpression(this.value, this.operator, this.expression) {
544 assert(PRECEDENCE_MAP[operator.kind] != null); 797 assert(PRECEDENCE_MAP[operator.kind] != null);
545 } 798 }
546 799
547 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY; 800 ConstantExpressionKind get kind => ConstantExpressionKind.UNARY;
548 801
549 accept(ConstantExpressionVisitor visitor, [context]) { 802 accept(ConstantExpressionVisitor visitor, [context]) {
550 return visitor.visitUnary(this, context); 803 return visitor.visitUnary(this, context);
551 } 804 }
552 805
806 ConstantExpression apply(Arguments arguments) {
807 return new UnaryConstantExpression(
808 value,
809 operator,
810 expression.apply(arguments));
811 }
812
553 int get precedence => PRECEDENCE_MAP[operator.kind]; 813 int get precedence => PRECEDENCE_MAP[operator.kind];
554 814
555 @override 815 @override
556 int _computeHashCode() { 816 int _computeHashCode() {
557 return 13 * operator.hashCode + 817 return 13 * operator.hashCode +
558 17 * expression.hashCode; 818 17 * expression.hashCode;
559 } 819 }
560 820
561 @override 821 @override
562 bool _equals(UnaryConstantExpression other) { 822 bool _equals(UnaryConstantExpression other) {
(...skipping 19 matching lines...) Expand all
582 this.condition, 842 this.condition,
583 this.trueExp, 843 this.trueExp,
584 this.falseExp); 844 this.falseExp);
585 845
586 ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL; 846 ConstantExpressionKind get kind => ConstantExpressionKind.CONDITIONAL;
587 847
588 accept(ConstantExpressionVisitor visitor, [context]) { 848 accept(ConstantExpressionVisitor visitor, [context]) {
589 return visitor.visitConditional(this, context); 849 return visitor.visitConditional(this, context);
590 } 850 }
591 851
852 ConstantExpression apply(Arguments arguments) {
853 return new ConditionalConstantExpression(
854 value,
855 condition.apply(arguments),
856 trueExp.apply(arguments),
857 falseExp.apply(arguments));
858 }
859
592 int get precedence => 3; 860 int get precedence => 3;
593 861
594 @override 862 @override
595 int _computeHashCode() { 863 int _computeHashCode() {
596 return 13 * condition.hashCode + 864 return 13 * condition.hashCode +
597 17 * trueExp.hashCode + 865 17 * trueExp.hashCode +
598 19 * falseExp.hashCode; 866 19 * falseExp.hashCode;
599 } 867 }
600 868
601 @override 869 @override
602 bool _equals(ConditionalConstantExpression other) { 870 bool _equals(ConditionalConstantExpression other) {
603 return condition == other.condition && 871 return condition == other.condition &&
604 trueExp == other.trueExp && 872 trueExp == other.trueExp &&
605 falseExp == other.falseExp; 873 falseExp == other.falseExp;
606 } 874 }
607 } 875 }
608 876
609 abstract class ConstantExpressionVisitor<C, R> { 877 /// A reference to a position parameter.
878 class PositionalArgumentReference extends ConstantExpression {
879 final int index;
880
881 PositionalArgumentReference(this.index);
882
883 ConstantExpressionKind get kind {
884 return ConstantExpressionKind.POSITIONAL_REFERENCE;
885 }
886
887 accept(ConstantExpressionVisitor visitor, [context]) {
888 return visitor.visitPositional(this, context);
889 }
890
891 ConstantValue get value {
892 throw new UnsupportedError('PositionalArgumentReference.value');
893 }
894
895 ConstantExpression apply(Arguments arguments) {
896 return arguments.getPositionalArgument(index);
897 }
898
899 @override
900 int _computeHashCode() => 13 * index.hashCode;
901
902 @override
903 bool _equals(PositionalArgumentReference other) => index == other.index;
904 }
905
906 /// A reference to a named parameter.
907 class NamedArgumentReference extends ConstantExpression {
908 final String name;
909
910 NamedArgumentReference(this.name);
911
912 ConstantExpressionKind get kind {
913 return ConstantExpressionKind.NAMED_REFERENCE;
914 }
915
916 accept(ConstantExpressionVisitor visitor, [context]) {
917 return visitor.visitNamed(this, context);
918 }
919
920 ConstantValue get value {
921 throw new UnsupportedError('NamedArgumentReference.value');
922 }
923
924 ConstantExpression apply(Arguments arguments) {
925 return arguments.getNamedArgument(name);
926 }
927
928 @override
929 int _computeHashCode() => 13 * name.hashCode;
930
931 @override
932 bool _equals(NamedArgumentReference other) => name == other.name;
933 }
934
935 abstract class FromEnvironmentConstantExpression extends ConstantExpression {
936 final ConstantValue value;
937 final String name;
938 final ConstantExpression defaultValue;
939
940 FromEnvironmentConstantExpression(this.value, this.name, this.defaultValue);
941
942 @override
943 int _computeHashCode() {
944 return 13 * name.hashCode +
945 17 * defaultValue.hashCode;
946 }
947
948 @override
949 bool _equals(FromEnvironmentConstantExpression other) {
950 return name == other.name &&
951 defaultValue == other.defaultValue;
952 }
953 }
954
955 /// A `const bool.fromEnvironment` constant.
956 class BoolFromEnvironmentConstantExpression
957 extends FromEnvironmentConstantExpression {
958
959 BoolFromEnvironmentConstantExpression(
960 ConstantValue value,
961 String name,
962 ConstantExpression defaultValue)
963 : super(value, name, defaultValue);
964
965 ConstantExpressionKind get kind {
966 return ConstantExpressionKind.BOOL_FROM_ENVIRONMENT;
967 }
968
969 accept(ConstantExpressionVisitor visitor, [context]) {
970 return visitor.visitBoolFromEnvironment(this, context);
971 }
972
973 ConstantExpression apply(Arguments arguments) {
974 return new BoolFromEnvironmentConstantExpression(
975 null, name, defaultValue.apply(arguments));
976 }
977 }
978
979 /// A `const int.fromEnvironment` constant.
980 class IntFromEnvironmentConstantExpression
981 extends FromEnvironmentConstantExpression {
982
983 IntFromEnvironmentConstantExpression(
984 ConstantValue value,
985 String name,
986 ConstantExpression defaultValue)
987 : super(value, name, defaultValue);
988
989 ConstantExpressionKind get kind {
990 return ConstantExpressionKind.INT_FROM_ENVIRONMENT;
991 }
992
993 accept(ConstantExpressionVisitor visitor, [context]) {
994 return visitor.visitIntFromEnvironment(this, context);
995 }
996
997 ConstantExpression apply(Arguments arguments) {
998 return new IntFromEnvironmentConstantExpression(
999 null, name, defaultValue.apply(arguments));
1000 }
1001 }
1002
1003 /// A `const String.fromEnvironment` constant.
1004 class StringFromEnvironmentConstantExpression
1005 extends FromEnvironmentConstantExpression {
1006
1007 StringFromEnvironmentConstantExpression(
1008 ConstantValue value,
1009 String name,
1010 ConstantExpression defaultValue)
1011 : super(value, name, defaultValue);
1012
1013 ConstantExpressionKind get kind {
1014 return ConstantExpressionKind.STRING_FROM_ENVIRONMENT;
1015 }
1016
1017 accept(ConstantExpressionVisitor visitor, [context]) {
1018 return visitor.visitStringFromEnvironment(this, context);
1019 }
1020
1021
1022 ConstantExpression apply(Arguments arguments) {
1023 return new StringFromEnvironmentConstantExpression(
1024 null, name, defaultValue.apply(arguments));
1025 }
1026 }
1027
1028 abstract class ConstantExpressionVisitor<R, A> {
610 const ConstantExpressionVisitor(); 1029 const ConstantExpressionVisitor();
611 1030
612 R visit(ConstantExpression constant, C context) { 1031 R visit(ConstantExpression constant, A context) {
613 return constant.accept(this, context); 1032 return constant.accept(this, context);
614 } 1033 }
615 1034
616 R visitPrimitive(PrimitiveConstantExpression exp, C context); 1035 R visitBool(BoolConstantExpression exp, A context);
617 R visitList(ListConstantExpression exp, C context); 1036 R visitInt(IntConstantExpression exp, A context);
618 R visitMap(MapConstantExpression exp, C context); 1037 R visitDouble(DoubleConstantExpression exp, A context);
619 R visitConstructed(ConstructedConstantExpression exp, C context); 1038 R visitString(StringConstantExpression exp, A context);
620 R visitConcatenate(ConcatenateConstantExpression exp, C context); 1039 R visitNull(NullConstantExpression exp, A context);
621 R visitSymbol(SymbolConstantExpression exp, C context); 1040 R visitList(ListConstantExpression exp, A context);
622 R visitType(TypeConstantExpression exp, C context); 1041 R visitMap(MapConstantExpression exp, A context);
623 R visitVariable(VariableConstantExpression exp, C context); 1042 R visitConstructed(ConstructedConstantExpression exp, A context);
624 R visitFunction(FunctionConstantExpression exp, C context); 1043 R visitConcatenate(ConcatenateConstantExpression exp, A context);
625 R visitBinary(BinaryConstantExpression exp, C context); 1044 R visitSymbol(SymbolConstantExpression exp, A context);
626 R visitIdentical(IdenticalConstantExpression exp, C context); 1045 R visitType(TypeConstantExpression exp, A context);
627 R visitUnary(UnaryConstantExpression exp, C context); 1046 R visitVariable(VariableConstantExpression exp, A context);
628 R visitConditional(ConditionalConstantExpression exp, C context); 1047 R visitFunction(FunctionConstantExpression exp, A context);
1048 R visitBinary(BinaryConstantExpression exp, A context);
1049 R visitIdentical(IdenticalConstantExpression exp, A context);
1050 R visitUnary(UnaryConstantExpression exp, A context);
1051 R visitConditional(ConditionalConstantExpression exp, A context);
1052 R visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp,
1053 A context);
1054 R visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp,
1055 A context);
1056 R visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp,
1057 A context);
1058
1059 R visitPositional(PositionalArgumentReference exp, A context);
1060 R visitNamed(NamedArgumentReference exp, A context);
629 } 1061 }
630 1062
631 /// Represents the declaration of a constant [element] with value [expression]. 1063 /// Represents the declaration of a constant [element] with value [expression].
632 // TODO(johnniwinther): Where does this class belong? 1064 // TODO(johnniwinther): Where does this class belong?
633 class ConstDeclaration { 1065 class ConstDeclaration {
634 final VariableElement element; 1066 final VariableElement element;
635 final ConstantExpression expression; 1067 final ConstantExpression expression;
636 1068
637 ConstDeclaration(this.element, this.expression); 1069 ConstDeclaration(this.element, this.expression);
638 } 1070 }
(...skipping 26 matching lines...) Expand all
665 needsComma = true; 1097 needsComma = true;
666 } 1098 }
667 sb.write('>'); 1099 sb.write('>');
668 } 1100 }
669 1101
670 @override 1102 @override
671 void visit(ConstantExpression constant, [_]) { 1103 void visit(ConstantExpression constant, [_]) {
672 return constant.accept(this, null); 1104 return constant.accept(this, null);
673 } 1105 }
674 1106
675 @override 1107 void visitPrimitive(PrimitiveConstantExpression exp) {
676 void visitPrimitive(PrimitiveConstantExpression exp, [_]) { 1108 sb.write(exp.primitiveValue);
677 sb.write(exp.value.unparse());
678 } 1109 }
679 1110
680 @override 1111 @override
1112 void visitBool(BoolConstantExpression exp, [_]) {
1113 visitPrimitive(exp);
1114 }
1115
1116 @override
1117 void visitDouble(DoubleConstantExpression exp, [_]) {
1118 visitPrimitive(exp);
1119 }
1120
1121 @override
1122 void visitInt(IntConstantExpression exp, [_]) {
1123 visitPrimitive(exp);
1124 }
1125
1126 @override
1127 void visitNull(NullConstantExpression exp, [_]) {
1128 visitPrimitive(exp);
1129 }
1130
1131 @override
1132 void visitString(StringConstantExpression exp, [_]) {
1133 // TODO(johnniwinther): Ensure correct escaping.
1134 sb.write('"${exp.primitiveValue}"');
1135 }
1136
1137 @override
681 void visitList(ListConstantExpression exp, [_]) { 1138 void visitList(ListConstantExpression exp, [_]) {
682 sb.write('const '); 1139 sb.write('const ');
683 writeTypeArguments(exp.type); 1140 writeTypeArguments(exp.type);
684 sb.write('['); 1141 sb.write('[');
685 bool needsComma = false; 1142 bool needsComma = false;
686 for (ConstantExpression value in exp.values) { 1143 for (ConstantExpression value in exp.values) {
687 if (needsComma) { 1144 if (needsComma) {
688 sb.write(', '); 1145 sb.write(', ');
689 } 1146 }
690 visit(value); 1147 visit(value);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 1258
802 @override 1259 @override
803 void visitConditional(ConditionalConstantExpression exp, [_]) { 1260 void visitConditional(ConditionalConstantExpression exp, [_]) {
804 write(exp, exp.condition, leftAssociative: false); 1261 write(exp, exp.condition, leftAssociative: false);
805 sb.write(' ? '); 1262 sb.write(' ? ');
806 write(exp, exp.trueExp); 1263 write(exp, exp.trueExp);
807 sb.write(' : '); 1264 sb.write(' : ');
808 write(exp, exp.falseExp); 1265 write(exp, exp.falseExp);
809 } 1266 }
810 1267
1268 @override
1269 void visitPositional(PositionalArgumentReference exp, [_]) {
1270 // TODO(johnniwinther): Maybe this should throw.
1271 sb.write('args[${exp.index}]');
1272 }
1273
1274 @override
1275 void visitNamed(NamedArgumentReference exp, [_]) {
1276 // TODO(johnniwinther): Maybe this should throw.
1277 sb.write('args[${exp.name}]');
1278 }
1279
811 String toString() => sb.toString(); 1280 String toString() => sb.toString();
1281
1282 @override
1283 visitBoolFromEnvironment(BoolFromEnvironmentConstantExpression exp, [_]) {
1284 sb.write('const bool.fromEnvironment("${exp.name}", defaultValue: ');
1285 visit(exp.defaultValue);
1286 sb.write(')');
1287 }
1288
1289 @override
1290 visitIntFromEnvironment(IntFromEnvironmentConstantExpression exp, [_]) {
1291 sb.write('const int.fromEnvironment("${exp.name}", defaultValue: ');
1292 visit(exp.defaultValue);
1293 sb.write(')');
1294 }
1295
1296 @override
1297 visitStringFromEnvironment(StringFromEnvironmentConstantExpression exp, [_]) {
1298 sb.write('const String.fromEnvironment("${exp.name}", defaultValue: ');
1299 visit(exp.defaultValue);
1300 sb.write(')');
1301 }
812 } 1302 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698