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; |
11 import 'package:analyzer/src/generated/constant.dart'; | 11 import 'package:analyzer/src/generated/constant.dart'; |
12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
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/generated/scanner.dart' | 14 import 'package:analyzer/src/generated/scanner.dart' |
15 show StringToken, Token, TokenType; | 15 show StringToken, Token, TokenType; |
16 import 'package:path/path.dart' as path; | 16 import 'package:path/path.dart' as path; |
17 | 17 |
18 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder; | 18 import 'package:dev_compiler/src/codegen/ast_builder.dart' show AstBuilder; |
19 import 'package:dev_compiler/src/codegen/reify_coercions.dart' | 19 import 'package:dev_compiler/src/codegen/reify_coercions.dart' |
20 show CoercionReifier; | 20 show CoercionReifier; |
21 | 21 |
22 // TODO(jmesserly): import from its own package | 22 // TODO(jmesserly): import from its own package |
23 import 'package:dev_compiler/src/js/js_ast.dart' as JS; | 23 import 'package:dev_compiler/src/js/js_ast.dart' as JS; |
24 import 'package:dev_compiler/src/js/js_ast.dart' show js; | 24 import 'package:dev_compiler/src/js/js_ast.dart' show js; |
25 | 25 |
| 26 import 'package:dev_compiler/devc.dart' show AbstractCompiler; |
26 import 'package:dev_compiler/src/checker/rules.dart'; | 27 import 'package:dev_compiler/src/checker/rules.dart'; |
27 import 'package:dev_compiler/src/info.dart'; | 28 import 'package:dev_compiler/src/info.dart'; |
28 import 'package:dev_compiler/src/options.dart'; | 29 import 'package:dev_compiler/src/options.dart'; |
29 import 'package:dev_compiler/src/utils.dart'; | 30 import 'package:dev_compiler/src/utils.dart'; |
30 | 31 |
31 import 'code_generator.dart'; | 32 import 'code_generator.dart'; |
32 import 'js_field_storage.dart'; | 33 import 'js_field_storage.dart'; |
33 import 'js_names.dart' as JS; | 34 import 'js_names.dart' as JS; |
34 import 'js_metalet.dart' as JS; | 35 import 'js_metalet.dart' as JS; |
35 import 'js_module_item_order.dart'; | 36 import 'js_module_item_order.dart'; |
36 import 'js_printer.dart' show writeJsLibrary; | 37 import 'js_printer.dart' show writeJsLibrary; |
37 import 'side_effect_analysis.dart'; | 38 import 'side_effect_analysis.dart'; |
38 | 39 |
39 // Various dynamic helpers we call. | 40 // Various dynamic helpers we call. |
40 // If renaming these, make sure to check other places like the | 41 // If renaming these, make sure to check other places like the |
41 // dart_runtime.js file and comments. | 42 // dart_runtime.js file and comments. |
42 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can | 43 // TODO(jmesserly): ideally we'd have a "dynamic call" dart library we can |
43 // import and generate calls to, rather than dart_runtime.js | 44 // import and generate calls to, rather than dart_runtime.js |
44 const DPUT = 'dput'; | 45 const DPUT = 'dput'; |
45 const DLOAD = 'dload'; | 46 const DLOAD = 'dload'; |
46 const DINDEX = 'dindex'; | 47 const DINDEX = 'dindex'; |
47 const DSETINDEX = 'dsetindex'; | 48 const DSETINDEX = 'dsetindex'; |
48 const DCALL = 'dcall'; | 49 const DCALL = 'dcall'; |
49 const DSEND = 'dsend'; | 50 const DSEND = 'dsend'; |
50 | 51 |
51 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { | 52 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| 53 final AbstractCompiler compiler; |
52 final CompilerOptions options; | 54 final CompilerOptions options; |
53 final TypeRules rules; | 55 final TypeRules rules; |
54 final LibraryInfo libraryInfo; | 56 final LibraryInfo libraryInfo; |
55 | 57 |
56 /// The global extension method table. | 58 /// The global extension method table. |
57 final HashMap<String, List<InterfaceType>> _extensionMethods; | 59 final HashMap<String, List<InterfaceType>> _extensionMethods; |
58 | 60 |
59 /// Information that is precomputed for this library, indicates which fields | 61 /// Information that is precomputed for this library, indicates which fields |
60 /// need storage slots. | 62 /// need storage slots. |
61 final HashSet<FieldElement> _fieldsNeedingStorage; | 63 final HashSet<FieldElement> _fieldsNeedingStorage; |
(...skipping 18 matching lines...) Expand all Loading... |
80 | 82 |
81 /// The name for the library's exports inside itself. | 83 /// The name for the library's exports inside itself. |
82 /// `exports` was chosen as the most similar to ES module patterns. | 84 /// `exports` was chosen as the most similar to ES module patterns. |
83 final _exportsVar = new JS.TemporaryId('exports'); | 85 final _exportsVar = new JS.TemporaryId('exports'); |
84 final _namedArgTemp = new JS.TemporaryId('opts'); | 86 final _namedArgTemp = new JS.TemporaryId('opts'); |
85 | 87 |
86 ConstFieldVisitor _constField; | 88 ConstFieldVisitor _constField; |
87 | 89 |
88 ModuleItemLoadOrder _loader; | 90 ModuleItemLoadOrder _loader; |
89 | 91 |
90 JSCodegenVisitor(this.options, this.rules, this.libraryInfo, | 92 JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, |
91 this._extensionMethods, this._fieldsNeedingStorage) { | 93 this._extensionMethods, this._fieldsNeedingStorage) |
| 94 : compiler = compiler, |
| 95 options = compiler.options, |
| 96 rules = compiler.rules { |
92 _loader = new ModuleItemLoadOrder(_emitModuleItem); | 97 _loader = new ModuleItemLoadOrder(_emitModuleItem); |
93 } | 98 } |
94 | 99 |
95 LibraryElement get currentLibrary => libraryInfo.library; | 100 LibraryElement get currentLibrary => libraryInfo.library; |
96 TypeProvider get types => rules.provider; | 101 TypeProvider get types => rules.provider; |
97 | 102 |
98 JS.Program emitLibrary(LibraryUnit library) { | 103 JS.Program emitLibrary(LibraryUnit library) { |
99 String jsDefaultValue = null; | 104 String jsDefaultValue = null; |
100 | 105 |
101 // Modify the AST to make coercions explicit. | 106 // Modify the AST to make coercions explicit. |
102 new CoercionReifier(library, rules, options).reify(); | 107 new CoercionReifier(library, compiler).reify(); |
103 | 108 |
104 var unit = library.library; | 109 var unit = library.library; |
105 if (unit.directives.isNotEmpty) { | 110 if (unit.directives.isNotEmpty) { |
106 var libraryDir = unit.directives.first; | 111 var libraryDir = unit.directives.first; |
107 if (libraryDir is LibraryDirective) { | 112 if (libraryDir is LibraryDirective) { |
108 var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation); | 113 var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation); |
109 jsDefaultValue = getConstantField(jsName, 'name', types.stringType); | 114 jsDefaultValue = getConstantField(jsName, 'name', types.stringType); |
110 } | 115 } |
111 } | 116 } |
112 if (jsDefaultValue == null) jsDefaultValue = '{}'; | 117 if (jsDefaultValue == null) jsDefaultValue = '{}'; |
(...skipping 2266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 JS.Identifier _libraryName(LibraryElement library) { | 2384 JS.Identifier _libraryName(LibraryElement library) { |
2380 if (library == currentLibrary) return _exportsVar; | 2385 if (library == currentLibrary) return _exportsVar; |
2381 return _imports.putIfAbsent( | 2386 return _imports.putIfAbsent( |
2382 library, () => new JS.TemporaryId(jsLibraryName(library))); | 2387 library, () => new JS.TemporaryId(jsLibraryName(library))); |
2383 } | 2388 } |
2384 | 2389 |
2385 DartType getStaticType(Expression e) => rules.getStaticType(e); | 2390 DartType getStaticType(Expression e) => rules.getStaticType(e); |
2386 } | 2391 } |
2387 | 2392 |
2388 class JSGenerator extends CodeGenerator { | 2393 class JSGenerator extends CodeGenerator { |
2389 final CompilerOptions options; | |
2390 | |
2391 /// For fast lookup of extension methods, we first check the name, then do a | 2394 /// For fast lookup of extension methods, we first check the name, then do a |
2392 /// (possibly expensive) subtype test to see if it matches one of the types | 2395 /// (possibly expensive) subtype test to see if it matches one of the types |
2393 /// that declares that method. | 2396 /// that declares that method. |
2394 final _extensionMethods = new HashMap<String, List<InterfaceType>>(); | 2397 final _extensionMethods = new HashMap<String, List<InterfaceType>>(); |
2395 | 2398 |
2396 JSGenerator(String outDir, Uri root, TypeRules rules, this.options) | 2399 JSGenerator(AbstractCompiler context) : super(context) { |
2397 : super(outDir, root, rules) { | |
2398 | 2400 |
2399 // TODO(jacobr): determine the the set of types with extension methods from | 2401 // TODO(jacobr): determine the the set of types with extension methods from |
2400 // the annotations rather than hard coding the list once the analyzer | 2402 // the annotations rather than hard coding the list once the analyzer |
2401 // supports summaries. | 2403 // supports summaries. |
2402 var extensionTypes = [types.listType, types.iterableType]; | 2404 var extensionTypes = [types.listType, types.iterableType]; |
2403 for (var type in extensionTypes) { | 2405 for (var type in extensionTypes) { |
2404 type = fillDynamicTypeArgs(type, rules.provider); | 2406 type = fillDynamicTypeArgs(type, rules.provider); |
2405 var e = type.element; | 2407 var e = type.element; |
2406 var names = new HashSet<String>() | 2408 var names = new HashSet<String>() |
2407 ..addAll(e.methods.map((m) => m.name)) | 2409 ..addAll(e.methods.map((m) => m.name)) |
2408 ..addAll(e.accessors.map((m) => m.name)); | 2410 ..addAll(e.accessors.map((m) => m.name)); |
2409 for (var name in names) { | 2411 for (var name in names) { |
2410 _extensionMethods.putIfAbsent(name, () => []).add(type); | 2412 _extensionMethods.putIfAbsent(name, () => []).add(type); |
2411 } | 2413 } |
2412 } | 2414 } |
2413 } | 2415 } |
2414 | 2416 |
2415 TypeProvider get types => rules.provider; | 2417 TypeProvider get types => rules.provider; |
2416 | 2418 |
2417 String generateLibrary(LibraryUnit unit, LibraryInfo info) { | 2419 String generateLibrary(LibraryUnit unit, LibraryInfo info) { |
2418 var fields = findFieldsNeedingStorage(unit); | 2420 var fields = findFieldsNeedingStorage(unit); |
2419 var codegen = | 2421 var codegen = |
2420 new JSCodegenVisitor(options, rules, info, _extensionMethods, fields); | 2422 new JSCodegenVisitor(compiler, info, _extensionMethods, fields); |
2421 var module = codegen.emitLibrary(unit); | 2423 var module = codegen.emitLibrary(unit); |
2422 var dir = path.join(outDir, jsOutputPath(info, root)); | 2424 var dir = path.join(outDir, jsOutputPath(info, root)); |
2423 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); | 2425 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); |
2424 } | 2426 } |
2425 } | 2427 } |
2426 | 2428 |
2427 /// Choose a canonical name from the library element. | 2429 /// Choose a canonical name from the library element. |
2428 /// This never uses the library's name (the identifier in the `library` | 2430 /// This never uses the library's name (the identifier in the `library` |
2429 /// declaration) as it doesn't have any meaningful rules enforced. | 2431 /// declaration) as it doesn't have any meaningful rules enforced. |
2430 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); | 2432 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2466 | 2468 |
2467 /// A special kind of element created by the compiler, signifying a temporary | 2469 /// A special kind of element created by the compiler, signifying a temporary |
2468 /// variable. These objects use instance equality, and should be shared | 2470 /// variable. These objects use instance equality, and should be shared |
2469 /// everywhere in the tree where they are treated as the same variable. | 2471 /// everywhere in the tree where they are treated as the same variable. |
2470 class TemporaryVariableElement extends LocalVariableElementImpl { | 2472 class TemporaryVariableElement extends LocalVariableElementImpl { |
2471 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2473 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
2472 | 2474 |
2473 int get hashCode => identityHashCode(this); | 2475 int get hashCode => identityHashCode(this); |
2474 bool operator ==(Object other) => identical(this, other); | 2476 bool operator ==(Object other) => identical(this, other); |
2475 } | 2477 } |
OLD | NEW |