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 |