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

Side by Side Diff: lib/src/codegen/js_metalet.dart

Issue 1316723003: implement null aware ops, fixes #249 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 3 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/codegen/js_codegen.dart ('k') | lib/src/js/nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dev_compiler.src.codegen.js_metalet; 5 library dev_compiler.src.codegen.js_metalet;
6 6
7 // TODO(jmesserly): import from its own package 7 // TODO(jmesserly): import from its own package
8 import 'package:dev_compiler/src/js/js_ast.dart'; 8 import 'package:dev_compiler/src/js/js_ast.dart';
9 import 'package:dev_compiler/src/js/precedence.dart'; 9 import 'package:dev_compiler/src/js/precedence.dart';
10 10
(...skipping 23 matching lines...) Expand all
34 /// used multiple times in the resulting expression. For example: 34 /// used multiple times in the resulting expression. For example:
35 /// `expr ** 2` could be compiled as `expr * expr`. The temporary scope will 35 /// `expr ** 2` could be compiled as `expr * expr`. The temporary scope will
36 /// ensure `expr` is only evaluated once: `(x => x * x)(expr)`. 36 /// ensure `expr` is only evaluated once: `(x => x * x)(expr)`.
37 /// 37 ///
38 /// If the expression does not end up using `x` more than once, or if those 38 /// If the expression does not end up using `x` more than once, or if those
39 /// expressions can be treated as [stateless] (e.g. they are non-mutated 39 /// expressions can be treated as [stateless] (e.g. they are non-mutated
40 /// variables), then the resulting code will be simplified automatically. 40 /// variables), then the resulting code will be simplified automatically.
41 final Map<String, Expression> variables; 41 final Map<String, Expression> variables;
42 42
43 /// A list of expressions in the body. 43 /// A list of expressions in the body.
44 /// Conceptually this is like a comma expression: the last value is returned. 44 /// The last value should represent the returned value.
45 final List<Expression> body; 45 final List<Expression> body;
46 46
47 /// True if the final expression in [body] can be skipped in [toStatement]. 47 /// True if the final expression in [body] can be skipped in [toStatement].
48 final bool statelessResult; 48 final bool statelessResult;
49 49
50 /// We run [toExpression] implicitly when the JS AST is visited, to get the 50 /// We run [toExpression] implicitly when the JS AST is visited, to get the
51 /// transformation to happen before the tree is printed. 51 /// transformation to happen before the tree is printed.
52 /// This happens multiple times, so ensure the expression form is cached. 52 /// This happens multiple times, so ensure the expression form is cached.
53 Expression _expression; 53 Expression _expression;
54 54
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 113 }
114 114
115 Block toYieldStatement({bool star: false}) { 115 Block toYieldStatement({bool star: false}) {
116 var statements = body 116 var statements = body
117 .map((e) => 117 .map((e) =>
118 e == body.last ? e.toYieldStatement(star: star) : e.toStatement()) 118 e == body.last ? e.toYieldStatement(star: star) : e.toStatement())
119 .toList(); 119 .toList();
120 return _finishStatement(statements); 120 return _finishStatement(statements);
121 } 121 }
122 122
123 accept(NodeVisitor visitor) => toExpression().accept(visitor); 123 accept(NodeVisitor visitor) {
124 // TODO(jmesserly): we special case vistors from js_ast.Template, because it
125 // doesn't know about MetaLet. Should we integrate directly?
126 if (visitor is InstantiatorGeneratorVisitor) {
127 return _templateVisitMetaLet(visitor);
128 } else if (visitor is InterpolatedNodeAnalysis) {
129 return visitor.visitNode(this);
130 } else {
131 return toExpression().accept(visitor);
132 }
133 }
124 134
125 void visitChildren(NodeVisitor visitor) { 135 void visitChildren(NodeVisitor visitor) {
126 toExpression().visitChildren(visitor); 136 // TODO(jmesserly): we special case vistors from js_ast.Template, because it
137 // doesn't know about MetaLet. Should we integrate directly?
138 if (visitor is InterpolatedNodeAnalysis ||
139 visitor is InstantiatorGeneratorVisitor) {
140 variables.values.forEach((v) => v.accept(visitor));
141 body.forEach((v) => v.accept(visitor));
142 } else {
143 toExpression().visitChildren(visitor);
144 }
127 } 145 }
128 146
129 /// This generates as either a comma expression or a call. 147 /// This generates as either a comma expression or a call.
130 int get precedenceLevel => variables.isEmpty ? EXPRESSION : CALL; 148 int get precedenceLevel => variables.isEmpty ? EXPRESSION : CALL;
131 149
150 /// Patch to pretend [Template] supports visitMetaLet.
151 Instantiator _templateVisitMetaLet(InstantiatorGeneratorVisitor visitor) {
152 var valueInstantiators = variables.values.map(visitor.visit);
153 var bodyInstantiators = body.map(visitor.visit);
154
155 return (args) => new MetaLet(
156 new Map.fromIterables(
157 variables.keys, valueInstantiators.map((i) => i(args))),
158 bodyInstantiators.map((i) => i(args)).toList(),
159 statelessResult: statelessResult);
160 }
161
132 Expression _toInvokedFunction(Statement block) { 162 Expression _toInvokedFunction(Statement block) {
133 var finder = new _YieldFinder(); 163 var finder = new _YieldFinder();
134 block.accept(finder); 164 block.accept(finder);
135 if (!finder.hasYield) { 165 if (!finder.hasYield) {
136 return new Call(new ArrowFun([], block), []); 166 return new Call(new ArrowFun([], block), []);
137 } 167 }
138 // If we have a yield, it's more tricky. We'll create a `function*`, which 168 // If we have a yield, it's more tricky. We'll create a `function*`, which
139 // we `yield*` to immediately invoke. We also may need to bind this: 169 // we `yield*` to immediately invoke. We also may need to bind this:
140 Expression fn = new Fun([], block, isGenerator: true); 170 Expression fn = new Fun([], block, isGenerator: true);
141 if (finder.hasThis) fn = js.call('#.bind(this)', fn); 171 if (finder.hasThis) fn = js.call('#.bind(this)', fn);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 /// ((_) => _.addAll(result), _.add(2), result = _)([]) 232 /// ((_) => _.addAll(result), _.add(2), result = _)([])
203 /// 233 ///
204 MetaLet _simplifyAssignment(Identifier left, {bool isDeclaration: false}) { 234 MetaLet _simplifyAssignment(Identifier left, {bool isDeclaration: false}) {
205 // See if the result value is a let* temporary variable. 235 // See if the result value is a let* temporary variable.
206 if (body.last is! InterpolatedExpression) return null; 236 if (body.last is! InterpolatedExpression) return null;
207 237
208 InterpolatedExpression last = body.last; 238 InterpolatedExpression last = body.last;
209 String name = last.nameOrPosition; 239 String name = last.nameOrPosition;
210 if (!variables.containsKey(name)) return null; 240 if (!variables.containsKey(name)) return null;
211 241
212 // Variables declared can't be used inside their initializer. 242 // Variables declared can't be used inside their initializer, so make
243 // sure we don't transform an assignment into an initializer.
244 // If this already was a declaration, then we know it's legal, so we can
245 // skip the check.
213 if (!isDeclaration) { 246 if (!isDeclaration) {
214 var finder = new _IdentFinder(left.name); 247 var finder = new _IdentFinder(left.name);
215 for (var expr in body) { 248 for (var expr in body) {
216 if (finder.found) break; 249 if (finder.found) break;
217 expr.accept(finder); 250 expr.accept(finder);
218 } 251 }
219 // If the identifier was used elsewhere, bail, because we're going to 252 // If the identifier was used elsewhere, bail, because we're going to
220 // change the order of when the assignment happens. 253 // change the order of when the assignment happens.
221 if (finder.found) return null; 254 if (finder.found) return null;
222 } 255 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 } 312 }
280 313
281 @override visitYield(Yield node) { 314 @override visitYield(Yield node) {
282 if (!_nestedFunction) hasYield = true; 315 if (!_nestedFunction) hasYield = true;
283 } 316 }
284 317
285 @override visitNode(Node node) { 318 @override visitNode(Node node) {
286 if (!hasYield) super.visitNode(node); 319 if (!hasYield) super.visitNode(node);
287 } 320 }
288 } 321 }
OLDNEW
« no previous file with comments | « lib/src/codegen/js_codegen.dart ('k') | lib/src/js/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698