OLD | NEW |
| (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 js; | |
6 | |
7 abstract class NodeVisitor<T> { | |
8 T visitProgram(Program node); | |
9 | |
10 T visitBlock(Block node); | |
11 T visitExpressionStatement(ExpressionStatement node); | |
12 T visitEmptyStatement(EmptyStatement node); | |
13 T visitIf(If node); | |
14 T visitFor(For node); | |
15 T visitForIn(ForIn node); | |
16 T visitWhile(While node); | |
17 T visitDo(Do node); | |
18 T visitContinue(Continue node); | |
19 T visitBreak(Break node); | |
20 T visitReturn(Return node); | |
21 T visitThrow(Throw node); | |
22 T visitTry(Try node); | |
23 T visitCatch(Catch node); | |
24 T visitSwitch(Switch node); | |
25 T visitCase(Case node); | |
26 T visitDefault(Default node); | |
27 T visitFunctionDeclaration(FunctionDeclaration node); | |
28 T visitLabeledStatement(LabeledStatement node); | |
29 T visitLiteralStatement(LiteralStatement node); | |
30 | |
31 T visitBlob(Blob node); | |
32 T visitLiteralExpression(LiteralExpression node); | |
33 T visitVariableDeclarationList(VariableDeclarationList node); | |
34 T visitAssignment(Assignment node); | |
35 T visitVariableInitialization(VariableInitialization node); | |
36 T visitConditional(Conditional cond); | |
37 T visitNew(New node); | |
38 T visitCall(Call node); | |
39 T visitBinary(Binary node); | |
40 T visitPrefix(Prefix node); | |
41 T visitPostfix(Postfix node); | |
42 | |
43 T visitVariableUse(VariableUse node); | |
44 T visitThis(This node); | |
45 T visitVariableDeclaration(VariableDeclaration node); | |
46 T visitParameter(Parameter node); | |
47 T visitAccess(PropertyAccess node); | |
48 | |
49 T visitNamedFunction(NamedFunction node); | |
50 T visitFun(Fun node); | |
51 | |
52 T visitLiteralBool(LiteralBool node); | |
53 T visitLiteralString(LiteralString node); | |
54 T visitLiteralNumber(LiteralNumber node); | |
55 T visitLiteralNull(LiteralNull node); | |
56 | |
57 T visitArrayInitializer(ArrayInitializer node); | |
58 T visitArrayElement(ArrayElement node); | |
59 T visitObjectInitializer(ObjectInitializer node); | |
60 T visitProperty(Property node); | |
61 T visitRegExpLiteral(RegExpLiteral node); | |
62 | |
63 T visitComment(Comment node); | |
64 | |
65 T visitInterpolatedExpression(InterpolatedExpression node); | |
66 T visitInterpolatedLiteral(InterpolatedLiteral node); | |
67 T visitInterpolatedParameter(InterpolatedParameter node); | |
68 T visitInterpolatedSelector(InterpolatedSelector node); | |
69 T visitInterpolatedStatement(InterpolatedStatement node); | |
70 } | |
71 | |
72 class BaseVisitor<T> implements NodeVisitor<T> { | |
73 T visitNode(Node node) { | |
74 node.visitChildren(this); | |
75 return null; | |
76 } | |
77 | |
78 T visitProgram(Program node) => visitNode(node); | |
79 | |
80 T visitStatement(Statement node) => visitNode(node); | |
81 T visitLoop(Loop node) => visitStatement(node); | |
82 T visitJump(Statement node) => visitStatement(node); | |
83 | |
84 T visitBlock(Block node) => visitStatement(node); | |
85 T visitExpressionStatement(ExpressionStatement node) | |
86 => visitStatement(node); | |
87 T visitEmptyStatement(EmptyStatement node) => visitStatement(node); | |
88 T visitIf(If node) => visitStatement(node); | |
89 T visitFor(For node) => visitLoop(node); | |
90 T visitForIn(ForIn node) => visitLoop(node); | |
91 T visitWhile(While node) => visitLoop(node); | |
92 T visitDo(Do node) => visitLoop(node); | |
93 T visitContinue(Continue node) => visitJump(node); | |
94 T visitBreak(Break node) => visitJump(node); | |
95 T visitReturn(Return node) => visitJump(node); | |
96 T visitThrow(Throw node) => visitJump(node); | |
97 T visitTry(Try node) => visitStatement(node); | |
98 T visitSwitch(Switch node) => visitStatement(node); | |
99 T visitFunctionDeclaration(FunctionDeclaration node) | |
100 => visitStatement(node); | |
101 T visitLabeledStatement(LabeledStatement node) => visitStatement(node); | |
102 T visitLiteralStatement(LiteralStatement node) => visitStatement(node); | |
103 | |
104 T visitCatch(Catch node) => visitNode(node); | |
105 T visitCase(Case node) => visitNode(node); | |
106 T visitDefault(Default node) => visitNode(node); | |
107 | |
108 T visitExpression(Expression node) => visitNode(node); | |
109 T visitBlob(Blob node) => visitExpression(node); | |
110 T visitVariableReference(VariableReference node) => visitExpression(node); | |
111 | |
112 T visitLiteralExpression(LiteralExpression node) => visitExpression(node); | |
113 T visitVariableDeclarationList(VariableDeclarationList node) | |
114 => visitExpression(node); | |
115 T visitAssignment(Assignment node) => visitExpression(node); | |
116 T visitVariableInitialization(VariableInitialization node) { | |
117 if (node.value != null) { | |
118 return visitAssignment(node); | |
119 } else { | |
120 return visitExpression(node); | |
121 } | |
122 } | |
123 T visitConditional(Conditional node) => visitExpression(node); | |
124 T visitNew(New node) => visitExpression(node); | |
125 T visitCall(Call node) => visitExpression(node); | |
126 T visitBinary(Binary node) => visitExpression(node); | |
127 T visitPrefix(Prefix node) => visitExpression(node); | |
128 T visitPostfix(Postfix node) => visitExpression(node); | |
129 T visitAccess(PropertyAccess node) => visitExpression(node); | |
130 | |
131 T visitVariableUse(VariableUse node) => visitVariableReference(node); | |
132 T visitVariableDeclaration(VariableDeclaration node) | |
133 => visitVariableReference(node); | |
134 T visitParameter(Parameter node) => visitVariableDeclaration(node); | |
135 T visitThis(This node) => visitParameter(node); | |
136 | |
137 T visitNamedFunction(NamedFunction node) => visitExpression(node); | |
138 T visitFun(Fun node) => visitExpression(node); | |
139 | |
140 T visitLiteral(Literal node) => visitExpression(node); | |
141 | |
142 T visitLiteralBool(LiteralBool node) => visitLiteral(node); | |
143 T visitLiteralString(LiteralString node) => visitLiteral(node); | |
144 T visitLiteralNumber(LiteralNumber node) => visitLiteral(node); | |
145 T visitLiteralNull(LiteralNull node) => visitLiteral(node); | |
146 | |
147 T visitArrayInitializer(ArrayInitializer node) => visitExpression(node); | |
148 T visitArrayElement(ArrayElement node) => visitNode(node); | |
149 T visitObjectInitializer(ObjectInitializer node) => visitExpression(node); | |
150 T visitProperty(Property node) => visitNode(node); | |
151 T visitRegExpLiteral(RegExpLiteral node) => visitExpression(node); | |
152 | |
153 T visitInterpolatedNode(InterpolatedNode node) => visitNode(node); | |
154 | |
155 T visitInterpolatedExpression(InterpolatedExpression node) | |
156 => visitInterpolatedNode(node); | |
157 T visitInterpolatedLiteral(InterpolatedLiteral node) | |
158 => visitInterpolatedNode(node); | |
159 T visitInterpolatedParameter(InterpolatedParameter node) | |
160 => visitInterpolatedNode(node); | |
161 T visitInterpolatedSelector(InterpolatedSelector node) | |
162 => visitInterpolatedNode(node); | |
163 T visitInterpolatedStatement(InterpolatedStatement node) | |
164 => visitInterpolatedNode(node); | |
165 | |
166 // Ignore comments by default. | |
167 T visitComment(Comment node) => null; | |
168 } | |
169 | |
170 abstract class Node { | |
171 get sourcePosition => _sourcePosition; | |
172 get endSourcePosition => _endSourcePosition; | |
173 | |
174 var _sourcePosition; | |
175 var _endSourcePosition; | |
176 | |
177 accept(NodeVisitor visitor); | |
178 void visitChildren(NodeVisitor visitor); | |
179 | |
180 // Shallow clone of node. Does not clone positions since the only use of this | |
181 // private method is create a copy with a new position. | |
182 Node _clone(); | |
183 | |
184 // Returns a node equivalent to [this], but with new source position and end | |
185 // source position. | |
186 Node withPosition(var sourcePosition, var endSourcePosition) { | |
187 if (sourcePosition == _sourcePosition && | |
188 endSourcePosition == _endSourcePosition) { | |
189 return this; | |
190 } | |
191 Node clone = _clone(); | |
192 // TODO(sra): Should existing data be 'sticky' if we try to overwrite with | |
193 // `null`? | |
194 clone._sourcePosition = sourcePosition; | |
195 clone._endSourcePosition = endSourcePosition; | |
196 return clone; | |
197 } | |
198 | |
199 // Returns a node equivalent to [this], but with new [this.sourcePositions], | |
200 // keeping the existing [endPosition] | |
201 Node withLocation(var sourcePosition) => | |
202 withPosition(sourcePosition, this.endSourcePosition); | |
203 | |
204 VariableUse asVariableUse() => null; | |
205 | |
206 bool get isCommaOperator => false; | |
207 | |
208 Statement toStatement() { | |
209 throw new UnsupportedError('toStatement'); | |
210 } | |
211 } | |
212 | |
213 class Program extends Node { | |
214 final List<Statement> body; | |
215 Program(this.body); | |
216 | |
217 accept(NodeVisitor visitor) => visitor.visitProgram(this); | |
218 void visitChildren(NodeVisitor visitor) { | |
219 for (Statement statement in body) statement.accept(visitor); | |
220 } | |
221 Program _clone() => new Program(body); | |
222 } | |
223 | |
224 abstract class Statement extends Node { | |
225 Statement toStatement() => this; | |
226 | |
227 Statement withPosition(var sourcePosition, var endSourcePosition) => | |
228 super.withPosition(sourcePosition, endSourcePosition); | |
229 } | |
230 | |
231 class Block extends Statement { | |
232 final List<Statement> statements; | |
233 Block(this.statements); | |
234 Block.empty() : this.statements = <Statement>[]; | |
235 | |
236 accept(NodeVisitor visitor) => visitor.visitBlock(this); | |
237 void visitChildren(NodeVisitor visitor) { | |
238 for (Statement statement in statements) statement.accept(visitor); | |
239 } | |
240 Block _clone() => new Block(statements); | |
241 } | |
242 | |
243 class ExpressionStatement extends Statement { | |
244 final Expression expression; | |
245 ExpressionStatement(this.expression); | |
246 | |
247 accept(NodeVisitor visitor) => visitor.visitExpressionStatement(this); | |
248 void visitChildren(NodeVisitor visitor) { expression.accept(visitor); } | |
249 ExpressionStatement _clone() => new ExpressionStatement(expression); | |
250 } | |
251 | |
252 class EmptyStatement extends Statement { | |
253 EmptyStatement(); | |
254 | |
255 accept(NodeVisitor visitor) => visitor.visitEmptyStatement(this); | |
256 void visitChildren(NodeVisitor visitor) {} | |
257 EmptyStatement _clone() => new EmptyStatement(); | |
258 } | |
259 | |
260 class If extends Statement { | |
261 final Expression condition; | |
262 final Node then; | |
263 final Node otherwise; | |
264 | |
265 If(this.condition, this.then, this.otherwise); | |
266 If.noElse(this.condition, this.then) : this.otherwise = new EmptyStatement(); | |
267 | |
268 bool get hasElse => otherwise is !EmptyStatement; | |
269 | |
270 accept(NodeVisitor visitor) => visitor.visitIf(this); | |
271 | |
272 void visitChildren(NodeVisitor visitor) { | |
273 condition.accept(visitor); | |
274 then.accept(visitor); | |
275 otherwise.accept(visitor); | |
276 } | |
277 | |
278 If _clone() => new If(condition, then, otherwise); | |
279 } | |
280 | |
281 abstract class Loop extends Statement { | |
282 final Statement body; | |
283 Loop(this.body); | |
284 } | |
285 | |
286 class For extends Loop { | |
287 final Expression init; | |
288 final Expression condition; | |
289 final Expression update; | |
290 | |
291 For(this.init, this.condition, this.update, Statement body) : super(body); | |
292 | |
293 accept(NodeVisitor visitor) => visitor.visitFor(this); | |
294 | |
295 void visitChildren(NodeVisitor visitor) { | |
296 if (init != null) init.accept(visitor); | |
297 if (condition != null) condition.accept(visitor); | |
298 if (update != null) update.accept(visitor); | |
299 body.accept(visitor); | |
300 } | |
301 | |
302 For _clone() => new For(init, condition, update, body); | |
303 } | |
304 | |
305 class ForIn extends Loop { | |
306 // Note that [VariableDeclarationList] is a subclass of [Expression]. | |
307 // Therefore we can type the leftHandSide as [Expression]. | |
308 final Expression leftHandSide; | |
309 final Expression object; | |
310 | |
311 ForIn(this.leftHandSide, this.object, Statement body) : super(body); | |
312 | |
313 accept(NodeVisitor visitor) => visitor.visitForIn(this); | |
314 | |
315 void visitChildren(NodeVisitor visitor) { | |
316 leftHandSide.accept(visitor); | |
317 object.accept(visitor); | |
318 body.accept(visitor); | |
319 } | |
320 | |
321 ForIn _clone() => new ForIn(leftHandSide, object, body); | |
322 } | |
323 | |
324 class While extends Loop { | |
325 final Node condition; | |
326 | |
327 While(this.condition, Statement body) : super(body); | |
328 | |
329 accept(NodeVisitor visitor) => visitor.visitWhile(this); | |
330 | |
331 void visitChildren(NodeVisitor visitor) { | |
332 condition.accept(visitor); | |
333 body.accept(visitor); | |
334 } | |
335 | |
336 While _clone() => new While(condition, body); | |
337 } | |
338 | |
339 class Do extends Loop { | |
340 final Expression condition; | |
341 | |
342 Do(Statement body, this.condition) : super(body); | |
343 | |
344 accept(NodeVisitor visitor) => visitor.visitDo(this); | |
345 | |
346 void visitChildren(NodeVisitor visitor) { | |
347 body.accept(visitor); | |
348 condition.accept(visitor); | |
349 } | |
350 | |
351 Do _clone() => new Do(body, condition); | |
352 } | |
353 | |
354 class Continue extends Statement { | |
355 final String targetLabel; // Can be null. | |
356 | |
357 Continue(this.targetLabel); | |
358 | |
359 accept(NodeVisitor visitor) => visitor.visitContinue(this); | |
360 void visitChildren(NodeVisitor visitor) {} | |
361 | |
362 Continue _clone() => new Continue(targetLabel); | |
363 } | |
364 | |
365 class Break extends Statement { | |
366 final String targetLabel; // Can be null. | |
367 | |
368 Break(this.targetLabel); | |
369 | |
370 accept(NodeVisitor visitor) => visitor.visitBreak(this); | |
371 void visitChildren(NodeVisitor visitor) {} | |
372 | |
373 Break _clone() => new Break(targetLabel); | |
374 } | |
375 | |
376 class Return extends Statement { | |
377 final Expression value; // Can be null. | |
378 | |
379 Return([this.value = null]); | |
380 | |
381 accept(NodeVisitor visitor) => visitor.visitReturn(this); | |
382 | |
383 void visitChildren(NodeVisitor visitor) { | |
384 if (value != null) value.accept(visitor); | |
385 } | |
386 | |
387 Return _clone() => new Return(value); | |
388 } | |
389 | |
390 class Throw extends Statement { | |
391 final Expression expression; | |
392 | |
393 Throw(this.expression); | |
394 | |
395 accept(NodeVisitor visitor) => visitor.visitThrow(this); | |
396 | |
397 void visitChildren(NodeVisitor visitor) { | |
398 expression.accept(visitor); | |
399 } | |
400 | |
401 Throw _clone() => new Throw(expression); | |
402 } | |
403 | |
404 class Try extends Statement { | |
405 final Block body; | |
406 final Catch catchPart; // Can be null if [finallyPart] is non-null. | |
407 final Block finallyPart; // Can be null if [catchPart] is non-null. | |
408 | |
409 Try(this.body, this.catchPart, this.finallyPart) { | |
410 assert(catchPart != null || finallyPart != null); | |
411 } | |
412 | |
413 accept(NodeVisitor visitor) => visitor.visitTry(this); | |
414 | |
415 void visitChildren(NodeVisitor visitor) { | |
416 body.accept(visitor); | |
417 if (catchPart != null) catchPart.accept(visitor); | |
418 if (finallyPart != null) finallyPart.accept(visitor); | |
419 } | |
420 | |
421 Try _clone() => new Try(body, catchPart, finallyPart); | |
422 } | |
423 | |
424 class Catch extends Node { | |
425 final VariableDeclaration declaration; | |
426 final Block body; | |
427 | |
428 Catch(this.declaration, this.body); | |
429 | |
430 accept(NodeVisitor visitor) => visitor.visitCatch(this); | |
431 | |
432 void visitChildren(NodeVisitor visitor) { | |
433 declaration.accept(visitor); | |
434 body.accept(visitor); | |
435 } | |
436 | |
437 Catch _clone() => new Catch(declaration, body); | |
438 } | |
439 | |
440 class Switch extends Statement { | |
441 final Expression key; | |
442 final List<SwitchClause> cases; | |
443 | |
444 Switch(this.key, this.cases); | |
445 | |
446 accept(NodeVisitor visitor) => visitor.visitSwitch(this); | |
447 | |
448 void visitChildren(NodeVisitor visitor) { | |
449 key.accept(visitor); | |
450 for (SwitchClause clause in cases) clause.accept(visitor); | |
451 } | |
452 | |
453 Switch _clone() => new Switch(key, cases); | |
454 } | |
455 | |
456 abstract class SwitchClause extends Node { | |
457 final Block body; | |
458 | |
459 SwitchClause(this.body); | |
460 } | |
461 | |
462 class Case extends SwitchClause { | |
463 final Expression expression; | |
464 | |
465 Case(this.expression, Block body) : super(body); | |
466 | |
467 accept(NodeVisitor visitor) => visitor.visitCase(this); | |
468 | |
469 void visitChildren(NodeVisitor visitor) { | |
470 expression.accept(visitor); | |
471 body.accept(visitor); | |
472 } | |
473 | |
474 Case _clone() => new Case(expression, body); | |
475 } | |
476 | |
477 class Default extends SwitchClause { | |
478 Default(Block body) : super(body); | |
479 | |
480 accept(NodeVisitor visitor) => visitor.visitDefault(this); | |
481 | |
482 void visitChildren(NodeVisitor visitor) { | |
483 body.accept(visitor); | |
484 } | |
485 | |
486 Default _clone() => new Default(body); | |
487 } | |
488 | |
489 class FunctionDeclaration extends Statement { | |
490 final VariableDeclaration name; | |
491 final Fun function; | |
492 | |
493 FunctionDeclaration(this.name, this.function); | |
494 | |
495 accept(NodeVisitor visitor) => visitor.visitFunctionDeclaration(this); | |
496 | |
497 void visitChildren(NodeVisitor visitor) { | |
498 name.accept(visitor); | |
499 function.accept(visitor); | |
500 } | |
501 | |
502 FunctionDeclaration _clone() => new FunctionDeclaration(name, function); | |
503 } | |
504 | |
505 class LabeledStatement extends Statement { | |
506 final String label; | |
507 final Statement body; | |
508 | |
509 LabeledStatement(this.label, this.body); | |
510 | |
511 accept(NodeVisitor visitor) => visitor.visitLabeledStatement(this); | |
512 | |
513 void visitChildren(NodeVisitor visitor) { | |
514 body.accept(visitor); | |
515 } | |
516 | |
517 LabeledStatement _clone() => new LabeledStatement(label, body); | |
518 } | |
519 | |
520 class LiteralStatement extends Statement { | |
521 final String code; | |
522 | |
523 LiteralStatement(this.code); | |
524 | |
525 accept(NodeVisitor visitor) => visitor.visitLiteralStatement(this); | |
526 void visitChildren(NodeVisitor visitor) { } | |
527 | |
528 LiteralStatement _clone() => new LiteralStatement(code); | |
529 } | |
530 | |
531 abstract class Expression extends Node { | |
532 int get precedenceLevel; | |
533 | |
534 Statement toStatement() => new ExpressionStatement(this); | |
535 | |
536 Expression withPosition(var sourcePosition, var endSourcePosition) => | |
537 super.withPosition(sourcePosition, endSourcePosition); | |
538 } | |
539 | |
540 /// Wrap a CodeBuffer as an expression. | |
541 class Blob extends Expression { | |
542 // TODO(ahe): This class is an aid to convert everything to ASTs, remove when | |
543 // not needed anymore. | |
544 | |
545 final leg.CodeBuffer buffer; | |
546 | |
547 Blob(this.buffer); | |
548 | |
549 accept(NodeVisitor visitor) => visitor.visitBlob(this); | |
550 | |
551 void visitChildren(NodeVisitor visitor) {} | |
552 | |
553 Blob _clone() => new Blob(buffer); | |
554 | |
555 int get precedenceLevel => PRIMARY; | |
556 | |
557 } | |
558 | |
559 class LiteralExpression extends Expression { | |
560 final String template; | |
561 final List<Expression> inputs; | |
562 | |
563 LiteralExpression(this.template) : inputs = const []; | |
564 LiteralExpression.withData(this.template, this.inputs); | |
565 | |
566 accept(NodeVisitor visitor) => visitor.visitLiteralExpression(this); | |
567 | |
568 void visitChildren(NodeVisitor visitor) { | |
569 if (inputs != null) { | |
570 for (Expression expr in inputs) expr.accept(visitor); | |
571 } | |
572 } | |
573 | |
574 LiteralExpression _clone() => | |
575 new LiteralExpression.withData(template, inputs); | |
576 | |
577 // Code that uses JS must take care of operator precedences, and | |
578 // put parenthesis if needed. | |
579 int get precedenceLevel => PRIMARY; | |
580 } | |
581 | |
582 /** | |
583 * [VariableDeclarationList] is a subclass of [Expression] to simplify the | |
584 * AST. | |
585 */ | |
586 class VariableDeclarationList extends Expression { | |
587 final List<VariableInitialization> declarations; | |
588 | |
589 VariableDeclarationList(this.declarations); | |
590 | |
591 accept(NodeVisitor visitor) => visitor.visitVariableDeclarationList(this); | |
592 | |
593 void visitChildren(NodeVisitor visitor) { | |
594 for (VariableInitialization declaration in declarations) { | |
595 declaration.accept(visitor); | |
596 } | |
597 } | |
598 | |
599 VariableDeclarationList _clone() => new VariableDeclarationList(declarations); | |
600 | |
601 int get precedenceLevel => EXPRESSION; | |
602 } | |
603 | |
604 class Assignment extends Expression { | |
605 final Expression leftHandSide; | |
606 final String op; // Null, if the assignment is not compound. | |
607 final Expression value; // May be null, for [VariableInitialization]s. | |
608 | |
609 Assignment(leftHandSide, value) | |
610 : this.compound(leftHandSide, null, value); | |
611 Assignment.compound(this.leftHandSide, this.op, this.value); | |
612 | |
613 int get precedenceLevel => ASSIGNMENT; | |
614 | |
615 bool get isCompound => op != null; | |
616 | |
617 accept(NodeVisitor visitor) => visitor.visitAssignment(this); | |
618 | |
619 void visitChildren(NodeVisitor visitor) { | |
620 leftHandSide.accept(visitor); | |
621 if (value != null) value.accept(visitor); | |
622 } | |
623 | |
624 Assignment _clone() => | |
625 new Assignment.compound(leftHandSide, op, value); | |
626 } | |
627 | |
628 class VariableInitialization extends Assignment { | |
629 /** [value] may be null. */ | |
630 VariableInitialization(VariableDeclaration declaration, Expression value) | |
631 : super(declaration, value); | |
632 | |
633 VariableDeclaration get declaration => leftHandSide; | |
634 | |
635 accept(NodeVisitor visitor) => visitor.visitVariableInitialization(this); | |
636 | |
637 VariableInitialization _clone() => | |
638 new VariableInitialization(declaration, value); | |
639 } | |
640 | |
641 class Conditional extends Expression { | |
642 final Expression condition; | |
643 final Expression then; | |
644 final Expression otherwise; | |
645 | |
646 Conditional(this.condition, this.then, this.otherwise); | |
647 | |
648 accept(NodeVisitor visitor) => visitor.visitConditional(this); | |
649 | |
650 void visitChildren(NodeVisitor visitor) { | |
651 condition.accept(visitor); | |
652 then.accept(visitor); | |
653 otherwise.accept(visitor); | |
654 } | |
655 | |
656 Conditional _clone() => new Conditional(condition, then, otherwise); | |
657 | |
658 int get precedenceLevel => ASSIGNMENT; | |
659 } | |
660 | |
661 class Call extends Expression { | |
662 Expression target; | |
663 List<Expression> arguments; | |
664 | |
665 Call(this.target, this.arguments); | |
666 | |
667 accept(NodeVisitor visitor) => visitor.visitCall(this); | |
668 | |
669 void visitChildren(NodeVisitor visitor) { | |
670 target.accept(visitor); | |
671 for (Expression arg in arguments) arg.accept(visitor); | |
672 } | |
673 | |
674 Call _clone() => new Call(target, arguments); | |
675 | |
676 int get precedenceLevel => CALL; | |
677 } | |
678 | |
679 class New extends Call { | |
680 New(Expression cls, List<Expression> arguments) : super(cls, arguments); | |
681 | |
682 accept(NodeVisitor visitor) => visitor.visitNew(this); | |
683 | |
684 New _clone() => new New(target, arguments); | |
685 } | |
686 | |
687 class Binary extends Expression { | |
688 final String op; | |
689 final Expression left; | |
690 final Expression right; | |
691 | |
692 Binary(this.op, this.left, this.right); | |
693 | |
694 accept(NodeVisitor visitor) => visitor.visitBinary(this); | |
695 | |
696 Binary _clone() => new Binary(op, left, right); | |
697 | |
698 void visitChildren(NodeVisitor visitor) { | |
699 left.accept(visitor); | |
700 right.accept(visitor); | |
701 } | |
702 | |
703 bool get isCommaOperator => op == ','; | |
704 | |
705 int get precedenceLevel { | |
706 // TODO(floitsch): switch to constant map. | |
707 switch (op) { | |
708 case "*": | |
709 case "/": | |
710 case "%": | |
711 return MULTIPLICATIVE; | |
712 case "+": | |
713 case "-": | |
714 return ADDITIVE; | |
715 case "<<": | |
716 case ">>": | |
717 case ">>>": | |
718 return SHIFT; | |
719 case "<": | |
720 case ">": | |
721 case "<=": | |
722 case ">=": | |
723 case "instanceof": | |
724 case "in": | |
725 return RELATIONAL; | |
726 case "==": | |
727 case "===": | |
728 case "!=": | |
729 case "!==": | |
730 return EQUALITY; | |
731 case "&": | |
732 return BIT_AND; | |
733 case "^": | |
734 return BIT_XOR; | |
735 case "|": | |
736 return BIT_OR; | |
737 case "&&": | |
738 return LOGICAL_AND; | |
739 case "||": | |
740 return LOGICAL_OR; | |
741 case ',': | |
742 return EXPRESSION; | |
743 default: | |
744 throw new leg.CompilerCancelledException( | |
745 "Internal Error: Unhandled binary operator: $op"); | |
746 } | |
747 } | |
748 } | |
749 | |
750 class Prefix extends Expression { | |
751 final String op; | |
752 final Expression argument; | |
753 | |
754 Prefix(this.op, this.argument); | |
755 | |
756 accept(NodeVisitor visitor) => visitor.visitPrefix(this); | |
757 | |
758 Prefix _clone() => new Prefix(op, argument); | |
759 | |
760 void visitChildren(NodeVisitor visitor) { | |
761 argument.accept(visitor); | |
762 } | |
763 | |
764 int get precedenceLevel => UNARY; | |
765 } | |
766 | |
767 class Postfix extends Expression { | |
768 final String op; | |
769 final Expression argument; | |
770 | |
771 Postfix(this.op, this.argument); | |
772 | |
773 accept(NodeVisitor visitor) => visitor.visitPostfix(this); | |
774 | |
775 Postfix _clone() => new Postfix(op, argument); | |
776 | |
777 void visitChildren(NodeVisitor visitor) { | |
778 argument.accept(visitor); | |
779 } | |
780 | |
781 | |
782 int get precedenceLevel => UNARY; | |
783 } | |
784 | |
785 abstract class VariableReference extends Expression { | |
786 final String name; | |
787 | |
788 VariableReference(this.name) { | |
789 assert(_identifierRE.hasMatch(name)); | |
790 } | |
791 static RegExp _identifierRE = new RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$'); | |
792 | |
793 accept(NodeVisitor visitor); | |
794 int get precedenceLevel => PRIMARY; | |
795 void visitChildren(NodeVisitor visitor) {} | |
796 } | |
797 | |
798 class VariableUse extends VariableReference { | |
799 VariableUse(String name) : super(name); | |
800 | |
801 accept(NodeVisitor visitor) => visitor.visitVariableUse(this); | |
802 VariableUse _clone() => new VariableUse(name); | |
803 | |
804 VariableUse asVariableUse() => this; | |
805 | |
806 toString() => 'VariableUse($name)'; | |
807 } | |
808 | |
809 class VariableDeclaration extends VariableReference { | |
810 final bool allowRename; | |
811 VariableDeclaration(String name, {this.allowRename: true}) : super(name); | |
812 | |
813 accept(NodeVisitor visitor) => visitor.visitVariableDeclaration(this); | |
814 VariableDeclaration _clone() => new VariableDeclaration(name); | |
815 } | |
816 | |
817 class Parameter extends VariableDeclaration { | |
818 Parameter(String name) : super(name); | |
819 | |
820 accept(NodeVisitor visitor) => visitor.visitParameter(this); | |
821 Parameter _clone() => new Parameter(name); | |
822 } | |
823 | |
824 class This extends Parameter { | |
825 This() : super("this"); | |
826 | |
827 accept(NodeVisitor visitor) => visitor.visitThis(this); | |
828 This _clone() => new This(); | |
829 } | |
830 | |
831 class NamedFunction extends Expression { | |
832 final VariableDeclaration name; | |
833 final Fun function; | |
834 | |
835 NamedFunction(this.name, this.function); | |
836 | |
837 accept(NodeVisitor visitor) => visitor.visitNamedFunction(this); | |
838 | |
839 void visitChildren(NodeVisitor visitor) { | |
840 name.accept(visitor); | |
841 function.accept(visitor); | |
842 } | |
843 NamedFunction _clone() => new NamedFunction(name, function); | |
844 | |
845 int get precedenceLevel => CALL; | |
846 } | |
847 | |
848 class Fun extends Expression { | |
849 final List<Parameter> params; | |
850 final Block body; | |
851 | |
852 Fun(this.params, this.body); | |
853 | |
854 accept(NodeVisitor visitor) => visitor.visitFun(this); | |
855 | |
856 void visitChildren(NodeVisitor visitor) { | |
857 for (Parameter param in params) param.accept(visitor); | |
858 body.accept(visitor); | |
859 } | |
860 | |
861 Fun _clone() => new Fun(params, body); | |
862 | |
863 int get precedenceLevel => CALL; | |
864 } | |
865 | |
866 class PropertyAccess extends Expression { | |
867 final Expression receiver; | |
868 final Expression selector; | |
869 | |
870 PropertyAccess(this.receiver, this.selector); | |
871 PropertyAccess.field(this.receiver, String fieldName) | |
872 : selector = new LiteralString('"$fieldName"'); | |
873 PropertyAccess.indexed(this.receiver, int index) | |
874 : selector = new LiteralNumber('$index'); | |
875 | |
876 accept(NodeVisitor visitor) => visitor.visitAccess(this); | |
877 | |
878 void visitChildren(NodeVisitor visitor) { | |
879 receiver.accept(visitor); | |
880 selector.accept(visitor); | |
881 } | |
882 | |
883 PropertyAccess _clone() => new PropertyAccess(receiver, selector); | |
884 | |
885 int get precedenceLevel => CALL; | |
886 } | |
887 | |
888 abstract class Literal extends Expression { | |
889 void visitChildren(NodeVisitor visitor) {} | |
890 | |
891 int get precedenceLevel => PRIMARY; | |
892 } | |
893 | |
894 class LiteralBool extends Literal { | |
895 final bool value; | |
896 | |
897 LiteralBool(this.value); | |
898 | |
899 accept(NodeVisitor visitor) => visitor.visitLiteralBool(this); | |
900 // [visitChildren] inherited from [Literal]. | |
901 LiteralBool _clone() => new LiteralBool(value); | |
902 } | |
903 | |
904 class LiteralNull extends Literal { | |
905 LiteralNull(); | |
906 | |
907 accept(NodeVisitor visitor) => visitor.visitLiteralNull(this); | |
908 LiteralNull _clone() => new LiteralNull(); | |
909 } | |
910 | |
911 class LiteralString extends Literal { | |
912 final String value; | |
913 | |
914 /** | |
915 * Constructs a LiteralString from a string value. | |
916 * | |
917 * The constructor does not add the required quotes. If [value] is | |
918 * not surrounded by quotes, the resulting object is invalid as a JS | |
919 * value. | |
920 */ | |
921 LiteralString(this.value); | |
922 | |
923 accept(NodeVisitor visitor) => visitor.visitLiteralString(this); | |
924 LiteralString _clone() => new LiteralString(value); | |
925 } | |
926 | |
927 class LiteralNumber extends Literal { | |
928 final String value; | |
929 | |
930 LiteralNumber(this.value); | |
931 | |
932 accept(NodeVisitor visitor) => visitor.visitLiteralNumber(this); | |
933 LiteralNumber _clone() => new LiteralNumber(value); | |
934 } | |
935 | |
936 class ArrayInitializer extends Expression { | |
937 final int length; | |
938 // We represent the array as sparse list of elements. Each element knows its | |
939 // position in the array. | |
940 final List<ArrayElement> elements; | |
941 | |
942 ArrayInitializer(this.length, this.elements); | |
943 | |
944 factory ArrayInitializer.from(Iterable<Expression> expressions) { | |
945 List<ArrayElement> elements = _convert(expressions); | |
946 return new ArrayInitializer(elements.length, elements); | |
947 } | |
948 | |
949 accept(NodeVisitor visitor) => visitor.visitArrayInitializer(this); | |
950 | |
951 void visitChildren(NodeVisitor visitor) { | |
952 for (ArrayElement element in elements) element.accept(visitor); | |
953 } | |
954 | |
955 ArrayInitializer _clone() => new ArrayInitializer(length, elements); | |
956 | |
957 int get precedenceLevel => PRIMARY; | |
958 | |
959 static List<ArrayElement> _convert(Iterable<Expression> expressions) { | |
960 int index = 0; | |
961 return expressions.map( | |
962 (expression) => new ArrayElement(index++, expression)) | |
963 .toList(); | |
964 } | |
965 } | |
966 | |
967 /** | |
968 * An expression inside an [ArrayInitializer]. An [ArrayElement] knows | |
969 * its position in the containing [ArrayInitializer]. | |
970 */ | |
971 class ArrayElement extends Node { | |
972 final int index; | |
973 final Expression value; | |
974 | |
975 ArrayElement(this.index, this.value); | |
976 | |
977 accept(NodeVisitor visitor) => visitor.visitArrayElement(this); | |
978 | |
979 void visitChildren(NodeVisitor visitor) { | |
980 value.accept(visitor); | |
981 } | |
982 | |
983 ArrayElement _clone() => new ArrayElement(index, value); | |
984 } | |
985 | |
986 class ObjectInitializer extends Expression { | |
987 final List<Property> properties; | |
988 final bool isOneLiner; | |
989 | |
990 /** | |
991 * Constructs a new object-initializer containing the given [properties]. | |
992 * | |
993 * [isOneLiner] describes the behaviour when pretty-printing (non-minified). | |
994 * If true print all properties on the same line. | |
995 * If false print each property on a seperate line. | |
996 */ | |
997 ObjectInitializer(this.properties, {this.isOneLiner: true}); | |
998 | |
999 accept(NodeVisitor visitor) => visitor.visitObjectInitializer(this); | |
1000 | |
1001 void visitChildren(NodeVisitor visitor) { | |
1002 for (Property init in properties) init.accept(visitor); | |
1003 } | |
1004 | |
1005 ObjectInitializer _clone() => | |
1006 new ObjectInitializer(properties, isOneLiner: isOneLiner); | |
1007 | |
1008 int get precedenceLevel => PRIMARY; | |
1009 } | |
1010 | |
1011 class Property extends Node { | |
1012 final Literal name; | |
1013 final Expression value; | |
1014 | |
1015 Property(this.name, this.value); | |
1016 | |
1017 accept(NodeVisitor visitor) => visitor.visitProperty(this); | |
1018 | |
1019 void visitChildren(NodeVisitor visitor) { | |
1020 name.accept(visitor); | |
1021 value.accept(visitor); | |
1022 } | |
1023 | |
1024 Property _clone() => new Property(name, value); | |
1025 } | |
1026 | |
1027 /// Tag class for all interpolated positions. | |
1028 abstract class InterpolatedNode implements Node { | |
1029 get name; // 'int' for positional interpolated nodes, 'String' for named. | |
1030 } | |
1031 | |
1032 class InterpolatedExpression extends Expression implements InterpolatedNode { | |
1033 final name; | |
1034 | |
1035 InterpolatedExpression(this.name); | |
1036 | |
1037 accept(NodeVisitor visitor) => visitor.visitInterpolatedExpression(this); | |
1038 void visitChildren(NodeVisitor visitor) {} | |
1039 InterpolatedExpression _clone() => new InterpolatedExpression(name); | |
1040 | |
1041 int get precedenceLevel => PRIMARY; | |
1042 } | |
1043 | |
1044 class InterpolatedLiteral extends Literal implements InterpolatedNode { | |
1045 final name; | |
1046 | |
1047 InterpolatedLiteral(this.name); | |
1048 | |
1049 accept(NodeVisitor visitor) => visitor.visitInterpolatedLiteral(this); | |
1050 void visitChildren(NodeVisitor visitor) {} | |
1051 InterpolatedLiteral _clone() => new InterpolatedLiteral(name); | |
1052 } | |
1053 | |
1054 class InterpolatedParameter extends Expression | |
1055 implements Parameter, InterpolatedNode { | |
1056 final name; | |
1057 bool get allowRename => false; | |
1058 | |
1059 InterpolatedParameter(this.name); | |
1060 | |
1061 accept(NodeVisitor visitor) => visitor.visitInterpolatedParameter(this); | |
1062 void visitChildren(NodeVisitor visitor) {} | |
1063 InterpolatedParameter _clone() => new InterpolatedParameter(name); | |
1064 | |
1065 int get precedenceLevel => PRIMARY; | |
1066 } | |
1067 | |
1068 class InterpolatedSelector extends Expression implements InterpolatedNode { | |
1069 final name; | |
1070 | |
1071 InterpolatedSelector(this.name); | |
1072 | |
1073 accept(NodeVisitor visitor) => visitor.visitInterpolatedSelector(this); | |
1074 void visitChildren(NodeVisitor visitor) {} | |
1075 InterpolatedSelector _clone() => new InterpolatedSelector(name); | |
1076 | |
1077 int get precedenceLevel => PRIMARY; | |
1078 } | |
1079 | |
1080 class InterpolatedStatement extends Statement implements InterpolatedNode { | |
1081 final name; | |
1082 | |
1083 InterpolatedStatement(this.name); | |
1084 | |
1085 accept(NodeVisitor visitor) => visitor.visitInterpolatedStatement(this); | |
1086 void visitChildren(NodeVisitor visitor) {} | |
1087 InterpolatedStatement _clone() => new InterpolatedStatement(name); | |
1088 } | |
1089 | |
1090 /** | |
1091 * [RegExpLiteral]s, despite being called "Literal", do not inherit from | |
1092 * [Literal]. Indeed, regular expressions in JavaScript have a side-effect and | |
1093 * are thus not in the same category as numbers or strings. | |
1094 */ | |
1095 class RegExpLiteral extends Expression { | |
1096 /** Contains the pattern and the flags.*/ | |
1097 final String pattern; | |
1098 | |
1099 RegExpLiteral(this.pattern); | |
1100 | |
1101 accept(NodeVisitor visitor) => visitor.visitRegExpLiteral(this); | |
1102 void visitChildren(NodeVisitor visitor) {} | |
1103 RegExpLiteral _clone() => new RegExpLiteral(pattern); | |
1104 | |
1105 int get precedenceLevel => PRIMARY; | |
1106 } | |
1107 | |
1108 /** | |
1109 * A comment. | |
1110 * | |
1111 * Extends [Statement] so we can add comments before statements in | |
1112 * [Block] and [Program]. | |
1113 */ | |
1114 class Comment extends Statement { | |
1115 final String comment; | |
1116 | |
1117 Comment(this.comment); | |
1118 | |
1119 accept(NodeVisitor visitor) => visitor.visitComment(this); | |
1120 Comment _clone() => new Comment(comment); | |
1121 | |
1122 void visitChildren(NodeVisitor visitor) {} | |
1123 } | |
OLD | NEW |