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

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

Issue 1111893002: small refactor: use JS.* prefix for our other JS extensions (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 7 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 | « no previous file | 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; 7 import 'dart:collection' show HashSet, HashMap;
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 13 matching lines...) Expand all
24 import 'package:dev_compiler/src/js/js_ast.dart' show js; 24 import 'package:dev_compiler/src/js/js_ast.dart' show js;
25 25
26 import 'package:dev_compiler/src/checker/rules.dart'; 26 import 'package:dev_compiler/src/checker/rules.dart';
27 import 'package:dev_compiler/src/dependency_graph.dart'; 27 import 'package:dev_compiler/src/dependency_graph.dart';
28 import 'package:dev_compiler/src/info.dart'; 28 import 'package:dev_compiler/src/info.dart';
29 import 'package:dev_compiler/src/options.dart'; 29 import 'package:dev_compiler/src/options.dart';
30 import 'package:dev_compiler/src/utils.dart'; 30 import 'package:dev_compiler/src/utils.dart';
31 31
32 import 'code_generator.dart'; 32 import 'code_generator.dart';
33 import 'js_field_storage.dart'; 33 import 'js_field_storage.dart';
34 import 'js_names.dart' show JSTemporary, invalidJSStaticMethodName; 34 import 'js_names.dart' as JS;
35 import 'js_metalet.dart'; 35 import 'js_metalet.dart' as JS;
36 import 'js_printer.dart' show writeJsLibrary; 36 import 'js_printer.dart' show writeJsLibrary;
37 import 'side_effect_analysis.dart'; 37 import 'side_effect_analysis.dart';
38 38
39 // Various dynamic helpers we call. 39 // Various dynamic helpers we call.
40 // If renaming these, make sure to check other places like the 40 // If renaming these, make sure to check other places like the
41 // dart_runtime.js file and comments. 41 // dart_runtime.js file and comments.
42 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can 42 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can
43 // import and generate calls to, rather than dart_runtime.js 43 // import and generate calls to, rather than dart_runtime.js
44 const DPUT = 'dput'; 44 const DPUT = 'dput';
45 const DLOAD = 'dload'; 45 const DLOAD = 'dload';
(...skipping 18 matching lines...) Expand all
64 SimpleIdentifier _cascadeTarget; 64 SimpleIdentifier _cascadeTarget;
65 65
66 /// The variable for the current catch clause 66 /// The variable for the current catch clause
67 SimpleIdentifier _catchParameter; 67 SimpleIdentifier _catchParameter;
68 68
69 ConstantEvaluator _constEvaluator; 69 ConstantEvaluator _constEvaluator;
70 70
71 final _exports = new Set<String>(); 71 final _exports = new Set<String>();
72 final _lazyFields = <VariableDeclaration>[]; 72 final _lazyFields = <VariableDeclaration>[];
73 final _properties = <FunctionDeclaration>[]; 73 final _properties = <FunctionDeclaration>[];
74 final _privateNames = new HashMap<String, JSTemporary>(); 74 final _privateNames = new HashMap<String, JS.TemporaryId>();
75 final _extensionMethodNames = new HashSet<String>(); 75 final _extensionMethodNames = new HashSet<String>();
76 final _pendingStatements = <JS.Statement>[]; 76 final _pendingStatements = <JS.Statement>[];
77 final _temps = new HashMap<Element, JSTemporary>(); 77 final _temps = new HashMap<Element, JS.TemporaryId>();
78 78
79 /// The name for the library's exports inside itself. 79 /// The name for the library's exports inside itself.
80 /// This much be a constant because we interpolate it into template strings, 80 /// This much be a constant because we interpolate it into template strings,
81 /// and otherwise it would break caching for them. 81 /// and otherwise it would break caching for them.
82 /// `exports` was chosen as the most similar to ES module patterns. 82 /// `exports` was chosen as the most similar to ES module patterns.
83 final JSTemporary _exportsVar = new JSTemporary('exports'); 83 final _exportsVar = new JS.TemporaryId('exports');
84 final JSTemporary _namedArgTemp = new JSTemporary('opts'); 84 final _namedArgTemp = new JS.TemporaryId('opts');
85 85
86 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or 86 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or
87 /// [ClassTypeAlias]. 87 /// [ClassTypeAlias].
88 final _pendingClasses = new HashMap<Element, CompilationUnitMember>(); 88 final _pendingClasses = new HashMap<Element, CompilationUnitMember>();
89 89
90 /// Memoized results of [_lazyClass]. 90 /// Memoized results of [_lazyClass].
91 final _lazyClassMemo = new HashMap<Element, bool>(); 91 final _lazyClassMemo = new HashMap<Element, bool>();
92 92
93 /// Memoized results of [_inLibraryCycle]. 93 /// Memoized results of [_inLibraryCycle].
94 final _libraryCycleMemo = new HashMap<LibraryElement, bool>(); 94 final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 if (name[0] == '#') { 1090 if (name[0] == '#') {
1091 return new JS.InterpolatedExpression(name.substring(1)); 1091 return new JS.InterpolatedExpression(name.substring(1));
1092 } else { 1092 } else {
1093 return _getTemp(element, name); 1093 return _getTemp(element, name);
1094 } 1094 }
1095 } 1095 }
1096 1096
1097 return new JS.Identifier(name); 1097 return new JS.Identifier(name);
1098 } 1098 }
1099 1099
1100 JSTemporary _getTemp(Object key, String name) => 1100 JS.TemporaryId _getTemp(Object key, String name) =>
1101 _temps.putIfAbsent(key, () => new JSTemporary(name)); 1101 _temps.putIfAbsent(key, () => new JS.TemporaryId(name));
1102 1102
1103 JS.ArrayInitializer _emitTypeNames(List<DartType> types) { 1103 JS.ArrayInitializer _emitTypeNames(List<DartType> types) {
1104 return new JS.ArrayInitializer(types.map(_emitTypeName).toList()); 1104 return new JS.ArrayInitializer(types.map(_emitTypeName).toList());
1105 } 1105 }
1106 1106
1107 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { 1107 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) {
1108 var properties = <JS.Property>[]; 1108 var properties = <JS.Property>[];
1109 types.forEach((name, type) { 1109 types.forEach((name, type) {
1110 var key = new JS.LiteralString(name); 1110 var key = new JS.LiteralString(name);
1111 var value = _emitTypeName(type); 1111 var value = _emitTypeName(type);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 @override 1190 @override
1191 JS.Expression visitAssignmentExpression(AssignmentExpression node) { 1191 JS.Expression visitAssignmentExpression(AssignmentExpression node) {
1192 var left = node.leftHandSide; 1192 var left = node.leftHandSide;
1193 var right = node.rightHandSide; 1193 var right = node.rightHandSide;
1194 if (node.operator.type == TokenType.EQ) return _emitSet(left, right); 1194 if (node.operator.type == TokenType.EQ) return _emitSet(left, right);
1195 return _emitOpAssign( 1195 return _emitOpAssign(
1196 left, right, node.operator.lexeme[0], node.staticElement, 1196 left, right, node.operator.lexeme[0], node.staticElement,
1197 context: node); 1197 context: node);
1198 } 1198 }
1199 1199
1200 JSMetaLet _emitOpAssign( 1200 JS.MetaLet _emitOpAssign(
1201 Expression left, Expression right, String op, ExecutableElement element, 1201 Expression left, Expression right, String op, ExecutableElement element,
1202 {Expression context}) { 1202 {Expression context}) {
1203 // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions 1203 // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions
1204 // (for example, x is IndexExpression) we evaluate those once. 1204 // (for example, x is IndexExpression) we evaluate those once.
1205 var vars = {}; 1205 var vars = {};
1206 var lhs = _bindLeftHandSide(vars, left, context: context); 1206 var lhs = _bindLeftHandSide(vars, left, context: context);
1207 var inc = AstBuilder.binaryExpression(lhs, op, right); 1207 var inc = AstBuilder.binaryExpression(lhs, op, right);
1208 inc.staticElement = element; 1208 inc.staticElement = element;
1209 inc.staticType = getStaticType(left); 1209 inc.staticType = getStaticType(left);
1210 return new JSMetaLet(vars, [_emitSet(lhs, inc)]); 1210 return new JS.MetaLet(vars, [_emitSet(lhs, inc)]);
1211 } 1211 }
1212 1212
1213 JS.Expression _emitSet(Expression lhs, Expression rhs) { 1213 JS.Expression _emitSet(Expression lhs, Expression rhs) {
1214 if (lhs is IndexExpression) { 1214 if (lhs is IndexExpression) {
1215 return _emitSend(_getTarget(lhs), '[]=', [lhs.index, rhs]); 1215 return _emitSend(_getTarget(lhs), '[]=', [lhs.index, rhs]);
1216 } 1216 }
1217 1217
1218 Expression target = null; 1218 Expression target = null;
1219 SimpleIdentifier id; 1219 SimpleIdentifier id;
1220 if (lhs is PropertyAccess) { 1220 if (lhs is PropertyAccess) {
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
1771 /// We also need to ensure we can return the original value of the expression, 1771 /// We also need to ensure we can return the original value of the expression,
1772 /// and that it is only evaluated once. 1772 /// and that it is only evaluated once.
1773 /// 1773 ///
1774 /// We desugar this using let*. 1774 /// We desugar this using let*.
1775 /// 1775 ///
1776 /// For example, `expr1[expr2]++` can be transformed to this: 1776 /// For example, `expr1[expr2]++` can be transformed to this:
1777 /// 1777 ///
1778 /// // psuedocode mix of Scheme and JS: 1778 /// // psuedocode mix of Scheme and JS:
1779 /// (let* (x1=expr1, x2=expr2, t=expr1[expr2]) { x1[x2] = t + 1; t }) 1779 /// (let* (x1=expr1, x2=expr2, t=expr1[expr2]) { x1[x2] = t + 1; t })
1780 /// 1780 ///
1781 /// The [JSMetaLet] nodes automatically simplify themselves if they can. 1781 /// The [JS.JS.MetaLet] nodes automatically simplify themselves if they can.
1782 /// For example, if the result value is not used, then `t` goes away. 1782 /// For example, if the result value is not used, then `t` goes away.
1783 @override 1783 @override
1784 JS.Expression visitPostfixExpression(PostfixExpression node) { 1784 JS.Expression visitPostfixExpression(PostfixExpression node) {
1785 var op = node.operator; 1785 var op = node.operator;
1786 var expr = node.operand; 1786 var expr = node.operand;
1787 1787
1788 var dispatchType = getStaticType(expr); 1788 var dispatchType = getStaticType(expr);
1789 if (unaryOperationIsPrimitive(dispatchType)) { 1789 if (unaryOperationIsPrimitive(dispatchType)) {
1790 if (_isNonNullableExpression(expr)) { 1790 if (_isNonNullableExpression(expr)) {
1791 return js.call('#$op', _visit(expr)); 1791 return js.call('#$op', _visit(expr));
(...skipping 10 matching lines...) Expand all
1802 // Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value 1802 // Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value
1803 // and `x1` is the new value for `x`. 1803 // and `x1` is the new value for `x`.
1804 var x = _bindValue(vars, 'x', left, context: expr); 1804 var x = _bindValue(vars, 'x', left, context: expr);
1805 1805
1806 var one = AstBuilder.integerLiteral(1)..staticType = types.intType; 1806 var one = AstBuilder.integerLiteral(1)..staticType = types.intType;
1807 var increment = AstBuilder.binaryExpression(x, op.lexeme[0], one) 1807 var increment = AstBuilder.binaryExpression(x, op.lexeme[0], one)
1808 ..staticElement = node.staticElement 1808 ..staticElement = node.staticElement
1809 ..staticType = getStaticType(expr); 1809 ..staticType = getStaticType(expr);
1810 1810
1811 var body = [_emitSet(left, increment), _visit(x)]; 1811 var body = [_emitSet(left, increment), _visit(x)];
1812 return new JSMetaLet(vars, body, statelessResult: true); 1812 return new JS.MetaLet(vars, body, statelessResult: true);
1813 } 1813 }
1814 1814
1815 @override 1815 @override
1816 JS.Expression visitPrefixExpression(PrefixExpression node) { 1816 JS.Expression visitPrefixExpression(PrefixExpression node) {
1817 var op = node.operator; 1817 var op = node.operator;
1818 var expr = node.operand; 1818 var expr = node.operand;
1819 1819
1820 var dispatchType = getStaticType(expr); 1820 var dispatchType = getStaticType(expr);
1821 if (unaryOperationIsPrimitive(dispatchType)) { 1821 if (unaryOperationIsPrimitive(dispatchType)) {
1822 if (_isNonNullableExpression(expr)) { 1822 if (_isNonNullableExpression(expr)) {
1823 return js.call('$op#', _visit(expr)); 1823 return js.call('$op#', _visit(expr));
1824 } else if (op.lexeme == '++' || op.lexeme == '--') { 1824 } else if (op.lexeme == '++' || op.lexeme == '--') {
1825 // We need a null check, so the increment must be expanded out. 1825 // We need a null check, so the increment must be expanded out.
1826 var mathop = op.lexeme[0]; 1826 var mathop = op.lexeme[0];
1827 var vars = {}; 1827 var vars = {};
1828 var x = _bindLeftHandSide(vars, expr, context: expr); 1828 var x = _bindLeftHandSide(vars, expr, context: expr);
1829 var body = js.call('# = # $mathop 1', [_visit(x), notNull(x)]); 1829 var body = js.call('# = # $mathop 1', [_visit(x), notNull(x)]);
1830 return new JSMetaLet(vars, [body]); 1830 return new JS.MetaLet(vars, [body]);
1831 } else { 1831 } else {
1832 return js.call('$op#', notNull(expr)); 1832 return js.call('$op#', notNull(expr));
1833 } 1833 }
1834 } 1834 }
1835 1835
1836 if (op.lexeme == '++' || op.lexeme == '--') { 1836 if (op.lexeme == '++' || op.lexeme == '--') {
1837 // Increment or decrement requires expansion. 1837 // Increment or decrement requires expansion.
1838 // Desugar `++x` as `x = x + 1`, ensuring that if `x` has subexpressions 1838 // Desugar `++x` as `x = x + 1`, ensuring that if `x` has subexpressions
1839 // (for example, x is IndexExpression) we evaluate those once. 1839 // (for example, x is IndexExpression) we evaluate those once.
1840 var one = AstBuilder.integerLiteral(1)..staticType = types.intType; 1840 var one = AstBuilder.integerLiteral(1)..staticType = types.intType;
1841 return _emitOpAssign(expr, one, op.lexeme[0], node.staticElement, 1841 return _emitOpAssign(expr, one, op.lexeme[0], node.staticElement,
1842 context: expr); 1842 context: expr);
1843 } 1843 }
1844 1844
1845 return _emitSend(expr, op.lexeme[0], []); 1845 return _emitSend(expr, op.lexeme[0], []);
1846 } 1846 }
1847 1847
1848 // Cascades can contain [IndexExpression], [MethodInvocation] and 1848 // Cascades can contain [IndexExpression], [MethodInvocation] and
1849 // [PropertyAccess]. The code generation for those is handled in their 1849 // [PropertyAccess]. The code generation for those is handled in their
1850 // respective visit methods. 1850 // respective visit methods.
1851 @override 1851 @override
1852 JS.Node visitCascadeExpression(CascadeExpression node) { 1852 JS.Node visitCascadeExpression(CascadeExpression node) {
1853 var savedCascadeTemp = _cascadeTarget; 1853 var savedCascadeTemp = _cascadeTarget;
1854 1854
1855 var vars = {}; 1855 var vars = {};
1856 _cascadeTarget = _bindValue(vars, '_', node.target, context: node); 1856 _cascadeTarget = _bindValue(vars, '_', node.target, context: node);
1857 var sections = _visitList(node.cascadeSections); 1857 var sections = _visitList(node.cascadeSections);
1858 sections.add(_visit(_cascadeTarget)); 1858 sections.add(_visit(_cascadeTarget));
1859 var result = new JSMetaLet(vars, sections, statelessResult: true); 1859 var result = new JS.MetaLet(vars, sections, statelessResult: true);
1860 _cascadeTarget = savedCascadeTemp; 1860 _cascadeTarget = savedCascadeTemp;
1861 return result; 1861 return result;
1862 } 1862 }
1863 1863
1864 @override 1864 @override
1865 visitParenthesizedExpression(ParenthesizedExpression node) => 1865 visitParenthesizedExpression(ParenthesizedExpression node) =>
1866 // The printer handles precedence so we don't need to. 1866 // The printer handles precedence so we don't need to.
1867 _visit(node.expression); 1867 _visit(node.expression);
1868 1868
1869 @override 1869 @override
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
2353 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed 2353 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
2354 /// for this transformation to happen, otherwise binary minus is assumed. 2354 /// for this transformation to happen, otherwise binary minus is assumed.
2355 /// 2355 ///
2356 /// Equality is a bit special, it is generated via the Dart `equals` runtime 2356 /// Equality is a bit special, it is generated via the Dart `equals` runtime
2357 /// helper, that checks for null. The user defined method is called '=='. 2357 /// helper, that checks for null. The user defined method is called '=='.
2358 /// 2358 ///
2359 JS.Expression _emitMemberName(String name, 2359 JS.Expression _emitMemberName(String name,
2360 {DartType type, bool unary: false, bool isStatic: false}) { 2360 {DartType type, bool unary: false, bool isStatic: false}) {
2361 if (name.startsWith('_')) { 2361 if (name.startsWith('_')) {
2362 return _privateNames.putIfAbsent( 2362 return _privateNames.putIfAbsent(
2363 name, () => _initSymbol(new JSTemporary(name))); 2363 name, () => _initSymbol(new JS.TemporaryId(name)));
2364 } 2364 }
2365 2365
2366 // Check for extension method: 2366 // Check for extension method:
2367 var extLibrary = _findExtensionLibrary(name, type); 2367 var extLibrary = _findExtensionLibrary(name, type);
2368 2368
2369 if (name == '[]') { 2369 if (name == '[]') {
2370 name = 'get'; 2370 name = 'get';
2371 } else if (name == '[]=') { 2371 } else if (name == '[]=') {
2372 name = 'set'; 2372 name = 'set';
2373 } else if (name == '-' && unary) { 2373 } else if (name == '-' && unary) {
2374 name = 'unary-'; 2374 name = 'unary-';
2375 } 2375 }
2376 2376
2377 if (isStatic && invalidJSStaticMethodName(name)) { 2377 if (isStatic && JS.invalidStaticMethodName(name)) {
2378 // Choose an string name. Use an invalid identifier so it won't conflict 2378 // Choose an string name. Use an invalid identifier so it won't conflict
2379 // with any valid member names. 2379 // with any valid member names.
2380 // TODO(jmesserly): this works around the problem, but I'm pretty sure we 2380 // TODO(jmesserly): this works around the problem, but I'm pretty sure we
2381 // don't need it, as static methods seemed to work. The only concrete 2381 // don't need it, as static methods seemed to work. The only concrete
2382 // issue we saw was in the defineNamedConstructor helper function. 2382 // issue we saw was in the defineNamedConstructor helper function.
2383 name = '$name*'; 2383 name = '$name*';
2384 } 2384 }
2385 2385
2386 if (extLibrary != null) { 2386 if (extLibrary != null) {
2387 return _extensionMethodName(name, extLibrary); 2387 return _extensionMethodName(name, extLibrary);
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2511 // TODO(jmesserly): validate the library. See issue #135. 2511 // TODO(jmesserly): validate the library. See issue #135.
2512 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2512 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2513 2513
2514 bool _isJsPeerInterface(DartObjectImpl value) => 2514 bool _isJsPeerInterface(DartObjectImpl value) =>
2515 value.type.name == 'JsPeerInterface'; 2515 value.type.name == 'JsPeerInterface';
2516 2516
2517 // TODO(jacobr): we would like to do something like the following 2517 // TODO(jacobr): we would like to do something like the following
2518 // but we don't have summary support yet. 2518 // but we don't have summary support yet.
2519 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2519 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2520 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2520 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « no previous file | lib/src/codegen/js_metalet.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698