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

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

Issue 1348453004: fix some errors in our SDK, mostly around numbers (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 3 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/checker/rules.dart ('k') | test/codegen/expect/methods.js » ('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, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
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;
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 return 'Symbol'; 304 return 'Symbol';
305 } 305 }
306 306
307 bool isPublic(String name) => !name.startsWith('_'); 307 bool isPublic(String name) => !name.startsWith('_');
308 308
309 @override 309 @override
310 visitAsExpression(AsExpression node) { 310 visitAsExpression(AsExpression node) {
311 var from = getStaticType(node.expression); 311 var from = getStaticType(node.expression);
312 var to = node.type.type; 312 var to = node.type.type;
313 313
314 var fromExpr = _visit(node.expression);
315
314 // Skip the cast if it's not needed. 316 // Skip the cast if it's not needed.
315 if (rules.isSubTypeOf(from, to)) return _visit(node.expression); 317 if (rules.isSubTypeOf(from, to)) return fromExpr;
316 318
317 // All Dart number types map to a JS double. 319 // All Dart number types map to a JS double.
318 if (rules.isNumType(from) && 320 if (rules.isNumberInJS(from) && rules.isNumberInJS(to)) {
319 (rules.isIntType(to) || rules.isDoubleType(to))) { 321 // Make sure to check when converting to int.
320 // TODO(jmesserly): a lot of these checks are meaningless, as people use 322 if (!rules.isIntType(from) && rules.isIntType(to)) {
321 // `num` to mean "any kind of number" rather than "could be null". 323 return js.call('dart.asInt(#)', [fromExpr]);
322 // The core libraries especially suffer from this problem, with many of 324 }
323 // the `num` methods returning `num`. 325
324 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) { 326 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) {
325 // Converting from a nullable number to a non-nullable number 327 // Converting from a nullable number to a non-nullable number
326 // only requires a null check. 328 // only requires a null check.
327 return js.call('dart.notNull(#)', _visit(node.expression)); 329 // TODO(jmesserly): a lot of these checks are meaningless, as people use
330 // `num` to mean "any kind of number" rather than "could be null".
331 // The core libraries especially suffer from this problem, with many of
332 // the `num` methods returning `num`.
333 return js.call('dart.notNull(#)', fromExpr);
328 } else { 334 } else {
329 // A no-op in JavaScript. 335 // A no-op in JavaScript.
330 return _visit(node.expression); 336 return fromExpr;
331 } 337 }
332 } 338 }
333 339
334 return _emitCast(node.expression, to); 340 return js.call('dart.as(#, #)', [fromExpr, _emitTypeName(to)]);
335 } 341 }
336 342
337 _emitCast(Expression node, DartType type) => js.call('dart.as(#)', [
338 [_visit(node), _emitTypeName(type)]
339 ]);
340
341 @override 343 @override
342 visitIsExpression(IsExpression node) { 344 visitIsExpression(IsExpression node) {
343 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 345 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
344 JS.Expression result; 346 JS.Expression result;
345 var type = node.type.type; 347 var type = node.type.type;
346 var lhs = _visit(node.expression); 348 var lhs = _visit(node.expression);
347 var typeofName = _jsTypeofName(type); 349 var typeofName = _jsTypeofName(type);
348 if (typeofName != null) { 350 if (typeofName != null) {
349 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]); 351 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
350 } else { 352 } else {
351 // Always go through a runtime helper, because implicit interfaces. 353 // Always go through a runtime helper, because implicit interfaces.
352 result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]); 354 result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]);
353 } 355 }
354 356
355 if (node.notOperator != null) { 357 if (node.notOperator != null) {
356 return js.call('!#', result); 358 return js.call('!#', result);
357 } 359 }
358 return result; 360 return result;
359 } 361 }
360 362
361 String _jsTypeofName(DartType t) { 363 String _jsTypeofName(DartType t) {
362 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number'; 364 if (rules.isNumberInJS(t)) return 'number';
363 if (rules.isStringType(t)) return 'string'; 365 if (rules.isStringType(t)) return 'string';
364 if (rules.isBoolType(t)) return 'boolean'; 366 if (rules.isBoolType(t)) return 'boolean';
365 return null; 367 return null;
366 } 368 }
367 369
368 @override 370 @override
369 visitFunctionTypeAlias(FunctionTypeAlias node) { 371 visitFunctionTypeAlias(FunctionTypeAlias node) {
370 var element = node.element; 372 var element = node.element;
371 var type = element.type; 373 var type = element.type;
372 var name = element.name; 374 var name = element.name;
(...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 element, type, name, node.argumentList, node.isConst); 2161 element, type, name, node.argumentList, node.isConst);
2160 } 2162 }
2161 2163
2162 /// True if this type is built-in to JS, and we use the values unwrapped. 2164 /// True if this type is built-in to JS, and we use the values unwrapped.
2163 /// For these types we generate a calling convention via static 2165 /// For these types we generate a calling convention via static
2164 /// "extension methods". This allows types to be extended without adding 2166 /// "extension methods". This allows types to be extended without adding
2165 /// extensions directly on the prototype. 2167 /// extensions directly on the prototype.
2166 bool _isJSBuiltinType(DartType t) => 2168 bool _isJSBuiltinType(DartType t) =>
2167 typeIsPrimitiveInJS(t) || rules.isStringType(t); 2169 typeIsPrimitiveInJS(t) || rules.isStringType(t);
2168 2170
2169 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) || 2171 bool typeIsPrimitiveInJS(DartType t) =>
2170 rules.isDoubleType(t) || 2172 rules.isNumberInJS(t) || rules.isBoolType(t);
2171 rules.isBoolType(t) ||
2172 rules.isNumType(t);
2173 2173
2174 bool typeIsNonNullablePrimitiveInJS(DartType t) => 2174 bool typeIsNonNullablePrimitiveInJS(DartType t) =>
2175 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t); 2175 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t);
2176 2176
2177 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => 2177 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
2178 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); 2178 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT);
2179 2179
2180 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); 2180 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t);
2181 2181
2182 bool _isNonNullableExpression(Expression expr) { 2182 bool _isNonNullableExpression(Expression expr) {
(...skipping 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after
3256 class JSGenerator extends CodeGenerator { 3256 class JSGenerator extends CodeGenerator {
3257 final _extensionTypes = new HashSet<ClassElement>(); 3257 final _extensionTypes = new HashSet<ClassElement>();
3258 3258
3259 JSGenerator(AbstractCompiler compiler) : super(compiler) { 3259 JSGenerator(AbstractCompiler compiler) : super(compiler) {
3260 // TODO(jacobr): determine the the set of types with extension methods from 3260 // TODO(jacobr): determine the the set of types with extension methods from
3261 // the annotations rather than hard coding the list once the analyzer 3261 // the annotations rather than hard coding the list once the analyzer
3262 // supports summaries. 3262 // supports summaries.
3263 var context = compiler.context; 3263 var context = compiler.context;
3264 var src = context.sourceFactory.forUri('dart:_interceptors'); 3264 var src = context.sourceFactory.forUri('dart:_interceptors');
3265 var interceptors = context.computeLibraryElement(src); 3265 var interceptors = context.computeLibraryElement(src);
3266 for (var t in ['JSArray', 'JSString', 'JSInt', 'JSDouble', 'JSBool']) { 3266 for (var t in ['JSArray', 'JSString', 'JSNumber', 'JSBool']) {
3267 _addExtensionType(interceptors.getType(t).type); 3267 _addExtensionType(interceptors.getType(t).type);
3268 } 3268 }
3269 // TODO(jmesserly): manually add `int` and `double`
3270 // Unfortunately our current analyzer rejects "implements int".
3271 // Fix was landed, so we can remove this hack once we're updated:
3272 // https://github.com/dart-lang/sdk/commit/d7cd11f86a02f55269fc8d9843e7758eb eeb81c8
3273 _addExtensionType(context.typeProvider.intType);
3274 _addExtensionType(context.typeProvider.doubleType);
3269 } 3275 }
3270 3276
3271 void _addExtensionType(InterfaceType t) { 3277 void _addExtensionType(InterfaceType t) {
3272 if (t.isObject || !_extensionTypes.add(t.element)) return; 3278 if (t.isObject || !_extensionTypes.add(t.element)) return;
3273 t = fillDynamicTypeArgs(t, rules.provider) as InterfaceType; 3279 t = fillDynamicTypeArgs(t, rules.provider) as InterfaceType;
3274 t.interfaces.forEach(_addExtensionType); 3280 t.interfaces.forEach(_addExtensionType);
3275 t.mixins.forEach(_addExtensionType); 3281 t.mixins.forEach(_addExtensionType);
3276 _addExtensionType(t.superclass); 3282 _addExtensionType(t.superclass);
3277 } 3283 }
3278 3284
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 3321
3316 /// A special kind of element created by the compiler, signifying a temporary 3322 /// A special kind of element created by the compiler, signifying a temporary
3317 /// variable. These objects use instance equality, and should be shared 3323 /// variable. These objects use instance equality, and should be shared
3318 /// everywhere in the tree where they are treated as the same variable. 3324 /// everywhere in the tree where they are treated as the same variable.
3319 class TemporaryVariableElement extends LocalVariableElementImpl { 3325 class TemporaryVariableElement extends LocalVariableElementImpl {
3320 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3326 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3321 3327
3322 int get hashCode => identityHashCode(this); 3328 int get hashCode => identityHashCode(this);
3323 bool operator ==(Object other) => identical(this, other); 3329 bool operator ==(Object other) => identical(this, other);
3324 } 3330 }
OLDNEW
« no previous file with comments | « lib/src/checker/rules.dart ('k') | test/codegen/expect/methods.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698