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

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

Issue 1207313002: initial sync*, part of #221 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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
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_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 1110
1111 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1111 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) {
1112 if (node.isAbstract || _externalOrNative(node)) { 1112 if (node.isAbstract || _externalOrNative(node)) {
1113 return null; 1113 return null;
1114 } 1114 }
1115 1115
1116 var params = _visit(node.parameters); 1116 var params = _visit(node.parameters);
1117 if (params == null) params = []; 1117 if (params == null) params = [];
1118 1118
1119 return new JS.Method( 1119 return new JS.Method(
1120 _elementMemberName(node.element), new JS.Fun(params, _visit(node.body)), 1120 _elementMemberName(node.element), _emitJsFunction(params, node.body),
1121 isGetter: node.isGetter, 1121 isGetter: node.isGetter,
1122 isSetter: node.isSetter, 1122 isSetter: node.isSetter,
1123 isStatic: node.isStatic); 1123 isStatic: node.isStatic);
1124 } 1124 }
1125 1125
1126 @override 1126 @override
1127 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1127 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1128 assert(node.parent is CompilationUnit); 1128 assert(node.parent is CompilationUnit);
1129 1129
1130 if (_externalOrNative(node)) return null; 1130 if (_externalOrNative(node)) return null;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1195 } 1195 }
1196 throw 'Function has non function type: $type'; 1196 throw 'Function has non function type: $type';
1197 } 1197 }
1198 1198
1199 @override 1199 @override
1200 JS.Expression visitFunctionExpression(FunctionExpression node) { 1200 JS.Expression visitFunctionExpression(FunctionExpression node) {
1201 var params = _visit(node.parameters); 1201 var params = _visit(node.parameters);
1202 if (params == null) params = []; 1202 if (params == null) params = [];
1203 1203
1204 var parent = node.parent; 1204 var parent = node.parent;
1205 var inDecl = parent is FunctionDeclaration;
1206 var inStmt = parent.parent is FunctionDeclarationStatement; 1205 var inStmt = parent.parent is FunctionDeclarationStatement;
1207 if (inDecl && !inStmt) { 1206 if (parent is FunctionDeclaration) {
1208 return new JS.Fun(params, _visit(node.body)); 1207 return _emitJsFunction(params, node.body);
1209 } else { 1208 } else {
1210 String code; 1209 String code;
1211 AstNode body; 1210 AstNode body;
1212 var nodeBody = node.body; 1211 var nodeBody = node.body;
1213 if (nodeBody is ExpressionFunctionBody) { 1212 if (nodeBody is ExpressionFunctionBody) {
1214 code = '(#) => #'; 1213 code = '(#) => #';
1215 body = nodeBody.expression; 1214 body = nodeBody.expression;
1216 } else { 1215 } else {
1216 // We need to bind
Jennifer Messerly 2015/06/25 18:17:45 oops, removing this.
1217 code = '(#) => { #; }'; 1217 code = '(#) => { #; }';
1218 body = nodeBody; 1218 body = nodeBody;
1219 } 1219 }
1220 var clos = js.call(code, [params, _visit(body)]); 1220 var clos = js.call(code, [params, _visit(body)]);
1221 if (!inStmt) { 1221 if (!inStmt) {
1222 var type = getStaticType(node); 1222 var type = getStaticType(node);
1223 return _emitFunctionTagged(clos, type, 1223 return _emitFunctionTagged(clos, type,
1224 topLevel: _executesAtTopLevel(node)); 1224 topLevel: _executesAtTopLevel(node));
1225 } 1225 }
1226 return clos; 1226 return clos;
1227 } 1227 }
1228 } 1228 }
1229 1229
1230 JS.Fun _emitJsFunction(List<JS.Parameter> params, FunctionBody body) {
1231 // TODO(jmesserly): async/async*
1232 var syncStar = body.isSynchronous && body.star != null;
1233 return new JS.Fun(params, _visit(body), isGenerator: syncStar);
1234 }
1235
1230 @override 1236 @override
1231 JS.Statement visitFunctionDeclarationStatement( 1237 JS.Statement visitFunctionDeclarationStatement(
1232 FunctionDeclarationStatement node) { 1238 FunctionDeclarationStatement node) {
1233 var func = node.functionDeclaration; 1239 var func = node.functionDeclaration;
1234 if (func.isGetter || func.isSetter) { 1240 if (func.isGetter || func.isSetter) {
1235 return js.comment('Unimplemented function get/set statement: $node'); 1241 return js.comment('Unimplemented function get/set statement: $node');
1236 } 1242 }
1237 1243
1238 // Use an => function to bind this. 1244 var fn = _visit(func.functionExpression);
1239 // Technically we only need to do this if the function actually closes over 1245 var jsThis = new _JsThisFinder();
1240 // `this`, but it seems harmless enough to just do it always. 1246 fn.accept(jsThis);
1247
1241 var name = new JS.Identifier(func.name.name); 1248 var name = new JS.Identifier(func.name.name);
1249 JS.Statement declareFn;
1250 if (jsThis.found) {
1251 declareFn = js.statement('let # = #.bind(this);', [name, fn]);
1252 } else {
1253 declareFn = new JS.FunctionDeclaration(name, fn);
1254 }
1255
1242 return new JS.Block([ 1256 return new JS.Block([
1243 js.statement('let # = #;', [name, _visit(func.functionExpression)]), 1257 declareFn,
1244 _emitFunctionTagged(name, func.element.type).toStatement() 1258 _emitFunctionTagged(name, func.element.type).toStatement()
1245 ]); 1259 ]);
1246 } 1260 }
1247 1261
1248 /// Writes a simple identifier. This can handle implicit `this` as well as 1262 /// Writes a simple identifier. This can handle implicit `this` as well as
1249 /// going through the qualified library name if necessary. 1263 /// going through the qualified library name if necessary.
1250 @override 1264 @override
1251 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { 1265 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
1252 var accessor = node.staticElement; 1266 var accessor = node.staticElement;
1253 if (accessor == null) { 1267 if (accessor == null) {
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 1649
1636 @override 1650 @override
1637 JS.Statement visitAssertStatement(AssertStatement node) => 1651 JS.Statement visitAssertStatement(AssertStatement node) =>
1638 // TODO(jmesserly): only emit in checked mode. 1652 // TODO(jmesserly): only emit in checked mode.
1639 js.statement('dart.assert(#);', _visit(node.condition)); 1653 js.statement('dart.assert(#);', _visit(node.condition));
1640 1654
1641 @override 1655 @override
1642 JS.Statement visitReturnStatement(ReturnStatement node) { 1656 JS.Statement visitReturnStatement(ReturnStatement node) {
1643 var e = node.expression; 1657 var e = node.expression;
1644 if (e == null) return new JS.Return(); 1658 if (e == null) return new JS.Return();
1645 return _visit(e).toReturn(); 1659 return (_visit(e) as JS.Expression).toReturn();
1646 } 1660 }
1647 1661
1648 @override 1662 @override
1663 JS.Statement visitYieldStatement(YieldStatement node) {
1664 JS.Expression jsExpr = _visit(node.expression);
1665 return jsExpr.toYieldStatement(star: node.star != null);
1666 }
1667
1668 @override
1649 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 1669 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
1650 for (var v in node.variables.variables) { 1670 for (var v in node.variables.variables) {
1651 _loader.loadDeclaration(v, v.element); 1671 _loader.loadDeclaration(v, v.element);
1652 } 1672 }
1653 } 1673 }
1654 1674
1655 _addExport(String name) { 1675 _addExport(String name) {
1656 if (!_exports.add(name)) throw 'Duplicate top level name found: $name'; 1676 if (!_exports.add(name)) throw 'Duplicate top level name found: $name';
1657 } 1677 }
1658 1678
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
2572 visitInterpolationExpression(InterpolationExpression node) => 2592 visitInterpolationExpression(InterpolationExpression node) =>
2573 _visit(node.expression); 2593 _visit(node.expression);
2574 2594
2575 @override 2595 @override
2576 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); 2596 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value);
2577 2597
2578 @override 2598 @override
2579 JS.Expression visitExpression(Expression node) => 2599 JS.Expression visitExpression(Expression node) =>
2580 _unimplementedCall('Unimplemented ${node.runtimeType}: $node'); 2600 _unimplementedCall('Unimplemented ${node.runtimeType}: $node');
2581 2601
2582 @override
2583 JS.Statement visitYieldStatement(YieldStatement node) =>
2584 _unimplementedCall('Unimplemented yield: $node').toStatement();
2585
2586 JS.Expression _unimplementedCall(String comment) { 2602 JS.Expression _unimplementedCall(String comment) {
2587 return js.call('dart.throw_(#)', [js.escapedString(comment)]); 2603 return js.call('dart.throw_(#)', [js.escapedString(comment)]);
2588 } 2604 }
2589 2605
2590 @override 2606 @override
2591 visitNode(AstNode node) { 2607 visitNode(AstNode node) {
2592 // TODO(jmesserly): verify this is unreachable. 2608 // TODO(jmesserly): verify this is unreachable.
2593 throw 'Unimplemented ${node.runtimeType}: $node'; 2609 throw 'Unimplemented ${node.runtimeType}: $node';
2594 } 2610 }
2595 2611
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 2814
2799 /// A special kind of element created by the compiler, signifying a temporary 2815 /// A special kind of element created by the compiler, signifying a temporary
2800 /// variable. These objects use instance equality, and should be shared 2816 /// variable. These objects use instance equality, and should be shared
2801 /// everywhere in the tree where they are treated as the same variable. 2817 /// everywhere in the tree where they are treated as the same variable.
2802 class TemporaryVariableElement extends LocalVariableElementImpl { 2818 class TemporaryVariableElement extends LocalVariableElementImpl {
2803 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2819 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2804 2820
2805 int get hashCode => identityHashCode(this); 2821 int get hashCode => identityHashCode(this);
2806 bool operator ==(Object other) => identical(this, other); 2822 bool operator ==(Object other) => identical(this, other);
2807 } 2823 }
2824
2825 class _JsThisFinder extends JS.BaseVisitor {
2826 bool found = false;
2827 visitThis(JS.This node) {
2828 found = true;
2829 }
2830 visitNode(JS.Node node) {
2831 if (!found) super.visitNode(node);
2832 }
2833 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698