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

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

Issue 1757343002: upgrade to latest analyzer (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
« no previous file with comments | « lib/runtime/dart/js.js ('k') | lib/src/codegen/side_effect_analysis.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 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';
11 import 'package:analyzer/src/generated/element.dart'; 11 import 'package:analyzer/src/generated/element.dart';
12 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; 12 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
14 import 'package:analyzer/src/dart/ast/token.dart' 14 import 'package:analyzer/src/dart/ast/token.dart'
15 show StringToken, Token, TokenType; 15 show StringToken, Token, TokenType;
16 import 'package:analyzer/src/generated/type_system.dart' 16 import 'package:analyzer/src/generated/type_system.dart'
17 show StrongTypeSystemImpl; 17 show StrongTypeSystemImpl;
18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder;
19 18
20 import 'ast_builder.dart' show AstBuilder; 19 import 'ast_builder.dart' show AstBuilder;
21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; 20 import 'reify_coercions.dart' show CoercionReifier, Tuple2;
22 21
23 import '../js/js_ast.dart' as JS; 22 import '../js/js_ast.dart' as JS;
24 import '../js/js_ast.dart' show js; 23 import '../js/js_ast.dart' show js;
25 24
26 import '../closure/closure_annotator.dart' show ClosureAnnotator; 25 import '../closure/closure_annotator.dart' show ClosureAnnotator;
27 import '../compiler.dart' 26 import '../compiler.dart'
28 show AbstractCompiler, corelibOrder, getCorelibModuleName; 27 show AbstractCompiler, corelibOrder, getCorelibModuleName;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 98
100 final TypeProvider _types; 99 final TypeProvider _types;
101 100
102 ConstFieldVisitor _constField; 101 ConstFieldVisitor _constField;
103 102
104 ModuleItemLoadOrder _loader; 103 ModuleItemLoadOrder _loader;
105 104
106 /// _interceptors.JSArray<E>, used for List literals. 105 /// _interceptors.JSArray<E>, used for List literals.
107 ClassElement _jsArray; 106 ClassElement _jsArray;
108 107
108 /// The current function body being compiled.
109 FunctionBody _currentFunction;
110
109 /// The default value of the module object. See [visitLibraryDirective]. 111 /// The default value of the module object. See [visitLibraryDirective].
110 String _jsModuleValue; 112 String _jsModuleValue;
111 113
112 bool _isDartRuntime; 114 bool _isDartRuntime;
113 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 JS.Program emitLibrary(LibraryUnit library) { 132 JS.Program emitLibrary(LibraryUnit library) {
131 // Modify the AST to make coercions explicit. 133 // Modify the AST to make coercions explicit.
132 new CoercionReifier(library, rules).reify(); 134 new CoercionReifier(library, rules).reify();
133 135
134 // Build the public namespace for this library. This allows us to do
135 // constant time lookups (contrast with `Element.getChild(name)`).
136 if (currentLibrary.publicNamespace == null) {
137 (currentLibrary as LibraryElementImpl).publicNamespace =
138 new PublicNamespaceBuilder().build(currentLibrary);
139 }
140
141 library.library.directives.forEach(_visit); 136 library.library.directives.forEach(_visit);
142 137
143 var units = library.partsThenLibrary; 138 var units = library.partsThenLibrary;
144 139
145 // Rather than directly visit declarations, we instead use [_loader] to 140 // Rather than directly visit declarations, we instead use [_loader] to
146 // visit them. It has the ability to sort elements on demand, so 141 // visit them. It has the ability to sort elements on demand, so
147 // dependencies between top level items are handled with a minimal 142 // dependencies between top level items are handled with a minimal
148 // reordering of the user's input code. The loader will call back into 143 // 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 144 // this visitor via [_emitModuleItem] when it's ready to visit the item
150 // for real. 145 // for real.
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 // Mark the parameter as no-rename. 1098 // Mark the parameter as no-rename.
1104 body = js.statement('''{ 1099 body = js.statement('''{
1105 // Get the class name for this instance. 1100 // Get the class name for this instance.
1106 let name = this.constructor.name; 1101 let name = this.constructor.name;
1107 // Call the default constructor. 1102 // Call the default constructor.
1108 let result = void 0; 1103 let result = void 0;
1109 if (name in this) result = this[name](...arguments); 1104 if (name in this) result = this[name](...arguments);
1110 return result === void 0 ? this : result; 1105 return result === void 0 ? this : result;
1111 }''') as JS.Block; 1106 }''') as JS.Block;
1112 } else { 1107 } else {
1108 var savedFunction = _currentFunction;
1109 _currentFunction = node.body;
1113 body = _emitConstructorBody(node, fields); 1110 body = _emitConstructorBody(node, fields);
1111 _currentFunction = savedFunction;
1114 } 1112 }
1115 1113
1116 // We generate constructors as initializer methods in the class; 1114 // We generate constructors as initializer methods in the class;
1117 // this allows use of `super` for instance methods/properties. 1115 // this allows use of `super` for instance methods/properties.
1118 // It also avoids V8 restrictions on `super` in default constructors. 1116 // It also avoids V8 restrictions on `super` in default constructors.
1119 return annotate( 1117 return annotate(
1120 new JS.Method(name, new JS.Fun(params, body, returnType: returnType)), 1118 new JS.Method(name, new JS.Fun(params, body, returnType: returnType)),
1121 node, 1119 node,
1122 node.element); 1120 node.element);
1123 } 1121 }
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
1583 /// Contrast with [_emitFunction]. 1581 /// Contrast with [_emitFunction].
1584 @override 1582 @override
1585 JS.Expression visitFunctionExpression(FunctionExpression node) { 1583 JS.Expression visitFunctionExpression(FunctionExpression node) {
1586 assert(node.parent is! FunctionDeclaration && 1584 assert(node.parent is! FunctionDeclaration &&
1587 node.parent is! MethodDeclaration); 1585 node.parent is! MethodDeclaration);
1588 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node), 1586 return _emitFunctionTagged(_emitArrowFunction(node), getStaticType(node),
1589 topLevel: _executesAtTopLevel(node)); 1587 topLevel: _executesAtTopLevel(node));
1590 } 1588 }
1591 1589
1592 JS.ArrowFun _emitArrowFunction(FunctionExpression node) { 1590 JS.ArrowFun _emitArrowFunction(FunctionExpression node) {
1593 List<JS.Parameter> params; 1591 JS.Fun f = _emitFunctionBody(node.element, node.parameters, node.body);
1592 var body = f.body;
1594 1593
1595 var body = node.body; 1594 // Simplify `=> { return e; }` to `=> e`
1596 var type = node.element.type; 1595 if (body is JS.Block) {
1597 1596 JS.Block block = body;
1598 JS.Node jsBody; 1597 if (block.statements.length == 1) {
1599 if (body.isGenerator || body.isAsynchronous) { 1598 JS.Statement s = block.statements[0];
1600 params = visitFormalParameterList(node.parameters, destructure: false); 1599 if (s is JS.Return) body = s.value;
1601 jsBody = _emitGeneratorFunctionBody(node.element, node.parameters, body);
1602 } else {
1603 params = visitFormalParameterList(node.parameters);
1604
1605 // Chrome Canary does not accept default values with destructuring in
1606 // arrow functions yet (e.g. `({a} = {}) => 1`) but happily accepts them
1607 // with regular functions (e.g. `function({a} = {}) { return 1 }`).
1608 // Note that Firefox accepts both syntaxes just fine.
1609 // TODO(ochafik): Simplify this code when Chrome Canary catches up.
1610 bool destructureNamed = params.any((p) =>
1611 p is JS.DestructuredVariable &&
1612 p.structure is JS.ObjectBindingPattern);
1613
1614 if (body is ExpressionFunctionBody && !destructureNamed) {
1615 // An arrow function can use the expression directly.
1616 jsBody = _visit(body.expression);
1617 } else {
1618 jsBody = _visit(body);
1619 } 1600 }
1620 } 1601 }
1621 1602
1622 var fn = new JS.ArrowFun(params, jsBody, 1603 // Convert `function(...) { ... }` to `(...) => ...`
1623 typeParams: _emitTypeFormals(type.typeFormals), 1604 // This is for readability, but it also ensures correct `this` binding.
1624 returnType: emitTypeRef(type.returnType)); 1605 return annotate(
1625 return annotate(fn, node); 1606 new JS.ArrowFun(f.params, body,
1607 typeParams: f.typeParams, returnType: f.returnType),
1608 node);
1626 } 1609 }
1627 1610
1628 /// Emits a non-arrow FunctionExpression node. 1611 /// Emits a non-arrow FunctionExpression node.
1629 /// 1612 ///
1630 /// This should be used for all places in Dart's AST where FunctionExpression 1613 /// This should be used for all places in Dart's AST where FunctionExpression
1631 /// appears but the function is not actually in an Expression context, such 1614 /// appears but the function is not actually in an Expression context, such
1632 /// as methods, properties, and top-level functions. 1615 /// as methods, properties, and top-level functions.
1633 /// 1616 ///
1634 /// Contrast with [visitFunctionExpression]. 1617 /// Contrast with [visitFunctionExpression].
1635 JS.Fun _emitFunction(FunctionExpression node) { 1618 JS.Fun _emitFunction(FunctionExpression node) {
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after
2067 // or when one of the expressions is stateless, which seems common. 2050 // or when one of the expressions is stateless, which seems common.
2068 var vars = <String, JS.Expression>{}; 2051 var vars = <String, JS.Expression>{};
2069 var left = _bindValue(vars, 'l', node.target); 2052 var left = _bindValue(vars, 'l', node.target);
2070 var body = js.call('# == null ? null : #', 2053 var body = js.call('# == null ? null : #',
2071 [_visit(left), _emitSet(_stripNullAwareOp(node, left), right)]); 2054 [_visit(left), _emitSet(_stripNullAwareOp(node, left), right)]);
2072 return new JS.MetaLet(vars, [body]); 2055 return new JS.MetaLet(vars, [body]);
2073 } 2056 }
2074 2057
2075 @override 2058 @override
2076 JS.Block visitExpressionFunctionBody(ExpressionFunctionBody node) { 2059 JS.Block visitExpressionFunctionBody(ExpressionFunctionBody node) {
2060 var savedFunction = _currentFunction;
2061 _currentFunction = node;
2077 var initArgs = _emitArgumentInitializers(node.parent); 2062 var initArgs = _emitArgumentInitializers(node.parent);
2078 var ret = new JS.Return(_visit(node.expression)); 2063 var ret = new JS.Return(_visit(node.expression));
2064 _currentFunction = savedFunction;
2079 return new JS.Block(initArgs != null ? [initArgs, ret] : [ret]); 2065 return new JS.Block(initArgs != null ? [initArgs, ret] : [ret]);
2080 } 2066 }
2081 2067
2082 @override 2068 @override
2083 JS.Block visitEmptyFunctionBody(EmptyFunctionBody node) => new JS.Block([]); 2069 JS.Block visitEmptyFunctionBody(EmptyFunctionBody node) => new JS.Block([]);
2084 2070
2085 @override 2071 @override
2086 JS.Block visitBlockFunctionBody(BlockFunctionBody node) { 2072 JS.Block visitBlockFunctionBody(BlockFunctionBody node) {
2073 var savedFunction = _currentFunction;
2074 _currentFunction = node;
2087 var initArgs = _emitArgumentInitializers(node.parent); 2075 var initArgs = _emitArgumentInitializers(node.parent);
2088 var stmts = _visitList(node.block.statements) as List<JS.Statement>; 2076 var stmts = _visitList(node.block.statements) as List<JS.Statement>;
2089 if (initArgs != null) stmts.insert(0, initArgs); 2077 if (initArgs != null) stmts.insert(0, initArgs);
2078 _currentFunction = savedFunction;
2090 return new JS.Block(stmts); 2079 return new JS.Block(stmts);
2091 } 2080 }
2092 2081
2093 @override 2082 @override
2094 JS.Block visitBlock(Block node) => 2083 JS.Block visitBlock(Block node) =>
2095 new JS.Block(_visitList(node.statements) as List<JS.Statement>, 2084 new JS.Block(_visitList(node.statements) as List<JS.Statement>,
2096 isScope: true); 2085 isScope: true);
2097 2086
2098 @override 2087 @override
2099 visitMethodInvocation(MethodInvocation node) { 2088 visitMethodInvocation(MethodInvocation node) {
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after
2814 /// 2803 ///
2815 /// If the expression does not end up using `x` more than once, or if those 2804 /// If the expression does not end up using `x` more than once, or if those
2816 /// expressions can be treated as stateless (e.g. they are non-mutated 2805 /// expressions can be treated as stateless (e.g. they are non-mutated
2817 /// variables), then the resulting code will be simplified automatically. 2806 /// variables), then the resulting code will be simplified automatically.
2818 /// 2807 ///
2819 /// [scope] will be mutated to contain the new temporary's initialization. 2808 /// [scope] will be mutated to contain the new temporary's initialization.
2820 Expression _bindValue( 2809 Expression _bindValue(
2821 Map<String, JS.Expression> scope, String name, Expression expr, 2810 Map<String, JS.Expression> scope, String name, Expression expr,
2822 {Expression context}) { 2811 {Expression context}) {
2823 // No need to do anything for stateless expressions. 2812 // No need to do anything for stateless expressions.
2824 if (isStateless(expr, context)) return expr; 2813 if (isStateless(_currentFunction, expr, context)) return expr;
2825 2814
2826 var t = _createTemporary('#$name', getStaticType(expr)); 2815 var t = _createTemporary('#$name', getStaticType(expr));
2827 scope[name] = _visit(expr); 2816 scope[name] = _visit(expr);
2828 return t; 2817 return t;
2829 } 2818 }
2830 2819
2831 /// Desugars postfix increment. 2820 /// Desugars postfix increment.
2832 /// 2821 ///
2833 /// In the general case [expr] can be one of [IndexExpression], 2822 /// In the general case [expr] can be one of [IndexExpression],
2834 /// [PrefixExpression] or [PropertyAccess] and we need to 2823 /// [PrefixExpression] or [PropertyAccess] and we need to
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
3400 return _emitConst(emitSymbol); 3389 return _emitConst(emitSymbol);
3401 } 3390 }
3402 3391
3403 @override 3392 @override
3404 visitListLiteral(ListLiteral node) { 3393 visitListLiteral(ListLiteral node) {
3405 JS.Expression emitList() { 3394 JS.Expression emitList() {
3406 JS.Expression list = new JS.ArrayInitializer( 3395 JS.Expression list = new JS.ArrayInitializer(
3407 _visitList(node.elements) as List<JS.Expression>); 3396 _visitList(node.elements) as List<JS.Expression>);
3408 ParameterizedType type = node.staticType; 3397 ParameterizedType type = node.staticType;
3409 var elementType = type.typeArguments.single; 3398 var elementType = type.typeArguments.single;
3410 if (elementType != types.dynamicType) { 3399 // TODO(jmesserly): analyzer will usually infer `List<Object>` because
3400 // that is the least upper bound of the element types. So we rarely
3401 // generate a plain `List<dynamic>` anymore.
3402 if (!elementType.isDynamic) {
3411 // dart.list helper internally depends on _interceptors.JSArray. 3403 // dart.list helper internally depends on _interceptors.JSArray.
3412 _loader.declareBeforeUse(_jsArray); 3404 _loader.declareBeforeUse(_jsArray);
3413 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); 3405 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]);
3414 } 3406 }
3415 return list; 3407 return list;
3416 } 3408 }
3417 if (node.constKeyword != null) return _emitConst(emitList); 3409 if (node.constKeyword != null) return _emitConst(emitList);
3418 return emitList(); 3410 return emitList();
3419 } 3411 }
3420 3412
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
3851 3843
3852 /// A special kind of element created by the compiler, signifying a temporary 3844 /// A special kind of element created by the compiler, signifying a temporary
3853 /// variable. These objects use instance equality, and should be shared 3845 /// variable. These objects use instance equality, and should be shared
3854 /// everywhere in the tree where they are treated as the same variable. 3846 /// everywhere in the tree where they are treated as the same variable.
3855 class TemporaryVariableElement extends LocalVariableElementImpl { 3847 class TemporaryVariableElement extends LocalVariableElementImpl {
3856 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3848 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3857 3849
3858 int get hashCode => identityHashCode(this); 3850 int get hashCode => identityHashCode(this);
3859 bool operator ==(Object other) => identical(this, other); 3851 bool operator ==(Object other) => identical(this, other);
3860 } 3852 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/js.js ('k') | lib/src/codegen/side_effect_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698