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

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

Issue 1751963002: refactor/simplify nullable inference code (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 9 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 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 5 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
6 6
7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 7 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
8 import 'package:analyzer/dart/ast/token.dart'; 8 import 'package:analyzer/dart/ast/token.dart';
9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/constant.dart'; 10 import 'package:analyzer/src/generated/constant.dart';
(...skipping 22 matching lines...) Expand all
33 import 'code_generator.dart'; 33 import 'code_generator.dart';
34 import 'js_field_storage.dart'; 34 import 'js_field_storage.dart';
35 import 'js_interop.dart'; 35 import 'js_interop.dart';
36 import 'js_names.dart' as JS; 36 import 'js_names.dart' as JS;
37 import 'js_metalet.dart' as JS; 37 import 'js_metalet.dart' as JS;
38 import 'js_module_item_order.dart'; 38 import 'js_module_item_order.dart';
39 import 'js_names.dart'; 39 import 'js_names.dart';
40 import 'js_printer.dart' show writeJsLibrary; 40 import 'js_printer.dart' show writeJsLibrary;
41 import 'js_typeref_codegen.dart'; 41 import 'js_typeref_codegen.dart';
42 import 'module_builder.dart'; 42 import 'module_builder.dart';
43 import 'nullability_inferrer.dart'; 43 import 'nullable_type_inference.dart';
44 import 'side_effect_analysis.dart'; 44 import 'side_effect_analysis.dart';
45 45
46 // Various dynamic helpers we call. 46 // Various dynamic helpers we call.
47 // If renaming these, make sure to check other places like the 47 // If renaming these, make sure to check other places like the
48 // _runtime.js file and comments. 48 // _runtime.js file and comments.
49 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can 49 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can
50 // import and generate calls to, rather than dart_runtime.js 50 // import and generate calls to, rather than dart_runtime.js
51 const DPUT = 'dput'; 51 const DPUT = 'dput';
52 const DLOAD = 'dload'; 52 const DLOAD = 'dload';
53 const DINDEX = 'dindex'; 53 const DINDEX = 'dindex';
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 ModuleItemLoadOrder _loader; 104 ModuleItemLoadOrder _loader;
105 105
106 /// _interceptors.JSArray<E>, used for List literals. 106 /// _interceptors.JSArray<E>, used for List literals.
107 ClassElement _jsArray; 107 ClassElement _jsArray;
108 108
109 /// The default value of the module object. See [visitLibraryDirective]. 109 /// The default value of the module object. See [visitLibraryDirective].
110 String _jsModuleValue; 110 String _jsModuleValue;
111 111
112 bool _isDartRuntime; 112 bool _isDartRuntime;
113 113
114 NullableTypeInference _nullInference;
115
114 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary, 116 JSCodegenVisitor(AbstractCompiler compiler, this.rules, this.currentLibrary,
115 this._extensionTypes, this._fieldsNeedingStorage) 117 this._extensionTypes, this._fieldsNeedingStorage)
116 : compiler = compiler, 118 : compiler = compiler,
117 options = compiler.options.codegenOptions, 119 options = compiler.options.codegenOptions,
118 _types = compiler.context.typeProvider { 120 _types = compiler.context.typeProvider {
119 _loader = new ModuleItemLoadOrder(_emitModuleItem); 121 _loader = new ModuleItemLoadOrder(_emitModuleItem);
120 122
121 var context = compiler.context; 123 var context = compiler.context;
122 var src = context.sourceFactory.forUri('dart:_interceptors'); 124 var src = context.sourceFactory.forUri('dart:_interceptors');
123 var interceptors = context.computeLibraryElement(src); 125 var interceptors = context.computeLibraryElement(src);
124 _jsArray = interceptors.getType('JSArray'); 126 _jsArray = interceptors.getType('JSArray');
125 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; 127 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime';
126 } 128 }
127 129
128 TypeProvider get types => _types; 130 TypeProvider get types => _types;
129 131
130 NullableExpressionPredicate _isNullable;
131
132 JS.Program emitLibrary(LibraryUnit library) { 132 JS.Program emitLibrary(LibraryUnit library) {
133 // Modify the AST to make coercions explicit. 133 // Modify the AST to make coercions explicit.
134 new CoercionReifier(library, rules).reify(); 134 new CoercionReifier(library, rules).reify();
135 135
136 // Build the public namespace for this library. This allows us to do 136 // Build the public namespace for this library. This allows us to do
137 // constant time lookups (contrast with `Element.getChild(name)`). 137 // constant time lookups (contrast with `Element.getChild(name)`).
138 if (currentLibrary.publicNamespace == null) { 138 if (currentLibrary.publicNamespace == null) {
139 (currentLibrary as LibraryElementImpl).publicNamespace = 139 (currentLibrary as LibraryElementImpl).publicNamespace =
140 new PublicNamespaceBuilder().build(currentLibrary); 140 new PublicNamespaceBuilder().build(currentLibrary);
141 } 141 }
142 142
143 library.library.directives.forEach(_visit); 143 library.library.directives.forEach(_visit);
144 144
145 var units = library.partsThenLibrary;
146
145 // Rather than directly visit declarations, we instead use [_loader] to 147 // Rather than directly visit declarations, we instead use [_loader] to
146 // visit them. It has the ability to sort elements on demand, so 148 // visit them. It has the ability to sort elements on demand, so
147 // dependencies between top level items are handled with a minimal 149 // dependencies between top level items are handled with a minimal
148 // reordering of the user's input code. The loader will call back into 150 // reordering of the user's input code. The loader will call back into
149 // this visitor via [_emitModuleItem] when it's ready to visit the item 151 // this visitor via [_emitModuleItem] when it's ready to visit the item
150 // for real. 152 // for real.
151 _loader.collectElements(currentLibrary, library.partsThenLibrary); 153 _loader.collectElements(currentLibrary, units);
152 154
153 var units = library.partsThenLibrary; 155 // TODO(jmesserly): ideally we could do this at a smaller granularity.
154 // TODO(ochafik): Move this down to smaller scopes (method, top-levels) to 156 // We'll need to be consistent about when we're generating functions, and
155 // save memory. 157 // only run this on the outermost function.
156 _isNullable = new NullabilityInferrer(units, 158 _nullInference =
157 getStaticType: getStaticType, isJSBuiltinType: _isJSBuiltinType) 159 new NullableTypeInference.forLibrary(_isPrimitiveType, units);
158 .buildNullabilityPredicate(); 160
161 _constField = new ConstFieldVisitor(types, library.library.element.source);
159 162
160 for (var unit in units) { 163 for (var unit in units) {
161 _constField = new ConstFieldVisitor(types, unit);
162
163 for (var decl in unit.declarations) { 164 for (var decl in unit.declarations) {
164 if (decl is TopLevelVariableDeclaration) { 165 if (decl is TopLevelVariableDeclaration) {
165 visitTopLevelVariableDeclaration(decl); 166 visitTopLevelVariableDeclaration(decl);
166 } else { 167 } else {
167 _loader.loadDeclaration(decl, decl.element); 168 _loader.loadDeclaration(decl, decl.element);
168 } 169 }
169 } 170 }
170 } 171 }
171 172
172 // Flush any unwritten fields/properties. 173 // Flush any unwritten fields/properties.
(...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 1239
1239 /// Initialize fields. They follow the sequence: 1240 /// Initialize fields. They follow the sequence:
1240 /// 1241 ///
1241 /// 1. field declaration initializer if non-const, 1242 /// 1. field declaration initializer if non-const,
1242 /// 2. field initializing parameters, 1243 /// 2. field initializing parameters,
1243 /// 3. constructor field initializers, 1244 /// 3. constructor field initializers,
1244 /// 4. initialize fields not covered in 1-3 1245 /// 4. initialize fields not covered in 1-3
1245 JS.Statement _initializeFields( 1246 JS.Statement _initializeFields(
1246 ClassDeclaration cls, List<FieldDeclaration> fieldDecls, 1247 ClassDeclaration cls, List<FieldDeclaration> fieldDecls,
1247 [ConstructorDeclaration ctor]) { 1248 [ConstructorDeclaration ctor]) {
1248 var unit = cls.getAncestor((a) => a is CompilationUnit) as CompilationUnit;
1249 var constField = new ConstFieldVisitor(types, unit);
1250 bool isConst = ctor != null && ctor.constKeyword != null; 1249 bool isConst = ctor != null && ctor.constKeyword != null;
1251 if (isConst) _loader.startTopLevel(cls.element); 1250 if (isConst) _loader.startTopLevel(cls.element);
1252 1251
1253 // Run field initializers if they can have side-effects. 1252 // Run field initializers if they can have side-effects.
1254 var fields = new Map<FieldElement, JS.Expression>(); 1253 var fields = new Map<FieldElement, JS.Expression>();
1255 var unsetFields = new Map<FieldElement, VariableDeclaration>(); 1254 var unsetFields = new Map<FieldElement, VariableDeclaration>();
1256 for (var declaration in fieldDecls) { 1255 for (var declaration in fieldDecls) {
1257 for (var fieldNode in declaration.fields.variables) { 1256 for (var fieldNode in declaration.fields.variables) {
1258 var element = fieldNode.element; 1257 var element = fieldNode.element;
1259 if (constField.isFieldInitConstant(fieldNode)) { 1258 if (_constField.isFieldInitConstant(fieldNode)) {
1260 unsetFields[element as FieldElement] = fieldNode; 1259 unsetFields[element as FieldElement] = fieldNode;
1261 } else { 1260 } else {
1262 fields[element as FieldElement] = _visitInitializer(fieldNode); 1261 fields[element as FieldElement] = _visitInitializer(fieldNode);
1263 } 1262 }
1264 } 1263 }
1265 } 1264 }
1266 1265
1267 // Initialize fields from `this.fieldName` parameters. 1266 // Initialize fields from `this.fieldName` parameters.
1268 if (ctor != null) { 1267 if (ctor != null) {
1269 for (var p in ctor.parameters.parameters) { 1268 for (var p in ctor.parameters.parameters) {
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them 1609 // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them
1611 // with regular functions (e.g. `function({a} = {}) { return 1 }`). 1610 // with regular functions (e.g. `function({a} = {}) { return 1 }`).
1612 // Note that Firefox accepts both syntaxes just fine. 1611 // Note that Firefox accepts both syntaxes just fine.
1613 // TODO(ochafik): Simplify this code when Chrome Canary catches up. 1612 // TODO(ochafik): Simplify this code when Chrome Canary catches up.
1614 bool destructureNamed = params.any((p) => 1613 bool destructureNamed = params.any((p) =>
1615 p is JS.DestructuredVariable && 1614 p is JS.DestructuredVariable &&
1616 p.structure is JS.ObjectBindingPattern); 1615 p.structure is JS.ObjectBindingPattern);
1617 1616
1618 if (body is ExpressionFunctionBody && !destructureNamed) { 1617 if (body is ExpressionFunctionBody && !destructureNamed) {
1619 // An arrow function can use the expression directly. 1618 // An arrow function can use the expression directly.
1620 // Note: this only works if we don't need to emit argument initializers.
1621 jsBody = _visit(body.expression); 1619 jsBody = _visit(body.expression);
1622 } else { 1620 } else {
1623 jsBody = _visit(body); 1621 jsBody = _visit(body);
1624 } 1622 }
1625 } 1623 }
1626 1624
1627 var fn = new JS.ArrowFun(params, jsBody, 1625 var fn = new JS.ArrowFun(params, jsBody,
1628 typeParams: _emitTypeFormals(type.typeFormals), 1626 typeParams: _emitTypeFormals(type.typeFormals),
1629 returnType: emitTypeRef(type.returnType)); 1627 returnType: emitTypeRef(type.returnType));
1630 return annotate(fn, node); 1628 return annotate(fn, node);
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after
2638 var name = constructor.name; 2636 var name = constructor.name;
2639 var type = constructor.type.type; 2637 var type = constructor.type.type;
2640 return _emitInstanceCreationExpression( 2638 return _emitInstanceCreationExpression(
2641 element, type, name, node.argumentList, node.isConst); 2639 element, type, name, node.argumentList, node.isConst);
2642 } 2640 }
2643 2641
2644 /// True if this type is built-in to JS, and we use the values unwrapped. 2642 /// True if this type is built-in to JS, and we use the values unwrapped.
2645 /// For these types we generate a calling convention via static 2643 /// For these types we generate a calling convention via static
2646 /// "extension methods". This allows types to be extended without adding 2644 /// "extension methods". This allows types to be extended without adding
2647 /// extensions directly on the prototype. 2645 /// extensions directly on the prototype.
2648 bool _isJSBuiltinType(DartType t) => 2646 bool _isPrimitiveType(DartType t) =>
2649 typeIsPrimitiveInJS(t) || t == _types.stringType; 2647 typeIsPrimitiveInJS(t) || t == _types.stringType;
2650 2648
2651 bool typeIsPrimitiveInJS(DartType t) => 2649 bool typeIsPrimitiveInJS(DartType t) =>
2652 _isNumberInJS(t) || t == _types.boolType; 2650 _isNumberInJS(t) || t == _types.boolType;
2653 2651
2654 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => 2652 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
2655 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); 2653 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT);
2656 2654
2657 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); 2655 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t);
2658 2656
2659 JS.Expression notNull(Expression expr) { 2657 JS.Expression notNull(Expression expr) {
2660 if (expr == null) return null; 2658 if (expr == null) return null;
2661 var jsExpr = _visit(expr); 2659 var jsExpr = _visit(expr);
2662 if (!_isNullable(expr)) return jsExpr; 2660 if (!_isNullable(expr)) return jsExpr;
2663 return js.call('dart.notNull(#)', jsExpr); 2661 return js.call('dart.notNull(#)', jsExpr);
2664 } 2662 }
2665 2663
2664 /// Returns true if [expr] can be null, optionally using [localIsNullable]
2665 /// for locals.
2666 ///
2667 /// This analysis is conservative and incomplete, but it can optimize many
2668 /// common patterns.
2669 bool _isNullable(Expression expr) => _nullInference.isNullable(expr);
2670
2666 @override 2671 @override
2667 JS.Expression visitBinaryExpression(BinaryExpression node) { 2672 JS.Expression visitBinaryExpression(BinaryExpression node) {
2668 var op = node.operator; 2673 var op = node.operator;
2669 var left = node.leftOperand; 2674 var left = node.leftOperand;
2670 var right = node.rightOperand; 2675 var right = node.rightOperand;
2671 2676
2672 var leftType = getStaticType(left); 2677 var leftType = getStaticType(left);
2673 var rightType = getStaticType(right); 2678 var rightType = getStaticType(right);
2674 2679
2675 var code; 2680 var code;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2728 var numType = types.numType; 2733 var numType = types.numType;
2729 if (rules.isSubtypeOf(t, numType)) return numType; 2734 if (rules.isSubtypeOf(t, numType)) return numType;
2730 return t; 2735 return t;
2731 } 2736 }
2732 2737
2733 bool _canUsePrimitiveEquality(Expression left, Expression right) { 2738 bool _canUsePrimitiveEquality(Expression left, Expression right) {
2734 if (_isNull(left) || _isNull(right)) return true; 2739 if (_isNull(left) || _isNull(right)) return true;
2735 2740
2736 var leftType = _canonicalizeNumTypes(getStaticType(left)); 2741 var leftType = _canonicalizeNumTypes(getStaticType(left));
2737 var rightType = _canonicalizeNumTypes(getStaticType(right)); 2742 var rightType = _canonicalizeNumTypes(getStaticType(right));
2738 return _isJSBuiltinType(leftType) && leftType == rightType; 2743 return _isPrimitiveType(leftType) && leftType == rightType;
2739 } 2744 }
2740 2745
2741 bool _isNull(Expression expr) => expr is NullLiteral; 2746 bool _isNull(Expression expr) => expr is NullLiteral;
2742 2747
2743 SimpleIdentifier _createTemporary(String name, DartType type) { 2748 SimpleIdentifier _createTemporary(String name, DartType type,
2749 {bool nullable: true}) {
2744 // We use an invalid source location to signal that this is a temporary. 2750 // We use an invalid source location to signal that this is a temporary.
2745 // See [_isTemporary]. 2751 // See [_isTemporary].
2746 // TODO(jmesserly): alternatives are 2752 // TODO(jmesserly): alternatives are
2747 // * (ab)use Element.isSynthetic, which isn't currently used for 2753 // * (ab)use Element.isSynthetic, which isn't currently used for
2748 // LocalVariableElementImpl, so we could repurpose to mean "temp". 2754 // LocalVariableElementImpl, so we could repurpose to mean "temp".
2749 // * add a new property to LocalVariableElementImpl. 2755 // * add a new property to LocalVariableElementImpl.
2750 // * create a new subtype of LocalVariableElementImpl to mark a temp. 2756 // * create a new subtype of LocalVariableElementImpl to mark a temp.
2751 var id = 2757 var id =
2752 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); 2758 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1));
2753 id.staticElement = new TemporaryVariableElement.forNode(id); 2759 id.staticElement = new TemporaryVariableElement.forNode(id);
2754 id.staticType = type; 2760 id.staticType = type;
2755 DynamicInvoke.set(id, type.isDynamic); 2761 DynamicInvoke.set(id, type.isDynamic);
2762 _nullInference.addVariable(id.staticElement, nullable: nullable);
2756 return id; 2763 return id;
2757 } 2764 }
2758 2765
2759 JS.Expression _emitConst(JS.Expression expr()) { 2766 JS.Expression _emitConst(JS.Expression expr()) {
2760 // TODO(jmesserly): emit the constants at top level if possible. 2767 // TODO(jmesserly): emit the constants at top level if possible.
2761 // This wasn't quite working, so disabled for now. 2768 // This wasn't quite working, so disabled for now.
2762 return js.call('dart.const(#)', expr()); 2769 return js.call('dart.const(#)', expr());
2763 } 2770 }
2764 2771
2765 /// Returns a new expression, which can be be used safely *once* on the 2772 /// Returns a new expression, which can be be used safely *once* on the
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2988 var tail = <JS.Expression>[]; 2995 var tail = <JS.Expression>[];
2989 for (;;) { 2996 for (;;) {
2990 var op = _getOperator(node); 2997 var op = _getOperator(node);
2991 if (op != null && op.lexeme == '?.') { 2998 if (op != null && op.lexeme == '?.') {
2992 var nodeTarget = _getTarget(node); 2999 var nodeTarget = _getTarget(node);
2993 if (!_isNullable(nodeTarget)) { 3000 if (!_isNullable(nodeTarget)) {
2994 node = _stripNullAwareOp(node, nodeTarget); 3001 node = _stripNullAwareOp(node, nodeTarget);
2995 break; 3002 break;
2996 } 3003 }
2997 3004
2998 var param = _createTemporary('_', nodeTarget.staticType); 3005 var param =
3006 _createTemporary('_', nodeTarget.staticType, nullable: false);
2999 var baseNode = _stripNullAwareOp(node, param); 3007 var baseNode = _stripNullAwareOp(node, param);
3000 tail.add(new JS.ArrowFun([_visit(param)], _visit(baseNode))); 3008 tail.add(new JS.ArrowFun([_visit(param)], _visit(baseNode)));
3001 node = nodeTarget; 3009 node = nodeTarget;
3002 } else { 3010 } else {
3003 break; 3011 break;
3004 } 3012 }
3005 } 3013 }
3006 if (tail.isEmpty) return _visit(node); 3014 if (tail.isEmpty) return _visit(node);
3007 return js.call('dart.nullSafe(#, #)', [_visit(node), tail.reversed]); 3015 return js.call('dart.nullSafe(#, #)', [_visit(node), tail.reversed]);
3008 } 3016 }
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
3223 var T = node.loopVariable.element.type; 3231 var T = node.loopVariable.element.type;
3224 var StreamIterator_T = 3232 var StreamIterator_T =
3225 dart_async.getType('StreamIterator').type.substitute4([T]); 3233 dart_async.getType('StreamIterator').type.substitute4([T]);
3226 3234
3227 var createStreamIter = _emitInstanceCreationExpression( 3235 var createStreamIter = _emitInstanceCreationExpression(
3228 StreamIterator_T.element.unnamedConstructor, 3236 StreamIterator_T.element.unnamedConstructor,
3229 StreamIterator_T, 3237 StreamIterator_T,
3230 null, 3238 null,
3231 AstBuilder.argumentList([node.iterable]), 3239 AstBuilder.argumentList([node.iterable]),
3232 false); 3240 false);
3233 var iter = _visit(_createTemporary('it', StreamIterator_T)); 3241 var iter =
3242 _visit(_createTemporary('it', StreamIterator_T, nullable: false));
3234 3243
3235 var init = _visit(node.identifier); 3244 var init = _visit(node.identifier);
3236 if (init == null) { 3245 if (init == null) {
3237 init = js 3246 init = js
3238 .call('let # = #.current', [node.loopVariable.identifier.name, iter]); 3247 .call('let # = #.current', [node.loopVariable.identifier.name, iter]);
3239 } else { 3248 } else {
3240 init = js.call('# = #.current', [init, iter]); 3249 init = js.call('# = #.current', [init, iter]);
3241 } 3250 }
3242 return js.statement( 3251 return js.statement(
3243 '{' 3252 '{'
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
3639 /// Choose a canonical name from the library element. 3648 /// Choose a canonical name from the library element.
3640 /// This never uses the library's name (the identifier in the `library` 3649 /// This never uses the library's name (the identifier in the `library`
3641 /// declaration) as it doesn't have any meaningful rules enforced. 3650 /// declaration) as it doesn't have any meaningful rules enforced.
3642 JS.Identifier emitLibraryName(LibraryElement library) { 3651 JS.Identifier emitLibraryName(LibraryElement library) {
3643 if (library == currentLibrary) return _exportsVar; 3652 if (library == currentLibrary) return _exportsVar;
3644 if (library.name == 'dart._runtime') return _runtimeLibVar; 3653 if (library.name == 'dart._runtime') return _runtimeLibVar;
3645 return _imports.putIfAbsent( 3654 return _imports.putIfAbsent(
3646 library, () => new JS.TemporaryId(jsLibraryName(library))); 3655 library, () => new JS.TemporaryId(jsLibraryName(library)));
3647 } 3656 }
3648 3657
3649 DartType getStaticType(Expression e) =>
3650 e.staticType ?? DynamicTypeImpl.instance;
3651
3652 JS.Node annotate(JS.Node node, AstNode original, [Element element]) { 3658 JS.Node annotate(JS.Node node, AstNode original, [Element element]) {
3653 if (options.closure && element != null) { 3659 if (options.closure && element != null) {
3654 node = node.withClosureAnnotation(closureAnnotationFor( 3660 node = node.withClosureAnnotation(closureAnnotationFor(
3655 node, original, element, namedArgumentTemp.name)); 3661 node, original, element, namedArgumentTemp.name));
3656 } 3662 }
3657 return node..sourceInformation = original; 3663 return node..sourceInformation = original;
3658 } 3664 }
3659 3665
3660 /// Returns true if this is any kind of object represented by `Number` in JS. 3666 /// Returns true if this is any kind of object represented by `Number` in JS.
3661 /// 3667 ///
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
3814 3820
3815 /// A special kind of element created by the compiler, signifying a temporary 3821 /// A special kind of element created by the compiler, signifying a temporary
3816 /// variable. These objects use instance equality, and should be shared 3822 /// variable. These objects use instance equality, and should be shared
3817 /// everywhere in the tree where they are treated as the same variable. 3823 /// everywhere in the tree where they are treated as the same variable.
3818 class TemporaryVariableElement extends LocalVariableElementImpl { 3824 class TemporaryVariableElement extends LocalVariableElementImpl {
3819 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3825 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3820 3826
3821 int get hashCode => identityHashCode(this); 3827 int get hashCode => identityHashCode(this);
3822 bool operator ==(Object other) => identical(this, other); 3828 bool operator ==(Object other) => identical(this, other);
3823 } 3829 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698