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

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

Powered by Google App Engine
This is Rietveld 408576698