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

Side by Side Diff: pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart

Issue 2213673002: Delete dart_backend from compiler. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
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 dart_tree_printer;
6
7 import '../common.dart';
8 import '../constants/values.dart' as values;
9 import '../dart_types.dart' as types;
10 import '../elements/elements.dart' as elements;
11 import '../resolution/tree_elements.dart' show TreeElementMapping;
12 import '../tokens/token.dart';
13 import '../tokens/token_constants.dart';
14 import '../tokens/precedence.dart';
15 import '../tokens/precedence_constants.dart';
16 import '../tree/tree.dart' as tree;
17 import '../util/util.dart';
18 import 'backend_ast_nodes.dart';
19 import 'backend_ast_emitter.dart' show TypeGenerator;
20
21 /// Translates the backend AST to Dart frontend AST.
22 tree.Node emit(TreeElementMapping treeElements, RootNode root) {
23 return new TreePrinter(treeElements).makeDefinition(root);
24 }
25
26 /// If true, the unparser will insert a coment in front of every function
27 /// it emits. This helps indicate which functions were translated by the new
28 /// backend.
29 bool INSERT_NEW_BACKEND_COMMENT =
30 const bool.fromEnvironment("INSERT_NEW_BACKEND_COMMENT");
31
32 /// Converts backend ASTs to frontend ASTs.
33 class TreePrinter {
34 TreeElementMapping treeElements;
35
36 TreePrinter([this.treeElements]);
37
38 tree.Node makeDefinition(RootNode node) {
39 if (node is FieldDefinition) {
40 tree.Node definition;
41 if (node.initializer == null) {
42 definition = makeIdentifier(node.element.name);
43 } else {
44 definition = new tree.SendSet(
45 null,
46 makeIdentifier(node.element.name),
47 new tree.Operator(assignmentToken("=")),
48 singleton(makeExpression(node.initializer)));
49 }
50 setElement(definition, node.element, node);
51 return new tree.VariableDefinitions(
52 null, // TODO(sigurdm): Type
53 makeVarModifiers(
54 useVar: true,
55 isFinal: node.element.isFinal,
56 isStatic: node.element.isStatic,
57 isConst: node.element.isConst),
58 makeList(null, [definition], close: semicolon));
59 } else if (node is FunctionExpression) {
60 return makeExpression(node);
61 } else {
62 assert(false);
63 return null;
64 }
65 }
66
67 void setElement(tree.Node node, elements.Element element, source) {
68 if (treeElements != null) {
69 if (element == null) {
70 throw "Missing element from ${source}";
71 }
72 treeElements[node] = element;
73 }
74 }
75
76 void setType(tree.Node node, types.DartType type, source) {
77 if (treeElements != null) {
78 if (type == null) {
79 throw "Missing type from ${source}";
80 }
81 treeElements.setType(node, type);
82 }
83 }
84
85 // Group tokens: () [] {} <>
86 static BeginGroupToken makeGroup(PrecedenceInfo open, PrecedenceInfo close) {
87 BeginGroupToken openTok = new BeginGroupToken(open, -1);
88 openTok.endGroup = new SymbolToken(close, -1);
89 return openTok;
90 }
91
92 final BeginGroupToken openParen =
93 makeGroup(OPEN_PAREN_INFO, CLOSE_PAREN_INFO);
94 final BeginGroupToken openBrace =
95 makeGroup(OPEN_CURLY_BRACKET_INFO, CLOSE_CURLY_BRACKET_INFO);
96 final BeginGroupToken openBracket =
97 makeGroup(OPEN_SQUARE_BRACKET_INFO, CLOSE_SQUARE_BRACKET_INFO);
98 final BeginGroupToken lt = makeGroup(LT_INFO, GT_INFO);
99
100 Token get closeParen => openParen.endGroup;
101 Token get closeBrace => openBrace.endGroup;
102 Token get closeBracket => openBracket.endGroup;
103 Token get gt => lt.endGroup;
104
105 // Symbol tokens
106 final Token semicolon = new SymbolToken(SEMICOLON_INFO, -1);
107 final Token indexToken = new SymbolToken(INDEX_INFO, -1); // "[]"
108 final Token question = new SymbolToken(QUESTION_INFO, -1);
109 final Token colon = new SymbolToken(COLON_INFO, -1);
110 final Token hash = new SymbolToken(HASH_INFO, -1);
111 final Token bang = new SymbolToken(BANG_INFO, -1);
112 final Token eq = new SymbolToken(EQ_INFO, -1);
113
114 // Keyword tokens
115 static Token makeIdToken(String text) {
116 return new StringToken.fromString(IDENTIFIER_INFO, text, -1);
117 }
118
119 final Token newToken = makeIdToken('new');
120 final Token constToken = makeIdToken('const');
121 final Token throwToken = makeIdToken('throw');
122 final Token rethrowToken = makeIdToken('rethrow');
123 final Token breakToken = makeIdToken('break');
124 final Token continueToken = makeIdToken('continue');
125 final Token doToken = makeIdToken('do');
126 final Token whileToken = makeIdToken('while');
127 final Token ifToken = makeIdToken('if');
128 final Token elseToken = makeIdToken('else');
129 final Token awaitToken = makeIdToken('await');
130 final Token forToken = makeIdToken('for');
131 final Token inToken = makeIdToken('in');
132 final Token returnToken = makeIdToken('return');
133 final Token switchToken = makeIdToken('switch');
134 final Token caseToken = makeIdToken('case');
135 final Token defaultToken = makeIdToken('default');
136 final Token tryToken = makeIdToken('try');
137 final Token catchToken = makeIdToken('catch');
138 final Token onToken = makeIdToken('on');
139 final Token finallyToken = makeIdToken('finally');
140 final Token getToken = makeIdToken('get');
141 final Token setToken = makeIdToken('set');
142 final Token classToken = makeIdToken('class');
143 final Token extendsToken = makeIdToken('extends');
144 final Token withToken = makeIdToken('with');
145 final Token implementsToken = makeIdToken('implements');
146 final Token typedefToken = makeIdToken('typedef');
147 final Token enumToken = makeIdToken('enum');
148
149 static tree.Identifier makeIdentifier(String name) {
150 return new tree.Identifier(
151 new StringToken.fromString(IDENTIFIER_INFO, name, -1));
152 }
153
154 static tree.Operator makeOperator(String name) {
155 return new tree.Operator(
156 new StringToken.fromString(IDENTIFIER_INFO, name, -1));
157 }
158
159 // Utilities for creating NodeLists
160 Link<tree.Node> makeLink(Iterable<tree.Node> nodes) {
161 LinkBuilder builder = new LinkBuilder();
162 for (tree.Node node in nodes) {
163 builder.addLast(node);
164 }
165 return builder.toLink();
166 }
167
168 tree.NodeList blankList() {
169 return new tree.NodeList(null, makeLink([]), null, '');
170 }
171
172 tree.NodeList singleton(tree.Node node) {
173 return new tree.NodeList(null, makeLink([node]), null, '');
174 }
175
176 tree.NodeList makeList(String delimiter, Iterable<tree.Node> nodes,
177 {Token open, Token close}) {
178 return new tree.NodeList(open, makeLink(nodes), close, delimiter);
179 }
180
181 tree.NodeList parenList(String delimiter, Iterable<tree.Node> nodes) {
182 return makeList(delimiter, nodes, open: openParen, close: closeParen);
183 }
184
185 tree.NodeList bracketList(String delimiter, Iterable<tree.Node> nodes) {
186 return makeList(delimiter, nodes, open: openBracket, close: closeBracket);
187 }
188
189 tree.NodeList braceList(String delimiter, Iterable<tree.Node> nodes) {
190 return makeList(delimiter, nodes, open: openBrace, close: closeBrace);
191 }
192
193 tree.NodeList argList(Iterable<tree.Node> nodes) {
194 return parenList(',', nodes);
195 }
196
197 tree.NodeList typeArgList(Iterable<tree.Node> nodes) {
198 return makeList(',', nodes, open: lt, close: gt);
199 }
200
201 /// Converts a qualified name into nested Sends.
202 tree.Node makeName(String name) {
203 if (name == null) {
204 return null;
205 }
206 List<String> names = name.split('.').toList(growable: false);
207 tree.Node node = makeIdentifier(names[0]);
208 for (int i = 1; i < names.length; i++) {
209 node = new tree.Send(node, makeIdentifier(names[i]));
210 }
211 return node;
212 }
213
214 static Token assignmentToken(String operatorName) {
215 switch (operatorName) {
216 case '=':
217 return new SymbolToken(EQ_INFO, -1);
218 case '+=':
219 return new SymbolToken(PLUS_EQ_INFO, -1);
220 case '-=':
221 return new SymbolToken(MINUS_EQ_INFO, -1);
222 case '*=':
223 return new SymbolToken(STAR_EQ_INFO, -1);
224 case '/=':
225 return new SymbolToken(SLASH_EQ_INFO, -1);
226 case '~/=':
227 return new SymbolToken(TILDE_SLASH_EQ_INFO, -1);
228 case '%=':
229 return new SymbolToken(PERCENT_EQ_INFO, -1);
230 case '&=':
231 return new SymbolToken(AMPERSAND_EQ_INFO, -1);
232 case '^=':
233 return new SymbolToken(CARET_EQ_INFO, -1);
234 case '|=':
235 return new SymbolToken(BAR_EQ_INFO, -1);
236 case '>>=':
237 return new SymbolToken(GT_GT_EQ_INFO, -1);
238 case '<<=':
239 return new SymbolToken(LT_LT_EQ_INFO, -1);
240 default:
241 throw "Unrecognized assignment operator: $operatorName";
242 }
243 }
244
245 static Token binopToken(String operatorName) {
246 switch (operatorName) {
247 case '+':
248 return new SymbolToken(PLUS_INFO, -1);
249 case '-':
250 return new SymbolToken(MINUS_INFO, -1);
251 case '*':
252 return new SymbolToken(STAR_INFO, -1);
253 case '/':
254 return new SymbolToken(SLASH_INFO, -1);
255 case '~/':
256 return new SymbolToken(TILDE_SLASH_INFO, -1);
257 case '%':
258 return new SymbolToken(PERCENT_INFO, -1);
259 case '&':
260 return new SymbolToken(AMPERSAND_INFO, -1);
261 case '^':
262 return new SymbolToken(CARET_INFO, -1);
263 case '|':
264 return new SymbolToken(BAR_INFO, -1);
265 case '>>':
266 return new SymbolToken(GT_GT_INFO, -1);
267 case '<<':
268 return new SymbolToken(LT_LT_INFO, -1);
269 case '==':
270 return new SymbolToken(EQ_EQ_INFO, -1);
271 case '!=':
272 return new SymbolToken(BANG_EQ_INFO, -1);
273 case '>':
274 return new SymbolToken(GT_INFO, -1);
275 case '>=':
276 return new SymbolToken(GT_EQ_INFO, -1);
277 case '<':
278 return new SymbolToken(LT_INFO, -1);
279 case '<=':
280 return new SymbolToken(LT_EQ_INFO, -1);
281 case '&&':
282 return new SymbolToken(AMPERSAND_AMPERSAND_INFO, -1);
283 case '||':
284 return new SymbolToken(BAR_BAR_INFO, -1);
285 default:
286 throw "Unrecognized binary operator: $operatorName";
287 }
288 }
289
290 static Token incrementToken(String operatorName) {
291 switch (operatorName) {
292 case '++':
293 return new SymbolToken(PLUS_PLUS_INFO, -1);
294 case '--':
295 return new SymbolToken(MINUS_MINUS_INFO, -1);
296 default:
297 throw "Unrecognized increment operator: $operatorName";
298 }
299 }
300
301 static Token typeOpToken(String operatorName) {
302 switch (operatorName) {
303 // "is!" is not an operator in the frontend AST.
304 case 'is':
305 return new SymbolToken(IS_INFO, -1);
306 case 'as':
307 return new SymbolToken(AS_INFO, -1);
308 default:
309 throw 'Unrecognized type operator: $operatorName';
310 }
311 }
312
313 Token unopToken(String operatorName) {
314 switch (operatorName) {
315 case '-':
316 return new SymbolToken(MINUS_INFO, -1);
317 case '~':
318 return new SymbolToken(TILDE_INFO, -1);
319 case '!':
320 return bang;
321 default:
322 throw "Unrecognized unary operator: $operatorName";
323 }
324 }
325
326 tree.Node makeStaticReceiver(elements.Element element) {
327 if (treeElements == null) return null;
328 if (element.isStatic) {
329 elements.ClassElement enclosingClass = element.enclosingClass;
330 tree.Send send = new tree.Send(null, makeIdentifier(enclosingClass.name));
331 treeElements[send] = enclosingClass;
332 return send;
333 } else {
334 return null;
335 }
336 }
337
338 tree.Node makeArgument(Argument arg) {
339 if (arg is Expression) {
340 return makeExpression(arg);
341 } else if (arg is NamedArgument) {
342 return new tree.NamedArgument(
343 makeIdentifier(arg.name), colon, makeExpression(arg.expression));
344 } else {
345 throw "Unrecognized argument type: ${arg}";
346 }
347 }
348
349 tree.Node makeExpression(Expression exp) {
350 return makeExp(exp, EXPRESSION);
351 }
352
353 /// Converts [exp] to a [tree.Node] that unparses to an expression with
354 /// a precedence level of at least [minPrecedence]. The expression will be
355 /// wrapped in a parenthesis if necessary.
356 tree.Node makeExp(Receiver exp, int minPrecedence, {bool beginStmt: false}) {
357 tree.Node result;
358 int precedence;
359 bool needParen = false;
360 if (exp is SuperReceiver) {
361 precedence = CALLEE;
362 result = makeIdentifier('super');
363 } else if (exp is Assignment) {
364 Expression left = exp.left;
365 tree.Node receiver;
366 tree.Node selector;
367 tree.NodeList arguments;
368 elements.Element element;
369 if (left is Identifier) {
370 receiver = makeStaticReceiver(left.element);
371 selector = makeIdentifier(left.name);
372 arguments = singleton(makeExpression(exp.right));
373 element = left.element;
374 } else if (left is FieldExpression) {
375 receiver = makeExp(left.object, PRIMARY, beginStmt: beginStmt);
376 selector = makeIdentifier(left.fieldName);
377 arguments = singleton(makeExpression(exp.right));
378 } else if (left is IndexExpression) {
379 receiver = makeExp(left.object, PRIMARY, beginStmt: beginStmt);
380 selector = new tree.Operator(indexToken);
381 arguments = bracketList(
382 ',', [makeExpression(left.index), makeExpression(exp.right)]);
383 } else {
384 throw "Unexpected left-hand side of assignment: ${left}";
385 }
386 tree.Operator op = new tree.Operator(assignmentToken(exp.operator));
387 result = new tree.SendSet(receiver, selector, op, arguments);
388 if (left is Identifier) {
389 setElement(result, element, exp);
390 }
391 precedence = EXPRESSION;
392 } else if (exp is FieldInitializer) {
393 precedence = EXPRESSION;
394 tree.Node receiver = makeIdentifier('this');
395 tree.Node selector = makeIdentifier(exp.element.name);
396 tree.Operator op = new tree.Operator(assignmentToken("="));
397 // We pass CALLEE to ensure we write eg.:
398 // class B { var x; B() : x = (() {return a;}) {}}
399 // Not the invalid:
400 // class B { var x; B() : x = () {return a;} {}}
401 result = new tree.SendSet(
402 receiver, selector, op, singleton(makeExp(exp.body, CALLEE)));
403 setElement(result, exp.element, exp);
404 } else if (exp is SuperInitializer) {
405 precedence = EXPRESSION;
406 tree.Node receiver = makeIdentifier('super');
407 tree.NodeList arguments =
408 argList(exp.arguments.map(makeArgument).toList());
409 if (exp.target.name == "") {
410 result = new tree.Send(null, receiver, arguments);
411 } else {
412 result =
413 new tree.Send(receiver, makeIdentifier(exp.target.name), arguments);
414 }
415 setElement(result, exp.target, exp);
416 } else if (exp is BinaryOperator) {
417 precedence = BINARY_PRECEDENCE[exp.operator];
418 int deltaLeft = isAssociativeBinaryOperator(precedence) ? 0 : 1;
419 result = new tree.Send(
420 makeExp(exp.left, precedence + deltaLeft, beginStmt: beginStmt),
421 new tree.Operator(binopToken(exp.operator)),
422 singleton(makeExp(exp.right, precedence + 1)));
423 } else if (exp is CallFunction) {
424 precedence = CALLEE;
425 tree.Node selector;
426 Expression callee = exp.callee;
427 elements.Element element;
428 tree.Node receiver;
429 if (callee is Identifier) {
430 receiver = makeStaticReceiver(callee.element);
431 selector = makeIdentifier(callee.name);
432 element = callee.element;
433 } else {
434 selector = makeExp(callee, CALLEE, beginStmt: beginStmt);
435 }
436 result = new tree.Send(
437 receiver, selector, argList(exp.arguments.map(makeArgument)));
438 if (callee is Identifier) {
439 setElement(result, element, exp);
440 }
441 } else if (exp is CallMethod) {
442 precedence = CALLEE;
443 // TODO(sra): Elide receiver when This, but only if not in a scope that
444 // shadows the method (e.g. constructor body).
445 tree.Node receiver = makeExp(exp.object, PRIMARY, beginStmt: beginStmt);
446 result = new tree.Send(receiver, makeIdentifier(exp.methodName),
447 argList(exp.arguments.map(makeArgument)));
448 } else if (exp is CallNew) {
449 precedence = CALLEE;
450 tree.Node selector = makeName(exp.type.name);
451 if (exp.type.typeArguments.length > 0) {
452 selector = new tree.TypeAnnotation(
453 selector, typeArgList(exp.type.typeArguments.map(makeType)));
454 setType(selector, exp.dartType, exp);
455 }
456 if (exp.constructorName != null) {
457 selector = new tree.Send(selector, makeIdentifier(exp.constructorName));
458 }
459 tree.Send send = new tree.Send(
460 null, selector, argList(exp.arguments.map(makeArgument)));
461 result =
462 new tree.NewExpression(exp.isConst ? constToken : newToken, send);
463 setType(result, exp.dartType, exp);
464 setElement(send, exp.constructor, exp);
465 } else if (exp is CallStatic) {
466 precedence = CALLEE;
467 result = new tree.Send(
468 makeStaticReceiver(exp.element),
469 makeIdentifier(exp.methodName),
470 argList(exp.arguments.map(makeArgument)));
471 setElement(result, exp.element, exp);
472 } else if (exp is Conditional) {
473 precedence = CONDITIONAL;
474 result = new tree.Conditional(
475 makeExp(exp.condition, LOGICAL_OR, beginStmt: beginStmt),
476 makeExp(exp.thenExpression, EXPRESSION),
477 makeExp(exp.elseExpression, EXPRESSION),
478 question,
479 colon);
480 } else if (exp is FieldExpression) {
481 precedence = PRIMARY;
482 // TODO(sra): Elide receiver when This, but only if not in a scope that
483 // shadows the method (e.g. constructor body).
484 tree.Node receiver = makeExp(exp.object, PRIMARY, beginStmt: beginStmt);
485 result = new tree.Send(receiver, makeIdentifier(exp.fieldName));
486 } else if (exp is ConstructorDefinition) {
487 precedence = EXPRESSION;
488 tree.NodeList parameters = makeParameters(exp.parameters);
489 tree.NodeList initializers =
490 exp.initializers == null || exp.initializers.isEmpty
491 ? null
492 : makeList(",", exp.initializers.map(makeExpression).toList());
493 tree.Node body = exp.isConst || exp.body == null
494 ? new tree.EmptyStatement(semicolon)
495 : makeFunctionBody(exp.body);
496 result = new tree.FunctionExpression(
497 constructorName(exp),
498 // GENERIC_METHODS: In order to support generic methods fully,
499 // we must retrieve and pass the actual type variables here.
500 null, // typeVariables
501 parameters,
502 body,
503 null, // return type
504 makeFunctionModifiers(exp),
505 initializers,
506 null, // get/set
507 null); // async modifier
508 setElement(result, exp.element, exp);
509 } else if (exp is FunctionExpression) {
510 precedence = PRIMARY;
511 if (beginStmt && exp.name != null) {
512 needParen = true; // Do not mistake for function declaration.
513 }
514 Token getOrSet = exp.isGetter ? getToken : exp.isSetter ? setToken : null;
515 tree.NodeList parameters =
516 exp.isGetter ? makeList("", []) : makeParameters(exp.parameters);
517 tree.Node body = makeFunctionBody(exp.body);
518 result = new tree.FunctionExpression(
519 functionName(exp),
520 // GENERIC_METHODS: In order to support generic methods fully,
521 // we must retrieve and pass the actual type variables here.
522 null, // typeVariables
523 parameters,
524 body,
525 exp.returnType == null || exp.element.isConstructor
526 ? null
527 : makeType(exp.returnType),
528 makeFunctionModifiers(exp),
529 null, // initializers
530 getOrSet, // get/set
531 null); // async modifier
532 elements.Element element = exp.element;
533 if (element != null) setElement(result, element, exp);
534 } else if (exp is Identifier) {
535 precedence = CALLEE;
536 result = new tree.Send(
537 makeStaticReceiver(exp.element), makeIdentifier(exp.name));
538 setElement(result, exp.element, exp);
539 } else if (exp is Increment) {
540 Expression lvalue = exp.expression;
541 tree.Node receiver;
542 tree.Node selector;
543 tree.Node argument;
544 bool innerBeginStmt = beginStmt && !exp.isPrefix;
545 if (lvalue is Identifier) {
546 receiver = makeStaticReceiver(lvalue.element);
547 selector = makeIdentifier(lvalue.name);
548 } else if (lvalue is FieldExpression) {
549 receiver = makeExp(lvalue.object, PRIMARY, beginStmt: innerBeginStmt);
550 selector = makeIdentifier(lvalue.fieldName);
551 } else if (lvalue is IndexExpression) {
552 receiver = makeExp(lvalue.object, PRIMARY, beginStmt: innerBeginStmt);
553 selector = new tree.Operator(indexToken);
554 argument = makeExpression(lvalue.index);
555 } else {
556 throw "Unrecognized left-hand side: ${lvalue}";
557 }
558 tree.Operator op = new tree.Operator(incrementToken(exp.operator));
559 if (exp.isPrefix) {
560 precedence = UNARY;
561 result = new tree.SendSet.prefix(receiver, selector, op, argument);
562 } else {
563 precedence = POSTFIX_INCREMENT;
564 result = new tree.SendSet.postfix(receiver, selector, op, argument);
565 }
566 if (lvalue is Identifier) {
567 setElement(result, lvalue.element, exp);
568 }
569 } else if (exp is IndexExpression) {
570 precedence = CALLEE;
571 result = new tree.Send(
572 makeExp(exp.object, PRIMARY, beginStmt: beginStmt),
573 new tree.Operator(indexToken),
574 bracketList(',', [makeExpression(exp.index)]));
575 } else if (exp is Literal) {
576 precedence = CALLEE;
577 values.PrimitiveConstantValue value = exp.value;
578 Token tok = new StringToken.fromString(
579 STRING_INFO, '${value.primitiveValue}', -1);
580 if (value.isString) {
581 result = unparseStringLiteral(exp);
582 } else if (value.isInt) {
583 result = new tree.LiteralInt(tok, null);
584 } else if (value.isDouble) {
585 if (value.primitiveValue == double.INFINITY) {
586 precedence = MULTIPLICATIVE;
587 tok = new StringToken.fromString(STRING_INFO, '1/0.0', -1);
588 } else if (value.primitiveValue == double.NEGATIVE_INFINITY) {
589 precedence = MULTIPLICATIVE;
590 tok = new StringToken.fromString(STRING_INFO, '-1/0.0', -1);
591 } else if (value.primitiveValue.isNaN) {
592 precedence = MULTIPLICATIVE;
593 tok = new StringToken.fromString(STRING_INFO, '0/0.0', -1);
594 }
595 result = new tree.LiteralDouble(tok, null);
596 } else if (value.isBool) {
597 result = new tree.LiteralBool(tok, null);
598 } else if (value.isNull) {
599 result = new tree.LiteralNull(tok);
600 } else {
601 throw "Unrecognized constant: ${value}";
602 }
603 } else if (exp is LiteralList) {
604 precedence = PRIMARY;
605 tree.NodeList typeArgs = null;
606 if (exp.typeArgument != null) {
607 typeArgs = typeArgList([makeType(exp.typeArgument)]);
608 }
609 result = new tree.LiteralList(
610 typeArgs,
611 bracketList(',', exp.values.map(makeExpression)),
612 exp.isConst ? constToken : null);
613 } else if (exp is LiteralMap) {
614 precedence = PRIMARY;
615 if (beginStmt) {
616 // The opening brace can be confused with a block statement.
617 needParen = true;
618 }
619 tree.NodeList typeArgs = null;
620 if (exp.typeArguments != null && exp.typeArguments.length > 0) {
621 typeArgs = typeArgList(exp.typeArguments.map(makeType));
622 }
623 result = new tree.LiteralMap(
624 typeArgs,
625 braceList(',', exp.entries.map(makeLiteralMapEntry)),
626 exp.isConst ? constToken : null);
627 } else if (exp is LiteralSymbol) {
628 precedence = PRIMARY;
629 result = new tree.LiteralSymbol(
630 hash, makeList('.', exp.id.split('.').map(makeIdentifier)));
631 } else if (exp is LiteralType) {
632 precedence = TYPE_LITERAL;
633 elements.Element optionalElement = exp.type.element;
634 result = new tree.Send(
635 optionalElement == null ? null : makeStaticReceiver(optionalElement),
636 makeIdentifier(exp.name));
637 treeElements.setType(result, exp.type);
638 if (optionalElement != null) {
639 // dynamic does not have an element
640 setElement(result, optionalElement, exp);
641 }
642 } else if (exp is ReifyTypeVar) {
643 precedence = PRIMARY;
644 result = new tree.Send(null, makeIdentifier(exp.name));
645 setElement(result, exp.element, exp);
646 setType(result, exp.element.type, exp);
647 } else if (exp is StringConcat) {
648 precedence = PRIMARY;
649 result = unparseStringLiteral(exp);
650 } else if (exp is This) {
651 precedence = CALLEE;
652 result = makeIdentifier('this');
653 } else if (exp is Throw) {
654 precedence = EXPRESSION; // ???
655 result = new tree.Throw(makeExpression(exp.expression), throwToken,
656 throwToken); // endToken not used by unparser
657 } else if (exp is TypeOperator) {
658 precedence = RELATIONAL;
659 tree.Operator operator;
660 tree.Node rightOperand = makeType(exp.type);
661 if (exp.operator == 'is!') {
662 operator = new tree.Operator(typeOpToken('is'));
663 rightOperand =
664 new tree.Send(rightOperand, new tree.Operator(bang), blankList());
665 } else {
666 operator = new tree.Operator(typeOpToken(exp.operator));
667 }
668 result = new tree.Send(
669 makeExp(exp.expression, BITWISE_OR, beginStmt: beginStmt),
670 operator,
671 singleton(rightOperand));
672 } else if (exp is UnaryOperator) {
673 precedence = UNARY;
674 result = new tree.Send.prefix(makeExp(exp.operand, UNARY),
675 new tree.Operator(unopToken(exp.operatorName)));
676 } else {
677 throw "Unknown expression type: ${exp}";
678 }
679
680 needParen = needParen || precedence < minPrecedence;
681 if (needParen) {
682 result = parenthesize(result);
683 }
684 return result;
685 }
686
687 /// Creates a LiteralString with [verbatim] as the value.
688 /// No (un)quoting or (un)escaping will be performed by this method.
689 /// The [DartString] inside the literal will be set to null because the
690 /// code emitter does not use it.
691 tree.LiteralString makeVerbatimStringLiteral(String verbatim) {
692 Token tok = new StringToken.fromString(STRING_INFO, verbatim, -1);
693 return new tree.LiteralString(tok, null);
694 }
695
696 tree.LiteralMapEntry makeLiteralMapEntry(LiteralMapEntry en) {
697 return new tree.LiteralMapEntry(
698 makeExpression(en.key), colon, makeExpression(en.value));
699 }
700
701 /// A comment token to be inserted when [INSERT_NEW_BACKEND_COMMENT] is true.
702 final SymbolToken newBackendComment = new SymbolToken(
703 const PrecedenceInfo('/* new backend */ ', 0, OPEN_CURLY_BRACKET_TOKEN),
704 -1);
705
706 tree.Node makeFunctionBody(Statement stmt) {
707 if (INSERT_NEW_BACKEND_COMMENT) {
708 return new tree.Block(
709 makeList('', [makeBlock(stmt)], open: newBackendComment));
710 } else {
711 return makeBlock(stmt);
712 }
713 }
714
715 /// Produces a statement in a context where only blocks are allowed.
716 tree.Node makeBlock(Statement stmt) {
717 if (stmt is Block || stmt is EmptyStatement) {
718 return makeStatement(stmt);
719 } else {
720 return new tree.Block(braceList('', [makeStatement(stmt)]));
721 }
722 }
723
724 /// Adds the given statement to a block. If the statement itself is a block
725 /// it will be flattened (if this does not change lexical scoping).
726 void addBlockMember(Statement stmt, List<tree.Node> accumulator) {
727 if (stmt is Block && !stmt.statements.any(Unparser.definesVariable)) {
728 for (Statement innerStmt in stmt.statements) {
729 addBlockMember(innerStmt, accumulator);
730 }
731 } else if (stmt is EmptyStatement) {
732 // No need to include empty statements inside blocks
733 } else {
734 accumulator.add(makeStatement(stmt));
735 }
736 }
737
738 /// True if [stmt] is equivalent to an empty statement.
739 bool isEmptyStatement(Statement stmt) {
740 return stmt is EmptyStatement ||
741 (stmt is Block && stmt.statements.every(isEmptyStatement));
742 }
743
744 tree.Node makeStatement(Statement stmt, {bool shortIf: true}) {
745 if (stmt is Block) {
746 List<tree.Node> body = <tree.Node>[];
747 for (Statement innerStmt in stmt.statements) {
748 addBlockMember(innerStmt, body);
749 }
750 return new tree.Block(braceList('', body));
751 } else if (stmt is Break) {
752 return new tree.BreakStatement(
753 stmt.label == null ? null : makeIdentifier(stmt.label),
754 breakToken,
755 semicolon);
756 } else if (stmt is Continue) {
757 return new tree.ContinueStatement(
758 stmt.label == null ? null : makeIdentifier(stmt.label),
759 continueToken,
760 semicolon);
761 } else if (stmt is DoWhile) {
762 return new tree.DoWhile(
763 makeStatement(stmt.body, shortIf: shortIf),
764 parenthesize(makeExpression(stmt.condition)),
765 doToken,
766 whileToken,
767 semicolon);
768 } else if (stmt is EmptyStatement) {
769 return new tree.EmptyStatement(semicolon);
770 } else if (stmt is ExpressionStatement) {
771 return new tree.ExpressionStatement(
772 makeExp(stmt.expression, EXPRESSION, beginStmt: true), semicolon);
773 } else if (stmt is For) {
774 tree.Node initializer;
775 if (stmt.initializer is VariableDeclarations) {
776 initializer = makeVariableDeclarations(stmt.initializer);
777 } else if (stmt.initializer is Expression) {
778 initializer = makeExpression(stmt.initializer);
779 } else {
780 initializer = null;
781 }
782 tree.Node condition;
783 if (stmt.condition != null) {
784 condition = new tree.ExpressionStatement(
785 makeExpression(stmt.condition), semicolon);
786 } else {
787 condition = new tree.EmptyStatement(semicolon);
788 }
789 return new tree.For(
790 initializer,
791 condition,
792 makeList(',', stmt.updates.map(makeExpression)),
793 makeStatement(stmt.body, shortIf: shortIf),
794 forToken);
795 } else if (stmt is ForIn) {
796 tree.Node left;
797 if (stmt.leftHandValue is Identifier) {
798 left = makeExpression(stmt.leftHandValue);
799 } else {
800 left = makeVariableDeclarations(stmt.leftHandValue);
801 }
802 return new tree.SyncForIn(left, makeExpression(stmt.expression),
803 makeStatement(stmt.body, shortIf: shortIf), forToken, inToken);
804 } else if (stmt is FunctionDeclaration) {
805 tree.FunctionExpression function = new tree.FunctionExpression(
806 stmt.name != null ? makeIdentifier(stmt.name) : null,
807 // GENERIC_METHODS: In order to support generic methods fully,
808 // we must retrieve and pass the actual type variables here.
809 null, // typeVariables
810 makeParameters(stmt.parameters),
811 makeFunctionBody(stmt.body),
812 stmt.returnType != null ? makeType(stmt.returnType) : null,
813 makeEmptyModifiers(),
814 null, // initializers
815 null, // get/set
816 null); // async modifier
817 setElement(function, stmt.function.element, stmt);
818 return new tree.FunctionDeclaration(function);
819 } else if (stmt is If) {
820 if (stmt.elseStatement == null || isEmptyStatement(stmt.elseStatement)) {
821 tree.Node node = new tree.If(
822 parenthesize(makeExpression(stmt.condition)),
823 makeStatement(stmt.thenStatement),
824 null, // else statement
825 ifToken,
826 null); // else token
827 if (shortIf)
828 return node;
829 else
830 return new tree.Block(braceList('', [node]));
831 } else {
832 return new tree.If(
833 parenthesize(makeExpression(stmt.condition)),
834 makeStatement(stmt.thenStatement, shortIf: false),
835 makeStatement(stmt.elseStatement, shortIf: shortIf),
836 ifToken,
837 elseToken); // else token
838 }
839 } else if (stmt is LabeledStatement) {
840 List<tree.Label> labels = [];
841 Statement inner = stmt;
842 while (inner is LabeledStatement) {
843 LabeledStatement lbl = inner as LabeledStatement;
844 labels.add(new tree.Label(makeIdentifier(lbl.label), colon));
845 inner = lbl.statement;
846 }
847 return new tree.LabeledStatement(
848 makeList('', labels), makeStatement(inner, shortIf: shortIf));
849 } else if (stmt is Rethrow) {
850 return new tree.Rethrow(rethrowToken, semicolon);
851 } else if (stmt is Return) {
852 return new tree.Return(returnToken, semicolon,
853 stmt.expression == null ? null : makeExpression(stmt.expression));
854 } else if (stmt is Switch) {
855 return new tree.SwitchStatement(
856 parenthesize(makeExpression(stmt.expression)),
857 braceList('', stmt.cases.map(makeSwitchCase)),
858 switchToken);
859 } else if (stmt is Try) {
860 return new tree.TryStatement(
861 makeBlock(stmt.tryBlock),
862 makeList(null, stmt.catchBlocks.map(makeCatchBlock)),
863 stmt.finallyBlock == null ? null : makeBlock(stmt.finallyBlock),
864 tryToken,
865 stmt.finallyBlock == null ? null : finallyToken);
866 } else if (stmt is VariableDeclarations) {
867 return makeVariableDeclarations(stmt, useVar: true, endToken: semicolon);
868 } else if (stmt is While) {
869 return new tree.While(parenthesize(makeExpression(stmt.condition)),
870 makeStatement(stmt.body, shortIf: shortIf), whileToken);
871 } else {
872 throw "Unrecognized statement: ${stmt}";
873 }
874 }
875
876 tree.Node makeVariableDeclaration(VariableDeclaration vd) {
877 tree.Node id = makeIdentifier(vd.name);
878 setElement(id, vd.element, vd);
879 if (vd.initializer == null) {
880 return id;
881 }
882 tree.Node send = new tree.SendSet(null, id, new tree.Operator(eq),
883 singleton(makeExpression(vd.initializer)));
884 setElement(send, vd.element, vd);
885 return send;
886 }
887
888 /// If [useVar] is true, the variable definition will use `var` as modifier
889 /// if no other modifiers are present.
890 /// [endToken] will be used to terminate the declaration list.
891 tree.Node makeVariableDeclarations(VariableDeclarations decl,
892 {bool useVar: false, Token endToken: null}) {
893 return new tree.VariableDefinitions(
894 decl.type == null ? null : makeType(decl.type),
895 makeVarModifiers(
896 isConst: decl.isConst,
897 isFinal: decl.isFinal,
898 useVar: useVar && decl.type == null),
899 makeList(',', decl.declarations.map(makeVariableDeclaration),
900 close: endToken));
901 }
902
903 tree.CatchBlock makeCatchBlock(CatchBlock block) {
904 List<tree.VariableDefinitions> formals = [];
905 if (block.exceptionVar != null) {
906 tree.Node exceptionName = makeIdentifier(block.exceptionVar.name);
907 setElement(exceptionName, block.exceptionVar.element, block.exceptionVar);
908 formals.add(new tree.VariableDefinitions(
909 null, makeEmptyModifiers(), singleton(exceptionName)));
910 }
911 if (block.stackVar != null) {
912 tree.Node stackTraceName = makeIdentifier(block.stackVar.name);
913 setElement(stackTraceName, block.stackVar.element, block.stackVar);
914 formals.add(new tree.VariableDefinitions(
915 null, makeEmptyModifiers(), singleton(stackTraceName)));
916 }
917 return new tree.CatchBlock(
918 block.onType == null ? null : makeType(block.onType),
919 block.exceptionVar == null ? null : argList(formals),
920 makeBlock(block.body),
921 block.onType == null ? null : onToken,
922 block.exceptionVar == null ? null : catchToken);
923 }
924
925 tree.SwitchCase makeSwitchCase(SwitchCase caze) {
926 if (caze.isDefaultCase) {
927 return new tree.SwitchCase(
928 blankList(),
929 defaultToken,
930 makeList('', caze.statements.map(makeStatement)),
931 null); // startToken unused by unparser
932 } else {
933 return new tree.SwitchCase(
934 makeList('', caze.expressions.map(makeCaseMatch)),
935 null, // defaultKeyword,
936 makeList('', caze.statements.map(makeStatement)),
937 null); // startToken unused by unparser
938 }
939 }
940
941 tree.CaseMatch makeCaseMatch(Expression exp) {
942 return new tree.CaseMatch(caseToken, makeExpression(exp), colon);
943 }
944
945 tree.TypeAnnotation makeType(TypeAnnotation type) {
946 tree.NodeList typeArgs;
947 if (type.typeArguments.length > 0) {
948 typeArgs = typeArgList(type.typeArguments.map(makeType));
949 } else {
950 typeArgs = null;
951 }
952 tree.TypeAnnotation result =
953 new tree.TypeAnnotation(makeIdentifier(type.name), typeArgs);
954 setType(result, type.dartType, type);
955 return result;
956 }
957
958 tree.NodeList makeParameters(Parameters params) {
959 List<tree.Node> nodes =
960 params.requiredParameters.map(makeParameter).toList();
961 if (params.hasOptionalParameters) {
962 Token assign = params.hasNamedParameters ? colon : eq;
963 Token open = params.hasNamedParameters ? openBrace : openBracket;
964 Token close = params.hasNamedParameters ? closeBrace : closeBracket;
965 Iterable<tree.Node> opt =
966 params.optionalParameters.map((p) => makeParameter(p, assign));
967 nodes.add(new tree.NodeList(open, makeLink(opt), close, ','));
968 }
969 return argList(nodes);
970 }
971
972 /// [assignOperator] is used for writing the default value.
973 tree.Node makeParameter(Parameter param, [Token assignOperator]) {
974 if (param.isFunction) {
975 tree.Node definition = new tree.FunctionExpression(
976 makeIdentifier(param.name),
977 // GENERIC_METHODS: In order to support generic methods fully,
978 // we must retrieve and pass the actual type variables here.
979 null, // typeVariables
980 makeParameters(param.parameters),
981 null, // body
982 param.type == null ? null : makeType(param.type),
983 makeEmptyModifiers(), // TODO: Function parameter modifiers?
984 null, // initializers
985 null, // get/set
986 null); // async modifier
987 if (param.element != null) {
988 setElement(definition, param.element, param);
989 }
990 if (param.defaultValue != null) {
991 definition = new tree.SendSet(
992 null,
993 definition,
994 new tree.Operator(assignOperator),
995 singleton(makeExpression(param.defaultValue)));
996 }
997 return new tree.VariableDefinitions(
998 null, makeEmptyModifiers(), singleton(definition));
999 } else {
1000 tree.Node definition;
1001 if (param.defaultValue != null) {
1002 definition = new tree.SendSet(
1003 null,
1004 makeIdentifier(param.name),
1005 new tree.Operator(assignOperator),
1006 singleton(makeExpression(param.defaultValue)));
1007 } else {
1008 definition = makeIdentifier(param.name);
1009 }
1010 if (param.element != null) {
1011 setElement(definition, param.element, param);
1012 }
1013 return new tree.VariableDefinitions(
1014 param.type == null ? null : makeType(param.type),
1015 makeEmptyModifiers(), // TODO: Parameter modifiers?
1016 singleton(definition));
1017 }
1018 }
1019
1020 tree.Modifiers makeEmptyModifiers() {
1021 return new tree.Modifiers(blankList());
1022 }
1023
1024 tree.Modifiers makeModifiers(
1025 {bool isExternal: false,
1026 bool isStatic: false,
1027 bool isAbstract: false,
1028 bool isFactory: false,
1029 bool isConst: false,
1030 bool isFinal: false,
1031 bool isVar: false}) {
1032 List<tree.Node> nodes = [];
1033 if (isExternal) {
1034 nodes.add(makeIdentifier('external'));
1035 }
1036 if (isStatic) {
1037 nodes.add(makeIdentifier('static'));
1038 }
1039 if (isAbstract) {
1040 nodes.add(makeIdentifier('abstract'));
1041 }
1042 if (isFactory) {
1043 nodes.add(makeIdentifier('factory'));
1044 }
1045 if (isConst) {
1046 nodes.add(makeIdentifier('const'));
1047 }
1048 if (isFinal) {
1049 nodes.add(makeIdentifier('final'));
1050 }
1051 if (isVar) {
1052 nodes.add(makeIdentifier('var'));
1053 }
1054 return new tree.Modifiers(makeList(' ', nodes));
1055 }
1056
1057 tree.Modifiers makeVarModifiers(
1058 {bool isConst: false,
1059 bool isFinal: false,
1060 bool useVar: false,
1061 bool isStatic: false}) {
1062 return makeModifiers(
1063 isStatic: isStatic,
1064 isConst: isConst,
1065 isFinal: isFinal,
1066 isVar: useVar && !(isConst || isFinal));
1067 }
1068
1069 tree.Modifiers makeFunctionModifiers(FunctionExpression exp) {
1070 if (exp.element == null) return makeEmptyModifiers();
1071 return makeModifiers(
1072 isExternal: exp.element.isExternal,
1073 isStatic: exp.element.isStatic,
1074 isFactory: exp.element.isFactoryConstructor,
1075 isConst: exp.element.isConst);
1076 }
1077
1078 tree.Node makeNodeForClassElement(elements.ClassElement cls) {
1079 if (cls.isMixinApplication) {
1080 return makeNamedMixinApplication(cls);
1081 } else if (cls.isEnumClass) {
1082 return makeEnum(cls);
1083 } else {
1084 return makeClassNode(cls);
1085 }
1086 }
1087
1088 tree.Typedef makeTypedef(elements.TypedefElement typdef) {
1089 types.FunctionType functionType = typdef.alias;
1090 final tree.TypeAnnotation returnType =
1091 makeType(TypeGenerator.createType(functionType.returnType));
1092
1093 final tree.Identifier name = makeIdentifier(typdef.name);
1094 final tree.NodeList typeParameters =
1095 makeTypeParameters(typdef.typeVariables);
1096 final tree.NodeList formals =
1097 makeParameters(TypeGenerator.createParametersFromType(functionType));
1098
1099 final Token typedefKeyword = typedefToken;
1100 final Token endToken = semicolon;
1101
1102 return new tree.Typedef(
1103 returnType, name, typeParameters, formals, typedefKeyword, endToken);
1104 }
1105
1106 /// Create a [tree.NodeList] containing the type variable declarations in
1107 /// [typeVaraiables.
1108 tree.NodeList makeTypeParameters(List<types.DartType> typeVariables) {
1109 if (typeVariables.isEmpty) {
1110 return new tree.NodeList.empty();
1111 } else {
1112 List<tree.Node> typeVariableList = <tree.Node>[];
1113 for (types.TypeVariableType typeVariable in typeVariables) {
1114 tree.Node id = makeIdentifier(typeVariable.name);
1115 treeElements[id] = typeVariable.element;
1116 tree.Node bound;
1117 if (!typeVariable.element.bound.isObject) {
1118 bound =
1119 makeType(TypeGenerator.createType(typeVariable.element.bound));
1120 }
1121 tree.TypeVariable node = new tree.TypeVariable(id, extendsToken, bound);
1122 treeElements.setType(node, typeVariable);
1123 typeVariableList.add(node);
1124 }
1125 return makeList(',', typeVariableList, open: lt, close: gt);
1126 }
1127 }
1128
1129 /// Create a [tree.NodeList] containing the declared interfaces.
1130 ///
1131 /// [interfaces] is from [elements.ClassElement] in reverse declaration order
1132 /// and it contains mixins. To produce a list of the declared interfaces only,
1133 /// interfaces in [mixinTypes] are omitted.
1134 ///
1135 /// [forNamedMixinApplication] is because the structure of the [tree.NodeList]
1136 /// differs between [tree.NamedMixinApplication] and [tree.ClassNode].
1137 // TODO(johnniwinther): Normalize interfaces on[tree.NamedMixinApplication]
1138 // and [tree.ClassNode].
1139 tree.NodeList makeInterfaces(
1140 Link<types.DartType> interfaces, Set<types.DartType> mixinTypes,
1141 {bool forNamedMixinApplication: false}) {
1142 Link<tree.Node> typeAnnotations = const Link<tree.Node>();
1143 for (Link<types.DartType> link = interfaces;
1144 !link.isEmpty;
1145 link = link.tail) {
1146 types.DartType interface = link.head;
1147 if (!mixinTypes.contains(interface)) {
1148 typeAnnotations = typeAnnotations
1149 .prepend(makeType(TypeGenerator.createType(interface)));
1150 }
1151 }
1152 if (typeAnnotations.isEmpty) {
1153 return forNamedMixinApplication ? null : new tree.NodeList.empty();
1154 } else {
1155 return new tree.NodeList(
1156 forNamedMixinApplication ? null : implementsToken,
1157 typeAnnotations,
1158 null,
1159 ',');
1160 }
1161 }
1162
1163 /// Creates a [tree.NamedMixinApplication] node for [cls].
1164 // TODO(johnniwinther): Unify creation of mixin lists between
1165 // [NamedMixinApplicationElement] and [ClassElement].
1166 tree.NamedMixinApplication makeNamedMixinApplication(
1167 elements.MixinApplicationElement cls) {
1168 assert(invariant(cls, !cls.isUnnamedMixinApplication,
1169 message: "Cannot create ClassNode for unnamed mixin application "
1170 "$cls."));
1171 tree.Modifiers modifiers = makeModifiers(isAbstract: cls.isAbstract);
1172 tree.Identifier name = makeIdentifier(cls.name);
1173 tree.NodeList typeParameters = makeTypeParameters(cls.typeVariables);
1174
1175 Set<types.DartType> mixinTypes = new Set<types.DartType>();
1176 Link<tree.Node> mixins = const Link<tree.Node>();
1177
1178 void addMixin(types.DartType mixinType) {
1179 mixinTypes.add(mixinType);
1180 mixins = mixins.prepend(makeType(TypeGenerator.createType(mixinType)));
1181 }
1182
1183 addMixin(cls.mixinType);
1184
1185 tree.Node superclass;
1186 types.InterfaceType supertype = cls.supertype;
1187 while (supertype.element.isUnnamedMixinApplication) {
1188 elements.MixinApplicationElement mixinApplication = supertype.element;
1189 addMixin(cls.asInstanceOf(mixinApplication.mixin));
1190 supertype = mixinApplication.supertype;
1191 }
1192 superclass =
1193 makeType(TypeGenerator.createType(cls.asInstanceOf(supertype.element)));
1194 tree.Node supernode = new tree.MixinApplication(
1195 superclass, new tree.NodeList(null, mixins, null, ','));
1196
1197 tree.NodeList interfaces = makeInterfaces(cls.interfaces, mixinTypes,
1198 forNamedMixinApplication: true);
1199
1200 return new tree.NamedMixinApplication(name, typeParameters, modifiers,
1201 supernode, interfaces, classToken, semicolon);
1202 }
1203
1204 tree.Enum makeEnum(elements.EnumClassElement cls) {
1205 return new tree.Enum(
1206 enumToken,
1207 makeIdentifier(cls.name),
1208 makeList(',', cls.enumValues.map((e) => makeIdentifier(e.name)),
1209 open: openBrace, close: closeBrace));
1210 }
1211
1212 /// Creates a [tree.ClassNode] node for [cls].
1213 tree.ClassNode makeClassNode(elements.ClassElement cls) {
1214 assert(invariant(cls, !cls.isUnnamedMixinApplication,
1215 message: "Cannot create ClassNode for unnamed mixin application "
1216 "$cls."));
1217 tree.Modifiers modifiers = makeModifiers(isAbstract: cls.isAbstract);
1218 tree.Identifier name = makeIdentifier(cls.name);
1219 tree.NodeList typeParameters = makeTypeParameters(cls.typeVariables);
1220 tree.Node supernode;
1221 types.InterfaceType supertype = cls.supertype;
1222 Set<types.DartType> mixinTypes = new Set<types.DartType>();
1223 Link<tree.Node> mixins = const Link<tree.Node>();
1224
1225 void addMixin(types.DartType mixinType) {
1226 mixinTypes.add(mixinType);
1227 mixins = mixins.prepend(makeType(TypeGenerator.createType(mixinType)));
1228 }
1229
1230 if (supertype != null) {
1231 if (supertype.element.isUnnamedMixinApplication) {
1232 while (supertype.element.isUnnamedMixinApplication) {
1233 elements.MixinApplicationElement mixinApplication = supertype.element;
1234 addMixin(cls.asInstanceOf(mixinApplication.mixin));
1235 supertype = mixinApplication.supertype;
1236 }
1237 tree.Node superclass = makeType(
1238 TypeGenerator.createType(cls.asInstanceOf(supertype.element)));
1239 supernode = new tree.MixinApplication(
1240 superclass, new tree.NodeList(null, mixins, null, ','));
1241 } else if (!supertype.isObject) {
1242 supernode = makeType(TypeGenerator.createType(supertype));
1243 }
1244 }
1245 tree.NodeList interfaces = makeInterfaces(cls.interfaces, mixinTypes);
1246
1247 Token extendsKeyword = supernode != null ? extendsToken : null;
1248 return new tree.ClassNode(
1249 modifiers,
1250 name,
1251 typeParameters,
1252 supernode,
1253 interfaces,
1254 openBrace,
1255 extendsKeyword,
1256 null, // No body.
1257 closeBrace);
1258 }
1259
1260 tree.Node constructorName(ConstructorDefinition exp) {
1261 String name = exp.name;
1262 tree.Identifier className = makeIdentifier(exp.element.enclosingClass.name);
1263 tree.Node result =
1264 name == "" ? className : new tree.Send(className, makeIdentifier(name));
1265 setElement(result, exp.element, exp);
1266 return result;
1267 }
1268
1269 tree.Node functionName(FunctionExpression exp) {
1270 String name = exp.name;
1271 if (name == null) return null;
1272 if (isUserDefinableOperator(name)) {
1273 return makeOperator("operator$name");
1274 } else if (name == "unary-") {
1275 return makeOperator("operator-");
1276 }
1277 return makeIdentifier(name);
1278 }
1279
1280 tree.Node parenthesize(tree.Node node) {
1281 return new tree.ParenthesizedExpression(node, openParen);
1282 }
1283
1284 tree.Node unparseStringLiteral(Expression exp) {
1285 StringLiteralOutput output = Unparser.analyzeStringLiteral(exp);
1286 List parts = output.parts;
1287 tree.Node printStringChunk(StringChunk chunk) {
1288 bool raw = chunk.quoting.raw;
1289 int quoteCode = chunk.quoting.quote;
1290
1291 List<tree.StringInterpolationPart> literalParts = [];
1292 tree.LiteralString firstLiteral;
1293 tree.Node currentInterpolation;
1294
1295 // sb contains the current unfinished LiteralString
1296 StringBuffer sb = new StringBuffer();
1297 if (raw) {
1298 sb.write('r');
1299 }
1300 for (int i = 0; i < chunk.quoting.leftQuoteCharCount; i++) {
1301 sb.write(chunk.quoting.quoteChar);
1302 }
1303
1304 // Print every character and string interpolation
1305 int startIndex = chunk.previous != null ? chunk.previous.endIndex : 0;
1306 for (int i = startIndex; i < chunk.endIndex; i++) {
1307 var part = parts[i];
1308 if (part is Expression) {
1309 // Finish the previous string interpolation, if there is one.
1310 tree.LiteralString lit = makeVerbatimStringLiteral(sb.toString());
1311 if (currentInterpolation != null) {
1312 literalParts.add(
1313 new tree.StringInterpolationPart(currentInterpolation, lit));
1314 } else {
1315 firstLiteral = lit;
1316 }
1317 sb.clear();
1318 currentInterpolation = makeExpression(part);
1319 } else {
1320 int char = part;
1321 sb.write(Unparser.getEscapedCharacter(char, quoteCode, raw));
1322 }
1323 }
1324
1325 // Print ending quotes
1326 for (int i = 0; i < chunk.quoting.rightQuoteLength; i++) {
1327 sb.write(chunk.quoting.quoteChar);
1328 }
1329
1330 // Finish the previous string interpolation, if there is one.
1331 // Then wrap everything in a StringInterpolation, if relevant.
1332 tree.LiteralString lit = makeVerbatimStringLiteral(sb.toString());
1333 tree.Node node;
1334 if (firstLiteral == null) {
1335 node = lit;
1336 } else {
1337 literalParts
1338 .add(new tree.StringInterpolationPart(currentInterpolation, lit));
1339 node = new tree.StringInterpolation(
1340 firstLiteral, makeList('', literalParts));
1341 }
1342
1343 // Juxtapose with the previous string chunks, if any.
1344 if (chunk.previous != null) {
1345 return new tree.StringJuxtaposition(
1346 printStringChunk(chunk.previous), node);
1347 } else {
1348 return node;
1349 }
1350 }
1351 return printStringChunk(output.chunk);
1352 }
1353 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart ('k') | pkg/compiler/lib/src/dart_backend/dart_backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698