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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/const_expression.dart

Issue 574683002: Use ConstExp for storing constants. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Remove ConstExpBuilder. Created 6 years, 3 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 const_expression; 5 library const_expression;
6 6
7 import '../dart2jslib.dart' show Constant, ListConstant, MapConstant, 7 import '../dart2jslib.dart' show Constant, ListConstant, MapConstant,
8 PrimitiveConstant, ConstructedConstant, TypeConstant, FunctionConstant, 8 PrimitiveConstant, ConstructedConstant, TypeConstant, FunctionConstant,
9 StringConstant; 9 StringConstant;
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
11 import '../elements/elements.dart'; 11 import '../elements/elements.dart';
12 import '../universe/universe.dart'; 12 import '../universe/universe.dart';
13 13
14 /// An expression that is a compile-time constant. 14 /// An expression that is a compile-time constant.
15 /// 15 ///
16 /// Whereas [Constant] represent a compile-time value, a [ConstExp] 16 /// Whereas [Constant] represent a compile-time value, a [ConstExp]
17 /// represents an expression for creating a constant. 17 /// represents an expression for creating a constant.
18 /// 18 ///
19 /// There is no one-to-one mapping between [ConstExp] and [Constant], because 19 /// There is no one-to-one mapping between [ConstExp] and [Constant], because
20 /// different expressions can denote the same constant. For instance, 20 /// different expressions can denote the same constant. For instance,
21 /// multiple `const` constructors may be used to create the same object, and 21 /// multiple `const` constructors may be used to create the same object, and
22 /// different `const` variables may hold the same value. 22 /// different `const` variables may hold the same value.
23 abstract class ConstExp { 23 abstract class ConstExp {
24 /// Returns the value of this constant expression.
25 Constant get value;
26
27 // TODO(johnniwinther): Unify precedence handled between constants, front-end
28 // and back-end.
29 int get precedence => 16;
30
24 accept(ConstExpVisitor visitor); 31 accept(ConstExpVisitor visitor);
32
33 String toString() {
34 ConstExpPrinter printer = new ConstExpPrinter();
35 accept(printer);
36 return printer.toString();
37 }
25 } 38 }
26 39
27 /// Boolean, int, double, string, or null constant. 40 /// Boolean, int, double, string, or null constant.
28 class PrimitiveConstExp extends ConstExp { 41 class PrimitiveConstExp extends ConstExp {
29 final PrimitiveConstant constant; 42 final PrimitiveConstant value;
30 43
31 PrimitiveConstExp(this.constant) { 44 PrimitiveConstExp(this.value) {
32 assert(constant != null); 45 assert(value != null);
33 } 46 }
34 47
35 accept(ConstExpVisitor visitor) => visitor.visitPrimitive(this); 48 accept(ConstExpVisitor visitor) => visitor.visitPrimitive(this);
36 } 49 }
37 50
38 /// Literal list constant. 51 /// Literal list constant.
39 class ListConstExp extends ConstExp { 52 class ListConstExp extends ConstExp {
53 final ListConstant value;
40 final GenericType type; 54 final GenericType type;
41 final List<ConstExp> values; 55 final List<ConstExp> values;
42 56
43 ListConstExp(this.type, this.values); 57 ListConstExp(this.value, this.type, this.values);
44 58
45 accept(ConstExpVisitor visitor) => visitor.visitList(this); 59 accept(ConstExpVisitor visitor) => visitor.visitList(this);
46 } 60 }
47 61
48 /// Literal map constant. 62 /// Literal map constant.
49 class MapConstExp extends ConstExp { 63 class MapConstExp extends ConstExp {
64 final MapConstant value;
50 final GenericType type; 65 final GenericType type;
51 final List<ConstExp> keys; 66 final List<ConstExp> keys;
52 final List<ConstExp> values; 67 final List<ConstExp> values;
53 68
54 MapConstExp(this.type, this.keys, this.values); 69 MapConstExp(this.value, this.type, this.keys, this.values);
55 70
56 accept(ConstExpVisitor visitor) => visitor.visitMap(this); 71 accept(ConstExpVisitor visitor) => visitor.visitMap(this);
57 } 72 }
58 73
59 /// Invocation of a const constructor. 74 /// Invocation of a const constructor.
60 class ConstructorConstExp extends ConstExp { 75 class ConstructorConstExp extends ConstExp {
76 final Constant value;
61 final GenericType type; 77 final GenericType type;
62 final FunctionElement target; 78 final FunctionElement target;
63 final Selector selector; 79 final Selector selector;
64 final List<ConstExp> arguments; 80 final List<ConstExp> arguments;
65 81
66 ConstructorConstExp(this.type, this.target, this.selector, this.arguments) { 82 ConstructorConstExp(this.value,
83 this.type,
84 this.target,
85 this.selector,
86 this.arguments) {
67 assert(type.element == target.enclosingClass); 87 assert(type.element == target.enclosingClass);
68 } 88 }
69 89
70 accept(ConstExpVisitor visitor) => visitor.visitConstructor(this); 90 accept(ConstExpVisitor visitor) => visitor.visitConstructor(this);
71 } 91 }
72 92
73 /// String literal with juxtaposition and/or interpolations. 93 /// String literal with juxtaposition and/or interpolations.
94 // TODO(johnniwinther): Do we need this?
74 class ConcatenateConstExp extends ConstExp { 95 class ConcatenateConstExp extends ConstExp {
96 final StringConstant value;
75 final List<ConstExp> arguments; 97 final List<ConstExp> arguments;
76 98
77 ConcatenateConstExp(this.arguments); 99 ConcatenateConstExp(this.value, this.arguments);
78 100
79 accept(ConstExpVisitor visitor) => visitor.visitConcatenate(this); 101 accept(ConstExpVisitor visitor) => visitor.visitConcatenate(this);
80 } 102 }
81 103
82 /// Symbol literal. 104 /// Symbol literal.
83 class SymbolConstExp extends ConstExp { 105 class SymbolConstExp extends ConstExp {
106 final ConstructedConstant value;
84 final String name; 107 final String name;
85 108
86 SymbolConstExp(this.name); 109 SymbolConstExp(this.value, this.name);
87 110
88 accept(ConstExpVisitor visitor) => visitor.visitSymbol(this); 111 accept(ConstExpVisitor visitor) => visitor.visitSymbol(this);
89 } 112 }
90 113
91 /// Type literal. 114 /// Type literal.
92 class TypeConstExp extends ConstExp { 115 class TypeConstExp extends ConstExp {
116 final TypeConstant value;
93 /// Either [DynamicType] or a raw [GenericType]. 117 /// Either [DynamicType] or a raw [GenericType].
94 final DartType type; 118 final DartType type;
95 119
96 TypeConstExp(this.type) { 120 TypeConstExp(this.value, this.type) {
97 assert(type is GenericType || type is DynamicType); 121 assert(type is GenericType || type is DynamicType);
98 } 122 }
99 123
100 accept(ConstExpVisitor visitor) => visitor.visitType(this); 124 accept(ConstExpVisitor visitor) => visitor.visitType(this);
101 } 125 }
102 126
103 /// A constant local, top-level, or static variable. 127 /// A constant local, top-level, or static variable.
104 class VariableConstExp extends ConstExp { 128 class VariableConstExp extends ConstExp {
129 final Constant value;
105 final VariableElement element; 130 final VariableElement element;
106 131
107 VariableConstExp(this.element); 132 VariableConstExp(this.value, this.element);
108 133
109 accept(ConstExpVisitor visitor) => visitor.visitVariable(this); 134 accept(ConstExpVisitor visitor) => visitor.visitVariable(this);
110 } 135 }
111 136
112 /// Reference to a top-level or static function. 137 /// Reference to a top-level or static function.
113 class FunctionConstExp extends ConstExp { 138 class FunctionConstExp extends ConstExp {
139 final FunctionConstant value;
114 final FunctionElement element; 140 final FunctionElement element;
115 141
116 FunctionConstExp(this.element); 142 FunctionConstExp(this.value, this.element);
117 143
118 accept(ConstExpVisitor visitor) => visitor.visitFunction(this); 144 accept(ConstExpVisitor visitor) => visitor.visitFunction(this);
119 } 145 }
120 146
147 /// A constant binary expression like `a * b` or `identical(a, b)`.
148 class BinaryConstExp extends ConstExp {
149 final Constant value;
150 final ConstExp left;
151 final String operator;
152 final ConstExp right;
153
154 BinaryConstExp(this.value, this.left, this.operator, this.right) {
155 assert(PRECEDENCE_MAP[operator] != null);
156 }
157
158 accept(ConstExpVisitor visitor) => visitor.visitBinary(this);
159
160 int get precedence => PRECEDENCE_MAP[operator];
161
162 static const Map<String, int> PRECEDENCE_MAP = const {
163 'identical': 15,
164 '==': 6,
165 '!=': 6,
166 '&&': 5,
167 '||': 4,
168 '^': 9,
169 '&': 10,
170 '|': 8,
171 '>>': 11,
172 '<<': 11,
173 '+': 12,
174 '-': 12,
175 '*': 13,
176 '/': 13,
177 '~/': 13,
178 '>': 7,
179 '<': 7,
180 '>=': 7,
181 '<=': 7,
182 '%': 13,
183 };
184 }
185
186 /// A unary constant expression like `-a`.
187 class UnaryConstExp extends ConstExp {
188 final Constant value;
189 final String operator;
190 final ConstExp expression;
191
192 UnaryConstExp(this.value, this.operator, this.expression) {
193 assert(PRECEDENCE_MAP[operator] != null);
194 }
195
196 accept(ConstExpVisitor visitor) => visitor.visitUnary(this);
197
198 int get precedence => PRECEDENCE_MAP[operator];
199
200 static const Map<String, int> PRECEDENCE_MAP = const {
201 '!': 14,
202 '~': 14,
203 '-': 14,
204 };
205 }
206
207 /// A constant conditional expression like `a ? b : c`.
208 class ConditionalConstExp extends ConstExp {
209 final Constant value;
210 final ConstExp condition;
211 final ConstExp trueExp;
212 final ConstExp falseExp;
213
214 ConditionalConstExp(this.value, this.condition, this.trueExp, this.falseExp);
215
216 accept(ConstExpVisitor visitor) => visitor.visitConditional(this);
217
218 int get precedence => 3;
219 }
220
121 abstract class ConstExpVisitor<T> { 221 abstract class ConstExpVisitor<T> {
122 T visit(ConstExp constant) => constant.accept(this); 222 T visit(ConstExp constant) => constant.accept(this);
123 223
124 T visitPrimitive(PrimitiveConstExp exp); 224 T visitPrimitive(PrimitiveConstExp exp);
125 T visitList(ListConstExp exp); 225 T visitList(ListConstExp exp);
126 T visitMap(MapConstExp exp); 226 T visitMap(MapConstExp exp);
127 T visitConstructor(ConstructorConstExp exp); 227 T visitConstructor(ConstructorConstExp exp);
128 T visitConcatenate(ConcatenateConstExp exp); 228 T visitConcatenate(ConcatenateConstExp exp);
129 T visitSymbol(SymbolConstExp exp); 229 T visitSymbol(SymbolConstExp exp);
130 T visitType(TypeConstExp exp); 230 T visitType(TypeConstExp exp);
131 T visitVariable(VariableConstExp exp); 231 T visitVariable(VariableConstExp exp);
132 T visitFunction(FunctionConstExp exp); 232 T visitFunction(FunctionConstExp exp);
233 T visitBinary(BinaryConstExp exp);
234 T visitUnary(UnaryConstExp exp);
235 T visitConditional(ConditionalConstExp exp);
133 } 236 }
134 237
135 /// Represents the declaration of a constant [element] with value [expression]. 238 /// Represents the declaration of a constant [element] with value [expression].
136 class ConstDeclaration { 239 class ConstDeclaration {
137 final VariableElement element; 240 final VariableElement element;
138 final ConstExp expression; 241 final ConstExp expression;
139 242
140 ConstDeclaration(this.element, this.expression); 243 ConstDeclaration(this.element, this.expression);
141 } 244 }
245
246 class ConstExpPrinter extends ConstExpVisitor {
247 final StringBuffer sb = new StringBuffer();
248
249 write(ConstExp parent, ConstExp child, {bool leftAssociative: true}) {
250 if (child.precedence < parent.precedence ||
251 !leftAssociative && child.precedence == parent.precedence) {
252 sb.write('(');
253 child.accept(this);
254 sb.write(')');
255 } else {
256 child.accept(this);
257 }
258 }
259
260 writeTypeArguments(InterfaceType type) {
261 if (type.treatAsRaw) return;
262 sb.write('<');
263 bool needsComma = false;
264 for (DartType value in type.typeArguments) {
265 if (needsComma) {
266 sb.write(', ');
267 }
268 sb.write(value);
269 needsComma = true;
270 }
271 sb.write('>');
272 }
273
274 visitPrimitive(PrimitiveConstExp exp) {
275 sb.write(exp.value.toSyntax());
276 }
277
278 visitList(ListConstExp exp) {
279 sb.write('const ');
280 writeTypeArguments(exp.type);
281 sb.write('[');
282 bool needsComma = false;
283 for (ConstExp value in exp.values) {
284 if (needsComma) {
285 sb.write(', ');
286 }
287 visit(value);
288 needsComma = true;
289 }
290 sb.write(']');
291 }
292
293 visitMap(MapConstExp exp) {
294 sb.write('const ');
295 writeTypeArguments(exp.type);
296 sb.write('{');
297 for (int index = 0; index < exp.keys.length; index++) {
298 if (index > 0) {
299 sb.write(', ');
300 }
301 visit(exp.keys[index]);
302 sb.write(': ');
303 visit(exp.values[index]);
304 }
305 sb.write('}');
306 }
307
308 visitConstructor(ConstructorConstExp exp) {
309 sb.write('const ');
310 sb.write(exp.target.enclosingClass.name);
311 if (exp.target.name != '') {
312 sb.write('.');
313 sb.write(exp.target.name);
314 }
315 writeTypeArguments(exp.type);
316 sb.write('(');
317 bool needsComma = false;
318
319 int namedOffset = exp.selector.positionalArgumentCount;
320 for (int index = 0; index < namedOffset; index++) {
321 if (needsComma) {
322 sb.write(', ');
323 }
324 visit(exp.arguments[index]);
325 needsComma = true;
326 }
327 for (int index = 0; index < exp.selector.namedArgumentCount; index++) {
328 if (needsComma) {
329 sb.write(', ');
330 }
331 sb.write(exp.selector.namedArguments[index]);
332 sb.write(': ');
333 visit(exp.arguments[namedOffset + index]);
334 needsComma = true;
335 }
336 sb.write(')');
337 }
338
339 visitConcatenate(ConcatenateConstExp exp) {
340 sb.write(exp.value.toSyntax());
341 }
342
343 visitSymbol(SymbolConstExp exp) {
344 sb.write('#');
345 sb.write(exp.name);
346 }
347
348 visitType(TypeConstExp exp) {
349 sb.write(exp.type.name);
350 }
351
352 visitVariable(VariableConstExp exp) {
353 if (exp.element.isStatic) {
354 sb.write(exp.element.enclosingClass.name);
355 sb.write('.');
356 }
357 sb.write(exp.element.name);
358 }
359
360 visitFunction(FunctionConstExp exp) {
361 if (exp.element.isStatic) {
362 sb.write(exp.element.enclosingClass.name);
363 sb.write('.');
364 }
365 sb.write(exp.element.name);
366 }
367
368 visitBinary(BinaryConstExp exp) {
369 if (exp.operator == 'identical') {
370 sb.write('identical(');
371 visit(exp.left);
372 sb.write(', ');
373 visit(exp.right);
374 sb.write(')');
375 } else {
376 write(exp, exp.left);
377 sb.write(' ');
378 sb.write(exp.operator);
379 sb.write(' ');
380 write(exp, exp.right);
381 }
382 }
383
384 visitUnary(UnaryConstExp exp) {
385 sb.write(exp.operator);
386 write(exp, exp.expression);
387 }
388
389 visitConditional(ConditionalConstExp exp) {
390 write(exp, exp.condition, leftAssociative: false);
391 sb.write(' ? ');
392 write(exp, exp.trueExp);
393 sb.write(' : ');
394 write(exp, exp.falseExp);
395 }
396
397 String toString() => sb.toString();
398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698