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

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

Issue 1243503007: fixes #221, initial sync*, async, async* implementation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 4 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/info.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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 /// Returns an expression that ignores the result. This is a cross between 57 /// Returns an expression that ignores the result. This is a cross between
58 /// [toExpression] and [toStatement]. Used for C-style for-loop updaters, 58 /// [toExpression] and [toStatement]. Used for C-style for-loop updaters,
59 /// which is an expression syntactically, but functions more like a statement. 59 /// which is an expression syntactically, but functions more like a statement.
60 Expression toVoidExpression() { 60 Expression toVoidExpression() {
61 var block = toStatement(); 61 var block = toStatement();
62 var s = block.statements; 62 var s = block.statements;
63 if (s.length == 1 && s.first is ExpressionStatement) { 63 if (s.length == 1 && s.first is ExpressionStatement) {
64 ExpressionStatement es = s.first; 64 ExpressionStatement es = s.first;
65 return es.expression; 65 return es.expression;
66 } 66 }
67 return new Call(new ArrowFun([], block), []); 67
68 return _toInvokedFunction(block);
68 } 69 }
69 70
70 Expression toAssignExpression(Expression left) { 71 Expression toAssignExpression(Expression left) {
71 if (left is Identifier) { 72 if (left is Identifier) {
72 var simple = _simplifyAssignment(left); 73 var simple = _simplifyAssignment(left);
73 if (simple != null) return simple; 74 if (simple != null) return simple;
74 75
75 var exprs = body.toList(); 76 var exprs = body.toList();
76 exprs.add(exprs.removeLast().toAssignExpression(left)); 77 exprs.add(exprs.removeLast().toAssignExpression(left));
77 return new MetaLet(variables, exprs); 78 return new MetaLet(variables, exprs);
78 } 79 }
79 return super.toAssignExpression(left); 80 return super.toAssignExpression(left);
80 } 81 }
81 82
82 Statement toVariableDeclaration(Identifier name) { 83 Statement toVariableDeclaration(Identifier name) {
83 var simple = _simplifyAssignment(name, isDeclaration: true); 84 var simple = _simplifyAssignment(name, isDeclaration: true);
84 if (simple != null) return simple.toStatement(); 85 if (simple != null) return simple.toStatement();
85 return super.toVariableDeclaration(name); 86 return super.toVariableDeclaration(name);
86 } 87 }
87 88
88 Expression toExpression() { 89 Expression toExpression() {
89 if (_expression != null) return _expression; 90 if (_expression != null) return _expression;
90 var block = toReturn(); 91 var block = toReturn();
91 var s = block.statements; 92 var s = block.statements;
92 if (s.length == 1 && s.first is Return) { 93 if (s.length == 1 && s.first is Return) {
93 Return es = s.first; 94 Return es = s.first;
94 return _expression = es.value; 95 return _expression = es.value;
95 } 96 }
96 // Wrap it in an immediately called function to get in expression context. 97 // Wrap it in an immediately called function to get in expression context.
97 // TODO(jmesserly): 98 return _expression = _toInvokedFunction(block);
98 return _expression = new Call(new ArrowFun([], block), []);
99 } 99 }
100 100
101 Block toStatement() { 101 Block toStatement() {
102 // Skip return value if not used. 102 // Skip return value if not used.
103 var statements = body.map((e) => e.toStatement()).toList(); 103 var statements = body.map((e) => e.toStatement()).toList();
104 if (statelessResult) statements.removeLast(); 104 if (statelessResult) statements.removeLast();
105 return _finishStatement(statements); 105 return _finishStatement(statements);
106 } 106 }
107 107
108 Block toReturn() { 108 Block toReturn() {
(...skipping 13 matching lines...) Expand all
122 122
123 accept(NodeVisitor visitor) => toExpression().accept(visitor); 123 accept(NodeVisitor visitor) => toExpression().accept(visitor);
124 124
125 void visitChildren(NodeVisitor visitor) { 125 void visitChildren(NodeVisitor visitor) {
126 toExpression().visitChildren(visitor); 126 toExpression().visitChildren(visitor);
127 } 127 }
128 128
129 /// This generates as either a comma expression or a call. 129 /// This generates as either a comma expression or a call.
130 int get precedenceLevel => variables.isEmpty ? EXPRESSION : CALL; 130 int get precedenceLevel => variables.isEmpty ? EXPRESSION : CALL;
131 131
132 Expression _toInvokedFunction(Statement block) {
133 var finder = new _YieldFinder();
134 block.accept(finder);
135 if (!finder.hasYield) {
136 return new Call(new ArrowFun([], block), []);
137 }
138 // 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:
140 Expression fn = new Fun([], block, isGenerator: true);
141 if (finder.hasThis) fn = js.call('#.bind(this)', fn);
142 return new Yield(new Call(fn, []), star: true);
143 }
144
132 Block _finishStatement(List<Statement> statements) { 145 Block _finishStatement(List<Statement> statements) {
133 var params = <TemporaryId>[]; 146 var params = <TemporaryId>[];
134 var values = <Expression>[]; 147 var values = <Expression>[];
135 var block = _build(params, values, new Block(statements)); 148 var block = _build(params, values, new Block(statements));
136 if (params.isEmpty) return block; 149 if (params.isEmpty) return block;
137 150
138 var vars = []; 151 var vars = [];
139 for (int i = 0; i < params.length; i++) { 152 for (int i = 0; i < params.length; i++) {
140 vars.add(new VariableInitialization(params[i], values[i])); 153 vars.add(new VariableInitialization(params[i], values[i]));
141 } 154 }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 236
224 var newBody = new Expression.binary([assign]..addAll(body), ','); 237 var newBody = new Expression.binary([assign]..addAll(body), ',');
225 Binary comma = new Template(null, newBody).safeCreate({name: left}); 238 Binary comma = new Template(null, newBody).safeCreate({name: left});
226 return new MetaLet(vars, comma.commaToExpressionList(), 239 return new MetaLet(vars, comma.commaToExpressionList(),
227 statelessResult: statelessResult); 240 statelessResult: statelessResult);
228 } 241 }
229 } 242 }
230 243
231 class _VariableUseCounter extends BaseVisitor { 244 class _VariableUseCounter extends BaseVisitor {
232 final counts = <String, int>{}; 245 final counts = <String, int>{};
233 visitInterpolatedExpression(InterpolatedExpression node) { 246 @override visitInterpolatedExpression(InterpolatedExpression node) {
234 int n = counts[node.nameOrPosition]; 247 int n = counts[node.nameOrPosition];
235 counts[node.nameOrPosition] = n == null ? 1 : n + 1; 248 counts[node.nameOrPosition] = n == null ? 1 : n + 1;
236 } 249 }
237 } 250 }
238 251
239 class _IdentFinder extends BaseVisitor { 252 class _IdentFinder extends BaseVisitor {
240 final String name; 253 final String name;
241 bool found = false; 254 bool found = false;
242 _IdentFinder(this.name); 255 _IdentFinder(this.name);
243 256
244 visitIdentifier(Identifier node) { 257 @override visitIdentifier(Identifier node) {
245 if (node.name == name) found = true; 258 if (node.name == name) found = true;
246 } 259 }
247 visitNode(Node node) { 260 @override visitNode(Node node) {
248 if (!found) super.visitNode(node); 261 if (!found) super.visitNode(node);
249 } 262 }
250 } 263 }
264
265 class _YieldFinder extends BaseVisitor {
266 bool hasYield = false;
267 bool hasThis = false;
268 bool _nestedFunction = false;
269 @override visitThis(This node) {
270 hasThis = true;
271 }
272 @override visitFunctionExpression(FunctionExpression node) {
273 var savedNested = _nestedFunction;
274 _nestedFunction = true;
275 super.visitFunctionExpression(node);
276 _nestedFunction = savedNested;
277 }
278 @override visitYield(Yield node) {
279 if (!_nestedFunction) hasYield = true;
280 }
281 @override visitNode(Node node) {
282 if (!hasYield) super.visitNode(node);
283 }
284 }
OLDNEW
« no previous file with comments | « lib/src/codegen/js_codegen.dart ('k') | lib/src/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698