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 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/dart/ast/ast.dart' show FunctionBodyImpl; |
9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/src/generated/constant.dart'; | 11 import 'package:analyzer/src/generated/constant.dart'; |
11 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
12 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; | 13 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |
| 14 import 'package:analyzer/src/generated/parser.dart' show ResolutionCopier; |
13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; | 15 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
14 import 'package:analyzer/src/dart/ast/token.dart' | 16 import 'package:analyzer/src/dart/ast/token.dart' |
15 show StringToken, Token, TokenType; | 17 show StringToken, Token, TokenType; |
16 import 'package:analyzer/src/generated/type_system.dart' | 18 import 'package:analyzer/src/generated/type_system.dart' |
17 show StrongTypeSystemImpl; | 19 show StrongTypeSystemImpl; |
| 20 import 'package:analyzer/src/task/strong/info.dart'; |
18 | 21 |
19 import 'ast_builder.dart' show AstBuilder; | 22 import 'ast_builder.dart' show AstBuilder; |
20 import 'reify_coercions.dart' show CoercionReifier, Tuple2; | 23 import 'reify_coercions.dart' show CoercionReifier, Tuple2; |
21 | 24 |
22 import '../js/js_ast.dart' as JS; | 25 import '../js/js_ast.dart' as JS; |
23 import '../js/js_ast.dart' show js; | 26 import '../js/js_ast.dart' show js; |
24 | 27 |
25 import '../closure/closure_annotator.dart' show ClosureAnnotator; | 28 import '../closure/closure_annotator.dart' show ClosureAnnotator; |
26 import '../compiler.dart' | 29 import '../compiler.dart' |
27 show AbstractCompiler, corelibOrder, getCorelibModuleName; | 30 show AbstractCompiler, corelibOrder, getCorelibModuleName; |
28 import '../info.dart'; | |
29 import '../options.dart' show CodegenOptions; | 31 import '../options.dart' show CodegenOptions; |
30 import '../utils.dart'; | 32 import '../utils.dart'; |
31 | 33 |
32 import 'code_generator.dart'; | |
33 import 'js_field_storage.dart'; | 34 import 'js_field_storage.dart'; |
34 import 'js_interop.dart'; | 35 import 'js_interop.dart'; |
35 import 'js_names.dart' as JS; | 36 import 'js_names.dart' as JS; |
36 import 'js_metalet.dart' as JS; | 37 import 'js_metalet.dart' as JS; |
37 import 'js_module_item_order.dart'; | 38 import 'js_module_item_order.dart'; |
38 import 'js_names.dart'; | 39 import 'js_names.dart'; |
39 import 'js_printer.dart' show writeJsLibrary; | 40 import 'js_printer.dart' show writeJsLibrary; |
40 import 'js_typeref_codegen.dart'; | 41 import 'js_typeref_codegen.dart'; |
41 import 'module_builder.dart'; | 42 import 'module_builder.dart'; |
42 import 'nullable_type_inference.dart'; | 43 import 'nullable_type_inference.dart'; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 | 123 |
123 var context = compiler.context; | 124 var context = compiler.context; |
124 var src = context.sourceFactory.forUri('dart:_interceptors'); | 125 var src = context.sourceFactory.forUri('dart:_interceptors'); |
125 var interceptors = context.computeLibraryElement(src); | 126 var interceptors = context.computeLibraryElement(src); |
126 _jsArray = interceptors.getType('JSArray'); | 127 _jsArray = interceptors.getType('JSArray'); |
127 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; | 128 _isDartRuntime = currentLibrary.source.uri.toString() == 'dart:_runtime'; |
128 } | 129 } |
129 | 130 |
130 TypeProvider get types => _types; | 131 TypeProvider get types => _types; |
131 | 132 |
132 JS.Program emitLibrary(LibraryUnit library) { | 133 JS.Program emitLibrary(List<CompilationUnit> units) { |
| 134 // Copy the AST before modifying it. |
| 135 units = units.map(_cloneCompilationUnit).toList(); |
| 136 |
133 // Modify the AST to make coercions explicit. | 137 // Modify the AST to make coercions explicit. |
134 new CoercionReifier(library, rules).reify(); | 138 new CoercionReifier(currentLibrary, rules).reify(units); |
135 | 139 |
136 library.library.directives.forEach(_visit); | 140 units.last.directives.forEach(_visit); |
137 | |
138 var units = library.partsThenLibrary; | |
139 | 141 |
140 // Rather than directly visit declarations, we instead use [_loader] to | 142 // Rather than directly visit declarations, we instead use [_loader] to |
141 // visit them. It has the ability to sort elements on demand, so | 143 // visit them. It has the ability to sort elements on demand, so |
142 // dependencies between top level items are handled with a minimal | 144 // dependencies between top level items are handled with a minimal |
143 // reordering of the user's input code. The loader will call back into | 145 // reordering of the user's input code. The loader will call back into |
144 // this visitor via [_emitModuleItem] when it's ready to visit the item | 146 // this visitor via [_emitModuleItem] when it's ready to visit the item |
145 // for real. | 147 // for real. |
146 _loader.collectElements(currentLibrary, units); | 148 _loader.collectElements(currentLibrary, units); |
147 | 149 |
148 // TODO(jmesserly): ideally we could do this at a smaller granularity. | 150 // TODO(jmesserly): ideally we could do this at a smaller granularity. |
149 // We'll need to be consistent about when we're generating functions, and | 151 // We'll need to be consistent about when we're generating functions, and |
150 // only run this on the outermost function. | 152 // only run this on the outermost function. |
151 inferNullableTypesInLibrary(units); | 153 inferNullableTypesInLibrary(units); |
152 | 154 |
153 _constField = new ConstFieldVisitor(types, library.library.element.source); | 155 _constField = new ConstFieldVisitor(types, currentLibrary.source); |
154 | 156 |
155 for (var unit in units) { | 157 for (var unit in units) { |
156 for (var decl in unit.declarations) { | 158 for (var decl in unit.declarations) { |
157 if (decl is TopLevelVariableDeclaration) { | 159 if (decl is TopLevelVariableDeclaration) { |
158 visitTopLevelVariableDeclaration(decl); | 160 visitTopLevelVariableDeclaration(decl); |
159 } else { | 161 } else { |
160 _loader.loadDeclaration(decl, decl.element); | 162 _loader.loadDeclaration(decl, decl.element); |
161 } | 163 } |
162 } | 164 } |
163 } | 165 } |
(...skipping 3585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3749 _addExtensionTypes(libraryUri); | 3751 _addExtensionTypes(libraryUri); |
3750 } | 3752 } |
3751 _pendingLibraries.clear(); | 3753 _pendingLibraries.clear(); |
3752 return _extensionTypes.contains(element); | 3754 return _extensionTypes.contains(element); |
3753 } | 3755 } |
3754 } | 3756 } |
3755 return false; | 3757 return false; |
3756 } | 3758 } |
3757 } | 3759 } |
3758 | 3760 |
3759 class JSGenerator extends CodeGenerator { | 3761 class JSGenerator { |
| 3762 final AbstractCompiler compiler; |
3760 final ExtensionTypeSet _extensionTypes; | 3763 final ExtensionTypeSet _extensionTypes; |
3761 final TypeProvider _types; | 3764 final TypeProvider _types; |
3762 | 3765 |
3763 JSGenerator(AbstractCompiler compiler) | 3766 JSGenerator(AbstractCompiler compiler) |
3764 : _types = compiler.context.typeProvider, | 3767 : compiler = compiler, |
3765 _extensionTypes = new ExtensionTypeSet(compiler), | 3768 _types = compiler.context.typeProvider, |
3766 super(compiler) { | 3769 _extensionTypes = new ExtensionTypeSet(compiler) { |
3767 // TODO(vsm): Eventually, we want to make this extensible - i.e., find | 3770 // TODO(vsm): Eventually, we want to make this extensible - i.e., find |
3768 // annotations in user code as well. It would need to be summarized in | 3771 // annotations in user code as well. It would need to be summarized in |
3769 // the element model - not searched this way on every compile. To make this | 3772 // the element model - not searched this way on every compile. To make this |
3770 // a little more efficient now, we do this in two phases. | 3773 // a little more efficient now, we do this in two phases. |
3771 | 3774 |
3772 // First, core types: | 3775 // First, core types: |
3773 _extensionTypes._addExtensionTypes('dart:_interceptors'); | 3776 _extensionTypes._addExtensionTypes('dart:_interceptors'); |
3774 _extensionTypes._addExtensionTypes('dart:_native_typed_data'); | 3777 _extensionTypes._addExtensionTypes('dart:_native_typed_data'); |
3775 // TODO(vsm): If we're analyzing against the main SDK, those | 3778 // TODO(vsm): If we're analyzing against the main SDK, those |
3776 // types are not explicitly annotated. | 3779 // types are not explicitly annotated. |
(...skipping 10 matching lines...) Expand all Loading... |
3787 | 3790 |
3788 // Second, html types - these are only searched if we use dart:html, etc.: | 3791 // Second, html types - these are only searched if we use dart:html, etc.: |
3789 _extensionTypes._addPendingExtensionTypes('dart:html'); | 3792 _extensionTypes._addPendingExtensionTypes('dart:html'); |
3790 _extensionTypes._addPendingExtensionTypes('dart:indexed_db'); | 3793 _extensionTypes._addPendingExtensionTypes('dart:indexed_db'); |
3791 _extensionTypes._addPendingExtensionTypes('dart:svg'); | 3794 _extensionTypes._addPendingExtensionTypes('dart:svg'); |
3792 _extensionTypes._addPendingExtensionTypes('dart:web_audio'); | 3795 _extensionTypes._addPendingExtensionTypes('dart:web_audio'); |
3793 _extensionTypes._addPendingExtensionTypes('dart:web_gl'); | 3796 _extensionTypes._addPendingExtensionTypes('dart:web_gl'); |
3794 _extensionTypes._addPendingExtensionTypes('dart:web_sql'); | 3797 _extensionTypes._addPendingExtensionTypes('dart:web_sql'); |
3795 } | 3798 } |
3796 | 3799 |
3797 String generateLibrary(LibraryUnit unit) { | 3800 void generateLibrary(List<CompilationUnit> units) { |
3798 // Clone the AST first, so we can mutate it. | 3801 var library = units.first.element.library; |
3799 unit = unit.clone(); | 3802 var fields = |
3800 var library = unit.library.element.library; | 3803 findFieldsNeedingStorage(units.map((c) => c.element), _extensionTypes); |
3801 var fields = findFieldsNeedingStorage(unit, _extensionTypes); | |
3802 var rules = new StrongTypeSystemImpl(); | 3804 var rules = new StrongTypeSystemImpl(); |
3803 var codegen = | 3805 var codegen = |
3804 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); | 3806 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); |
3805 var module = codegen.emitLibrary(unit); | 3807 var module = codegen.emitLibrary(units); |
3806 var out = compiler.getOutputPath(library.source.uri); | 3808 var out = compiler.getOutputPath(library.source.uri); |
3807 var flags = compiler.options; | 3809 var options = compiler.options.codegenOptions; |
3808 var serverUri = flags.serverMode | 3810 writeJsLibrary(module, out, compiler.inputBaseDir, |
3809 ? Uri.parse('http://${flags.host}:${flags.port}/') | |
3810 : null; | |
3811 return writeJsLibrary(module, out, compiler.inputBaseDir, serverUri, | |
3812 emitTypes: options.closure, | 3811 emitTypes: options.closure, |
3813 emitSourceMaps: options.emitSourceMaps, | 3812 emitSourceMaps: options.emitSourceMaps, |
3814 fileSystem: compiler.fileSystem); | 3813 fileSystem: compiler.fileSystem); |
3815 } | 3814 } |
3816 } | 3815 } |
3817 | 3816 |
3818 /// Choose a canonical name from the library element. | 3817 /// Choose a canonical name from the library element. |
3819 /// This never uses the library's name (the identifier in the `library` | 3818 /// This never uses the library's name (the identifier in the `library` |
3820 /// declaration) as it doesn't have any meaningful rules enforced. | 3819 /// declaration) as it doesn't have any meaningful rules enforced. |
3821 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 3820 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
(...skipping 11 matching lines...) Expand all Loading... |
3833 | 3832 |
3834 /// A special kind of element created by the compiler, signifying a temporary | 3833 /// A special kind of element created by the compiler, signifying a temporary |
3835 /// variable. These objects use instance equality, and should be shared | 3834 /// variable. These objects use instance equality, and should be shared |
3836 /// everywhere in the tree where they are treated as the same variable. | 3835 /// everywhere in the tree where they are treated as the same variable. |
3837 class TemporaryVariableElement extends LocalVariableElementImpl { | 3836 class TemporaryVariableElement extends LocalVariableElementImpl { |
3838 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3837 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3839 | 3838 |
3840 int get hashCode => identityHashCode(this); | 3839 int get hashCode => identityHashCode(this); |
3841 bool operator ==(Object other) => identical(this, other); | 3840 bool operator ==(Object other) => identical(this, other); |
3842 } | 3841 } |
| 3842 |
| 3843 CompilationUnit _cloneCompilationUnit(CompilationUnit unit) { |
| 3844 var result = new _TreeCloner().visitCompilationUnit(unit); |
| 3845 ResolutionCopier.copyResolutionData(unit, result); |
| 3846 return result; |
| 3847 } |
| 3848 |
| 3849 class _TreeCloner extends AstCloner { |
| 3850 void _cloneProperties(AstNode clone, AstNode node) { |
| 3851 if (clone != null) { |
| 3852 CoercionInfo.set(clone, CoercionInfo.get(node)); |
| 3853 DynamicInvoke.set(clone, DynamicInvoke.get(node)); |
| 3854 } |
| 3855 } |
| 3856 |
| 3857 @override |
| 3858 AstNode cloneNode(AstNode node) { |
| 3859 var clone = super.cloneNode(node); |
| 3860 _cloneProperties(clone, node); |
| 3861 return clone; |
| 3862 } |
| 3863 |
| 3864 @override |
| 3865 List cloneNodeList(List list) { |
| 3866 var clone = super.cloneNodeList(list); |
| 3867 for (int i = 0, len = list.length; i < len; i++) { |
| 3868 _cloneProperties(clone[i], list[i]); |
| 3869 } |
| 3870 return clone; |
| 3871 } |
| 3872 |
| 3873 // TODO(jmesserly): ResolutionCopier is not copying this yet. |
| 3874 @override |
| 3875 BlockFunctionBody visitBlockFunctionBody(BlockFunctionBody node) { |
| 3876 var clone = super.visitBlockFunctionBody(node); |
| 3877 (clone as FunctionBodyImpl).localVariableInfo = |
| 3878 (node as FunctionBodyImpl).localVariableInfo; |
| 3879 return clone; |
| 3880 } |
| 3881 |
| 3882 @override |
| 3883 ExpressionFunctionBody visitExpressionFunctionBody( |
| 3884 ExpressionFunctionBody node) { |
| 3885 var clone = super.visitExpressionFunctionBody(node); |
| 3886 (clone as FunctionBodyImpl).localVariableInfo = |
| 3887 (node as FunctionBodyImpl).localVariableInfo; |
| 3888 return clone; |
| 3889 } |
| 3890 } |
OLD | NEW |