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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/tree/nodes.dart

Issue 692513002: Remove old dart2js code. (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) 2012, 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 part of tree;
6
7 abstract class Visitor<R> {
8 const Visitor();
9
10 R visitNode(Node node);
11
12 R visitBlock(Block node) => visitStatement(node);
13 R visitBreakStatement(BreakStatement node) => visitGotoStatement(node);
14 R visitCascade(Cascade node) => visitExpression(node);
15 R visitCascadeReceiver(CascadeReceiver node) => visitExpression(node);
16 R visitCaseMatch(CaseMatch node) => visitNode(node);
17 R visitCatchBlock(CatchBlock node) => visitNode(node);
18 R visitClassNode(ClassNode node) => visitNode(node);
19 R visitCombinator(Combinator node) => visitNode(node);
20 R visitConditional(Conditional node) => visitExpression(node);
21 R visitContinueStatement(ContinueStatement node) => visitGotoStatement(node);
22 R visitDoWhile(DoWhile node) => visitLoop(node);
23 R visitEmptyStatement(EmptyStatement node) => visitStatement(node);
24 R visitExport(Export node) => visitLibraryDependency(node);
25 R visitExpression(Expression node) => visitNode(node);
26 R visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
27 R visitFor(For node) => visitLoop(node);
28 R visitForIn(ForIn node) => visitLoop(node);
29 R visitFunctionDeclaration(FunctionDeclaration node) => visitStatement(node);
30 R visitFunctionExpression(FunctionExpression node) => visitExpression(node);
31 R visitGotoStatement(GotoStatement node) => visitStatement(node);
32 R visitIdentifier(Identifier node) => visitExpression(node);
33 R visitIf(If node) => visitStatement(node);
34 R visitImport(Import node) => visitLibraryDependency(node);
35 R visitLabel(Label node) => visitNode(node);
36 R visitLabeledStatement(LabeledStatement node) => visitStatement(node);
37 R visitLibraryDependency(LibraryDependency node) => visitLibraryTag(node);
38 R visitLibraryName(LibraryName node) => visitLibraryTag(node);
39 R visitLibraryTag(LibraryTag node) => visitNode(node);
40 R visitLiteral(Literal node) => visitExpression(node);
41 R visitLiteralBool(LiteralBool node) => visitLiteral(node);
42 R visitLiteralDouble(LiteralDouble node) => visitLiteral(node);
43 R visitLiteralInt(LiteralInt node) => visitLiteral(node);
44 R visitLiteralList(LiteralList node) => visitExpression(node);
45 R visitLiteralMap(LiteralMap node) => visitExpression(node);
46 R visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node);
47 R visitLiteralNull(LiteralNull node) => visitLiteral(node);
48 R visitLiteralString(LiteralString node) => visitStringNode(node);
49 R visitStringJuxtaposition(StringJuxtaposition node) => visitStringNode(node);
50 R visitLoop(Loop node) => visitStatement(node);
51 R visitMetadata(Metadata node) => visitNode(node);
52 R visitMixinApplication(MixinApplication node) => visitNode(node);
53 R visitModifiers(Modifiers node) => visitNode(node);
54 R visitNamedArgument(NamedArgument node) => visitExpression(node);
55 R visitNamedMixinApplication(NamedMixinApplication node) {
56 return visitMixinApplication(node);
57 }
58 R visitNewExpression(NewExpression node) => visitExpression(node);
59 R visitNodeList(NodeList node) => visitNode(node);
60 R visitOperator(Operator node) => visitIdentifier(node);
61 R visitParenthesizedExpression(ParenthesizedExpression node) {
62 return visitExpression(node);
63 }
64 R visitPart(Part node) => visitLibraryTag(node);
65 R visitPartOf(PartOf node) => visitNode(node);
66 R visitPostfix(Postfix node) => visitNodeList(node);
67 R visitPrefix(Prefix node) => visitNodeList(node);
68 R visitRedirectingFactoryBody(RedirectingFactoryBody node) {
69 return visitStatement(node);
70 }
71 R visitRethrow(Rethrow node) => visitStatement(node);
72 R visitReturn(Return node) => visitStatement(node);
73 R visitSend(Send node) => visitExpression(node);
74 R visitSendSet(SendSet node) => visitSend(node);
75 R visitStatement(Statement node) => visitNode(node);
76 R visitStringNode(StringNode node) => visitExpression(node);
77 R visitStringInterpolation(StringInterpolation node) => visitStringNode(node);
78 R visitStringInterpolationPart(StringInterpolationPart node) {
79 return visitNode(node);
80 }
81 R visitSwitchCase(SwitchCase node) => visitNode(node);
82 R visitSwitchStatement(SwitchStatement node) => visitStatement(node);
83 R visitLiteralSymbol(LiteralSymbol node) => visitExpression(node);
84 R visitThrow(Throw node) => visitExpression(node);
85 R visitTryStatement(TryStatement node) => visitStatement(node);
86 R visitTypeAnnotation(TypeAnnotation node) => visitNode(node);
87 R visitTypedef(Typedef node) => visitNode(node);
88 R visitTypeVariable(TypeVariable node) => visitNode(node);
89 R visitVariableDefinitions(VariableDefinitions node) => visitStatement(node);
90 R visitWhile(While node) => visitLoop(node);
91 }
92
93 Token firstBeginToken(Node first, Node second) {
94 Token token = null;
95 if (first != null) {
96 token = first.getBeginToken();
97 }
98 if (token == null && second != null) {
99 // [token] might be null even when [first] is not, e.g. for empty Modifiers.
100 token = second.getBeginToken();
101 }
102 return token;
103 }
104
105 /**
106 * A node in a syntax tree.
107 *
108 * The abstract part of "abstract syntax tree" is invalidated when
109 * supporting tools such as code formatting. These tools need concrete
110 * syntax such as parentheses and no constant folding.
111 *
112 * We support these tools by storing additional references back to the
113 * token stream. These references are stored in fields ending with
114 * "Token".
115 */
116 abstract class Node extends NullTreeElementMixin implements Spannable {
117 final int hashCode;
118 static int _HASH_COUNTER = 0;
119
120 Node() : hashCode = ++_HASH_COUNTER;
121
122 accept(Visitor visitor);
123
124 visitChildren(Visitor visitor);
125
126 /**
127 * Returns this node unparsed to Dart source string.
128 */
129 toString() => unparse(this);
130
131 /**
132 * Returns Xml-like tree representation of this node.
133 */
134 toDebugString() {
135 return PrettyPrinter.prettyPrint(this);
136 }
137
138 String getObjectDescription() => super.toString();
139
140 Token getBeginToken();
141
142 Token getEndToken();
143
144 Block asBlock() => null;
145 BreakStatement asBreakStatement() => null;
146 Cascade asCascade() => null;
147 CascadeReceiver asCascadeReceiver() => null;
148 CaseMatch asCaseMatch() => null;
149 CatchBlock asCatchBlock() => null;
150 ClassNode asClassNode() => null;
151 Combinator asCombinator() => null;
152 Conditional asConditional() => null;
153 ContinueStatement asContinueStatement() => null;
154 DoWhile asDoWhile() => null;
155 EmptyStatement asEmptyStatement() => null;
156 ErrorExpression asErrorExpression() => null;
157 Export asExport() => null;
158 Expression asExpression() => null;
159 ExpressionStatement asExpressionStatement() => null;
160 For asFor() => null;
161 ForIn asForIn() => null;
162 FunctionDeclaration asFunctionDeclaration() => null;
163 FunctionExpression asFunctionExpression() => null;
164 Identifier asIdentifier() => null;
165 If asIf() => null;
166 Import asImport() => null;
167 Label asLabel() => null;
168 LabeledStatement asLabeledStatement() => null;
169 LibraryName asLibraryName() => null;
170 LibraryDependency asLibraryDependency() => null;
171 LiteralBool asLiteralBool() => null;
172 LiteralDouble asLiteralDouble() => null;
173 LiteralInt asLiteralInt() => null;
174 LiteralList asLiteralList() => null;
175 LiteralMap asLiteralMap() => null;
176 LiteralMapEntry asLiteralMapEntry() => null;
177 LiteralNull asLiteralNull() => null;
178 LiteralString asLiteralString() => null;
179 LiteralSymbol asLiteralSymbol() => null;
180 Metadata asMetadata() => null;
181 MixinApplication asMixinApplication() => null;
182 Modifiers asModifiers() => null;
183 NamedArgument asNamedArgument() => null;
184 NamedMixinApplication asNamedMixinApplication() => null;
185 NewExpression asNewExpression() => null;
186 NodeList asNodeList() => null;
187 Operator asOperator() => null;
188 ParenthesizedExpression asParenthesizedExpression() => null;
189 Part asPart() => null;
190 PartOf asPartOf() => null;
191 RedirectingFactoryBody asRedirectingFactoryBody() => null;
192 Rethrow asRethrow() => null;
193 Return asReturn() => null;
194 Send asSend() => null;
195 SendSet asSendSet() => null;
196 Statement asStatement() => null;
197 StringInterpolation asStringInterpolation() => null;
198 StringInterpolationPart asStringInterpolationPart() => null;
199 StringJuxtaposition asStringJuxtaposition() => null;
200 StringNode asStringNode() => null;
201 SwitchCase asSwitchCase() => null;
202 SwitchStatement asSwitchStatement() => null;
203 Throw asThrow() => null;
204 TryStatement asTryStatement() => null;
205 TypeAnnotation asTypeAnnotation() => null;
206 TypeVariable asTypeVariable() => null;
207 Typedef asTypedef() => null;
208 VariableDefinitions asVariableDefinitions() => null;
209 While asWhile() => null;
210
211 bool isValidBreakTarget() => false;
212 bool isValidContinueTarget() => false;
213 bool isThis() => false;
214 bool isSuper() => false;
215
216 bool get isErroneous => false;
217 }
218
219 class ClassNode extends Node {
220 final Modifiers modifiers;
221 final Identifier name;
222 final Node superclass;
223 final NodeList interfaces;
224 final NodeList typeParameters;
225 final NodeList body;
226
227 final Token beginToken;
228 final Token extendsKeyword;
229 final Token endToken;
230
231 ClassNode(this.modifiers, this.name, this.typeParameters, this.superclass,
232 this.interfaces, this.beginToken,
233 this.extendsKeyword, this.body, this.endToken);
234
235 ClassNode asClassNode() => this;
236
237 accept(Visitor visitor) => visitor.visitClassNode(this);
238
239 visitChildren(Visitor visitor) {
240 if (name != null) name.accept(visitor);
241 if (typeParameters != null) typeParameters.accept(visitor);
242 if (superclass != null) superclass.accept(visitor);
243 if (interfaces != null) interfaces.accept(visitor);
244 if (body != null) body.accept(visitor);
245 }
246
247 Token getBeginToken() => beginToken;
248
249 Token getEndToken() => endToken;
250 }
251
252 class MixinApplication extends Node {
253 final TypeAnnotation superclass;
254 final NodeList mixins;
255
256 MixinApplication(this.superclass, this.mixins);
257
258 MixinApplication asMixinApplication() => this;
259
260 accept(Visitor visitor) => visitor.visitMixinApplication(this);
261
262 visitChildren(Visitor visitor) {
263 if (superclass != null) superclass.accept(visitor);
264 if (mixins != null) mixins.accept(visitor);
265 }
266
267 Token getBeginToken() => superclass.getBeginToken();
268 Token getEndToken() => mixins.getEndToken();
269 }
270
271 // TODO(kasperl): Let this share some structure with the typedef for function
272 // type aliases?
273 class NamedMixinApplication extends Node implements MixinApplication {
274 final Identifier name;
275 final NodeList typeParameters;
276
277 final Modifiers modifiers;
278 final MixinApplication mixinApplication;
279 final NodeList interfaces;
280
281 final Token classKeyword;
282 final Token endToken;
283
284 NamedMixinApplication(this.name, this.typeParameters,
285 this.modifiers, this.mixinApplication, this.interfaces,
286 this.classKeyword, this.endToken);
287
288 TypeAnnotation get superclass => mixinApplication.superclass;
289 NodeList get mixins => mixinApplication.mixins;
290
291 MixinApplication asMixinApplication() => this;
292 NamedMixinApplication asNamedMixinApplication() => this;
293
294 accept(Visitor visitor) => visitor.visitNamedMixinApplication(this);
295
296 visitChildren(Visitor visitor) {
297 name.accept(visitor);
298 if (typeParameters != null) typeParameters.accept(visitor);
299 if (modifiers != null) modifiers.accept(visitor);
300 if (interfaces != null) interfaces.accept(visitor);
301 mixinApplication.accept(visitor);
302 }
303
304 Token getBeginToken() => classKeyword;
305 Token getEndToken() => endToken;
306 }
307
308 abstract class Expression extends Node {
309 Expression();
310
311 Expression asExpression() => this;
312
313 // TODO(ahe): make class abstract instead of adding an abstract method.
314 accept(Visitor visitor);
315 }
316
317 abstract class Statement extends Node {
318 Statement();
319
320 Statement asStatement() => this;
321
322 // TODO(ahe): make class abstract instead of adding an abstract method.
323 accept(Visitor visitor);
324
325 bool isValidBreakTarget() => true;
326 }
327
328 /// Erroneous expression that behaves as a literal null.
329 class ErrorExpression extends LiteralNull {
330 ErrorExpression(token)
331 : super(token);
332
333 ErrorExpression asErrorExpression() => this;
334
335 bool get isErroneous => true;
336 }
337
338 /**
339 * A message send aka method invocation. In Dart, most operations can
340 * (and should) be considered as message sends. Getters and setters
341 * are just methods with a special syntax. Consequently, we model
342 * property access, assignment, operators, and method calls with this
343 * one node.
344 */
345 class Send extends Expression with StoredTreeElementMixin {
346 final Node receiver;
347 final Node selector;
348 final NodeList argumentsNode;
349 Link<Node> get arguments => argumentsNode.nodes;
350
351 Send([this.receiver, this.selector, this.argumentsNode]);
352 Send.postfix(this.receiver, this.selector, [Node argument = null])
353 : argumentsNode = (argument == null)
354 ? new Postfix()
355 : new Postfix.singleton(argument);
356 Send.prefix(this.receiver, this.selector, [Node argument = null])
357 : argumentsNode = (argument == null)
358 ? new Prefix()
359 : new Prefix.singleton(argument);
360
361 Send asSend() => this;
362
363 accept(Visitor visitor) => visitor.visitSend(this);
364
365 visitChildren(Visitor visitor) {
366 if (receiver != null) receiver.accept(visitor);
367 if (selector != null) selector.accept(visitor);
368 if (argumentsNode != null) argumentsNode.accept(visitor);
369 }
370
371 int argumentCount() {
372 return (argumentsNode == null) ? -1 : argumentsNode.slowLength();
373 }
374
375 bool get isSuperCall {
376 return receiver != null && receiver.isSuper();
377 }
378 bool get isOperator => selector is Operator;
379 bool get isPropertyAccess => argumentsNode == null;
380 bool get isFunctionObjectInvocation => selector == null;
381 bool get isPrefix => argumentsNode is Prefix;
382 bool get isPostfix => argumentsNode is Postfix;
383 bool get isCall => !isOperator && !isPropertyAccess;
384 bool get isIndex =>
385 isOperator && identical(selector.asOperator().source, '[]');
386 bool get isLogicalAnd =>
387 isOperator && identical(selector.asOperator().source, '&&');
388 bool get isLogicalOr =>
389 isOperator && identical(selector.asOperator().source, '||');
390
391 bool get isTypeCast {
392 return isOperator
393 && identical(selector.asOperator().source, 'as');
394 }
395
396 bool get isTypeTest {
397 return isOperator
398 && identical(selector.asOperator().source, 'is');
399 }
400
401 bool get isIsNotCheck {
402 return isTypeTest && arguments.head.asSend() != null;
403 }
404
405 TypeAnnotation get typeAnnotationFromIsCheckOrCast {
406 assert(isOperator);
407 assert(identical(selector.asOperator().source, 'is') ||
408 identical(selector.asOperator().source, 'as'));
409 return isIsNotCheck
410 ? arguments.head.asSend().receiver
411 : arguments.head;
412 }
413
414 Token getBeginToken() {
415 if (isPrefix && !isIndex) return selector.getBeginToken();
416 return firstBeginToken(receiver, selector);
417 }
418
419 Token getEndToken() {
420 if (isPrefix) {
421 if (receiver != null) return receiver.getEndToken();
422 if (selector != null) return selector.getEndToken();
423 return null;
424 }
425 if (!isPostfix && argumentsNode != null) {
426 Token token = argumentsNode.getEndToken();
427 if (token != null) return token;
428 }
429 if (selector != null) return selector.getEndToken();
430 return getBeginToken();
431 }
432
433 Send copyWithReceiver(Node newReceiver) {
434 assert(receiver == null);
435 return new Send(newReceiver, selector, argumentsNode);
436 }
437 }
438
439 class Postfix extends NodeList {
440 Postfix() : super(null, const Link<Node>());
441 Postfix.singleton(Node argument) : super.singleton(argument);
442 }
443
444 class Prefix extends NodeList {
445 Prefix() : super(null, const Link<Node>());
446 Prefix.singleton(Node argument) : super.singleton(argument);
447 }
448
449 class SendSet extends Send {
450 final Operator assignmentOperator;
451 SendSet(receiver, selector, this.assignmentOperator, argumentsNode)
452 : super(receiver, selector, argumentsNode);
453 SendSet.postfix(receiver,
454 selector,
455 this.assignmentOperator,
456 [Node argument = null])
457 : super.postfix(receiver, selector, argument);
458 SendSet.prefix(receiver,
459 selector,
460 this.assignmentOperator,
461 [Node argument = null])
462 : super.prefix(receiver, selector, argument);
463
464 SendSet asSendSet() => this;
465
466 accept(Visitor visitor) => visitor.visitSendSet(this);
467
468 visitChildren(Visitor visitor) {
469 super.visitChildren(visitor);
470 if (assignmentOperator != null) assignmentOperator.accept(visitor);
471 }
472
473 Send copyWithReceiver(Node newReceiver) {
474 assert(receiver == null);
475 return new SendSet(newReceiver, selector, assignmentOperator,
476 argumentsNode);
477 }
478
479 Token getBeginToken() {
480 if (isPrefix) return assignmentOperator.getBeginToken();
481 return super.getBeginToken();
482 }
483
484 Token getEndToken() {
485 if (isPostfix) return assignmentOperator.getEndToken();
486 return super.getEndToken();
487 }
488 }
489
490 class NewExpression extends Expression {
491 /** The token NEW or CONST or `null` for metadata */
492 final Token newToken;
493
494 // Note: we expect that send.receiver is null.
495 final Send send;
496
497 NewExpression([this.newToken, this.send]);
498
499 NewExpression asNewExpression() => this;
500
501 accept(Visitor visitor) => visitor.visitNewExpression(this);
502
503 visitChildren(Visitor visitor) {
504 if (send != null) send.accept(visitor);
505 }
506
507 bool get isConst {
508 return newToken == null || identical(newToken.stringValue, 'const');
509 }
510
511 Token getBeginToken() => newToken != null ? newToken : send.getBeginToken();
512
513 Token getEndToken() => send.getEndToken();
514 }
515
516 class NodeList extends Node {
517 final Link<Node> nodes;
518 final Token beginToken;
519 final Token endToken;
520 final String delimiter;
521 bool get isEmpty => nodes.isEmpty;
522
523 NodeList([this.beginToken, this.nodes, this.endToken, this.delimiter]);
524
525 Iterator<Node> get iterator => nodes.iterator;
526
527 NodeList.singleton(Node node) : this(null, const Link<Node>().prepend(node));
528 NodeList.empty() : this(null, const Link<Node>());
529
530 NodeList asNodeList() => this;
531
532 int slowLength() {
533 int result = 0;
534 for (Link<Node> cursor = nodes; !cursor.isEmpty; cursor = cursor.tail) {
535 result++;
536 }
537 return result;
538 }
539
540 accept(Visitor visitor) => visitor.visitNodeList(this);
541
542 visitChildren(Visitor visitor) {
543 if (nodes == null) return;
544 for (Link<Node> link = nodes; !link.isEmpty; link = link.tail) {
545 if (link.head != null) link.head.accept(visitor);
546 }
547 }
548
549 Token getBeginToken() {
550 if (beginToken != null) return beginToken;
551 if (nodes != null) {
552 for (Link<Node> link = nodes; !link.isEmpty; link = link.tail) {
553 if (link.head.getBeginToken() != null) {
554 return link.head.getBeginToken();
555 }
556 if (link.head.getEndToken() != null) {
557 return link.head.getEndToken();
558 }
559 }
560 }
561 return endToken;
562 }
563
564 Token getEndToken() {
565 if (endToken != null) return endToken;
566 if (nodes != null) {
567 Link<Node> link = nodes;
568 if (link.isEmpty) return beginToken;
569 while (!link.tail.isEmpty) link = link.tail;
570 Node lastNode = link.head;
571 if (lastNode != null) {
572 if (lastNode.getEndToken() != null) return lastNode.getEndToken();
573 if (lastNode.getBeginToken() != null) return lastNode.getBeginToken();
574 }
575 }
576 return beginToken;
577 }
578 }
579
580 class Block extends Statement {
581 final NodeList statements;
582
583 Block(this.statements);
584
585 Block asBlock() => this;
586
587 accept(Visitor visitor) => visitor.visitBlock(this);
588
589 visitChildren(Visitor visitor) {
590 if (statements != null) statements.accept(visitor);
591 }
592
593 Token getBeginToken() => statements.getBeginToken();
594
595 Token getEndToken() => statements.getEndToken();
596 }
597
598 class If extends Statement {
599 final ParenthesizedExpression condition;
600 final Statement thenPart;
601 final Statement elsePart;
602
603 final Token ifToken;
604 final Token elseToken;
605
606 If(this.condition, this.thenPart, this.elsePart,
607 this.ifToken, this.elseToken);
608
609 If asIf() => this;
610
611 bool get hasElsePart => elsePart != null;
612
613 accept(Visitor visitor) => visitor.visitIf(this);
614
615 visitChildren(Visitor visitor) {
616 if (condition != null) condition.accept(visitor);
617 if (thenPart != null) thenPart.accept(visitor);
618 if (elsePart != null) elsePart.accept(visitor);
619 }
620
621 Token getBeginToken() => ifToken;
622
623 Token getEndToken() {
624 if (elsePart == null) return thenPart.getEndToken();
625 return elsePart.getEndToken();
626 }
627 }
628
629 class Conditional extends Expression {
630 final Expression condition;
631 final Expression thenExpression;
632 final Expression elseExpression;
633
634 final Token questionToken;
635 final Token colonToken;
636
637 Conditional(this.condition, this.thenExpression,
638 this.elseExpression, this.questionToken, this.colonToken);
639
640 Conditional asConditional() => this;
641
642 accept(Visitor visitor) => visitor.visitConditional(this);
643
644 visitChildren(Visitor visitor) {
645 condition.accept(visitor);
646 thenExpression.accept(visitor);
647 elseExpression.accept(visitor);
648 }
649
650 Token getBeginToken() => condition.getBeginToken();
651
652 Token getEndToken() => elseExpression.getEndToken();
653 }
654
655 class For extends Loop {
656 /** Either a variable declaration or an expression. */
657 final Node initializer;
658 /** Either an expression statement or an empty statement. */
659 final Statement conditionStatement;
660 final NodeList update;
661
662 final Token forToken;
663
664 For(this.initializer, this.conditionStatement, this.update, body,
665 this.forToken) : super(body);
666
667 For asFor() => this;
668
669 Expression get condition {
670 if (conditionStatement is ExpressionStatement) {
671 return conditionStatement.asExpressionStatement().expression;
672 } else {
673 return null;
674 }
675 }
676
677 accept(Visitor visitor) => visitor.visitFor(this);
678
679 visitChildren(Visitor visitor) {
680 if (initializer != null) initializer.accept(visitor);
681 if (conditionStatement != null) conditionStatement.accept(visitor);
682 if (update != null) update.accept(visitor);
683 if (body != null) body.accept(visitor);
684 }
685
686 Token getBeginToken() => forToken;
687
688 Token getEndToken() {
689 return body.getEndToken();
690 }
691 }
692
693 class FunctionDeclaration extends Statement {
694 final FunctionExpression function;
695
696 FunctionDeclaration(this.function);
697
698 FunctionDeclaration asFunctionDeclaration() => this;
699
700 accept(Visitor visitor) => visitor.visitFunctionDeclaration(this);
701
702 visitChildren(Visitor visitor) => function.accept(visitor);
703
704 Token getBeginToken() => function.getBeginToken();
705 Token getEndToken() => function.getEndToken();
706 }
707
708 class FunctionExpression extends Expression with StoredTreeElementMixin {
709 final Node name;
710
711 /**
712 * List of VariableDefinitions or NodeList.
713 *
714 * A NodeList can only occur at the end and holds named parameters.
715 */
716 final NodeList parameters;
717
718 final Statement body;
719 final TypeAnnotation returnType;
720 final Modifiers modifiers;
721 final NodeList initializers;
722
723 final Token getOrSet;
724
725 FunctionExpression(this.name, this.parameters, this.body, this.returnType,
726 this.modifiers, this.initializers, this.getOrSet) {
727 assert(modifiers != null);
728 }
729
730 FunctionExpression asFunctionExpression() => this;
731
732 accept(Visitor visitor) => visitor.visitFunctionExpression(this);
733
734 bool get isRedirectingFactory {
735 return body != null && body.asRedirectingFactoryBody() != null;
736 }
737
738 visitChildren(Visitor visitor) {
739 if (modifiers != null) modifiers.accept(visitor);
740 if (returnType != null) returnType.accept(visitor);
741 if (name != null) name.accept(visitor);
742 if (parameters != null) parameters.accept(visitor);
743 if (initializers != null) initializers.accept(visitor);
744 if (body != null) body.accept(visitor);
745 }
746
747 bool hasBody() => body.asEmptyStatement() == null;
748
749 bool hasEmptyBody() {
750 Block block = body.asBlock();
751 if (block == null) return false;
752 return block.statements.isEmpty;
753 }
754
755 Token getBeginToken() {
756 Token token = firstBeginToken(modifiers, returnType);
757 if (token != null) return token;
758 if (getOrSet != null) return getOrSet;
759 return firstBeginToken(name, parameters);
760 }
761
762 Token getEndToken() {
763 Token token = (body == null) ? null : body.getEndToken();
764 token = (token == null) ? parameters.getEndToken() : token;
765 return (token == null) ? name.getEndToken() : token;
766 }
767 }
768
769 typedef void DecodeErrorHandler(Token token, var error);
770
771 abstract class Literal<T> extends Expression {
772 final Token token;
773 final DecodeErrorHandler handler;
774
775 Literal(Token this.token, DecodeErrorHandler this.handler);
776
777 T get value;
778
779 visitChildren(Visitor visitor) {}
780
781 Token getBeginToken() => token;
782
783 Token getEndToken() => token;
784 }
785
786 class LiteralInt extends Literal<int> {
787 LiteralInt(Token token, DecodeErrorHandler handler) : super(token, handler);
788
789 LiteralInt asLiteralInt() => this;
790
791 int get value {
792 try {
793 Token valueToken = token;
794 if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
795 return int.parse(valueToken.value);
796 } on FormatException catch (ex) {
797 (this.handler)(token, ex);
798 }
799 }
800
801 accept(Visitor visitor) => visitor.visitLiteralInt(this);
802 }
803
804 class LiteralDouble extends Literal<double> {
805 LiteralDouble(Token token, DecodeErrorHandler handler)
806 : super(token, handler);
807
808 LiteralDouble asLiteralDouble() => this;
809
810 double get value {
811 try {
812 Token valueToken = token;
813 if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
814 return double.parse(valueToken.value);
815 } on FormatException catch (ex) {
816 (this.handler)(token, ex);
817 }
818 }
819
820 accept(Visitor visitor) => visitor.visitLiteralDouble(this);
821 }
822
823 class LiteralBool extends Literal<bool> {
824 LiteralBool(Token token, DecodeErrorHandler handler) : super(token, handler);
825
826 LiteralBool asLiteralBool() => this;
827
828 bool get value {
829 if (identical(token.stringValue, 'true')) return true;
830 if (identical(token.stringValue, 'false')) return false;
831 (this.handler)(token, "not a bool ${token.value}");
832 throw false;
833 }
834
835 accept(Visitor visitor) => visitor.visitLiteralBool(this);
836 }
837
838
839 class StringQuoting {
840
841 /// Cache of common quotings.
842 static const List<StringQuoting> _mapping = const <StringQuoting>[
843 const StringQuoting($SQ, raw: false, leftQuoteLength: 1),
844 const StringQuoting($SQ, raw: true, leftQuoteLength: 1),
845 const StringQuoting($DQ, raw: false, leftQuoteLength: 1),
846 const StringQuoting($DQ, raw: true, leftQuoteLength: 1),
847 // No string quotes with 2 characters.
848 null,
849 null,
850 null,
851 null,
852 // Multiline quotings.
853 const StringQuoting($SQ, raw: false, leftQuoteLength: 3),
854 const StringQuoting($SQ, raw: true, leftQuoteLength: 3),
855 const StringQuoting($DQ, raw: false, leftQuoteLength: 3),
856 const StringQuoting($DQ, raw: true, leftQuoteLength: 3),
857 // Leading single whitespace or espaped newline.
858 const StringQuoting($SQ, raw: false, leftQuoteLength: 4),
859 const StringQuoting($SQ, raw: true, leftQuoteLength: 4),
860 const StringQuoting($DQ, raw: false, leftQuoteLength: 4),
861 const StringQuoting($DQ, raw: true, leftQuoteLength: 4),
862 // Other combinations of leading whitespace and/or escaped newline.
863 const StringQuoting($SQ, raw: false, leftQuoteLength: 5),
864 const StringQuoting($SQ, raw: true, leftQuoteLength: 5),
865 const StringQuoting($DQ, raw: false, leftQuoteLength: 5),
866 const StringQuoting($DQ, raw: true, leftQuoteLength: 5),
867 const StringQuoting($SQ, raw: false, leftQuoteLength: 6),
868 const StringQuoting($SQ, raw: true, leftQuoteLength: 6),
869 const StringQuoting($DQ, raw: false, leftQuoteLength: 6),
870 const StringQuoting($DQ, raw: true, leftQuoteLength: 6)
871 ];
872
873 final bool raw;
874 final int leftQuoteCharCount;
875 final int quote;
876 const StringQuoting(this.quote, { this.raw, int leftQuoteLength })
877 : this.leftQuoteCharCount = leftQuoteLength;
878 String get quoteChar => identical(quote, $DQ) ? '"' : "'";
879
880 int get leftQuoteLength => (raw ? 1 : 0) + leftQuoteCharCount;
881 int get rightQuoteLength => (leftQuoteCharCount > 2) ? 3 : 1;
882 static StringQuoting getQuoting(int quote, bool raw, int leftQuoteLength) {
883 int quoteKindOffset = (quote == $DQ) ? 2 : 0;
884 int rawOffset = raw ? 1 : 0;
885 int index = (leftQuoteLength - 1) * 4 + rawOffset + quoteKindOffset;
886 if (index < _mapping.length) return _mapping[index];
887 return new StringQuoting(quote, raw: raw, leftQuoteLength: leftQuoteLength);
888 }
889 }
890
891 /**
892 * Superclass for classes representing string literals.
893 */
894 abstract class StringNode extends Expression {
895 DartString get dartString;
896 bool get isInterpolation;
897
898 StringNode asStringNode() => this;
899 }
900
901 class LiteralString extends StringNode {
902 final Token token;
903 /** Non-null on validated string literals. */
904 final DartString dartString;
905
906 LiteralString(this.token, this.dartString);
907
908 LiteralString asLiteralString() => this;
909
910 void visitChildren(Visitor visitor) {}
911
912 bool get isInterpolation => false;
913
914 Token getBeginToken() => token;
915 Token getEndToken() => token;
916
917 accept(Visitor visitor) => visitor.visitLiteralString(this);
918 }
919
920 class LiteralNull extends Literal<String> {
921 LiteralNull(Token token) : super(token, null);
922
923 LiteralNull asLiteralNull() => this;
924
925 String get value => null;
926
927 accept(Visitor visitor) => visitor.visitLiteralNull(this);
928 }
929
930 class LiteralList extends Expression {
931 final NodeList typeArguments;
932 final NodeList elements;
933
934 final Token constKeyword;
935
936 LiteralList(this.typeArguments, this.elements, this.constKeyword);
937
938 bool get isConst => constKeyword != null;
939
940 LiteralList asLiteralList() => this;
941 accept(Visitor visitor) => visitor.visitLiteralList(this);
942
943 visitChildren(Visitor visitor) {
944 if (typeArguments != null) typeArguments.accept(visitor);
945 elements.accept(visitor);
946 }
947
948 Token getBeginToken() {
949 if (constKeyword != null) return constKeyword;
950 return firstBeginToken(typeArguments, elements);
951 }
952
953 Token getEndToken() => elements.getEndToken();
954 }
955
956 class LiteralSymbol extends Expression {
957 final Token hashToken;
958 final NodeList identifiers;
959
960 LiteralSymbol(this.hashToken, this.identifiers);
961
962 LiteralSymbol asLiteralSymbol() => this;
963
964 void visitChildren(Visitor visitor) {
965 if (identifiers != null) identifiers.accept(visitor);
966 }
967
968 accept(Visitor visitor) => visitor.visitLiteralSymbol(this);
969
970 Token getBeginToken() => hashToken;
971
972 Token getEndToken() => identifiers.getEndToken();
973
974 String get slowNameString {
975 Unparser unparser = new Unparser();
976 unparser.unparseNodeListOfIdentifiers(identifiers);
977 return unparser.result;
978 }
979 }
980
981 class Identifier extends Expression with StoredTreeElementMixin {
982 final Token token;
983
984 String get source => token.value;
985
986 Identifier(Token this.token);
987
988 bool isThis() => identical(source, 'this');
989
990 bool isSuper() => identical(source, 'super');
991
992 Identifier asIdentifier() => this;
993
994 accept(Visitor visitor) => visitor.visitIdentifier(this);
995
996 visitChildren(Visitor visitor) {}
997
998 Token getBeginToken() => token;
999
1000 Token getEndToken() => token;
1001 }
1002
1003 class Operator extends Identifier {
1004 static const COMPLEX_OPERATORS =
1005 const ["--", "++", '+=', "-=", "*=", "/=", "%=", "&=", "|=", "~/=", "^=",
1006 ">>=", "<<="];
1007
1008 static const INCREMENT_OPERATORS = const <String>["++", "--"];
1009
1010 Operator(Token token) : super(token);
1011
1012 Operator asOperator() => this;
1013
1014 accept(Visitor visitor) => visitor.visitOperator(this);
1015 }
1016
1017 class Return extends Statement {
1018 final Node expression;
1019 final Token beginToken;
1020 final Token endToken;
1021
1022 Return(this.beginToken, this.endToken, this.expression);
1023
1024 Return asReturn() => this;
1025
1026 bool get hasExpression => expression != null;
1027
1028 accept(Visitor visitor) => visitor.visitReturn(this);
1029
1030 visitChildren(Visitor visitor) {
1031 if (expression != null) expression.accept(visitor);
1032 }
1033
1034 Token getBeginToken() => beginToken;
1035
1036 Token getEndToken() {
1037 if (endToken == null) return expression.getEndToken();
1038 return endToken;
1039 }
1040 }
1041
1042 class RedirectingFactoryBody extends Statement with StoredTreeElementMixin {
1043 final Node constructorReference;
1044 final Token beginToken;
1045 final Token endToken;
1046
1047 RedirectingFactoryBody(this.beginToken, this.endToken,
1048 this.constructorReference);
1049
1050 RedirectingFactoryBody asRedirectingFactoryBody() => this;
1051
1052 accept(Visitor visitor) => visitor.visitRedirectingFactoryBody(this);
1053
1054 visitChildren(Visitor visitor) {
1055 constructorReference.accept(visitor);
1056 }
1057
1058 Token getBeginToken() => beginToken;
1059
1060 Token getEndToken() => endToken;
1061 }
1062
1063 class ExpressionStatement extends Statement {
1064 final Expression expression;
1065 final Token endToken;
1066
1067 ExpressionStatement(this.expression, this.endToken);
1068
1069 ExpressionStatement asExpressionStatement() => this;
1070
1071 accept(Visitor visitor) => visitor.visitExpressionStatement(this);
1072
1073 visitChildren(Visitor visitor) {
1074 if (expression != null) expression.accept(visitor);
1075 }
1076
1077 Token getBeginToken() => expression.getBeginToken();
1078
1079 Token getEndToken() => endToken;
1080 }
1081
1082 class Throw extends Expression {
1083 final Expression expression;
1084
1085 final Token throwToken;
1086 final Token endToken;
1087
1088 Throw(this.expression, this.throwToken, this.endToken);
1089
1090 Throw asThrow() => this;
1091
1092 accept(Visitor visitor) => visitor.visitThrow(this);
1093
1094 visitChildren(Visitor visitor) {
1095 expression.accept(visitor);
1096 }
1097
1098 Token getBeginToken() => throwToken;
1099
1100 Token getEndToken() => endToken;
1101 }
1102
1103 class Rethrow extends Statement {
1104 final Token throwToken;
1105 final Token endToken;
1106
1107 Rethrow(this.throwToken, this.endToken);
1108
1109 Rethrow asRethrow() => this;
1110
1111 accept(Visitor visitor) => visitor.visitRethrow(this);
1112 visitChildren(Visitor visitor) { }
1113
1114 Token getBeginToken() => throwToken;
1115 Token getEndToken() => endToken;
1116 }
1117
1118 class TypeAnnotation extends Node {
1119 final Expression typeName;
1120 final NodeList typeArguments;
1121
1122 TypeAnnotation(Expression this.typeName, NodeList this.typeArguments);
1123
1124 TypeAnnotation asTypeAnnotation() => this;
1125
1126 accept(Visitor visitor) => visitor.visitTypeAnnotation(this);
1127
1128 visitChildren(Visitor visitor) {
1129 typeName.accept(visitor);
1130 if (typeArguments != null) typeArguments.accept(visitor);
1131 }
1132
1133 Token getBeginToken() => typeName.getBeginToken();
1134
1135 Token getEndToken() => typeName.getEndToken();
1136 }
1137
1138 class TypeVariable extends Node {
1139 final Identifier name;
1140 final TypeAnnotation bound;
1141 TypeVariable(Identifier this.name, TypeAnnotation this.bound);
1142
1143 accept(Visitor visitor) => visitor.visitTypeVariable(this);
1144
1145 visitChildren(Visitor visitor) {
1146 name.accept(visitor);
1147 if (bound != null) {
1148 bound.accept(visitor);
1149 }
1150 }
1151
1152 TypeVariable asTypeVariable() => this;
1153
1154 Token getBeginToken() => name.getBeginToken();
1155
1156 Token getEndToken() {
1157 return (bound != null) ? bound.getEndToken() : name.getEndToken();
1158 }
1159 }
1160
1161 class VariableDefinitions extends Statement {
1162 final NodeList metadata;
1163 final TypeAnnotation type;
1164 final Modifiers modifiers;
1165 final NodeList definitions;
1166
1167 VariableDefinitions(this.type,
1168 this.modifiers,
1169 this.definitions)
1170 : this.metadata = null {
1171 assert(modifiers != null);
1172 }
1173
1174 // TODO(johnniwinther): Make this its own node type.
1175 VariableDefinitions.forParameter(this.metadata,
1176 this.type,
1177 this.modifiers,
1178 this.definitions) {
1179 assert(modifiers != null);
1180 }
1181
1182 VariableDefinitions asVariableDefinitions() => this;
1183
1184 accept(Visitor visitor) => visitor.visitVariableDefinitions(this);
1185
1186 visitChildren(Visitor visitor) {
1187 if (metadata != null) metadata.accept(visitor);
1188 if (type != null) type.accept(visitor);
1189 if (definitions != null) definitions.accept(visitor);
1190 }
1191
1192 Token getBeginToken() {
1193 var token = firstBeginToken(modifiers, type);
1194 if (token == null) {
1195 token = definitions.getBeginToken();
1196 }
1197 return token;
1198 }
1199
1200 Token getEndToken() => definitions.getEndToken();
1201 }
1202
1203 abstract class Loop extends Statement {
1204 Expression get condition;
1205 final Statement body;
1206
1207 Loop(this.body);
1208
1209 bool isValidContinueTarget() => true;
1210 }
1211
1212 class DoWhile extends Loop {
1213 final Token doKeyword;
1214 final Token whileKeyword;
1215 final Token endToken;
1216
1217 final Expression condition;
1218
1219 DoWhile(Statement body, Expression this.condition,
1220 Token this.doKeyword, Token this.whileKeyword, Token this.endToken)
1221 : super(body);
1222
1223 DoWhile asDoWhile() => this;
1224
1225 accept(Visitor visitor) => visitor.visitDoWhile(this);
1226
1227 visitChildren(Visitor visitor) {
1228 if (condition != null) condition.accept(visitor);
1229 if (body != null) body.accept(visitor);
1230 }
1231
1232 Token getBeginToken() => doKeyword;
1233
1234 Token getEndToken() => endToken;
1235 }
1236
1237 class While extends Loop {
1238 final Token whileKeyword;
1239 final Expression condition;
1240
1241 While(Expression this.condition, Statement body,
1242 Token this.whileKeyword) : super(body);
1243
1244 While asWhile() => this;
1245
1246 accept(Visitor visitor) => visitor.visitWhile(this);
1247
1248 visitChildren(Visitor visitor) {
1249 if (condition != null) condition.accept(visitor);
1250 if (body != null) body.accept(visitor);
1251 }
1252
1253 Token getBeginToken() => whileKeyword;
1254
1255 Token getEndToken() => body.getEndToken();
1256 }
1257
1258 class ParenthesizedExpression extends Expression {
1259 final Expression expression;
1260 final BeginGroupToken beginToken;
1261
1262 ParenthesizedExpression(Expression this.expression,
1263 BeginGroupToken this.beginToken);
1264
1265 ParenthesizedExpression asParenthesizedExpression() => this;
1266
1267 accept(Visitor visitor) => visitor.visitParenthesizedExpression(this);
1268
1269 visitChildren(Visitor visitor) {
1270 if (expression != null) expression.accept(visitor);
1271 }
1272
1273 Token getBeginToken() => beginToken;
1274
1275 Token getEndToken() => beginToken.endGroup;
1276 }
1277
1278 /** Representation of modifiers such as static, abstract, final, etc. */
1279 class Modifiers extends Node {
1280 /**
1281 * Pseudo-constant for empty modifiers.
1282 */
1283 static final Modifiers EMPTY = new Modifiers(new NodeList.empty());
1284
1285 /* TODO(ahe): The following should be validated relating to modifiers:
1286 * 1. The nodes must come in a certain order.
1287 * 2. The keywords "var" and "final" may not be used at the same time.
1288 * 3. The keywords "abstract" and "external" may not be used at the same time.
1289 * 4. The type of an element must be null if isVar() is true.
1290 */
1291
1292 final NodeList nodes;
1293 /** Bit pattern to easy check what modifiers are present. */
1294 final int flags;
1295
1296 static const int FLAG_STATIC = 1;
1297 static const int FLAG_ABSTRACT = FLAG_STATIC << 1;
1298 static const int FLAG_FINAL = FLAG_ABSTRACT << 1;
1299 static const int FLAG_VAR = FLAG_FINAL << 1;
1300 static const int FLAG_CONST = FLAG_VAR << 1;
1301 static const int FLAG_FACTORY = FLAG_CONST << 1;
1302 static const int FLAG_EXTERNAL = FLAG_FACTORY << 1;
1303
1304 Modifiers(NodeList nodes) : this.withFlags(nodes, computeFlags(nodes.nodes));
1305
1306 Modifiers.withFlags(this.nodes, this.flags);
1307
1308 static int computeFlags(Link<Node> nodes) {
1309 int flags = 0;
1310 for (; !nodes.isEmpty; nodes = nodes.tail) {
1311 String value = nodes.head.asIdentifier().source;
1312 if (identical(value, 'static')) flags |= FLAG_STATIC;
1313 else if (identical(value, 'abstract')) flags |= FLAG_ABSTRACT;
1314 else if (identical(value, 'final')) flags |= FLAG_FINAL;
1315 else if (identical(value, 'var')) flags |= FLAG_VAR;
1316 else if (identical(value, 'const')) flags |= FLAG_CONST;
1317 else if (identical(value, 'factory')) flags |= FLAG_FACTORY;
1318 else if (identical(value, 'external')) flags |= FLAG_EXTERNAL;
1319 else throw 'internal error: ${nodes.head}';
1320 }
1321 return flags;
1322 }
1323
1324 Node findModifier(String modifier) {
1325 Link<Node> nodeList = nodes.nodes;
1326 for (; !nodeList.isEmpty; nodeList = nodeList.tail) {
1327 String value = nodeList.head.asIdentifier().source;
1328 if(identical(value, modifier)) {
1329 return nodeList.head;
1330 }
1331 }
1332 return null;
1333 }
1334
1335 Modifiers asModifiers() => this;
1336 Token getBeginToken() => nodes.getBeginToken();
1337 Token getEndToken() => nodes.getEndToken();
1338 accept(Visitor visitor) => visitor.visitModifiers(this);
1339 visitChildren(Visitor visitor) => nodes.accept(visitor);
1340
1341 bool get isStatic => (flags & FLAG_STATIC) != 0;
1342 bool get isAbstract => (flags & FLAG_ABSTRACT) != 0;
1343 bool get isFinal => (flags & FLAG_FINAL) != 0;
1344 bool get isVar => (flags & FLAG_VAR) != 0;
1345 bool get isConst => (flags & FLAG_CONST) != 0;
1346 bool get isFactory => (flags & FLAG_FACTORY) != 0;
1347 bool get isExternal => (flags & FLAG_EXTERNAL) != 0;
1348
1349 Node getStatic() => findModifier('static');
1350
1351 /**
1352 * Use this to check if the declaration is either explicitly or implicitly
1353 * final.
1354 */
1355 bool get isFinalOrConst => isFinal || isConst;
1356
1357 String toString() {
1358 return modifiersToString(isStatic: isStatic,
1359 isAbstract: isAbstract,
1360 isFinal: isFinal,
1361 isVar: isVar,
1362 isConst: isConst,
1363 isFactory: isFactory,
1364 isExternal: isExternal);
1365 }
1366 }
1367
1368 class StringInterpolation extends StringNode {
1369 final LiteralString string;
1370 final NodeList parts;
1371
1372 StringInterpolation(this.string, this.parts);
1373
1374 StringInterpolation asStringInterpolation() => this;
1375
1376 DartString get dartString => null;
1377 bool get isInterpolation => true;
1378
1379 accept(Visitor visitor) => visitor.visitStringInterpolation(this);
1380
1381 visitChildren(Visitor visitor) {
1382 string.accept(visitor);
1383 parts.accept(visitor);
1384 }
1385
1386 Token getBeginToken() => string.getBeginToken();
1387 Token getEndToken() => parts.getEndToken();
1388 }
1389
1390 class StringInterpolationPart extends Node {
1391 final Expression expression;
1392 final LiteralString string;
1393
1394 StringInterpolationPart(this.expression, this.string);
1395
1396 StringInterpolationPart asStringInterpolationPart() => this;
1397
1398 accept(Visitor visitor) => visitor.visitStringInterpolationPart(this);
1399
1400 visitChildren(Visitor visitor) {
1401 expression.accept(visitor);
1402 string.accept(visitor);
1403 }
1404
1405 Token getBeginToken() => expression.getBeginToken();
1406
1407 Token getEndToken() => string.getEndToken();
1408 }
1409
1410 /**
1411 * A class representing juxtaposed string literals.
1412 * The string literals can be both plain literals and string interpolations.
1413 */
1414 class StringJuxtaposition extends StringNode {
1415 final Expression first;
1416 final Expression second;
1417
1418 /**
1419 * Caches the check for whether this juxtaposition contains a string
1420 * interpolation
1421 */
1422 bool isInterpolationCache = null;
1423
1424 /**
1425 * Caches a Dart string representation of the entire juxtaposition's
1426 * content. Only juxtapositions that don't (transitively) contains
1427 * interpolations have a static representation.
1428 */
1429 DartString dartStringCache = null;
1430
1431 StringJuxtaposition(this.first, this.second);
1432
1433 StringJuxtaposition asStringJuxtaposition() => this;
1434
1435 bool get isInterpolation {
1436 if (isInterpolationCache == null) {
1437 isInterpolationCache = (first.accept(const IsInterpolationVisitor()) ||
1438 second.accept(const IsInterpolationVisitor()));
1439 }
1440 return isInterpolationCache;
1441 }
1442
1443 /**
1444 * Retrieve a single DartString that represents this entire juxtaposition
1445 * of string literals.
1446 * Should only be called if [isInterpolation] returns false.
1447 */
1448 DartString get dartString {
1449 if (isInterpolation) {
1450 throw new SpannableAssertionFailure(
1451 this, "Getting dartString on interpolation;");
1452 }
1453 if (dartStringCache == null) {
1454 DartString firstString = first.accept(const GetDartStringVisitor());
1455 DartString secondString = second.accept(const GetDartStringVisitor());
1456 if (firstString == null || secondString == null) {
1457 return null;
1458 }
1459 dartStringCache = new DartString.concat(firstString, secondString);
1460 }
1461 return dartStringCache;
1462 }
1463
1464 accept(Visitor visitor) => visitor.visitStringJuxtaposition(this);
1465
1466 void visitChildren(Visitor visitor) {
1467 first.accept(visitor);
1468 second.accept(visitor);
1469 }
1470
1471 Token getBeginToken() => first.getBeginToken();
1472
1473 Token getEndToken() => second.getEndToken();
1474 }
1475
1476 class EmptyStatement extends Statement {
1477 final Token semicolonToken;
1478
1479 EmptyStatement(this.semicolonToken);
1480
1481 EmptyStatement asEmptyStatement() => this;
1482
1483 accept(Visitor visitor) => visitor.visitEmptyStatement(this);
1484
1485 visitChildren(Visitor visitor) {}
1486
1487 Token getBeginToken() => semicolonToken;
1488
1489 Token getEndToken() => semicolonToken;
1490 }
1491
1492 class LiteralMap extends Expression {
1493 final NodeList typeArguments;
1494 final NodeList entries;
1495
1496 final Token constKeyword;
1497
1498 LiteralMap(this.typeArguments, this.entries, this.constKeyword);
1499
1500 bool get isConst => constKeyword != null;
1501
1502 LiteralMap asLiteralMap() => this;
1503
1504 accept(Visitor visitor) => visitor.visitLiteralMap(this);
1505
1506 visitChildren(Visitor visitor) {
1507 if (typeArguments != null) typeArguments.accept(visitor);
1508 entries.accept(visitor);
1509 }
1510
1511 Token getBeginToken() {
1512 if (constKeyword != null) return constKeyword;
1513 return firstBeginToken(typeArguments, entries);
1514 }
1515
1516 Token getEndToken() => entries.getEndToken();
1517 }
1518
1519 class LiteralMapEntry extends Node {
1520 final Expression key;
1521 final Expression value;
1522
1523 final Token colonToken;
1524
1525 LiteralMapEntry(this.key, this.colonToken, this.value);
1526
1527 LiteralMapEntry asLiteralMapEntry() => this;
1528
1529 accept(Visitor visitor) => visitor.visitLiteralMapEntry(this);
1530
1531 visitChildren(Visitor visitor) {
1532 key.accept(visitor);
1533 value.accept(visitor);
1534 }
1535
1536 Token getBeginToken() => key.getBeginToken();
1537
1538 Token getEndToken() => value.getEndToken();
1539 }
1540
1541 class NamedArgument extends Expression {
1542 final Identifier name;
1543 final Expression expression;
1544
1545 final Token colonToken;
1546
1547 NamedArgument(this.name, this.colonToken, this.expression);
1548
1549 NamedArgument asNamedArgument() => this;
1550
1551 accept(Visitor visitor) => visitor.visitNamedArgument(this);
1552
1553 visitChildren(Visitor visitor) {
1554 name.accept(visitor);
1555 expression.accept(visitor);
1556 }
1557
1558 Token getBeginToken() => name.getBeginToken();
1559
1560 Token getEndToken() => expression.getEndToken();
1561 }
1562
1563 class SwitchStatement extends Statement {
1564 final ParenthesizedExpression parenthesizedExpression;
1565 final NodeList cases;
1566
1567 final Token switchKeyword;
1568
1569 SwitchStatement(this.parenthesizedExpression, this.cases,
1570 this.switchKeyword);
1571
1572 SwitchStatement asSwitchStatement() => this;
1573
1574 Expression get expression => parenthesizedExpression.expression;
1575
1576 accept(Visitor visitor) => visitor.visitSwitchStatement(this);
1577
1578 visitChildren(Visitor visitor) {
1579 parenthesizedExpression.accept(visitor);
1580 cases.accept(visitor);
1581 }
1582
1583 Token getBeginToken() => switchKeyword;
1584
1585 Token getEndToken() => cases.getEndToken();
1586 }
1587
1588 class CaseMatch extends Node {
1589 final Token caseKeyword;
1590 final Expression expression;
1591 final Token colonToken;
1592 CaseMatch(this.caseKeyword, this.expression, this.colonToken);
1593
1594 CaseMatch asCaseMatch() => this;
1595 Token getBeginToken() => caseKeyword;
1596 Token getEndToken() => colonToken;
1597 accept(Visitor visitor) => visitor.visitCaseMatch(this);
1598 visitChildren(Visitor visitor) => expression.accept(visitor);
1599 }
1600
1601 class SwitchCase extends Node {
1602 // The labels and case patterns are collected in [labelsAndCases].
1603 // The default keyword, if present, is collected in [defaultKeyword].
1604 // Any actual switch case must have at least one 'case' or 'default'
1605 // clause.
1606 // Notice: The labels and cases can occur interleaved in the source.
1607 // They are separated here, since the order is irrelevant to the meaning
1608 // of the switch.
1609
1610 /** List of [Label] and [CaseMatch] nodes. */
1611 final NodeList labelsAndCases;
1612 /** A "default" keyword token, if applicable. */
1613 final Token defaultKeyword;
1614 /** List of statements, the body of the case. */
1615 final NodeList statements;
1616
1617 final Token startToken;
1618
1619 SwitchCase(this.labelsAndCases, this.defaultKeyword,
1620 this.statements, this.startToken);
1621
1622 SwitchCase asSwitchCase() => this;
1623
1624 bool get isDefaultCase => defaultKeyword != null;
1625
1626 bool isValidContinueTarget() => true;
1627
1628 accept(Visitor visitor) => visitor.visitSwitchCase(this);
1629
1630 visitChildren(Visitor visitor) {
1631 labelsAndCases.accept(visitor);
1632 statements.accept(visitor);
1633 }
1634
1635 Token getBeginToken() {
1636 return startToken;
1637 }
1638
1639 Token getEndToken() {
1640 if (statements.nodes.isEmpty) {
1641 // All cases must have at least one expression or be the default.
1642 if (defaultKeyword != null) {
1643 // The colon after 'default'.
1644 return defaultKeyword.next;
1645 }
1646 // The colon after the last expression.
1647 return labelsAndCases.getEndToken();
1648 } else {
1649 return statements.getEndToken();
1650 }
1651 }
1652 }
1653
1654 abstract class GotoStatement extends Statement {
1655 final Identifier target;
1656 final Token keywordToken;
1657 final Token semicolonToken;
1658
1659 GotoStatement(this.target, this.keywordToken, this.semicolonToken);
1660
1661 visitChildren(Visitor visitor) {
1662 if (target != null) target.accept(visitor);
1663 }
1664
1665 Token getBeginToken() => keywordToken;
1666
1667 Token getEndToken() => semicolonToken;
1668
1669 // TODO(ahe): make class abstract instead of adding an abstract method.
1670 accept(Visitor visitor);
1671 }
1672
1673 class BreakStatement extends GotoStatement {
1674 BreakStatement(Identifier target, Token keywordToken, Token semicolonToken)
1675 : super(target, keywordToken, semicolonToken);
1676
1677 BreakStatement asBreakStatement() => this;
1678
1679 accept(Visitor visitor) => visitor.visitBreakStatement(this);
1680 }
1681
1682 class ContinueStatement extends GotoStatement {
1683 ContinueStatement(Identifier target, Token keywordToken, Token semicolonToken)
1684 : super(target, keywordToken, semicolonToken);
1685
1686 ContinueStatement asContinueStatement() => this;
1687
1688 accept(Visitor visitor) => visitor.visitContinueStatement(this);
1689 }
1690
1691 class ForIn extends Loop with StoredTreeElementMixin {
1692 final Node declaredIdentifier;
1693 final Expression expression;
1694
1695 final Token forToken;
1696 final Token inToken;
1697
1698 ForIn(this.declaredIdentifier, this.expression,
1699 Statement body, this.forToken, this.inToken) : super(body);
1700
1701 Expression get condition => null;
1702
1703 ForIn asForIn() => this;
1704
1705 accept(Visitor visitor) => visitor.visitForIn(this);
1706
1707 visitChildren(Visitor visitor) {
1708 declaredIdentifier.accept(visitor);
1709 expression.accept(visitor);
1710 body.accept(visitor);
1711 }
1712
1713 Token getBeginToken() => forToken;
1714
1715 Token getEndToken() => body.getEndToken();
1716 }
1717
1718 class Label extends Node {
1719 final Identifier identifier;
1720 final Token colonToken;
1721
1722 Label(this.identifier, this.colonToken);
1723
1724 String get labelName => identifier.source;
1725
1726 Label asLabel() => this;
1727
1728 accept(Visitor visitor) => visitor.visitLabel(this);
1729
1730 void visitChildren(Visitor visitor) {
1731 identifier.accept(visitor);
1732 }
1733
1734 Token getBeginToken() => identifier.token;
1735 Token getEndToken() => colonToken;
1736 }
1737
1738 class LabeledStatement extends Statement {
1739 final NodeList labels;
1740 final Statement statement;
1741
1742 LabeledStatement(this.labels, this.statement);
1743
1744 LabeledStatement asLabeledStatement() => this;
1745
1746 accept(Visitor visitor) => visitor.visitLabeledStatement(this);
1747
1748 visitChildren(Visitor visitor) {
1749 labels.accept(visitor);
1750 statement.accept(visitor);
1751 }
1752
1753 Token getBeginToken() => labels.getBeginToken();
1754
1755 Token getEndToken() => statement.getEndToken();
1756
1757 bool isValidContinueTarget() => statement.isValidContinueTarget();
1758 }
1759
1760 abstract class LibraryTag extends Node {
1761 final Link<MetadataAnnotation> metadata;
1762
1763 LibraryTag(this.metadata);
1764
1765 bool get isLibraryName => false;
1766 bool get isImport => false;
1767 bool get isExport => false;
1768 bool get isPart => false;
1769 bool get isPartOf => false;
1770 }
1771
1772 class LibraryName extends LibraryTag {
1773 final Expression name;
1774
1775 final Token libraryKeyword;
1776
1777 LibraryName(this.libraryKeyword,
1778 this.name,
1779 Link<MetadataAnnotation> metadata)
1780 : super(metadata);
1781
1782 bool get isLibraryName => true;
1783
1784 LibraryName asLibraryName() => this;
1785
1786 accept(Visitor visitor) => visitor.visitLibraryName(this);
1787
1788 visitChildren(Visitor visitor) => name.accept(visitor);
1789
1790 Token getBeginToken() => libraryKeyword;
1791
1792 Token getEndToken() => name.getEndToken().next;
1793 }
1794
1795 /**
1796 * This tag describes a dependency between one library and the exported
1797 * identifiers of another library. The other library is specified by the [uri].
1798 * Combinators filter away some identifiers from the other library.
1799 */
1800 abstract class LibraryDependency extends LibraryTag {
1801 final StringNode uri;
1802 final NodeList combinators;
1803
1804 LibraryDependency(this.uri,
1805 this.combinators,
1806 Link<MetadataAnnotation> metadata)
1807 : super(metadata);
1808
1809 LibraryDependency asLibraryDependency() => this;
1810 }
1811
1812 /**
1813 * An [:import:] library tag.
1814 *
1815 * An import tag is dependency on another library where the exported identifiers
1816 * are put into the import scope of the importing library. The import scope is
1817 * only visible inside the library.
1818 */
1819 class Import extends LibraryDependency {
1820 final Identifier prefix;
1821 final Token importKeyword;
1822 final bool isDeferred;
1823
1824 Import(this.importKeyword, StringNode uri,
1825 this.prefix, NodeList combinators,
1826 Link<MetadataAnnotation> metadata,
1827 {this.isDeferred})
1828 : super(uri, combinators, metadata);
1829
1830 bool get isImport => true;
1831
1832 Import asImport() => this;
1833
1834 accept(Visitor visitor) => visitor.visitImport(this);
1835
1836 visitChildren(Visitor visitor) {
1837 uri.accept(visitor);
1838 if (prefix != null) prefix.accept(visitor);
1839 if (combinators != null) combinators.accept(visitor);
1840 }
1841
1842 Token getBeginToken() => importKeyword;
1843
1844 Token getEndToken() {
1845 if (combinators != null) return combinators.getEndToken().next;
1846 if (prefix != null) return prefix.getEndToken().next;
1847 return uri.getEndToken().next;
1848 }
1849 }
1850
1851 /**
1852 * An [:export:] library tag.
1853 *
1854 * An export tag is dependency on another library where the exported identifiers
1855 * are put into the export scope of the exporting library. The export scope is
1856 * not visible inside the library.
1857 */
1858 class Export extends LibraryDependency {
1859 final Token exportKeyword;
1860
1861 Export(this.exportKeyword,
1862 StringNode uri,
1863 NodeList combinators,
1864 Link<MetadataAnnotation> metadata)
1865 : super(uri, combinators, metadata);
1866
1867 bool get isExport => true;
1868
1869 Export asExport() => this;
1870
1871 accept(Visitor visitor) => visitor.visitExport(this);
1872
1873 visitChildren(Visitor visitor) {
1874 uri.accept(visitor);
1875 if (combinators != null) combinators.accept(visitor);
1876 }
1877
1878 Token getBeginToken() => exportKeyword;
1879
1880 Token getEndToken() {
1881 if (combinators != null) return combinators.getEndToken().next;
1882 return uri.getEndToken().next;
1883 }
1884 }
1885
1886 class Part extends LibraryTag {
1887 final StringNode uri;
1888
1889 final Token partKeyword;
1890
1891 Part(this.partKeyword, this.uri, Link<MetadataAnnotation> metadata)
1892 : super(metadata);
1893
1894 bool get isPart => true;
1895
1896 Part asPart() => this;
1897
1898 accept(Visitor visitor) => visitor.visitPart(this);
1899
1900 visitChildren(Visitor visitor) => uri.accept(visitor);
1901
1902 Token getBeginToken() => partKeyword;
1903
1904 Token getEndToken() => uri.getEndToken().next;
1905 }
1906
1907 class PartOf extends Node {
1908 final Expression name;
1909
1910 final Token partKeyword;
1911
1912 final Link<MetadataAnnotation> metadata;
1913
1914 PartOf(this.partKeyword, this.name, this.metadata);
1915
1916 Token get ofKeyword => partKeyword.next;
1917
1918 bool get isPartOf => true;
1919
1920 PartOf asPartOf() => this;
1921
1922 accept(Visitor visitor) => visitor.visitPartOf(this);
1923
1924 visitChildren(Visitor visitor) => name.accept(visitor);
1925
1926 Token getBeginToken() => partKeyword;
1927
1928 Token getEndToken() => name.getEndToken().next;
1929 }
1930
1931 class Combinator extends Node {
1932 final NodeList identifiers;
1933
1934 final Token keywordToken;
1935
1936 Combinator(this.identifiers, this.keywordToken);
1937
1938 bool get isShow => identical(keywordToken.stringValue, 'show');
1939
1940 bool get isHide => identical(keywordToken.stringValue, 'hide');
1941
1942 Combinator asCombinator() => this;
1943
1944 accept(Visitor visitor) => visitor.visitCombinator(this);
1945
1946 visitChildren(Visitor visitor) => identifiers.accept(visitor);
1947
1948 Token getBeginToken() => keywordToken;
1949
1950 Token getEndToken() => identifiers.getEndToken();
1951 }
1952
1953 class Typedef extends Node {
1954 final TypeAnnotation returnType;
1955 final Identifier name;
1956 final NodeList typeParameters;
1957 final NodeList formals;
1958
1959 final Token typedefKeyword;
1960 final Token endToken;
1961
1962 Typedef(this.returnType, this.name, this.typeParameters, this.formals,
1963 this.typedefKeyword, this.endToken);
1964
1965 Typedef asTypedef() => this;
1966
1967 accept(Visitor visitor) => visitor.visitTypedef(this);
1968
1969 visitChildren(Visitor visitor) {
1970 if (returnType != null) returnType.accept(visitor);
1971 name.accept(visitor);
1972 if (typeParameters != null) typeParameters.accept(visitor);
1973 formals.accept(visitor);
1974 }
1975
1976 Token getBeginToken() => typedefKeyword;
1977
1978 Token getEndToken() => endToken;
1979 }
1980
1981 class TryStatement extends Statement {
1982 final Block tryBlock;
1983 final NodeList catchBlocks;
1984 final Block finallyBlock;
1985
1986 final Token tryKeyword;
1987 final Token finallyKeyword;
1988
1989 TryStatement(this.tryBlock, this.catchBlocks, this.finallyBlock,
1990 this.tryKeyword, this.finallyKeyword);
1991
1992 TryStatement asTryStatement() => this;
1993
1994 accept(Visitor visitor) => visitor.visitTryStatement(this);
1995
1996 visitChildren(Visitor visitor) {
1997 tryBlock.accept(visitor);
1998 catchBlocks.accept(visitor);
1999 if (finallyBlock != null) finallyBlock.accept(visitor);
2000 }
2001
2002 Token getBeginToken() => tryKeyword;
2003
2004 Token getEndToken() {
2005 if (finallyBlock != null) return finallyBlock.getEndToken();
2006 if (!catchBlocks.isEmpty) return catchBlocks.getEndToken();
2007 return tryBlock.getEndToken();
2008 }
2009 }
2010
2011 class Cascade extends Expression {
2012 final Expression expression;
2013 Cascade(this.expression);
2014
2015 Cascade asCascade() => this;
2016 accept(Visitor visitor) => visitor.visitCascade(this);
2017
2018 void visitChildren(Visitor visitor) {
2019 expression.accept(visitor);
2020 }
2021
2022 Token getBeginToken() => expression.getBeginToken();
2023
2024 Token getEndToken() => expression.getEndToken();
2025 }
2026
2027 class CascadeReceiver extends Expression {
2028 final Expression expression;
2029 final Token cascadeOperator;
2030 CascadeReceiver(this.expression, this.cascadeOperator);
2031
2032 CascadeReceiver asCascadeReceiver() => this;
2033 accept(Visitor visitor) => visitor.visitCascadeReceiver(this);
2034
2035 void visitChildren(Visitor visitor) {
2036 expression.accept(visitor);
2037 }
2038
2039 Token getBeginToken() => expression.getBeginToken();
2040
2041 Token getEndToken() => expression.getEndToken();
2042 }
2043
2044 class CatchBlock extends Node {
2045 final TypeAnnotation type;
2046 final NodeList formals;
2047 final Block block;
2048
2049 final Token onKeyword;
2050 final Token catchKeyword;
2051
2052 CatchBlock(this.type, this.formals, this.block,
2053 this.onKeyword, this.catchKeyword);
2054
2055 CatchBlock asCatchBlock() => this;
2056
2057 accept(Visitor visitor) => visitor.visitCatchBlock(this);
2058
2059 Node get exception {
2060 if (formals == null || formals.nodes.isEmpty) return null;
2061 VariableDefinitions declarations = formals.nodes.head;
2062 return declarations.definitions.nodes.head;
2063 }
2064
2065 Node get trace {
2066 if (formals == null || formals.nodes.isEmpty) return null;
2067 Link<Node> declarations = formals.nodes.tail;
2068 if (declarations.isEmpty) return null;
2069 VariableDefinitions head = declarations.head;
2070 return head.definitions.nodes.head;
2071 }
2072
2073 visitChildren(Visitor visitor) {
2074 if (type != null) type.accept(visitor);
2075 if (formals != null) formals.accept(visitor);
2076 block.accept(visitor);
2077 }
2078
2079 Token getBeginToken() => onKeyword != null ? onKeyword : catchKeyword;
2080
2081 Token getEndToken() => block.getEndToken();
2082 }
2083
2084 class Metadata extends Node {
2085 final Token token;
2086 final Expression expression;
2087
2088 Metadata(this.token, this.expression);
2089
2090 Metadata asMetadata() => this;
2091
2092 accept(Visitor visitor) => visitor.visitMetadata(this);
2093
2094 visitChildren(Visitor visitor) {
2095 expression.accept(visitor);
2096 }
2097
2098 Token getBeginToken() => token;
2099
2100 Token getEndToken() => expression.getEndToken();
2101 }
2102
2103 class Initializers {
2104 static bool isSuperConstructorCall(Send node) {
2105 return (node.receiver == null && node.selector.isSuper()) ||
2106 (node.receiver != null &&
2107 node.receiver.isSuper() &&
2108 node.selector.asIdentifier() != null);
2109 }
2110
2111 static bool isConstructorRedirect(Send node) {
2112 return (node.receiver == null && node.selector.isThis()) ||
2113 (node.receiver != null &&
2114 node.receiver.isThis() &&
2115 node.selector.asIdentifier() != null);
2116 }
2117 }
2118
2119 class GetDartStringVisitor extends Visitor<DartString> {
2120 const GetDartStringVisitor();
2121 DartString visitNode(Node node) => null;
2122 DartString visitStringJuxtaposition(StringJuxtaposition node)
2123 => node.dartString;
2124 DartString visitLiteralString(LiteralString node) => node.dartString;
2125 }
2126
2127 class IsInterpolationVisitor extends Visitor<bool> {
2128 const IsInterpolationVisitor();
2129 bool visitNode(Node node) => false;
2130 bool visitStringInterpolation(StringInterpolation node) => true;
2131 bool visitStringJuxtaposition(StringJuxtaposition node)
2132 => node.isInterpolation;
2133 }
2134
2135 /// Erroneous node used to recover from parser errors. Implements various
2136 /// interfaces and provides bare minimum of implementation to avoid unnecessary
2137 /// messages.
2138 class ErrorNode
2139 extends Node
2140 implements FunctionExpression, VariableDefinitions, Typedef {
2141 final Token token;
2142 final String reason;
2143 final Identifier name;
2144 final NodeList definitions;
2145
2146 ErrorNode.internal(this.token, this.reason, this.name, this.definitions);
2147
2148 factory ErrorNode(Token token, String reason) {
2149 Identifier name = new Identifier(token);
2150 NodeList definitions = new NodeList(
2151 null, const Link<Node>().prepend(name), null, null);
2152 return new ErrorNode.internal(token, reason, name, definitions);
2153 }
2154
2155 Token get beginToken => token;
2156 Token get endToken => token;
2157
2158 Token getBeginToken() => token;
2159
2160 Token getEndToken() => token;
2161
2162 accept(Visitor visitor) {}
2163
2164 visitChildren(Visitor visitor) {}
2165
2166 bool get isErroneous => true;
2167
2168 // FunctionExpression.
2169 get parameters => null;
2170 get body => null;
2171 get returnType => null;
2172 get modifiers => Modifiers.EMPTY;
2173 get initializers => null;
2174 get getOrSet => null;
2175 get isRedirectingFactory => false;
2176 bool hasBody() => false;
2177 bool hasEmptyBody() => false;
2178
2179 // VariableDefinitions.
2180 get metadata => null;
2181 get type => null;
2182
2183 // Typedef.
2184 get typeParameters => null;
2185 get formals => null;
2186 get typedefKeyword => null;
2187 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698