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

Side by Side Diff: lib/src/compiler/code_generator.dart

Issue 1992373002: Simplify ordering of top-level declarations. (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 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/compiler/element_loader.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 HashMap, HashSet; 5 import 'dart:collection' show HashMap, HashSet;
6 import 'dart:math' show min, max; 6 import 'dart:math' show min, max;
7 7
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // Collect all Element -> Node mappings, in case we need to forward declare 227 // Collect all Element -> Node mappings, in case we need to forward declare
228 // any nodes. 228 // any nodes.
229 var nodes = new HashMap<Element, AstNode>.identity(); 229 var nodes = new HashMap<Element, AstNode>.identity();
230 var sdkBootstrappingFns = new List<FunctionElement>(); 230 var sdkBootstrappingFns = new List<FunctionElement>();
231 for (var unit in compilationUnits) { 231 for (var unit in compilationUnits) {
232 if (_isDartRuntime(unit.element.library)) { 232 if (_isDartRuntime(unit.element.library)) {
233 sdkBootstrappingFns.addAll(unit.element.functions); 233 sdkBootstrappingFns.addAll(unit.element.functions);
234 } 234 }
235 _collectElements(unit, nodes); 235 _collectElements(unit, nodes);
236 } 236 }
237 _loader = new ElementLoader(_emitModuleItem, nodes); 237 _loader = new ElementLoader(nodes);
238 238
239 // Add implicit dart:core dependency so it is first. 239 // Add implicit dart:core dependency so it is first.
240 emitLibraryName(dartCoreLibrary); 240 emitLibraryName(dartCoreLibrary);
241 241
242 // Emit SDK bootstrapping functions first, if any. 242 // Emit SDK bootstrapping functions first, if any.
243 sdkBootstrappingFns.forEach(_loader.emitDeclaration); 243 sdkBootstrappingFns.forEach(_emitDeclaration);
244 244
245 // Visit each compilation unit and emit its code. 245 // Visit each compilation unit and emit its code.
246 // 246 //
247 // NOTE: declarations are not necessarily emitted in this order. 247 // NOTE: declarations are not necessarily emitted in this order.
248 // Order will be changed as needed so the resulting code can execute. 248 // Order will be changed as needed so the resulting code can execute.
249 // This is done by forward declaring items. 249 // This is done by forward declaring items.
250 compilationUnits.forEach(visitCompilationUnit); 250 compilationUnits.forEach(visitCompilationUnit);
251 251
252 // Declare imports 252 // Declare imports
253 _finishImports(items); 253 _finishImports(items);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 if (declaration is TopLevelVariableDeclaration) { 381 if (declaration is TopLevelVariableDeclaration) {
382 for (var field in declaration.variables.variables) { 382 for (var field in declaration.variables.variables) {
383 map[field.element] = field; 383 map[field.element] = field;
384 } 384 }
385 } else { 385 } else {
386 map[declaration.element] = declaration; 386 map[declaration.element] = declaration;
387 } 387 }
388 } 388 }
389 } 389 }
390 390
391 void _emitModuleItem(AstNode node) { 391 /// Called to emit all top-level declarations.
392 // TODO(jmesserly): ideally we could do this at a smaller granularity. 392 ///
393 // We'll need to be consistent about when we're generating functions, and 393 /// During the course of emitting one item, we may emit another. For example
394 // only run this on the outermost function. 394 ///
395 inferNullableTypes(node); 395 /// class D extends B { C m() { ... } }
396 ///
397 /// Because D depends on B, we'll emit B first if needed. However C is not
398 /// used by top-level JavaScript code, so we can ignore that dependency.
399 void _emitDeclaration(Element e) {
400 var item = _loader.emitDeclaration(e, (AstNode node) {
401 // TODO(jmesserly): this is not really the right place for this.
402 // Ideally we do this per function body.
403 //
404 // We'll need to be consistent about when we're generating functions, and
405 // only run this on the outermost function, and not any closures.
406 inferNullableTypes(node);
407 return _visit(node);
408 });
396 409
397 var code = _visit(node); 410 if (item != null) _moduleItems.add(item);
398 if (code != null) _moduleItems.add(code); 411 }
412
413 void _declareBeforeUse(Element e) {
414 _loader.declareBeforeUse(e, _emitDeclaration);
399 } 415 }
400 416
401 @override 417 @override
402 void visitCompilationUnit(CompilationUnit unit) { 418 void visitCompilationUnit(CompilationUnit unit) {
403 _constField = new ConstFieldVisitor(types, unit.element.source); 419 _constField = new ConstFieldVisitor(types, unit.element.source);
404 420
405 for (var declaration in unit.declarations) { 421 for (var declaration in unit.declarations) {
406 var element = declaration.element; 422 var element = declaration.element;
407 if (element != null) { 423 if (element != null) {
408 _loader.emitDeclaration(element); 424 _emitDeclaration(element);
409 } else { 425 } else {
410 declaration.accept(this); 426 declaration.accept(this);
411 } 427 }
412 } 428 }
413 for (var directive in unit.directives) { 429 for (var directive in unit.directives) {
414 directive.accept(this); 430 directive.accept(this);
415 } 431 }
416 } 432 }
417 433
418 @override 434 @override
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 487
472 for (var export in exportedNames.definedNames.values) { 488 for (var export in exportedNames.definedNames.values) {
473 if (export is PropertyAccessorElement) { 489 if (export is PropertyAccessorElement) {
474 export = (export as PropertyAccessorElement).variable; 490 export = (export as PropertyAccessorElement).variable;
475 } 491 }
476 492
477 // Don't allow redefining names from this library. 493 // Don't allow redefining names from this library.
478 if (currentNames.containsKey(export.name)) continue; 494 if (currentNames.containsKey(export.name)) continue;
479 495
480 if (export.isSynthetic && export is PropertyInducingElement) { 496 if (export.isSynthetic && export is PropertyInducingElement) {
481 _loader.emitDeclaration(export.getter); 497 _emitDeclaration(export.getter);
482 _loader.emitDeclaration(export.setter); 498 _emitDeclaration(export.setter);
483 } else { 499 } else {
484 _loader.emitDeclaration(export); 500 _emitDeclaration(export);
485 } 501 }
486 if (export is ClassElement && export.typeParameters.isNotEmpty) { 502 if (export is ClassElement && export.typeParameters.isNotEmpty) {
487 // Export the generic name as well. 503 // Export the generic name as well.
488 // TODO(jmesserly): revisit generic classes 504 // TODO(jmesserly): revisit generic classes
489 emitExport(export, suffix: r'$'); 505 emitExport(export, suffix: r'$');
490 } 506 }
491 emitExport(export); 507 emitExport(export);
492 } 508 }
493 } 509 }
494 510
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 typeParams: fn.typeParams, 1801 typeParams: fn.typeParams,
1786 returnType: fn.returnType)..sourceInformation = fn.sourceInformation; 1802 returnType: fn.returnType)..sourceInformation = fn.sourceInformation;
1787 } 1803 }
1788 1804
1789 @override 1805 @override
1790 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { 1806 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
1791 assert(node.parent is CompilationUnit); 1807 assert(node.parent is CompilationUnit);
1792 1808
1793 if (_externalOrNative(node)) return null; 1809 if (_externalOrNative(node)) return null;
1794 1810
1795 if (node.isGetter || node.isSetter) { 1811 // If we have a getter/setter pair, they need to be defined together.
1796 // If we have a getter/setter pair, they need to be defined together. 1812 if (node.isGetter) {
1797 PropertyAccessorElement element = node.element; 1813 PropertyAccessorElement element = node.element;
1798 var props = <JS.Method>[]; 1814 var props = <JS.Method>[_emitTopLevelProperty(node)];
1799 var getter = element.variable.getter; 1815 var setter = element.correspondingSetter;
1800 if (getter != null) { 1816 if (setter != null) {
1801 props.add(_loader.customEmitDeclaration(getter, _emitTopLevelProperty)); 1817 props.add(_loader.emitDeclaration(setter, _emitTopLevelProperty));
1802 } 1818 }
1803 var setter = element.variable.setter;
1804 if (setter != null) {
1805 props.add(_loader.customEmitDeclaration(setter, _emitTopLevelProperty));
1806 }
1807
1808 return js.statement('dart.copyProperties(#, { # });', 1819 return js.statement('dart.copyProperties(#, { # });',
1809 [emitLibraryName(currentLibrary), props]); 1820 [emitLibraryName(currentLibrary), props]);
1810 } 1821 }
1822 if (node.isSetter) {
1823 PropertyAccessorElement element = node.element;
1824 var props = <JS.Method>[_emitTopLevelProperty(node)];
1825 var getter = element.correspondingGetter;
1826 if (getter != null) {
1827 props.add(_loader.emitDeclaration(getter, _emitTopLevelProperty));
1828 }
1829 return js.statement('dart.copyProperties(#, { # });',
1830 [emitLibraryName(currentLibrary), props]);
1831 }
1811 1832
1812 var body = <JS.Statement>[]; 1833 var body = <JS.Statement>[];
1813 var fn = _emitFunction(node.functionExpression); 1834 var fn = _emitFunction(node.functionExpression);
1814 1835
1815 if (currentLibrary.source.isInSystemLibrary && 1836 if (currentLibrary.source.isInSystemLibrary &&
1816 _isInlineJSFunction(node.functionExpression)) { 1837 _isInlineJSFunction(node.functionExpression)) {
1817 fn = _simplifyPassThroughArrowFunCallBody(fn); 1838 fn = _simplifyPassThroughArrowFunCallBody(fn);
1818 } 1839 }
1819 1840
1820 var element = node.element; 1841 var element = node.element;
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
2122 if (accessor == null) { 2143 if (accessor == null) {
2123 return js.commentExpression( 2144 return js.commentExpression(
2124 'Unimplemented unknown name', new JS.Identifier(node.name)); 2145 'Unimplemented unknown name', new JS.Identifier(node.name));
2125 } 2146 }
2126 2147
2127 // Get the original declaring element. If we had a property accessor, this 2148 // Get the original declaring element. If we had a property accessor, this
2128 // indirects back to a (possibly synthetic) field. 2149 // indirects back to a (possibly synthetic) field.
2129 var element = accessor; 2150 var element = accessor;
2130 if (accessor is PropertyAccessorElement) element = accessor.variable; 2151 if (accessor is PropertyAccessorElement) element = accessor.variable;
2131 2152
2132 _loader.declareBeforeUse(element); 2153 _declareBeforeUse(element);
2133 2154
2134 // type literal 2155 // type literal
2135 if (element is TypeDefiningElement) { 2156 if (element is TypeDefiningElement) {
2136 var typeName = _emitType(fillDynamicTypeArgs(element.type)); 2157 var typeName = _emitType(fillDynamicTypeArgs(element.type));
2137 2158
2138 // If the type is a type literal expression in Dart code, wrap the raw 2159 // If the type is a type literal expression in Dart code, wrap the raw
2139 // runtime type in a "Type" instance. 2160 // runtime type in a "Type" instance.
2140 if (!_isInForeignJS && _isTypeLiteral(node)) { 2161 if (!_isInForeignJS && _isTypeLiteral(node)) {
2141 typeName = js.call('dart.wrapType(#)', typeName); 2162 typeName = js.call('dart.wrapType(#)', typeName);
2142 } 2163 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2312 JS.Expression className}) { 2333 JS.Expression className}) {
2313 // The void and dynamic types are not defined in core. 2334 // The void and dynamic types are not defined in core.
2314 if (type.isVoid) { 2335 if (type.isVoid) {
2315 return js.call('dart.void'); 2336 return js.call('dart.void');
2316 } else if (type.isDynamic) { 2337 } else if (type.isDynamic) {
2317 return js.call('dart.dynamic'); 2338 return js.call('dart.dynamic');
2318 } else if (type.isBottom) { 2339 } else if (type.isBottom) {
2319 return js.call('dart.bottom'); 2340 return js.call('dart.bottom');
2320 } 2341 }
2321 2342
2322 _loader.declareBeforeUse(type.element); 2343 _declareBeforeUse(type.element);
2323 2344
2324 // TODO(jmesserly): like constants, should we hoist function types out of 2345 // TODO(jmesserly): like constants, should we hoist function types out of
2325 // methods? Similar issue with generic types. For all of these, we may want 2346 // methods? Similar issue with generic types. For all of these, we may want
2326 // to canonicalize them too, at least when inside the same library. 2347 // to canonicalize them too, at least when inside the same library.
2327 var name = type.name; 2348 var name = type.name;
2328 var element = type.element; 2349 var element = type.element;
2329 if (name == '' || name == null || lowerTypedef) { 2350 if (name == '' || name == null || lowerTypedef) {
2330 // TODO(jmesserly): should we change how typedefs work? They currently 2351 // TODO(jmesserly): should we change how typedefs work? They currently
2331 // go through use similar logic as generic classes. This makes them 2352 // go through use similar logic as generic classes. This makes them
2332 // different from universal function types. 2353 // different from universal function types.
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
2862 } 2883 }
2863 2884
2864 @override 2885 @override
2865 JS.Expression visitAwaitExpression(AwaitExpression node) { 2886 JS.Expression visitAwaitExpression(AwaitExpression node) {
2866 return new JS.Yield(_visit(node.expression)); 2887 return new JS.Yield(_visit(node.expression));
2867 } 2888 }
2868 2889
2869 @override 2890 @override
2870 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 2891 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
2871 for (var variable in node.variables.variables) { 2892 for (var variable in node.variables.variables) {
2872 _loader.emitDeclaration(variable.element); 2893 _emitDeclaration(variable.element);
2873 } 2894 }
2874 } 2895 }
2875 2896
2876 /// This is not used--we emit fields as we are emitting the class, 2897 /// This is not used--we emit fields as we are emitting the class,
2877 /// see [visitClassDeclaration]. 2898 /// see [visitClassDeclaration].
2878 @override 2899 @override
2879 visitFieldDeclaration(FieldDeclaration node) { 2900 visitFieldDeclaration(FieldDeclaration node) {
2880 assert(false); 2901 assert(false);
2881 } 2902 }
2882 2903
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 JS.Expression emitList() { 4158 JS.Expression emitList() {
4138 JS.Expression list = new JS.ArrayInitializer( 4159 JS.Expression list = new JS.ArrayInitializer(
4139 _visitList(node.elements) as List<JS.Expression>); 4160 _visitList(node.elements) as List<JS.Expression>);
4140 ParameterizedType type = node.staticType; 4161 ParameterizedType type = node.staticType;
4141 var elementType = type.typeArguments.single; 4162 var elementType = type.typeArguments.single;
4142 // TODO(jmesserly): analyzer will usually infer `List<Object>` because 4163 // TODO(jmesserly): analyzer will usually infer `List<Object>` because
4143 // that is the least upper bound of the element types. So we rarely 4164 // that is the least upper bound of the element types. So we rarely
4144 // generate a plain `List<dynamic>` anymore. 4165 // generate a plain `List<dynamic>` anymore.
4145 if (!elementType.isDynamic) { 4166 if (!elementType.isDynamic) {
4146 // dart.list helper internally depends on _interceptors.JSArray. 4167 // dart.list helper internally depends on _interceptors.JSArray.
4147 _loader.declareBeforeUse(_jsArray); 4168 _declareBeforeUse(_jsArray);
4148 list = js.call('dart.list(#, #)', [list, _emitType(elementType)]); 4169 list = js.call('dart.list(#, #)', [list, _emitType(elementType)]);
4149 } 4170 }
4150 return list; 4171 return list;
4151 } 4172 }
4152 if (node.constKeyword != null) return _emitConst(emitList); 4173 if (node.constKeyword != null) return _emitConst(emitList);
4153 return emitList(); 4174 return emitList();
4154 } 4175 }
4155 4176
4156 @override 4177 @override
4157 visitMapLiteral(MapLiteral node) { 4178 visitMapLiteral(MapLiteral node) {
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
4535 } 4556 }
4536 4557
4537 bool isLibraryPrefix(Expression node) => 4558 bool isLibraryPrefix(Expression node) =>
4538 node is SimpleIdentifier && node.staticElement is PrefixElement; 4559 node is SimpleIdentifier && node.staticElement is PrefixElement;
4539 4560
4540 LibraryElement _getLibrary(AnalysisContext c, String uri) => 4561 LibraryElement _getLibrary(AnalysisContext c, String uri) =>
4541 c.computeLibraryElement(c.sourceFactory.forUri(uri)); 4562 c.computeLibraryElement(c.sourceFactory.forUri(uri));
4542 4563
4543 bool _isDartRuntime(LibraryElement l) => 4564 bool _isDartRuntime(LibraryElement l) =>
4544 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; 4565 l.isInSdk && l.source.uri.toString() == 'dart:_runtime';
OLDNEW
« no previous file with comments | « no previous file | lib/src/compiler/element_loader.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698