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

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

Issue 1096583002: Reifier hookup (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Address comments Created 5 years, 8 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/src/codegen/dart_codegen.dart ('k') | lib/src/codegen/reify_coercions.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 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'
20 show CoercionReifier;
19 21
20 // TODO(jmesserly): import from its own package 22 // TODO(jmesserly): import from its own package
21 import 'package:dev_compiler/src/js/js_ast.dart' as JS; 23 import 'package:dev_compiler/src/js/js_ast.dart' as JS;
22 import 'package:dev_compiler/src/js/js_ast.dart' show js; 24 import 'package:dev_compiler/src/js/js_ast.dart' show js;
23 25
24 import 'package:dev_compiler/src/checker/rules.dart'; 26 import 'package:dev_compiler/src/checker/rules.dart';
25 import 'package:dev_compiler/src/info.dart'; 27 import 'package:dev_compiler/src/info.dart';
26 import 'package:dev_compiler/src/options.dart'; 28 import 'package:dev_compiler/src/options.dart';
27 import 'package:dev_compiler/src/utils.dart'; 29 import 'package:dev_compiler/src/utils.dart';
28 30
(...skipping 15 matching lines...) Expand all
44 const DCALL = 'dcall'; 46 const DCALL = 'dcall';
45 const DSEND = 'dsend'; 47 const DSEND = 'dsend';
46 48
47 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { 49 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
48 final LibraryInfo libraryInfo; 50 final LibraryInfo libraryInfo;
49 final TypeRules rules; 51 final TypeRules rules;
50 52
51 /// The global extension method table. 53 /// The global extension method table.
52 final HashMap<String, List<InterfaceType>> _extensionMethods; 54 final HashMap<String, List<InterfaceType>> _extensionMethods;
53 55
56 final CompilerOptions options;
54 /// The variable for the target of the current `..` cascade expression. 57 /// The variable for the target of the current `..` cascade expression.
55 SimpleIdentifier _cascadeTarget; 58 SimpleIdentifier _cascadeTarget;
56 /// The variable for the current catch clause 59 /// The variable for the current catch clause
57 SimpleIdentifier _catchParameter; 60 SimpleIdentifier _catchParameter;
58 61
59 ClassDeclaration currentClass; 62 ClassDeclaration currentClass;
60 ConstantEvaluator _constEvaluator; 63 ConstantEvaluator _constEvaluator;
61 64
62 final _exports = new Set<String>(); 65 final _exports = new Set<String>();
63 final _lazyFields = <VariableDeclaration>[]; 66 final _lazyFields = <VariableDeclaration>[];
(...skipping 14 matching lines...) Expand all
78 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or 81 /// Classes we have not emitted yet. Values can be [ClassDeclaration] or
79 /// [ClassTypeAlias]. 82 /// [ClassTypeAlias].
80 final _pendingClasses = new HashMap<Element, CompilationUnitMember>(); 83 final _pendingClasses = new HashMap<Element, CompilationUnitMember>();
81 84
82 /// Memoized results of [_lazyClass]. 85 /// Memoized results of [_lazyClass].
83 final _lazyClassMemo = new HashMap<Element, bool>(); 86 final _lazyClassMemo = new HashMap<Element, bool>();
84 87
85 /// Memoized results of [_inLibraryCycle]. 88 /// Memoized results of [_inLibraryCycle].
86 final _libraryCycleMemo = new HashMap<LibraryElement, bool>(); 89 final _libraryCycleMemo = new HashMap<LibraryElement, bool>();
87 90
88 JSCodegenVisitor(this.libraryInfo, this.rules, this._extensionMethods); 91 JSCodegenVisitor(
92 this.libraryInfo, this.rules, this.options, this._extensionMethods);
89 93
90 LibraryElement get currentLibrary => libraryInfo.library; 94 LibraryElement get currentLibrary => libraryInfo.library;
91 TypeProvider get types => rules.provider; 95 TypeProvider get types => rules.provider;
92 96
93 JS.Program emitLibrary(LibraryUnit library) { 97 JS.Program emitLibrary(LibraryUnit library) {
94 String jsDefaultValue = null; 98 String jsDefaultValue = null;
99
100 // Modify the AST to make coercions explicit.
101 new CoercionReifier(library, rules, options).reify();
102
95 var unit = library.library; 103 var unit = library.library;
96 if (unit.directives.isNotEmpty) { 104 if (unit.directives.isNotEmpty) {
97 var libraryDir = unit.directives.first; 105 var libraryDir = unit.directives.first;
98 if (libraryDir is LibraryDirective) { 106 if (libraryDir is LibraryDirective) {
99 var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation); 107 var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation);
100 jsDefaultValue = getConstantField(jsName, 'name', types.stringType); 108 jsDefaultValue = getConstantField(jsName, 'name', types.stringType);
101 } 109 }
102 } 110 }
103 if (jsDefaultValue == null) jsDefaultValue = '{}'; 111 if (jsDefaultValue == null) jsDefaultValue = '{}';
104 112
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 200
193 assert(_pendingPrivateNames.isEmpty); 201 assert(_pendingPrivateNames.isEmpty);
194 return _statement(body); 202 return _statement(body);
195 } 203 }
196 204
197 bool isPublic(String name) => !name.startsWith('_'); 205 bool isPublic(String name) => !name.startsWith('_');
198 206
199 /// Conversions that we don't handle end up here. 207 /// Conversions that we don't handle end up here.
200 @override 208 @override
201 visitConversion(Conversion node) { 209 visitConversion(Conversion node) {
202 var from = node.baseType; 210 throw 'Unlowered conversion ${node.runtimeType}: $node';
203 var to = node.convertedType; 211 }
212
213 @override
214 visitAsExpression(AsExpression node) {
215 var from = getStaticType(node.expression);
216 var to = node.type.type;
204 217
205 // All Dart number types map to a JS double. 218 // All Dart number types map to a JS double.
206 if (rules.isNumType(from) && 219 if (rules.isNumType(from) &&
207 (rules.isIntType(to) || rules.isDoubleType(to))) { 220 (rules.isIntType(to) || rules.isDoubleType(to))) {
208 // TODO(jmesserly): a lot of these checks are meaningless, as people use 221 // TODO(jmesserly): a lot of these checks are meaningless, as people use
209 // `num` to mean "any kind of number" rather than "could be null". 222 // `num` to mean "any kind of number" rather than "could be null".
210 // The core libraries especially suffer from this problem, with many of 223 // The core libraries especially suffer from this problem, with many of
211 // the `num` methods returning `num`. 224 // the `num` methods returning `num`.
212 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) { 225 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) {
213 // Converting from a nullable number to a non-nullable number 226 // Converting from a nullable number to a non-nullable number
214 // only requires a null check. 227 // only requires a null check.
215 return js.call('dart.notNull(#)', _visit(node.expression)); 228 return js.call('dart.notNull(#)', _visit(node.expression));
216 } else { 229 } else {
217 // A no-op in JavaScript. 230 // A no-op in JavaScript.
218 return _visit(node.expression); 231 return _visit(node.expression);
219 } 232 }
220 } 233 }
221 234
222 return _emitCast(node.expression, to); 235 return _emitCast(node.expression, to);
223 } 236 }
224 237
225 // TODO(vsm): This should go away in the future. I'm passing in the type
226 // as a String for now to avoid breaking any existing code. In most cases,
227 // we currently throw for function types.
228 @override
229 visitClosureWrapBase(ClosureWrapBase node) {
230 var expression = _visit(node.expression);
231 var typeString = js.escapedString(node.convertedType.toString());
232 return js.call('dart.closureWrap(#, #)', [expression, typeString]);
233 }
234
235 @override
236 visitAsExpression(AsExpression node) =>
237 _emitCast(node.expression, node.type.type);
238
239 _emitCast(Expression node, DartType type) => 238 _emitCast(Expression node, DartType type) =>
240 js.call('dart.as(#)', [[_visit(node), _emitTypeName(type)]]); 239 js.call('dart.as(#)', [[_visit(node), _emitTypeName(type)]]);
241 240
242 @override 241 @override
243 visitIsExpression(IsExpression node) { 242 visitIsExpression(IsExpression node) {
244 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 243 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
245 JS.Expression result; 244 JS.Expression result;
246 var type = node.type.type; 245 var type = node.type.type;
247 var lhs = _visit(node.expression); 246 var lhs = _visit(node.expression);
248 var typeofName = _jsTypeofName(type); 247 var typeofName = _jsTypeofName(type);
(...skipping 2038 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 } 2286 }
2288 2287
2289 DartType getStaticType(Expression e) => rules.getStaticType(e); 2288 DartType getStaticType(Expression e) => rules.getStaticType(e);
2290 2289
2291 static bool _needsImplicitThis(Element e) => 2290 static bool _needsImplicitThis(Element e) =>
2292 e is PropertyAccessorElement && !e.variable.isStatic || 2291 e is PropertyAccessorElement && !e.variable.isStatic ||
2293 e is ClassMemberElement && !e.isStatic && e is! ConstructorElement; 2292 e is ClassMemberElement && !e.isStatic && e is! ConstructorElement;
2294 } 2293 }
2295 2294
2296 class JSGenerator extends CodeGenerator { 2295 class JSGenerator extends CodeGenerator {
2297 final JSCodeOptions options; 2296 final CompilerOptions options;
2298 2297
2299 /// For fast lookup of extension methods, we first check the name, then do a 2298 /// For fast lookup of extension methods, we first check the name, then do a
2300 /// (possibly expensive) subtype test to see if it matches one of the types 2299 /// (possibly expensive) subtype test to see if it matches one of the types
2301 /// that declares that method. 2300 /// that declares that method.
2302 final _extensionMethods = new HashMap<String, List<InterfaceType>>(); 2301 final _extensionMethods = new HashMap<String, List<InterfaceType>>();
2303 2302
2304 JSGenerator(String outDir, Uri root, TypeRules rules, this.options) 2303 JSGenerator(String outDir, Uri root, TypeRules rules, this.options)
2305 : super(outDir, root, rules) { 2304 : super(outDir, root, rules) {
2306 2305
2307 // TODO(jacobr): determine the the set of types with extension methods from 2306 // TODO(jacobr): determine the the set of types with extension methods from
2308 // the annotations rather than hard coding the list once the analyzer 2307 // the annotations rather than hard coding the list once the analyzer
2309 // supports summaries. 2308 // supports summaries.
2310 var extensionTypes = [types.listType, types.iterableType]; 2309 var extensionTypes = [types.listType, types.iterableType];
2311 for (var type in extensionTypes) { 2310 for (var type in extensionTypes) {
2312 type = fillDynamicTypeArgs(type, rules.provider); 2311 type = fillDynamicTypeArgs(type, rules.provider);
2313 var e = type.element; 2312 var e = type.element;
2314 var names = new HashSet<String>() 2313 var names = new HashSet<String>()
2315 ..addAll(e.methods.map((m) => m.name)) 2314 ..addAll(e.methods.map((m) => m.name))
2316 ..addAll(e.accessors.map((m) => m.name)); 2315 ..addAll(e.accessors.map((m) => m.name));
2317 for (var name in names) { 2316 for (var name in names) {
2318 _extensionMethods.putIfAbsent(name, () => []).add(type); 2317 _extensionMethods.putIfAbsent(name, () => []).add(type);
2319 } 2318 }
2320 } 2319 }
2321 } 2320 }
2322 2321
2323 TypeProvider get types => rules.provider; 2322 TypeProvider get types => rules.provider;
2324 2323
2325 String generateLibrary(LibraryUnit unit, LibraryInfo info) { 2324 String generateLibrary(LibraryUnit unit, LibraryInfo info) {
2326 var codegen = new JSCodegenVisitor(info, rules, _extensionMethods); 2325 var codegen = new JSCodegenVisitor(info, rules, options, _extensionMethods);
2327 var module = codegen.emitLibrary(unit); 2326 var module = codegen.emitLibrary(unit);
2328 var dir = path.join(outDir, jsOutputPath(info, root)); 2327 var dir = path.join(outDir, jsOutputPath(info, root));
2329 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); 2328 return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps);
2330 } 2329 }
2331 } 2330 }
2332 2331
2333 /// Choose a canonical name from the library element. 2332 /// Choose a canonical name from the library element.
2334 /// This never uses the library's name (the identifier in the `library` 2333 /// This never uses the library's name (the identifier in the `library`
2335 /// declaration) as it doesn't have any meaningful rules enforced. 2334 /// declaration) as it doesn't have any meaningful rules enforced.
2336 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library); 2335 String jsLibraryName(LibraryElement library) => canonicalLibraryName(library);
(...skipping 22 matching lines...) Expand all
2359 return filepath; 2358 return filepath;
2360 } 2359 }
2361 2360
2362 // TODO(jmesserly): validate the library. See issue #135. 2361 // TODO(jmesserly): validate the library. See issue #135.
2363 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; 2362 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
2364 2363
2365 // TODO(jacobr): we would like to do something like the following 2364 // TODO(jacobr): we would like to do something like the following
2366 // but we don't have summary support yet. 2365 // but we don't have summary support yet.
2367 // bool _supportJsExtensionMethod(AnnotatedNode node) => 2366 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2368 // _getAnnotation(node, "SupportJsExtensionMethod") != null; 2367 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « lib/src/codegen/dart_codegen.dart ('k') | lib/src/codegen/reify_coercions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698