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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/constants/expressions.dart

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

Powered by Google App Engine
This is Rietveld 408576698