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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js/template.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) 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;
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 // TODO(18886): Remove this function once the memory-leak in the VM is fixed.
14 void clear() {
15 expressionTemplates.clear();
16 statementTemplates.clear();
17 }
18
19 Template lookupExpressionTemplate(String source) {
20 return expressionTemplates[source];
21 }
22
23 Template defineExpressionTemplate(String source, Node ast) {
24 Template template =
25 new Template(source, ast, isExpression: true, forceCopy: false);
26 expressionTemplates[source] = template;
27 return template;
28 }
29
30 Template lookupStatementTemplate(String source) {
31 return statementTemplates[source];
32 }
33
34 Template defineStatementTemplate(String source, Node ast) {
35 Template template =
36 new Template(source, ast, isExpression: false, forceCopy: false);
37 statementTemplates[source] = template;
38 return template;
39 }
40 }
41
42 /**
43 * A Template is created with JavaScript AST containing placeholders (interface
44 * InterpolatedNode). The [instantiate] method creates an AST that looks like
45 * the original with the placeholders replaced by the arguments to
46 * [instantiate].
47 */
48 class Template {
49 final String source;
50 final bool isExpression;
51 final bool forceCopy;
52 final Node ast;
53
54 Instantiator instantiator;
55 int positionalArgumentCount = -1;
56 // TODO(sra): Named arguments.
57
58 Template(this.source, this.ast,
59 {this.isExpression: true, this.forceCopy: false}) {
60 _compile();
61 }
62
63 Template.withExpressionResult(this.ast)
64 : source = null, isExpression = true, 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, isExpression = false, forceCopy = false {
73 assert(ast is Statement);
74 assert(_checkNoPlaceholders());
75 positionalArgumentCount = 0;
76 instantiator = (arguments) => ast;
77 }
78
79 bool _checkNoPlaceholders() {
80 InstantiatorGeneratorVisitor generator =
81 new InstantiatorGeneratorVisitor(false);
82 generator.compile(ast);
83 return generator.analysis.count == 0;
84 }
85
86 void _compile() {
87 InstantiatorGeneratorVisitor generator =
88 new InstantiatorGeneratorVisitor(forceCopy);
89 instantiator = generator.compile(ast);
90 positionalArgumentCount = generator.analysis.count;
91 }
92
93 Node instantiate(List arguments) {
94 if (arguments is List) {
95 if (arguments.length != positionalArgumentCount) {
96 throw 'Wrong number of template arguments, given ${arguments.length}, '
97 'expected $positionalArgumentCount';
98 }
99 return instantiator(arguments);
100 }
101 // TODO(sra): Add named placeholders and a Map of arguments.
102 throw new UnimplementedError('Template arguments must be a list');
103 }
104 }
105
106 /**
107 * An Instantiator is a Function that generates a JS AST tree or List of
108 * trees. [arguments] is a List for positional templates, or (TODO) Map for
109 * named templates.
110 */
111 typedef Node Instantiator(var arguments);
112
113
114 /**
115 * InstantiatorGeneratorVisitor compiles a template. This class compiles a tree
116 * containing [InterpolatedNode]s into a function that will create a copy of the
117 * tree with the interpolated nodes substituted with provided values.
118 */
119 class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
120
121 final bool forceCopy;
122
123 InterpolatedNodeAnalysis analysis = new InterpolatedNodeAnalysis();
124
125 /**
126 * The entire tree is cloned if [forceCopy] is true.
127 */
128 InstantiatorGeneratorVisitor(this.forceCopy);
129
130 Instantiator compile(Node node) {
131 analysis.visit(node);
132 Instantiator result = visit(node);
133 return result;
134 }
135
136 static error(String message) {
137 throw message;
138 }
139
140 static Instantiator same(Node node) => (arguments) => node;
141 static Node makeNull(arguments) => null;
142
143 Instantiator visit(Node node) {
144 if (forceCopy || analysis.containsInterpolatedNodes(node)) {
145 return node.accept(this);
146 }
147 return same(node);
148 }
149
150 Instantiator visitNullable(Node node) {
151 if (node == null) return makeNull;
152 return visit(node);
153 }
154
155 Instantiator visitSplayable(Node node) {
156 // TODO(sra): Process immediate [InterpolatedNode]s, permitting splaying.
157 return visit(node);
158 }
159
160 Instantiator visitNode(Node node) {
161 throw 'Unimplemented InstantiatorGeneratorVisitor for $node';
162 }
163
164 static RegExp identiferRE = new RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$');
165
166 static Expression convertStringToVariableUse(String value) {
167 assert(identiferRE.hasMatch(value));
168 return new VariableUse(value);
169 }
170
171 Instantiator visitInterpolatedExpression(InterpolatedExpression node) {
172 int position = node.name;
173 return (arguments) {
174 var value = arguments[position];
175 if (value is Expression) return value;
176 if (value is String) return convertStringToVariableUse(value);;
177 error('Interpolated value #$position is not an Expression: $value');
178 };
179 }
180
181 Instantiator visitSplayableExpression(Node node) {
182 if (node is InterpolatedExpression) {
183 int position = node.name;
184 return (arguments) {
185 var value = arguments[position];
186 Expression toExpression(item) {
187 if (item is Expression) return item;
188 if (item is String) return convertStringToVariableUse(item);
189 return error('Interpolated value #$position is not '
190 'an Expression or List of Expressions: $value');
191 }
192 if (value is Iterable) return value.map(toExpression);
193 return toExpression(value);
194 };
195 }
196 return visit(node);
197 }
198
199 Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) {
200 int position = node.name;
201 return (arguments) {
202 var value = arguments[position];
203 if (value is Literal) return value;
204 error('Interpolated value #$position is not a Literal: $value');
205 };
206 }
207
208 Instantiator visitInterpolatedParameter(InterpolatedParameter node) {
209 int position = node.name;
210 return (arguments) {
211 var value = arguments[position];
212
213 Parameter toParameter(item) {
214 if (item is Parameter) return item;
215 if (item is String) return new Parameter(item);
216 return error('Interpolated value #$position is not a Parameter or '
217 'List of Parameters: $value');
218 }
219 if (value is Iterable) return value.map(toParameter);
220 return toParameter(value);
221 };
222 }
223
224 Instantiator visitInterpolatedSelector(InterpolatedSelector node) {
225 // A selector is an expression, as in `a[selector]`.
226 // A String argument converted into a LiteralString, so `a.#` with argument
227 // 'foo' generates `a["foo"]` which prints as `a.foo`.
228 int position = node.name;
229 return (arguments) {
230 var value = arguments[position];
231 if (value is Expression) return value;
232 if (value is String) return new LiteralString('"$value"');
233 error('Interpolated value #$position is not a selector: $value');
234 };
235 }
236
237 Instantiator visitInterpolatedStatement(InterpolatedStatement node) {
238 int position = node.name;
239 return (arguments) {
240 var value = arguments[position];
241 if (value is Node) return value.toStatement();
242 error('Interpolated value #$position is not a Statement: $value');
243 };
244 }
245
246 Instantiator visitSplayableStatement(Node node) {
247 if (node is InterpolatedStatement) {
248 int position = node.name;
249 return (arguments) {
250 var value = arguments[position];
251 Statement toStatement(item) {
252 if (item is Statement) return item;
253 if (item is Expression) return item.toStatement();;
254 return error('Interpolated value #$position is not '
255 'a Statement or List of Statements: $value');
256 }
257 if (value is Iterable) return value.map(toStatement);
258 return toStatement(value);
259 };
260 }
261 return visit(node);
262 }
263
264 Instantiator visitProgram(Program node) {
265 List instantiators = node.body.map(visitSplayableStatement).toList();
266 return (arguments) {
267 List<Statement> statements = <Statement>[];
268 void add(node) {
269 if (node is EmptyStatement) return;
270 if (node is Iterable) {
271 statements.addAll(node);
272 } else {
273 statements.add(node.toStatement());
274 }
275 }
276 for (Instantiator instantiator in instantiators) {
277 add(instantiator(arguments));
278 }
279 return new Program(statements);
280 };
281 }
282
283 Instantiator visitBlock(Block node) {
284 List instantiators = node.statements.map(visitSplayableStatement).toList();
285 return (arguments) {
286 List<Statement> statements = <Statement>[];
287 void add(node) {
288 if (node is EmptyStatement) return;
289 if (node is Iterable) {
290 statements.addAll(node);
291 } else if (node is Block) {
292 statements.addAll(node.statements);
293 } else {
294 statements.add(node.toStatement());
295 }
296 }
297 for (Instantiator instantiator in instantiators) {
298 add(instantiator(arguments));
299 }
300 return new Block(statements);
301 };
302 }
303
304 Instantiator visitExpressionStatement(ExpressionStatement node) {
305 Instantiator buildExpression = visit(node.expression);
306 return (arguments) {
307 return buildExpression(arguments).toStatement();
308 };
309 }
310
311 Instantiator visitEmptyStatement(EmptyStatement node) =>
312 (arguments) => new EmptyStatement();
313
314 Instantiator visitIf(If node) {
315 if (node.condition is InterpolatedExpression) {
316 return visitIfConditionalCompilation(node);
317 } else {
318 return visitIfNormal(node);
319 }
320 }
321
322 Instantiator visitIfConditionalCompilation(If node) {
323 // Special version of visitInterpolatedExpression that permits bools.
324 compileCondition(InterpolatedExpression node) {
325 int position = node.name;
326 return (arguments) {
327 var value = arguments[position];
328 if (value is bool) return value;
329 if (value is Expression) return value;
330 if (value is String) return convertStringToVariableUse(value);;
331 error('Interpolated value #$position is not an Expression: $value');
332 };
333 }
334 var makeCondition = compileCondition(node.condition);
335 Instantiator makeThen = visit(node.then);
336 Instantiator makeOtherwise = visit(node.otherwise);
337 return (arguments) {
338 var condition = makeCondition(arguments);
339 if (condition is bool) {
340 if (condition == true) {
341 return makeThen(arguments);
342 } else {
343 return makeOtherwise(arguments);
344 }
345 }
346 return new If(
347 condition,
348 makeThen(arguments),
349 makeOtherwise(arguments));
350 };
351 }
352
353 Instantiator visitIfNormal(If node) {
354 Instantiator makeCondition = visit(node.condition);
355 Instantiator makeThen = visit(node.then);
356 Instantiator makeOtherwise = visit(node.otherwise);
357 return (arguments) {
358 return new If(
359 makeCondition(arguments),
360 makeThen(arguments),
361 makeOtherwise(arguments));
362 };
363 }
364
365 Instantiator visitFor(For node) {
366 Instantiator makeInit = visitNullable(node.init);
367 Instantiator makeCondition = visitNullable(node.condition);
368 Instantiator makeUpdate = visitNullable(node.update);
369 Instantiator makeBody = visit(node.body);
370 return (arguments) {
371 return new For(
372 makeInit(arguments), makeCondition(arguments), makeUpdate(arguments),
373 makeBody(arguments));
374 };
375 }
376
377 Instantiator visitForIn(ForIn node) {
378 Instantiator makeLeftHandSide = visit(node.leftHandSide);
379 Instantiator makeObject = visit(node.object);
380 Instantiator makeBody = visit(node.body);
381 return (arguments) {
382 return new ForIn(
383 makeLeftHandSide(arguments),
384 makeObject(arguments),
385 makeBody(arguments));
386 };
387 }
388
389 TODO(String name) {
390 throw new UnimplementedError('$this.$name');
391 }
392
393 Instantiator visitWhile(While node) => TODO('visitWhile');
394 Instantiator visitDo(Do node) => TODO('visitDo');
395
396 Instantiator visitContinue(Continue node) =>
397 (arguments) => new Continue(node.targetLabel);
398
399 Instantiator visitBreak(Break node) =>
400 (arguments) => new Break(node.targetLabel);
401
402 Instantiator visitReturn(Return node) {
403 Instantiator makeExpression = visitNullable(node.value);
404 return (arguments) => new Return(makeExpression(arguments));
405 }
406
407 Instantiator visitThrow(Throw node) {
408 Instantiator makeExpression = visit(node.expression);
409 return (arguments) => new Throw(makeExpression(arguments));
410 }
411
412
413 Instantiator visitTry(Try node) {
414 Instantiator makeBody = visit(node.body);
415 Instantiator makeCatch = visitNullable(node.catchPart);
416 Instantiator makeFinally = visitNullable(node.finallyPart);
417 return (arguments) => new Try(
418 makeBody(arguments), makeCatch(arguments), makeFinally(arguments));
419 }
420
421 Instantiator visitCatch(Catch node) {
422 Instantiator makeDeclaration = visit(node.declaration);
423 Instantiator makeBody = visit(node.body);
424 return (arguments) => new Catch(
425 makeDeclaration(arguments), makeBody(arguments));
426 }
427
428 Instantiator visitSwitch(Switch node) => TODO('visitSwitch');
429 Instantiator visitCase(Case node) => TODO('visitCase');
430 Instantiator visitDefault(Default node) => TODO('visitDefault');
431
432 Instantiator visitFunctionDeclaration(FunctionDeclaration node) {
433 Instantiator makeName = visit(node.name);
434 Instantiator makeFunction = visit(node.function);
435 return (arguments) =>
436 new FunctionDeclaration(makeName(arguments), makeFunction(arguments));
437 }
438
439 Instantiator visitLabeledStatement(LabeledStatement node) =>
440 TODO('visitLabeledStatement');
441 Instantiator visitLiteralStatement(LiteralStatement node) =>
442 TODO('visitLiteralStatement');
443 Instantiator visitBlob(Blob node) =>
444 TODO('visitBlob');
445 Instantiator visitLiteralExpression(LiteralExpression node) =>
446 TODO('visitLiteralExpression');
447
448 Instantiator visitVariableDeclarationList(VariableDeclarationList node) {
449 List<Instantiator> declarationMakers =
450 node.declarations.map(visit).toList();
451 return (arguments) {
452 List<VariableInitialization> declarations = <VariableInitialization>[];
453 for (Instantiator instantiator in declarationMakers) {
454 var result = instantiator(arguments);
455 declarations.add(result);
456 }
457 return new VariableDeclarationList(declarations);
458 };
459 }
460
461 Instantiator visitAssignment(Assignment node) {
462 Instantiator makeLeftHandSide = visit(node.leftHandSide);
463 String op = node.op;
464 Instantiator makeValue = visitNullable(node.value);
465 return (arguments) {
466 return new Assignment.compound(
467 makeLeftHandSide(arguments),
468 op,
469 makeValue(arguments));
470 };
471 }
472
473 Instantiator visitVariableInitialization(VariableInitialization node) {
474 Instantiator makeDeclaration = visit(node.declaration);
475 Instantiator makeValue = visitNullable(node.value);
476 return (arguments) {
477 return new VariableInitialization(
478 makeDeclaration(arguments), makeValue(arguments));
479 };
480 }
481
482 Instantiator visitConditional(Conditional cond) {
483 Instantiator makeCondition = visit(cond.condition);
484 Instantiator makeThen = visit(cond.then);
485 Instantiator makeOtherwise = visit(cond.otherwise);
486 return (arguments) => new Conditional(
487 makeCondition(arguments),
488 makeThen(arguments),
489 makeOtherwise(arguments));
490 }
491
492 Instantiator visitNew(New node) =>
493 handleCallOrNew(node, (target, arguments) => new New(target, arguments));
494
495 Instantiator visitCall(Call node) =>
496 handleCallOrNew(node, (target, arguments) => new Call(target, arguments));
497
498 Instantiator handleCallOrNew(Call node, finish(target, arguments)) {
499 Instantiator makeTarget = visit(node.target);
500 Iterable<Instantiator> argumentMakers =
501 node.arguments.map(visitSplayableExpression).toList();
502
503 // TODO(sra): Avoid copying call arguments if no interpolation or forced
504 // copying.
505 return (arguments) {
506 Node target = makeTarget(arguments);
507 List<Expression> callArguments = <Expression>[];
508 for (Instantiator instantiator in argumentMakers) {
509 var result = instantiator(arguments);
510 if (result is Iterable) {
511 callArguments.addAll(result);
512 } else {
513 callArguments.add(result);
514 }
515 }
516 return finish(target, callArguments.toList(growable: false));
517 };
518 }
519
520 Instantiator visitBinary(Binary node) {
521 Instantiator makeLeft = visit(node.left);
522 Instantiator makeRight = visit(node.right);
523 String op = node.op;
524 return (arguments) =>
525 new Binary(op, makeLeft(arguments), makeRight(arguments));
526 }
527
528 Instantiator visitPrefix(Prefix node) {
529 Instantiator makeOperand = visit(node.argument);
530 String op = node.op;
531 return (arguments) => new Prefix(op, makeOperand(arguments));
532 }
533
534 Instantiator visitPostfix(Postfix node) {
535 Instantiator makeOperand = visit(node.argument);
536 String op = node.op;
537 return (arguments) => new Postfix(op, makeOperand(arguments));
538 }
539
540 Instantiator visitVariableUse(VariableUse node) =>
541 (arguments) => new VariableUse(node.name);
542
543 Instantiator visitThis(This node) => (arguments) => new This();
544
545 Instantiator visitVariableDeclaration(VariableDeclaration node) =>
546 (arguments) => new VariableDeclaration(node.name);
547
548 Instantiator visitParameter(Parameter node) =>
549 (arguments) => new Parameter(node.name);
550
551 Instantiator visitAccess(PropertyAccess node) {
552 Instantiator makeReceiver = visit(node.receiver);
553 Instantiator makeSelector = visit(node.selector);
554 return (arguments) =>
555 new PropertyAccess(makeReceiver(arguments), makeSelector(arguments));
556 }
557
558 Instantiator visitNamedFunction(NamedFunction node) {
559 Instantiator makeDeclaration = visit(node.name);
560 Instantiator makeFunction = visit(node.function);
561 return (arguments) =>
562 new NamedFunction(makeDeclaration(arguments), makeFunction(arguments));
563 }
564
565 Instantiator visitFun(Fun node) {
566 List<Instantiator> paramMakers = node.params.map(visitSplayable).toList();
567 Instantiator makeBody = visit(node.body);
568 // TODO(sra): Avoid copying params if no interpolation or forced copying.
569 return (arguments) {
570 List<Parameter> params = <Parameter>[];
571 for (Instantiator instantiator in paramMakers) {
572 var result = instantiator(arguments);
573 if (result is Iterable) {
574 params.addAll(result);
575 } else {
576 params.add(result);
577 }
578 }
579 Statement body = makeBody(arguments);
580 return new Fun(params, body);
581 };
582 }
583
584 Instantiator visitLiteralBool(LiteralBool node) =>
585 (arguments) => new LiteralBool(node.value);
586
587 Instantiator visitLiteralString(LiteralString node) =>
588 (arguments) => new LiteralString(node.value);
589
590 Instantiator visitLiteralNumber(LiteralNumber node) =>
591 (arguments) => new LiteralNumber(node.value);
592
593 Instantiator visitLiteralNull(LiteralNull node) =>
594 (arguments) => new LiteralNull();
595
596 Instantiator visitArrayInitializer(ArrayInitializer node) {
597 // Assume array has no missing elements.
598 // TODO(sra): Implement splicing?
599 List<Instantiator> elementMakers = node.elements
600 .map((ArrayElement element) => visit(element.value))
601 .toList();
602 return (arguments) {
603 List<ArrayElement> elements = <ArrayElement>[];
604 void add(Expression value) {
605 elements.add(new ArrayElement(elements.length, value));
606 }
607 for (Instantiator instantiator in elementMakers) {
608 var result = instantiator(arguments);
609 add(result);
610 }
611 return new ArrayInitializer(elements.length, elements);
612 };
613 }
614
615 Instantiator visitArrayElement(ArrayElement node) {
616 throw 'Should not get here'; // Handled in visitArrayInitializer.
617 }
618
619 Instantiator visitObjectInitializer(ObjectInitializer node) {
620 List<Instantiator> propertyMakers =
621 node.properties.map(visitSplayable).toList();
622 bool isOneLiner = node.isOneLiner;
623 return (arguments) {
624 List<Property> properties = <Property>[];
625 for (Instantiator instantiator in propertyMakers) {
626 var result = instantiator(arguments);
627 if (result is Iterable) {
628 properties.addAll(result);
629 } else {
630 properties.add(result);
631 }
632 }
633 return new ObjectInitializer(properties, isOneLiner: isOneLiner);
634 };
635 }
636
637 Instantiator visitProperty(Property node) {
638 Instantiator makeName = visit(node.name);
639 Instantiator makeValue = visit(node.value);
640 return (arguments) {
641 return new Property(makeName(arguments), makeValue(arguments));
642 };
643 }
644
645 Instantiator visitRegExpLiteral(RegExpLiteral node) =>
646 (arguments) => new RegExpLiteral(node.pattern);
647
648 Instantiator visitComment(Comment node) => TODO('visitComment');
649 }
650
651 /**
652 * InterpolatedNodeAnalysis extract [InterpolatedNode]s from AST.
653 */
654 class InterpolatedNodeAnalysis extends BaseVisitor {
655 final Set<Node> containsInterpolatedNode = new Set<Node>();
656 final List<InterpolatedNode> interpolatedNodes = <InterpolatedNode>[];
657 int count = 0;
658
659 InterpolatedNodeAnalysis();
660
661 bool containsInterpolatedNodes(Node node) =>
662 containsInterpolatedNode.contains(node);
663
664 void visit(Node node) {
665 node.accept(this);
666 }
667
668 void visitNode(Node node) {
669 int before = count;
670 node.visitChildren(this);
671 if (count != before) containsInterpolatedNode.add(node);
672 return null;
673 }
674
675 visitInterpolatedNode(InterpolatedNode node) {
676 interpolatedNodes.add(node);
677 containsInterpolatedNode.add(node);
678 ++count;
679 }
680 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698