| OLD | NEW |
| 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 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1165 // initializing formal parameter, e.g. `Point(this.x)` | 1165 // initializing formal parameter, e.g. `Point(this.x)` |
| 1166 if (element is ParameterElement && | 1166 if (element is ParameterElement && |
| 1167 element.isInitializingFormal && | 1167 element.isInitializingFormal && |
| 1168 element.isPrivate) { | 1168 element.isPrivate) { |
| 1169 /// Rename private names so they don't shadow the private field symbol. | 1169 /// Rename private names so they don't shadow the private field symbol. |
| 1170 /// The renamer would handle this, but it would prefer to rename the | 1170 /// The renamer would handle this, but it would prefer to rename the |
| 1171 /// temporary used for the private symbol. Instead rename the parameter. | 1171 /// temporary used for the private symbol. Instead rename the parameter. |
| 1172 return _getTemp(element, '${name.substring(1)}'); | 1172 return _getTemp(element, '${name.substring(1)}'); |
| 1173 } | 1173 } |
| 1174 | 1174 |
| 1175 if (_isTemporary(element)) { | 1175 if (element is TemporaryVariableElement) { |
| 1176 if (name[0] == '#') { | 1176 if (name[0] == '#') { |
| 1177 return new JS.InterpolatedExpression(name.substring(1)); | 1177 return new JS.InterpolatedExpression(name.substring(1)); |
| 1178 } else { | 1178 } else { |
| 1179 return _getTemp(element, name); | 1179 return _getTemp(element, name); |
| 1180 } | 1180 } |
| 1181 } | 1181 } |
| 1182 | 1182 |
| 1183 return new JS.Identifier(name); | 1183 return new JS.Identifier(name); |
| 1184 } | 1184 } |
| 1185 | 1185 |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1768 SimpleIdentifier _createTemporary(String name, DartType type) { | 1768 SimpleIdentifier _createTemporary(String name, DartType type) { |
| 1769 // We use an invalid source location to signal that this is a temporary. | 1769 // We use an invalid source location to signal that this is a temporary. |
| 1770 // See [_isTemporary]. | 1770 // See [_isTemporary]. |
| 1771 // TODO(jmesserly): alternatives are | 1771 // TODO(jmesserly): alternatives are |
| 1772 // * (ab)use Element.isSynthetic, which isn't currently used for | 1772 // * (ab)use Element.isSynthetic, which isn't currently used for |
| 1773 // LocalVariableElementImpl, so we could repurpose to mean "temp". | 1773 // LocalVariableElementImpl, so we could repurpose to mean "temp". |
| 1774 // * add a new property to LocalVariableElementImpl. | 1774 // * add a new property to LocalVariableElementImpl. |
| 1775 // * create a new subtype of LocalVariableElementImpl to mark a temp. | 1775 // * create a new subtype of LocalVariableElementImpl to mark a temp. |
| 1776 var id = | 1776 var id = |
| 1777 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); | 1777 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); |
| 1778 id.staticElement = new LocalVariableElementImpl.forNode(id); | 1778 id.staticElement = new TemporaryVariableElement.forNode(id); |
| 1779 id.staticType = type; | 1779 id.staticType = type; |
| 1780 return id; | 1780 return id; |
| 1781 } | 1781 } |
| 1782 | 1782 |
| 1783 JS.Expression _const(Expression node, JS.Expression expr, [String nameHint]) { | 1783 JS.Expression _const(Expression node, JS.Expression expr, [String nameHint]) { |
| 1784 var value = js.call('dart.const(#)', expr); | 1784 var value = js.call('dart.const(#)', expr); |
| 1785 | 1785 |
| 1786 // If we're inside a method or function, capture the value into a | 1786 // If we're inside a method or function, capture the value into a |
| 1787 // global temporary, so we don't do the expensive canonicalization step. | 1787 // global temporary, so we don't do the expensive canonicalization step. |
| 1788 var ancestor = node.getAncestor((n) => n is FunctionBody || | 1788 var ancestor = node.getAncestor((n) => n is FunctionBody || |
| 1789 (n is FieldDeclaration && n.staticKeyword == null)); | 1789 (n is FieldDeclaration && n.staticKeyword == null)); |
| 1790 if (ancestor == null) return value; | 1790 if (ancestor == null) return value; |
| 1791 | 1791 |
| 1792 if (nameHint == null) { | 1792 if (nameHint == null) { |
| 1793 nameHint = 'const_' + getStaticType(node).name; | 1793 nameHint = 'const_' + getStaticType(node).name; |
| 1794 } | 1794 } |
| 1795 | 1795 |
| 1796 // TODO(jmesserly): enable this once we fix | 1796 // TODO(jmesserly): enable this once we fix |
| 1797 // https://github.com/dart-lang/dev_compiler/issues/131 | 1797 // https://github.com/dart-lang/dev_compiler/issues/131 |
| 1798 /*var temp = new JSTemporary(nameHint); | 1798 /*var temp = new JSTemporary(nameHint); |
| 1799 _pendingStatements.add(js.statement('let # = #;', [temp, value])); | 1799 _pendingStatements.add(js.statement('let # = #;', [temp, value])); |
| 1800 return temp;*/ | 1800 return temp;*/ |
| 1801 assert(nameHint != null); // so it's not marked unused | 1801 assert(nameHint != null); // so it's not marked unused |
| 1802 return value; | 1802 return value; |
| 1803 } | 1803 } |
| 1804 | 1804 |
| 1805 bool _isTemporary(Element node) => node.nameOffset == -1; | |
| 1806 | |
| 1807 /// Returns a new expression, which can be be used safely *once* on the | 1805 /// Returns a new expression, which can be be used safely *once* on the |
| 1808 /// left hand side, and *once* on the right side of an assignment. | 1806 /// left hand side, and *once* on the right side of an assignment. |
| 1809 /// For example: `expr1[expr2] += y` can be compiled as | 1807 /// For example: `expr1[expr2] += y` can be compiled as |
| 1810 /// `expr1[expr2] = expr1[expr2] + y`. | 1808 /// `expr1[expr2] = expr1[expr2] + y`. |
| 1811 /// | 1809 /// |
| 1812 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated | 1810 /// The temporary scope will ensure `expr1` and `expr2` are only evaluated |
| 1813 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`. | 1811 /// once: `((x1, x2) => x1[x2] = x1[x2] + y)(expr1, expr2)`. |
| 1814 /// | 1812 /// |
| 1815 /// If the expression does not end up using `x1` or `x2` more than once, or | 1813 /// If the expression does not end up using `x1` or `x2` more than once, or |
| 1816 /// if those expressions can be treated as stateless (e.g. they are | 1814 /// if those expressions can be treated as stateless (e.g. they are |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2612 // TODO(jmesserly): validate the library. See issue #135. | 2610 // TODO(jmesserly): validate the library. See issue #135. |
| 2613 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 2611 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
| 2614 | 2612 |
| 2615 bool _isJsPeerInterface(DartObjectImpl value) => | 2613 bool _isJsPeerInterface(DartObjectImpl value) => |
| 2616 value.type.name == 'JsPeerInterface'; | 2614 value.type.name == 'JsPeerInterface'; |
| 2617 | 2615 |
| 2618 // TODO(jacobr): we would like to do something like the following | 2616 // TODO(jacobr): we would like to do something like the following |
| 2619 // but we don't have summary support yet. | 2617 // but we don't have summary support yet. |
| 2620 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 2618 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
| 2621 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 2619 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
| 2620 |
| 2621 /// A special kind of element created by the compiler, signifying a temporary |
| 2622 /// variable. These objects use instance equality, and should be shared |
| 2623 /// everywhere in the tree where they are treated as the same variable. |
| 2624 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2625 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2626 |
| 2627 int get hashCode => identityHashCode(this); |
| 2628 bool operator ==(Object other) => identical(this, other); |
| 2629 } |
| OLD | NEW |