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

Side by Side Diff: lib/src/js/template.dart

Issue 1879373004: Implement modular compilation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/js/printer.dart ('k') | lib/src/js/type_printer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of js_ast;
6
7 class TemplateManager {
8 Map<String, Template> expressionTemplates = new Map<String, Template>();
9 Map<String, Template> statementTemplates = new Map<String, Template>();
10
11 TemplateManager();
12
13 Template lookupExpressionTemplate(String source) {
14 return expressionTemplates[source];
15 }
16
17 Template defineExpressionTemplate(String source, Node ast) {
18 Template template =
19 new Template(source, ast, isExpression: true, forceCopy: false);
20 expressionTemplates[source] = template;
21 return template;
22 }
23
24 Template lookupStatementTemplate(String source) {
25 return statementTemplates[source];
26 }
27
28 Template defineStatementTemplate(String source, Node ast) {
29 Template template =
30 new Template(source, ast, isExpression: false, forceCopy: false);
31 statementTemplates[source] = template;
32 return template;
33 }
34 }
35
36 /**
37 * A Template is created with JavaScript AST containing placeholders (interface
38 * InterpolatedNode). The [instantiate] method creates an AST that looks like
39 * the original with the placeholders replaced by the arguments to
40 * [instantiate].
41 */
42 class Template {
43 final String source;
44 final bool isExpression;
45 final bool forceCopy;
46 final Node ast;
47
48 Instantiator instantiator;
49
50 int positionalArgumentCount = -1;
51
52 // Null, unless there are named holes.
53 List<String> holeNames;
54 bool get isPositional => holeNames == null;
55
56 Template(this.source, this.ast,
57 {this.isExpression: true, this.forceCopy: false}) {
58 _compile();
59 }
60
61 Template.withExpressionResult(this.ast)
62 : source = null,
63 isExpression = true,
64 forceCopy = false {
65 assert(ast is Expression);
66 assert(_checkNoPlaceholders());
67 positionalArgumentCount = 0;
68 instantiator = (arguments) => ast;
69 }
70
71 Template.withStatementResult(this.ast)
72 : source = null,
73 isExpression = false,
74 forceCopy = false {
75 assert(ast is Statement);
76 assert(_checkNoPlaceholders());
77 positionalArgumentCount = 0;
78 instantiator = (arguments) => ast;
79 }
80
81 bool _checkNoPlaceholders() {
82 InstantiatorGeneratorVisitor generator =
83 new InstantiatorGeneratorVisitor(false);
84 generator.compile(ast);
85 return generator.analysis.count == 0;
86 }
87
88 void _compile() {
89 InstantiatorGeneratorVisitor generator =
90 new InstantiatorGeneratorVisitor(forceCopy);
91 instantiator = generator.compile(ast);
92 positionalArgumentCount = generator.analysis.count;
93 Set<String> names = generator.analysis.holeNames;
94 holeNames = names.toList(growable: false);
95 }
96
97 /// Instantiates the template with the given [arguments].
98 ///
99 /// This method fills in the holes with the given arguments. The [arguments]
100 /// must be either a [List] or a [Map].
101 Node instantiate(var arguments) {
102 if (arguments is List) {
103 if (arguments.length != positionalArgumentCount) {
104 throw 'Wrong number of template arguments, given ${arguments.length}, '
105 'expected $positionalArgumentCount:\n$source';
106 }
107 return instantiator(arguments);
108 }
109 assert(arguments is Map);
110 if (holeNames.length < arguments.length) {
111 // This search is in O(n), but we only do it in case of an error, and the
112 // number of holes should be quite limited.
113 String unusedNames =
114 arguments.keys.where((name) => !holeNames.contains(name)).join(", ");
115 throw "Template arguments has unused mappings: $unusedNames";
116 }
117 if (!holeNames.every((String name) => arguments.containsKey(name))) {
118 String notFound =
119 holeNames.where((name) => !arguments.containsKey(name)).join(", ");
120 throw "Template arguments is missing mappings for: $notFound";
121 }
122 return instantiator(arguments);
123 }
124
125 /// Like [instantiate] but works with free variables.
126 Node safeCreate(Map arguments) {
127 if (holeNames.isEmpty) return ast;
128 return instantiator(new Map.fromIterable(holeNames, value: (name) {
129 var a = arguments[name];
130 return a != null ? a : new InterpolatedExpression(name);
131 }));
132 }
133 }
134
135 /**
136 * An Instantiator is a Function that generates a JS AST tree or List of
137 * trees. [arguments] is a List for positional templates, or Map for
138 * named templates.
139 */
140 typedef Instantiator(var arguments);
141
142 /**
143 * InstantiatorGeneratorVisitor compiles a template. This class compiles a tree
144 * containing [InterpolatedNode]s into a function that will create a copy of the
145 * tree with the interpolated nodes substituted with provided values.
146 */
147 class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
148 final bool forceCopy;
149
150 InterpolatedNodeAnalysis analysis = new InterpolatedNodeAnalysis();
151
152 /**
153 * The entire tree is cloned if [forceCopy] is true.
154 */
155 InstantiatorGeneratorVisitor(this.forceCopy);
156
157 Instantiator compile(Node node) {
158 analysis.visit(node);
159 Instantiator result = visit(node);
160 return result;
161 }
162
163 static error(String message) {
164 throw message;
165 }
166
167 static Instantiator same(Node node) => (arguments) => node;
168 static Node makeNull(arguments) => null;
169
170 Instantiator visit(Node node) {
171 if (forceCopy || analysis.containsInterpolatedNodes(node)) {
172 return node.accept(this);
173 }
174 return same(node);
175 }
176
177 Instantiator visitNullable(Node node) {
178 if (node == null) return makeNull;
179 return visit(node);
180 }
181
182 Instantiator visitSplayable(Node node) {
183 // TODO(sra): Process immediate [InterpolatedNode]s, permitting splaying.
184 return visit(node);
185 }
186
187 Instantiator visitNode(Node node) {
188 throw 'Unimplemented InstantiatorGeneratorVisitor for $node';
189 }
190
191 Instantiator visitInterpolatedExpression(InterpolatedExpression node) {
192 var nameOrPosition = node.nameOrPosition;
193 return (arguments) {
194 var value = arguments[nameOrPosition];
195 if (value is Expression) return value;
196 if (value is String) return new Identifier(value);
197 error('Interpolated value #$nameOrPosition is not an Expression: $value');
198 };
199 }
200
201 Instantiator visitSplayableExpression(Node node) {
202 if (node is InterpolatedExpression) {
203 var nameOrPosition = node.nameOrPosition;
204 return (arguments) {
205 var value = arguments[nameOrPosition];
206 Expression toExpression(item) {
207 if (item is Expression) return item;
208 if (item is String) return new Identifier(item);
209 return error('Interpolated value #$nameOrPosition is not '
210 'an Expression or List of Expressions: $value');
211 }
212 if (value is Iterable) return value.map(toExpression);
213 return toExpression(value);
214 };
215 }
216 return visit(node);
217 }
218
219 Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) {
220 var nameOrPosition = node.nameOrPosition;
221 return (arguments) {
222 var value = arguments[nameOrPosition];
223 if (value is Literal) return value;
224 error('Interpolated value #$nameOrPosition is not a Literal: $value');
225 };
226 }
227
228 Instantiator visitInterpolatedParameter(InterpolatedParameter node) {
229 var nameOrPosition = node.nameOrPosition;
230 return (arguments) {
231 var value = arguments[nameOrPosition];
232
233 Parameter toIdentifier(item) {
234 if (item is Parameter) return item;
235 if (item is String) return new Identifier(item);
236 return error('Interpolated value #$nameOrPosition is not an Identifier'
237 ' or List of Identifiers: $value');
238 }
239 if (value is Iterable) return value.map(toIdentifier);
240 return toIdentifier(value);
241 };
242 }
243
244 Instantiator visitInterpolatedSelector(InterpolatedSelector node) {
245 // A selector is an expression, as in `a[selector]`.
246 // A String argument converted into a LiteralString, so `a.#` with argument
247 // 'foo' generates `a["foo"]` which prints as `a.foo`.
248 var nameOrPosition = node.nameOrPosition;
249 return (arguments) {
250 var value = arguments[nameOrPosition];
251 if (value is Expression) return value;
252 if (value is String) return new LiteralString('"$value"');
253 error('Interpolated value #$nameOrPosition is not a selector: $value');
254 };
255 }
256
257 Instantiator visitInterpolatedStatement(InterpolatedStatement node) {
258 var nameOrPosition = node.nameOrPosition;
259 return (arguments) {
260 var value = arguments[nameOrPosition];
261 if (value is Node) return value.toStatement();
262 error('Interpolated value #$nameOrPosition is not a Statement: $value');
263 };
264 }
265
266 Instantiator visitInterpolatedMethod(InterpolatedMethod node) {
267 var nameOrPosition = node.nameOrPosition;
268 return (arguments) {
269 var value = arguments[nameOrPosition];
270 Method toMethod(item) {
271 if (item is Method) return item;
272 return error('Interpolated value #$nameOrPosition is not a Method '
273 'or List of Methods: $value');
274 }
275 if (value is Iterable) return value.map(toMethod);
276 return toMethod(value);
277 };
278 }
279
280 Instantiator visitInterpolatedIdentifier(InterpolatedIdentifier node) {
281 var nameOrPosition = node.nameOrPosition;
282 return (arguments) {
283 var item = arguments[nameOrPosition];
284 if (item is Identifier) return item;
285 if (item is String) return new Identifier(item);
286 return error('Interpolated value #$nameOrPosition is not a '
287 'Identifier or String: $item');
288 };
289 }
290
291 Instantiator visitSplayableStatement(Node node) {
292 if (node is InterpolatedStatement) {
293 var nameOrPosition = node.nameOrPosition;
294 return (arguments) {
295 var value = arguments[nameOrPosition];
296 Statement toStatement(item) {
297 if (item is Statement) return item;
298 if (item is Expression) return item.toStatement();
299 ;
300 return error('Interpolated value #$nameOrPosition is not '
301 'a Statement or List of Statements: $value');
302 }
303 if (value is Iterable) return value.map(toStatement);
304 return toStatement(value);
305 };
306 }
307 return visit(node);
308 }
309
310 Instantiator visitProgram(Program node) {
311 List instantiators = node.body.map(visitSplayableStatement).toList();
312 return (arguments) {
313 List<Statement> statements = <Statement>[];
314 void add(node) {
315 if (node is EmptyStatement) return;
316 if (node is Iterable) {
317 statements.addAll(node);
318 } else {
319 statements.add(node.toStatement());
320 }
321 }
322 for (Instantiator instantiator in instantiators) {
323 add(instantiator(arguments));
324 }
325 return new Program(statements);
326 };
327 }
328
329 Instantiator visitBlock(Block node) {
330 List instantiators = node.statements.map(visitSplayableStatement).toList();
331 return (arguments) {
332 List<Statement> statements = <Statement>[];
333 void add(node) {
334 if (node is EmptyStatement) return;
335 if (node is Iterable) {
336 statements.addAll(node);
337 } else if (node is Block) {
338 statements.addAll(node.statements);
339 } else {
340 statements.add(node.toStatement());
341 }
342 }
343 for (Instantiator instantiator in instantiators) {
344 add(instantiator(arguments));
345 }
346 return new Block(statements);
347 };
348 }
349
350 Instantiator visitExpressionStatement(ExpressionStatement node) {
351 Instantiator buildExpression = visit(node.expression);
352 return (arguments) {
353 return buildExpression(arguments).toStatement();
354 };
355 }
356
357 Instantiator visitEmptyStatement(EmptyStatement node) =>
358 (arguments) => new EmptyStatement();
359
360 Instantiator visitIf(If node) {
361 if (node.condition is InterpolatedExpression) {
362 return visitIfConditionalCompilation(node);
363 } else {
364 return visitIfNormal(node);
365 }
366 }
367
368 Instantiator visitIfConditionalCompilation(If node) {
369 // Special version of visitInterpolatedExpression that permits bools.
370 compileCondition(InterpolatedExpression node) {
371 var nameOrPosition = node.nameOrPosition;
372 return (arguments) {
373 var value = arguments[nameOrPosition];
374 if (value is bool) return value;
375 if (value is Expression) return value;
376 if (value is String) return new Identifier(value);
377 error('Interpolated value #$nameOrPosition '
378 'is not an Expression: $value');
379 };
380 }
381 var makeCondition = compileCondition(node.condition);
382 Instantiator makeThen = visit(node.then);
383 Instantiator makeOtherwise = visit(node.otherwise);
384 return (arguments) {
385 var condition = makeCondition(arguments);
386 if (condition is bool) {
387 if (condition == true) {
388 return makeThen(arguments);
389 } else {
390 return makeOtherwise(arguments);
391 }
392 }
393 return new If(condition, makeThen(arguments), makeOtherwise(arguments));
394 };
395 }
396
397 Instantiator visitIfNormal(If node) {
398 Instantiator makeCondition = visit(node.condition);
399 Instantiator makeThen = visit(node.then);
400 Instantiator makeOtherwise = visit(node.otherwise);
401 return (arguments) {
402 return new If(makeCondition(arguments), makeThen(arguments),
403 makeOtherwise(arguments));
404 };
405 }
406
407 Instantiator visitFor(For node) {
408 Instantiator makeInit = visitNullable(node.init);
409 Instantiator makeCondition = visitNullable(node.condition);
410 Instantiator makeUpdate = visitNullable(node.update);
411 Instantiator makeBody = visit(node.body);
412 return (arguments) {
413 return new For(makeInit(arguments), makeCondition(arguments),
414 makeUpdate(arguments), makeBody(arguments));
415 };
416 }
417
418 Instantiator visitForIn(ForIn node) {
419 Instantiator makeLeftHandSide = visit(node.leftHandSide);
420 Instantiator makeObject = visit(node.object);
421 Instantiator makeBody = visit(node.body);
422 return (arguments) {
423 return new ForIn(makeLeftHandSide(arguments), makeObject(arguments),
424 makeBody(arguments));
425 };
426 }
427
428 Instantiator visitForOf(ForOf node) {
429 Instantiator makeLeftHandSide = visit(node.leftHandSide);
430 Instantiator makeObject = visit(node.iterable);
431 Instantiator makeBody = visit(node.body);
432 return (arguments) {
433 return new ForOf(makeLeftHandSide(arguments), makeObject(arguments),
434 makeBody(arguments));
435 };
436 }
437
438 TODO(String name) {
439 throw new UnimplementedError('$this.$name');
440 }
441
442 Instantiator visitWhile(While node) {
443 Instantiator makeCondition = visit(node.condition);
444 Instantiator makeBody = visit(node.body);
445 return (arguments) {
446 return new While(makeCondition(arguments), makeBody(arguments));
447 };
448 }
449
450 Instantiator visitDo(Do node) {
451 Instantiator makeBody = visit(node.body);
452 Instantiator makeCondition = visit(node.condition);
453 return (arguments) {
454 return new Do(makeBody(arguments), makeCondition(arguments));
455 };
456 }
457
458 Instantiator visitContinue(Continue node) =>
459 (arguments) => new Continue(node.targetLabel);
460
461 Instantiator visitBreak(Break node) =>
462 (arguments) => new Break(node.targetLabel);
463
464 Instantiator visitReturn(Return node) {
465 Instantiator makeExpression = visitNullable(node.value);
466 return (arguments) => new Return(makeExpression(arguments));
467 }
468
469 Instantiator visitDartYield(DartYield node) {
470 Instantiator makeExpression = visit(node.expression);
471 return (arguments) =>
472 new DartYield(makeExpression(arguments), node.hasStar);
473 }
474
475 Instantiator visitThrow(Throw node) {
476 Instantiator makeExpression = visit(node.expression);
477 return (arguments) => new Throw(makeExpression(arguments));
478 }
479
480 Instantiator visitTry(Try node) {
481 Instantiator makeBody = visit(node.body);
482 Instantiator makeCatch = visitNullable(node.catchPart);
483 Instantiator makeFinally = visitNullable(node.finallyPart);
484 return (arguments) => new Try(
485 makeBody(arguments), makeCatch(arguments), makeFinally(arguments));
486 }
487
488 Instantiator visitCatch(Catch node) {
489 Instantiator makeDeclaration = visit(node.declaration);
490 Instantiator makeBody = visit(node.body);
491 return (arguments) =>
492 new Catch(makeDeclaration(arguments), makeBody(arguments));
493 }
494
495 Instantiator visitSwitch(Switch node) {
496 Instantiator makeKey = visit(node.key);
497 Iterable<Instantiator> makeCases = node.cases.map(visit);
498 return (arguments) {
499 return new Switch(
500 makeKey(arguments),
501 makeCases
502 .map((Instantiator makeCase) => makeCase(arguments))
503 .toList());
504 };
505 }
506
507 Instantiator visitCase(Case node) {
508 Instantiator makeExpression = visit(node.expression);
509 Instantiator makeBody = visit(node.body);
510 return (arguments) {
511 return new Case(makeExpression(arguments), makeBody(arguments));
512 };
513 }
514
515 Instantiator visitDefault(Default node) {
516 Instantiator makeBody = visit(node.body);
517 return (arguments) {
518 return new Default(makeBody(arguments));
519 };
520 }
521
522 Instantiator visitFunctionDeclaration(FunctionDeclaration node) {
523 Instantiator makeName = visit(node.name);
524 Instantiator makeFunction = visit(node.function);
525 return (arguments) =>
526 new FunctionDeclaration(makeName(arguments), makeFunction(arguments));
527 }
528
529 Instantiator visitLabeledStatement(LabeledStatement node) {
530 Instantiator makeBody = visit(node.body);
531 return (arguments) => new LabeledStatement(node.label, makeBody(arguments));
532 }
533
534 Instantiator visitLiteralStatement(LiteralStatement node) =>
535 TODO('visitLiteralStatement');
536 Instantiator visitLiteralExpression(LiteralExpression node) =>
537 TODO('visitLiteralExpression');
538
539 Instantiator visitVariableDeclarationList(VariableDeclarationList node) {
540 List<Instantiator> declarationMakers =
541 node.declarations.map(visit).toList();
542 return (arguments) {
543 List<VariableInitialization> declarations = <VariableInitialization>[];
544 for (Instantiator instantiator in declarationMakers) {
545 var result = instantiator(arguments);
546 declarations.add(result);
547 }
548 return new VariableDeclarationList(node.keyword, declarations);
549 };
550 }
551
552 Instantiator visitAssignment(Assignment node) {
553 Instantiator makeLeftHandSide = visit(node.leftHandSide);
554 String op = node.op;
555 Instantiator makeValue = visitNullable(node.value);
556 return (arguments) {
557 return new Assignment.compound(
558 makeLeftHandSide(arguments), op, makeValue(arguments));
559 };
560 }
561
562 Instantiator visitVariableInitialization(VariableInitialization node) {
563 Instantiator makeDeclaration = visit(node.declaration);
564 Instantiator makeValue = visitNullable(node.value);
565 return (arguments) {
566 return new VariableInitialization(
567 makeDeclaration(arguments), makeValue(arguments));
568 };
569 }
570
571 Instantiator visitConditional(Conditional cond) {
572 Instantiator makeCondition = visit(cond.condition);
573 Instantiator makeThen = visit(cond.then);
574 Instantiator makeOtherwise = visit(cond.otherwise);
575 return (arguments) => new Conditional(makeCondition(arguments),
576 makeThen(arguments), makeOtherwise(arguments));
577 }
578
579 Instantiator visitNew(New node) =>
580 handleCallOrNew(node, (target, arguments) => new New(target, arguments));
581
582 Instantiator visitCall(Call node) =>
583 handleCallOrNew(node, (target, arguments) => new Call(target, arguments));
584
585 Instantiator handleCallOrNew(Call node, finish(target, arguments)) {
586 Instantiator makeTarget = visit(node.target);
587 Iterable<Instantiator> argumentMakers =
588 node.arguments.map(visitSplayableExpression).toList();
589
590 // TODO(sra): Avoid copying call arguments if no interpolation or forced
591 // copying.
592 return (arguments) {
593 Node target = makeTarget(arguments);
594 List<Expression> callArguments = <Expression>[];
595 for (Instantiator instantiator in argumentMakers) {
596 var result = instantiator(arguments);
597 if (result is Iterable) {
598 callArguments.addAll(result);
599 } else {
600 callArguments.add(result);
601 }
602 }
603 return finish(target, callArguments.toList(growable: false));
604 };
605 }
606
607 Instantiator visitBinary(Binary node) {
608 Instantiator makeLeft = visit(node.left);
609 Instantiator makeRight = visit(node.right);
610 String op = node.op;
611 return (arguments) =>
612 new Binary(op, makeLeft(arguments), makeRight(arguments));
613 }
614
615 Instantiator visitPrefix(Prefix node) {
616 Instantiator makeOperand = visit(node.argument);
617 String op = node.op;
618 return (arguments) => new Prefix(op, makeOperand(arguments));
619 }
620
621 Instantiator visitPostfix(Postfix node) {
622 Instantiator makeOperand = visit(node.argument);
623 String op = node.op;
624 return (arguments) => new Postfix(op, makeOperand(arguments));
625 }
626
627 Instantiator visitThis(This node) => (arguments) => new This();
628 Instantiator visitSuper(Super node) => (arguments) => new Super();
629
630 Instantiator visitIdentifier(Identifier node) =>
631 (arguments) => new Identifier(node.name);
632
633 Instantiator visitSpread(Spread node) =>
634 (args) => new Spread(visit(node.argument)(args));
635
636 Instantiator visitYield(Yield node) =>
637 (args) => new Yield(node.value != null ? visit(node.value)(args) : null,
638 star: node.star);
639
640 Instantiator visitRestParameter(RestParameter node) =>
641 (args) => new RestParameter(visit(node.parameter)(args));
642
643 Instantiator visitAccess(PropertyAccess node) {
644 Instantiator makeReceiver = visit(node.receiver);
645 Instantiator makeSelector = visit(node.selector);
646 return (arguments) =>
647 new PropertyAccess(makeReceiver(arguments), makeSelector(arguments));
648 }
649
650 Instantiator visitNamedFunction(NamedFunction node) {
651 Instantiator makeDeclaration = visit(node.name);
652 Instantiator makeFunction = visit(node.function);
653 return (arguments) =>
654 new NamedFunction(makeDeclaration(arguments), makeFunction(arguments));
655 }
656
657 Instantiator visitFunctionExpression(FunctionExpression node) {
658 List<Instantiator> paramMakers = node.params.map(visitSplayable).toList();
659 Instantiator makeBody = visit(node.body);
660 // TODO(sra): Avoid copying params if no interpolation or forced copying.
661 return (arguments) {
662 List<Parameter> params = <Parameter>[];
663 for (Instantiator instantiator in paramMakers) {
664 var result = instantiator(arguments);
665 if (result is Iterable) {
666 params.addAll(result);
667 } else {
668 params.add(result);
669 }
670 }
671 var body = makeBody(arguments);
672 if (node is ArrowFun) {
673 return new ArrowFun(params, body);
674 } else if (node is Fun) {
675 return new Fun(params, body);
676 } else {
677 throw "Unknown FunctionExpression type ${node.runtimeType}: $node";
678 }
679 };
680 }
681
682 Instantiator visitFun(Fun node) => visitFunctionExpression(node);
683
684 Instantiator visitArrowFun(ArrowFun node) => visitFunctionExpression(node);
685
686 Instantiator visitLiteralBool(LiteralBool node) =>
687 (arguments) => new LiteralBool(node.value);
688
689 Instantiator visitLiteralString(LiteralString node) =>
690 (arguments) => new LiteralString(node.value);
691
692 Instantiator visitLiteralNumber(LiteralNumber node) =>
693 (arguments) => new LiteralNumber(node.value);
694
695 Instantiator visitLiteralNull(LiteralNull node) =>
696 (arguments) => new LiteralNull();
697
698 Instantiator visitArrayInitializer(ArrayInitializer node) {
699 // TODO(sra): Implement splicing?
700 List<Instantiator> elementMakers =
701 node.elements.map(visit).toList(growable: false);
702 return (arguments) {
703 List<Expression> elements = elementMakers
704 .map((Instantiator instantiator) => instantiator(arguments))
705 .toList(growable: false);
706 return new ArrayInitializer(elements);
707 };
708 }
709
710 Instantiator visitArrayHole(ArrayHole node) {
711 return (arguments) => new ArrayHole();
712 }
713
714 Instantiator visitObjectInitializer(ObjectInitializer node) {
715 List<Instantiator> propertyMakers =
716 node.properties.map(visitSplayable).toList();
717 return (arguments) {
718 List<Property> properties = <Property>[];
719 for (Instantiator instantiator in propertyMakers) {
720 var result = instantiator(arguments);
721 if (result is Iterable) {
722 properties.addAll(result);
723 } else {
724 properties.add(result);
725 }
726 }
727 return new ObjectInitializer(properties);
728 };
729 }
730
731 Instantiator visitProperty(Property node) {
732 Instantiator makeName = visit(node.name);
733 Instantiator makeValue = visit(node.value);
734 return (arguments) {
735 return new Property(makeName(arguments), makeValue(arguments));
736 };
737 }
738
739 Instantiator visitRegExpLiteral(RegExpLiteral node) =>
740 (arguments) => new RegExpLiteral(node.pattern);
741
742 Instantiator visitTemplateString(TemplateString node) {
743 Iterable makeElements =
744 node.elements.map((e) => e is String ? e : visit(e));
745 return (arguments) {
746 return new TemplateString(makeElements
747 .map((m) => m is String ? m : m(arguments))
748 .toList(growable: false));
749 };
750 }
751
752 Instantiator visitTaggedTemplate(TaggedTemplate node) {
753 Instantiator makeTag = visit(node.tag);
754 Instantiator makeTemplate = visit(node.template);
755 return (arguments) {
756 return new TaggedTemplate(makeTag(arguments), makeTemplate(arguments));
757 };
758 }
759
760 Instantiator visitClassDeclaration(ClassDeclaration node) {
761 Instantiator makeClass = visit(node.classExpr);
762 return (arguments) {
763 return new ClassDeclaration(makeClass(arguments));
764 };
765 }
766
767 Instantiator visitClassExpression(ClassExpression node) {
768 List<Instantiator> makeMethods =
769 node.methods.map(visitSplayableExpression).toList(growable: true);
770 Instantiator makeName = visit(node.name);
771 Instantiator makeHeritage = visit(node.heritage);
772
773 return (arguments) {
774 var methods = <Method>[];
775 for (Instantiator instantiator in makeMethods) {
776 var result = instantiator(arguments);
777 if (result is Iterable) {
778 methods.addAll(result);
779 } else {
780 methods.add(result);
781 }
782 }
783 return new ClassExpression(
784 makeName(arguments), makeHeritage(arguments), methods);
785 };
786 }
787
788 Instantiator visitMethod(Method node) {
789 Instantiator makeName = visit(node.name);
790 Instantiator makeFunction = visit(node.function);
791 return (arguments) {
792 return new Method(makeName(arguments), makeFunction(arguments),
793 isGetter: node.isGetter,
794 isSetter: node.isSetter,
795 isStatic: node.isStatic);
796 };
797 }
798
799 Instantiator visitComment(Comment node) =>
800 (arguments) => new Comment(node.comment);
801
802 Instantiator visitCommentExpression(CommentExpression node) {
803 Instantiator makeExpr = visit(node.expression);
804 return (arguments) {
805 return new CommentExpression(node.comment, makeExpr(arguments));
806 };
807 }
808
809 Instantiator visitAwait(Await node) {
810 Instantiator makeExpression = visit(node.expression);
811 return (arguments) {
812 return new Await(makeExpression(arguments));
813 };
814 }
815
816 // Note: these are not supported yet in the interpolation grammar.
817 Instantiator visitModule(Module node) => throw new UnimplementedError();
818 Instantiator visitNameSpecifier(NameSpecifier node) =>
819 throw new UnimplementedError();
820
821 Instantiator visitImportDeclaration(ImportDeclaration node) =>
822 throw new UnimplementedError();
823
824 Instantiator visitExportDeclaration(ExportDeclaration node) =>
825 throw new UnimplementedError();
826
827 Instantiator visitExportClause(ExportClause node) =>
828 throw new UnimplementedError();
829
830 Instantiator visitAnyTypeRef(AnyTypeRef node) =>
831 throw new UnimplementedError();
832
833 Instantiator visitUnknownTypeRef(UnknownTypeRef node) =>
834 throw new UnimplementedError();
835
836 Instantiator visitArrayTypeRef(ArrayTypeRef node) =>
837 throw new UnimplementedError();
838
839 Instantiator visitFunctionTypeRef(FunctionTypeRef node) =>
840 throw new UnimplementedError();
841
842 Instantiator visitGenericTypeRef(GenericTypeRef node) =>
843 throw new UnimplementedError();
844
845 Instantiator visitQualifiedTypeRef(QualifiedTypeRef node) =>
846 throw new UnimplementedError();
847
848 Instantiator visitOptionalTypeRef(OptionalTypeRef node) =>
849 throw new UnimplementedError();
850
851 Instantiator visitRecordTypeRef(RecordTypeRef node) =>
852 throw new UnimplementedError();
853
854 Instantiator visitUnionTypeRef(UnionTypeRef node) =>
855 throw new UnimplementedError();
856
857 @override
858 Instantiator visitDestructuredVariable(DestructuredVariable node) {
859 Instantiator makeName = visit(node.name);
860 Instantiator makeStructure = visit(node.structure);
861 Instantiator makeDefaultValue = visit(node.defaultValue);
862 return (arguments) {
863 return new DestructuredVariable(
864 name: makeName(arguments),
865 structure: makeStructure(arguments),
866 defaultValue: makeDefaultValue(arguments));
867 };
868 }
869
870 @override
871 Instantiator visitArrayBindingPattern(ArrayBindingPattern node) {
872 List<Instantiator> makeVars = node.variables.map(this.visit).toList();
873 return (arguments) {
874 return new ArrayBindingPattern(
875 makeVars.map((m) => m(arguments)).toList());
876 };
877 }
878
879 @override
880 Instantiator visitObjectBindingPattern(ObjectBindingPattern node) {
881 List<Instantiator> makeVars = node.variables.map(this.visit).toList();
882 return (arguments) {
883 return new ObjectBindingPattern(
884 makeVars.map((m) => m(arguments)).toList());
885 };
886 }
887
888 @override
889 Instantiator visitSimpleBindingPattern(SimpleBindingPattern node) =>
890 (arguments) => new SimpleBindingPattern(new Identifier(node.name.name));
891 }
892
893 /**
894 * InterpolatedNodeAnalysis determines which AST trees contain
895 * [InterpolatedNode]s, and the names of the named interpolated nodes.
896 */
897 class InterpolatedNodeAnalysis extends BaseVisitor {
898 final Set<Node> containsInterpolatedNode = new Set<Node>();
899 final Set<String> holeNames = new Set<String>();
900 int count = 0;
901
902 InterpolatedNodeAnalysis();
903
904 bool containsInterpolatedNodes(Node node) =>
905 containsInterpolatedNode.contains(node);
906
907 void visit(Node node) {
908 node.accept(this);
909 }
910
911 void visitNode(Node node) {
912 int before = count;
913 node.visitChildren(this);
914 if (count != before) containsInterpolatedNode.add(node);
915 return null;
916 }
917
918 visitInterpolatedNode(InterpolatedNode node) {
919 containsInterpolatedNode.add(node);
920 if (node.isNamed) holeNames.add(node.nameOrPosition);
921 ++count;
922 }
923 }
OLDNEW
« no previous file with comments | « lib/src/js/printer.dart ('k') | lib/src/js/type_printer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698