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

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

Issue 1680263002: Support for dart:typed_data (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Refine comment Created 4 years, 10 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
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 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/src/generated/ast.dart' hide ConstantEvaluator; 8 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
9 import 'package:analyzer/src/generated/constant.dart'; 9 import 'package:analyzer/src/generated/constant.dart';
10 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
11 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
11 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 12 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
12 import 'package:analyzer/src/generated/scanner.dart' 13 import 'package:analyzer/src/generated/scanner.dart'
13 show StringToken, Token, TokenType; 14 show StringToken, Token, TokenType;
14 import 'package:analyzer/src/generated/type_system.dart' 15 import 'package:analyzer/src/generated/type_system.dart'
15 show StrongTypeSystemImpl; 16 show StrongTypeSystemImpl;
16 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; 17 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder;
17 18
18 import 'ast_builder.dart' show AstBuilder; 19 import 'ast_builder.dart' show AstBuilder;
19 import 'reify_coercions.dart' show CoercionReifier, Tuple2; 20 import 'reify_coercions.dart' show CoercionReifier, Tuple2;
20 21
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 } else if (member is MethodDeclaration) { 422 } else if (member is MethodDeclaration) {
422 methods.add(member); 423 methods.add(member);
423 } 424 }
424 } 425 }
425 426
426 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), 427 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
427 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); 428 _classHeritage(classElem), _emitClassMethods(node, ctors, fields));
428 429
429 String jsPeerName; 430 String jsPeerName;
430 var jsPeer = findAnnotation(classElem, isJsPeerInterface); 431 var jsPeer = findAnnotation(classElem, isJsPeerInterface);
432 // Only look at "Native" annotations on registered extension types.
433 // E.g., we're current ignoring the ones in dart:html.
434 if (jsPeer == null && _extensionTypes.contains(classElem)) {
435 jsPeer = findAnnotation(classElem, isNativeAnnotation);
436 }
431 if (jsPeer != null) { 437 if (jsPeer != null) {
432 jsPeerName = 438 jsPeerName =
433 getConstantField(jsPeer, 'name', types.stringType)?.toStringValue(); 439 getConstantField(jsPeer, 'name', types.stringType)?.toStringValue();
440 if (jsPeerName.contains(',')) {
441 jsPeerName = jsPeerName.split(',')[0];
442 }
434 } 443 }
435 444
436 var body = _finishClassMembers(classElem, classExpr, ctors, fields, 445 var body = _finishClassMembers(classElem, classExpr, ctors, fields,
437 staticFields, methods, node.metadata, jsPeerName); 446 staticFields, methods, node.metadata, jsPeerName);
438 447
439 var result = _finishClassDef(type, body); 448 var result = _finishClassDef(type, body);
440 449
441 if (jsPeerName != null) { 450 if (jsPeerName != null) {
442 // This class isn't allowed to be lazy, because we need to set up 451 // This class isn't allowed to be lazy, because we need to set up
443 // the native JS type eagerly at this point. 452 // the native JS type eagerly at this point.
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 1276
1268 JS.Expression _defaultParamValue(FormalParameter param) { 1277 JS.Expression _defaultParamValue(FormalParameter param) {
1269 if (param is DefaultFormalParameter && param.defaultValue != null) { 1278 if (param is DefaultFormalParameter && param.defaultValue != null) {
1270 return _visit(param.defaultValue); 1279 return _visit(param.defaultValue);
1271 } else { 1280 } else {
1272 return new JS.LiteralNull(); 1281 return new JS.LiteralNull();
1273 } 1282 }
1274 } 1283 }
1275 1284
1276 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) { 1285 JS.Method _emitMethodDeclaration(DartType type, MethodDeclaration node) {
1277 if (node.isAbstract || _externalOrNative(node)) { 1286 if (node.isAbstract) {
1278 return null; 1287 return null;
1279 } 1288 }
1280 1289
1281 var params = _visit(node.parameters) as List<JS.Parameter>; 1290 var params = _visit(node.parameters) as List<JS.Parameter>;
1282 if (params == null) params = <JS.Parameter>[]; 1291 if (params == null) params = <JS.Parameter>[];
1283 1292
1284 JS.Fun fn = _emitFunctionBody(params, node.body); 1293 JS.Fun fn;
1294 if (_externalOrNative(node)) {
1295 if (node.isStatic) {
Jennifer Messerly 2016/02/10 00:20:30 Perhaps factor this out into _emitNativeFunctionBo
vsm 2016/02/11 22:36:06 Done.
1296 // TODO(vsm): Do we need to handle this case?
1297 return null;
1298 }
1299
1300 String name = node.name.name;
1301 var annotation = findAnnotation(node.element, isJsName);
1302 if (annotation != null) {
1303 name = getConstantField(annotation, 'name', types.stringType)
1304 ?.toStringValue();
1305 }
1306 if (node.isGetter) {
1307 fn = new JS.Fun(params, js.statement('{ return this.#; }', [name]));
1308 } else if (node.isSetter) {
1309 fn = new JS.Fun(
1310 params, js.statement('{ this.# = #; }', [name, params.last]));
1311 } else {
1312 fn = new JS.Fun(
1313 params, js.statement('{ return this.#(#); }', [name, params]));
1314 }
1315 } else {
1316 fn = _emitFunctionBody(params, node.body);
1317 }
1318
1285 if (node.operatorKeyword != null && 1319 if (node.operatorKeyword != null &&
1286 node.name.name == '[]=' && 1320 node.name.name == '[]=' &&
1287 params.isNotEmpty) { 1321 params.isNotEmpty) {
1288 // []= methods need to return the value. We could also address this at 1322 // []= methods need to return the value. We could also address this at
1289 // call sites, but it's cleaner to instead transform the operator method. 1323 // call sites, but it's cleaner to instead transform the operator method.
1290 var returnValue = new JS.Return(params.last); 1324 var returnValue = new JS.Return(params.last);
1291 var body = fn.body; 1325 var body = fn.body;
1292 if (JS.Return.foundIn(fn)) { 1326 if (JS.Return.foundIn(fn)) {
1293 // If a return is inside body, transform `(params) { body }` to 1327 // If a return is inside body, transform `(params) { body }` to
1294 // `(params) { (() => { body })(); return value; }`. 1328 // `(params) { (() => { body })(); return value; }`.
(...skipping 2253 matching lines...) Expand 10 before | Expand all | Expand 10 after
3548 } else if (type is InterfaceType && type.element == expectedType.element) { 3582 } else if (type is InterfaceType && type.element == expectedType.element) {
3549 return type.typeArguments[0]; 3583 return type.typeArguments[0];
3550 } else { 3584 } else {
3551 // TODO(leafp): The above only handles the case where the return type 3585 // TODO(leafp): The above only handles the case where the return type
3552 // is exactly Future/Stream/Iterable. Handle the subtype case. 3586 // is exactly Future/Stream/Iterable. Handle the subtype case.
3553 return DynamicTypeImpl.instance; 3587 return DynamicTypeImpl.instance;
3554 } 3588 }
3555 } 3589 }
3556 } 3590 }
3557 3591
3558 class JSGenerator extends CodeGenerator { 3592 class _ExtensionFinder extends GeneralizingElementVisitor {
3559 final _extensionTypes = new HashSet<ClassElement>(); 3593 final AnalysisContext _context;
3594 final HashSet<ClassElement> _extensionTypes;
3560 final TypeProvider _types; 3595 final TypeProvider _types;
3561 JSGenerator(AbstractCompiler compiler) 3596
3562 : _types = compiler.context.typeProvider, 3597 _ExtensionFinder(this._context, this._extensionTypes, this._types);
3563 super(compiler) { 3598
3564 // TODO(jacobr): determine the the set of types with extension methods from 3599 visitClassElement(ClassElement element) {
3565 // the annotations rather than hard coding the list once the analyzer 3600 if (findAnnotation(element, isJsPeerInterface) != null ||
3566 // supports summaries. 3601 findAnnotation(element, isNativeAnnotation) != null) {
3567 var context = compiler.context; 3602 _addExtensionType(element.type);
3568 var src = context.sourceFactory.forUri('dart:_interceptors');
3569 var interceptors = context.computeLibraryElement(src);
3570 for (var t in ['JSArray', 'JSString', 'JSNumber', 'JSBool']) {
3571 _addExtensionType(interceptors.getType(t).type);
3572 } 3603 }
3573 // TODO(jmesserly): manually add `int` and `double`
3574 // Unfortunately our current analyzer rejects "implements int".
3575 // Fix was landed, so we can remove this hack once we're updated:
3576 // https://github.com/dart-lang/sdk/commit/d7cd11f86a02f55269fc8d9843e7758eb eeb81c8
3577 _addExtensionType(_types.intType);
3578 _addExtensionType(_types.doubleType);
3579 } 3604 }
3580 3605
3581 void _addExtensionType(InterfaceType t) { 3606 void _addExtensionType(InterfaceType t) {
3582 if (t.isObject || !_extensionTypes.add(t.element)) return; 3607 if (t.isObject || !_extensionTypes.add(t.element)) return;
3583 t = fillDynamicTypeArgs(t, _types) as InterfaceType; 3608 t = fillDynamicTypeArgs(t, _types) as InterfaceType;
3584 t.interfaces.forEach(_addExtensionType); 3609 t.interfaces.forEach(_addExtensionType);
3585 t.mixins.forEach(_addExtensionType); 3610 t.mixins.forEach(_addExtensionType);
3586 _addExtensionType(t.superclass); 3611 _addExtensionType(t.superclass);
3587 } 3612 }
3588 3613
3614 void _addExtensionTypes(String libraryUri) {
3615 var sourceFactory = _context.sourceFactory.forUri(libraryUri);
3616 var library = _context.computeLibraryElement(sourceFactory);
3617 visitLibraryElement(library);
3618 }
3619 }
3620
3621 class JSGenerator extends CodeGenerator {
3622 final _extensionTypes = new HashSet<ClassElement>();
3623 final TypeProvider _types;
3624
3625 JSGenerator(AbstractCompiler compiler)
3626 : _types = compiler.context.typeProvider,
3627 super(compiler) {
3628 // TODO(vsm): Eventually, we want to make this extensible - i.e., find
3629 // annotations in user code as well. It would need to be summarized in
3630 // the element model - not searched this way on every compile.
3631 var finder = new _ExtensionFinder(context, _extensionTypes, _types);
3632 finder._addExtensionTypes('dart:_interceptors');
3633 finder._addExtensionTypes('dart:_native_typed_data');
3634
3635 // TODO(vsm): If we're analyzing against the main SDK, those
3636 // types are not explicitly annotated.
3637 finder._addExtensionType(_types.intType);
3638 finder._addExtensionType(_types.doubleType);
3639 finder._addExtensionType(_types.boolType);
3640 finder._addExtensionType(_types.stringType);
3641 }
3642
3589 String generateLibrary(LibraryUnit unit) { 3643 String generateLibrary(LibraryUnit unit) {
3590 // Clone the AST first, so we can mutate it. 3644 // Clone the AST first, so we can mutate it.
3591 unit = unit.clone(); 3645 unit = unit.clone();
3592 var library = unit.library.element.library; 3646 var library = unit.library.element.library;
3593 var fields = findFieldsNeedingStorage(unit, _extensionTypes); 3647 var fields = findFieldsNeedingStorage(unit, _extensionTypes);
3594 var rules = new StrongTypeSystemImpl(); 3648 var rules = new StrongTypeSystemImpl();
3595 var codegen = 3649 var codegen =
3596 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields); 3650 new JSCodegenVisitor(compiler, rules, library, _extensionTypes, fields);
3597 var module = codegen.emitLibrary(unit); 3651 var module = codegen.emitLibrary(unit);
3598 var out = compiler.getOutputPath(library.source.uri); 3652 var out = compiler.getOutputPath(library.source.uri);
(...skipping 25 matching lines...) Expand all
3624 3678
3625 /// A special kind of element created by the compiler, signifying a temporary 3679 /// A special kind of element created by the compiler, signifying a temporary
3626 /// variable. These objects use instance equality, and should be shared 3680 /// variable. These objects use instance equality, and should be shared
3627 /// everywhere in the tree where they are treated as the same variable. 3681 /// everywhere in the tree where they are treated as the same variable.
3628 class TemporaryVariableElement extends LocalVariableElementImpl { 3682 class TemporaryVariableElement extends LocalVariableElementImpl {
3629 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3683 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3630 3684
3631 int get hashCode => identityHashCode(this); 3685 int get hashCode => identityHashCode(this);
3632 bool operator ==(Object other) => identical(this, other); 3686 bool operator ==(Object other) => identical(this, other);
3633 } 3687 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698