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

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, 5 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/runtime/dart/js.js ('k') | lib/src/codegen/js_metalet.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_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 {
1217 code = '(#) => { #; }'; 1216 code = '(#) => { #; }';
1218 body = nodeBody; 1217 body = nodeBody;
1219 } 1218 }
1220 var clos = js.call(code, [params, _visit(body)]); 1219 var clos = js.call(code, [params, _visit(body)]);
1221 if (!inStmt) { 1220 if (!inStmt) {
1222 var type = getStaticType(node); 1221 var type = getStaticType(node);
1223 return _emitFunctionTagged(clos, type, 1222 return _emitFunctionTagged(clos, type,
1224 topLevel: _executesAtTopLevel(node)); 1223 topLevel: _executesAtTopLevel(node));
1225 } 1224 }
1226 return clos; 1225 return clos;
1227 } 1226 }
1228 } 1227 }
1229 1228
1229 JS.Fun _emitJsFunction(List<JS.Parameter> params, FunctionBody body) {
1230 // TODO(jmesserly): async/async*
1231 var syncStar = body.isSynchronous && body.star != null;
1232 return new JS.Fun(params, _visit(body), isGenerator: syncStar);
1233 }
1234
1230 @override 1235 @override
1231 JS.Statement visitFunctionDeclarationStatement( 1236 JS.Statement visitFunctionDeclarationStatement(
1232 FunctionDeclarationStatement node) { 1237 FunctionDeclarationStatement node) {
1233 var func = node.functionDeclaration; 1238 var func = node.functionDeclaration;
1234 if (func.isGetter || func.isSetter) { 1239 if (func.isGetter || func.isSetter) {
1235 return js.comment('Unimplemented function get/set statement: $node'); 1240 return js.comment('Unimplemented function get/set statement: $node');
1236 } 1241 }
1237 1242
1238 // Use an => function to bind this. 1243 var fn = _visit(func.functionExpression);
1239 // Technically we only need to do this if the function actually closes over 1244 var jsThis = new _JsThisFinder();
1240 // `this`, but it seems harmless enough to just do it always. 1245 fn.accept(jsThis);
1246
1241 var name = new JS.Identifier(func.name.name); 1247 var name = new JS.Identifier(func.name.name);
1248 JS.Statement declareFn;
1249 if (jsThis.found) {
1250 declareFn = js.statement('let # = #.bind(this);', [name, fn]);
1251 } else {
1252 declareFn = new JS.FunctionDeclaration(name, fn);
1253 }
1254
1242 return new JS.Block([ 1255 return new JS.Block([
1243 js.statement('let # = #;', [name, _visit(func.functionExpression)]), 1256 declareFn,
1244 _emitFunctionTagged(name, func.element.type).toStatement() 1257 _emitFunctionTagged(name, func.element.type).toStatement()
1245 ]); 1258 ]);
1246 } 1259 }
1247 1260
1248 /// Writes a simple identifier. This can handle implicit `this` as well as 1261 /// Writes a simple identifier. This can handle implicit `this` as well as
1249 /// going through the qualified library name if necessary. 1262 /// going through the qualified library name if necessary.
1250 @override 1263 @override
1251 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { 1264 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) {
1252 var accessor = node.staticElement; 1265 var accessor = node.staticElement;
1253 if (accessor == null) { 1266 if (accessor == null) {
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 1648
1636 @override 1649 @override
1637 JS.Statement visitAssertStatement(AssertStatement node) => 1650 JS.Statement visitAssertStatement(AssertStatement node) =>
1638 // TODO(jmesserly): only emit in checked mode. 1651 // TODO(jmesserly): only emit in checked mode.
1639 js.statement('dart.assert(#);', _visit(node.condition)); 1652 js.statement('dart.assert(#);', _visit(node.condition));
1640 1653
1641 @override 1654 @override
1642 JS.Statement visitReturnStatement(ReturnStatement node) { 1655 JS.Statement visitReturnStatement(ReturnStatement node) {
1643 var e = node.expression; 1656 var e = node.expression;
1644 if (e == null) return new JS.Return(); 1657 if (e == null) return new JS.Return();
1645 return _visit(e).toReturn(); 1658 return (_visit(e) as JS.Expression).toReturn();
1646 } 1659 }
1647 1660
1648 @override 1661 @override
1662 JS.Statement visitYieldStatement(YieldStatement node) {
1663 JS.Expression jsExpr = _visit(node.expression);
1664 return jsExpr.toYieldStatement(star: node.star != null);
1665 }
1666
1667 @override
1649 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 1668 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
1650 for (var v in node.variables.variables) { 1669 for (var v in node.variables.variables) {
1651 _loader.loadDeclaration(v, v.element); 1670 _loader.loadDeclaration(v, v.element);
1652 } 1671 }
1653 } 1672 }
1654 1673
1655 _addExport(String name) { 1674 _addExport(String name) {
1656 if (!_exports.add(name)) throw 'Duplicate top level name found: $name'; 1675 if (!_exports.add(name)) throw 'Duplicate top level name found: $name';
1657 } 1676 }
1658 1677
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
2572 visitInterpolationExpression(InterpolationExpression node) => 2591 visitInterpolationExpression(InterpolationExpression node) =>
2573 _visit(node.expression); 2592 _visit(node.expression);
2574 2593
2575 @override 2594 @override
2576 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); 2595 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value);
2577 2596
2578 @override 2597 @override
2579 JS.Expression visitExpression(Expression node) => 2598 JS.Expression visitExpression(Expression node) =>
2580 _unimplementedCall('Unimplemented ${node.runtimeType}: $node'); 2599 _unimplementedCall('Unimplemented ${node.runtimeType}: $node');
2581 2600
2582 @override
2583 JS.Statement visitYieldStatement(YieldStatement node) =>
2584 _unimplementedCall('Unimplemented yield: $node').toStatement();
2585
2586 JS.Expression _unimplementedCall(String comment) { 2601 JS.Expression _unimplementedCall(String comment) {
2587 return js.call('dart.throw_(#)', [js.escapedString(comment)]); 2602 return js.call('dart.throw_(#)', [js.escapedString(comment)]);
2588 } 2603 }
2589 2604
2590 @override 2605 @override
2591 visitNode(AstNode node) { 2606 visitNode(AstNode node) {
2592 // TODO(jmesserly): verify this is unreachable. 2607 // TODO(jmesserly): verify this is unreachable.
2593 throw 'Unimplemented ${node.runtimeType}: $node'; 2608 throw 'Unimplemented ${node.runtimeType}: $node';
2594 } 2609 }
2595 2610
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 2813
2799 /// A special kind of element created by the compiler, signifying a temporary 2814 /// A special kind of element created by the compiler, signifying a temporary
2800 /// variable. These objects use instance equality, and should be shared 2815 /// variable. These objects use instance equality, and should be shared
2801 /// everywhere in the tree where they are treated as the same variable. 2816 /// everywhere in the tree where they are treated as the same variable.
2802 class TemporaryVariableElement extends LocalVariableElementImpl { 2817 class TemporaryVariableElement extends LocalVariableElementImpl {
2803 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2818 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2804 2819
2805 int get hashCode => identityHashCode(this); 2820 int get hashCode => identityHashCode(this);
2806 bool operator ==(Object other) => identical(this, other); 2821 bool operator ==(Object other) => identical(this, other);
2807 } 2822 }
2823
2824 class _JsThisFinder extends JS.BaseVisitor {
2825 bool found = false;
2826 visitThis(JS.This node) {
2827 found = true;
2828 }
2829 visitNode(JS.Node node) {
2830 if (!found) super.visitNode(node);
2831 }
2832 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/js.js ('k') | lib/src/codegen/js_metalet.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698