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

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

Issue 1266483003: format with dart_style 0.2.0-rc.3 (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 4 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/html_codegen.dart ('k') | lib/src/codegen/js_metalet.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, 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 for (var name in _exports) { 175 for (var name in _exports) {
176 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name])); 176 _moduleItems.add(js.statement('#.# = #;', [_exportsVar, name, name]));
177 } 177 }
178 178
179 var jsPath = compiler.getModuleName(currentLibrary.source.uri); 179 var jsPath = compiler.getModuleName(currentLibrary.source.uri);
180 180
181 // TODO(jmesserly): it would be great to run the renamer on the body, 181 // TODO(jmesserly): it would be great to run the renamer on the body,
182 // then figure out if we really need each of these parameters. 182 // then figure out if we really need each of these parameters.
183 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34 183 // See ES6 modules: https://github.com/dart-lang/dev_compiler/issues/34
184 var params = [_exportsVar, _runtimeLibVar]; 184 var params = [_exportsVar, _runtimeLibVar];
185 var processImport = (LibraryElement library, JS.TemporaryId temp, 185 var processImport =
186 List list) { 186 (LibraryElement library, JS.TemporaryId temp, List list) {
187 params.add(temp); 187 params.add(temp);
188 list.add(js.string(compiler.getModuleName(library.source.uri), "'")); 188 list.add(js.string(compiler.getModuleName(library.source.uri), "'"));
189 }; 189 };
190 190
191 var imports = <JS.Expression>[js.string('dart_runtime/dart')]; 191 var imports = <JS.Expression>[js.string('dart_runtime/dart')];
192 _imports.forEach((library, temp) { 192 _imports.forEach((library, temp) {
193 if (_loader.libraryIsLoaded(library)) { 193 if (_loader.libraryIsLoaded(library)) {
194 processImport(library, temp, imports); 194 processImport(library, temp, imports);
195 } 195 }
196 }); 196 });
197 197
198 var lazyImports = <JS.Expression>[]; 198 var lazyImports = <JS.Expression>[];
199 _imports.forEach((library, temp) { 199 _imports.forEach((library, temp) {
200 if (!_loader.libraryIsLoaded(library)) { 200 if (!_loader.libraryIsLoaded(library)) {
201 processImport(library, temp, lazyImports); 201 processImport(library, temp, lazyImports);
202 } 202 }
203 }); 203 });
204 204
205 var dartxImport = 205 var dartxImport =
206 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 206 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
207 207
208 var module = js.call("function(#) { 'use strict'; #; #; }", [ 208 var module = js.call("function(#) { 'use strict'; #; #; }",
209 params, 209 [params, dartxImport, _moduleItems]);
210 dartxImport,
211 _moduleItems
212 ]);
213 210
214 var program = <JS.Statement>[ 211 var program = <JS.Statement>[
215 js.statement("dart_library.library(#, #, #, #, #)", [ 212 js.statement("dart_library.library(#, #, #, #, #)", [
216 js.string(jsPath, "'"), 213 js.string(jsPath, "'"),
217 jsDefaultValue != null ? jsDefaultValue : new JS.LiteralNull(), 214 jsDefaultValue != null ? jsDefaultValue : new JS.LiteralNull(),
218 js.commentExpression( 215 js.commentExpression(
219 "Imports", new JS.ArrayInitializer(imports, multiline: true)), 216 "Imports", new JS.ArrayInitializer(imports, multiline: true)),
220 js.commentExpression("Lazy imports", 217 js.commentExpression("Lazy imports",
221 new JS.ArrayInitializer(lazyImports, multiline: true)), 218 new JS.ArrayInitializer(lazyImports, multiline: true)),
222 module 219 module
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 return js.call('dart.notNull(#)', _visit(node.expression)); 266 return js.call('dart.notNull(#)', _visit(node.expression));
270 } else { 267 } else {
271 // A no-op in JavaScript. 268 // A no-op in JavaScript.
272 return _visit(node.expression); 269 return _visit(node.expression);
273 } 270 }
274 } 271 }
275 272
276 return _emitCast(node.expression, to); 273 return _emitCast(node.expression, to);
277 } 274 }
278 275
279 _emitCast(Expression node, DartType type) => 276 _emitCast(Expression node, DartType type) => js.call('dart.as(#)', [
280 js.call('dart.as(#)', [[_visit(node), _emitTypeName(type)]]); 277 [_visit(node), _emitTypeName(type)]
278 ]);
281 279
282 @override 280 @override
283 visitIsExpression(IsExpression node) { 281 visitIsExpression(IsExpression node) {
284 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 282 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
285 JS.Expression result; 283 JS.Expression result;
286 var type = node.type.type; 284 var type = node.type.type;
287 var lhs = _visit(node.expression); 285 var lhs = _visit(node.expression);
288 var typeofName = _jsTypeofName(type); 286 var typeofName = _jsTypeofName(type);
289 if (typeofName != null) { 287 if (typeofName != null) {
290 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]); 288 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
(...skipping 14 matching lines...) Expand all
305 if (rules.isBoolType(t)) return 'boolean'; 303 if (rules.isBoolType(t)) return 'boolean';
306 return null; 304 return null;
307 } 305 }
308 306
309 @override 307 @override
310 visitFunctionTypeAlias(FunctionTypeAlias node) { 308 visitFunctionTypeAlias(FunctionTypeAlias node) {
311 var element = node.element; 309 var element = node.element;
312 var type = element.type; 310 var type = element.type;
313 var name = element.name; 311 var name = element.name;
314 312
315 var fnType = js.statement('let # = dart.typedef(#, () => #);', [ 313 var fnType = js.statement('let # = dart.typedef(#, () => #);',
316 name, 314 [name, js.string(name, "'"), _emitTypeName(type, lowerTypedef: true)]);
317 js.string(name, "'"),
318 _emitTypeName(type, lowerTypedef: true)
319 ]);
320 315
321 return _finishClassDef(type, fnType); 316 return _finishClassDef(type, fnType);
322 } 317 }
323 318
324 @override 319 @override
325 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type); 320 JS.Expression visitTypeName(TypeName node) => _emitTypeName(node.type);
326 321
327 @override 322 @override
328 JS.Statement visitClassTypeAlias(ClassTypeAlias node) { 323 JS.Statement visitClassTypeAlias(ClassTypeAlias node) {
329 var element = node.element; 324 var element = node.element;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 // the native JS type eagerly at this point. 396 // the native JS type eagerly at this point.
402 // If we wanted to support laziness, we could defer the hookup until 397 // If we wanted to support laziness, we could defer the hookup until
403 // the end of the Dart library cycle load. 398 // the end of the Dart library cycle load.
404 assert(_loader.isLoaded(classElem)); 399 assert(_loader.isLoaded(classElem));
405 400
406 // TODO(jmesserly): this copies the dynamic members. 401 // TODO(jmesserly): this copies the dynamic members.
407 // Probably fine for objects coming from JS, but not if we actually 402 // Probably fine for objects coming from JS, but not if we actually
408 // want to support construction of instances with generic types other 403 // want to support construction of instances with generic types other
409 // than dynamic. See issue #154 for Array and List<E> related bug. 404 // than dynamic. See issue #154 for Array and List<E> related bug.
410 var copyMembers = js.statement( 405 var copyMembers = js.statement(
411 'dart.registerExtension(dart.global.#, #);', [ 406 'dart.registerExtension(dart.global.#, #);',
412 _propertyName(jsPeerName), 407 [_propertyName(jsPeerName), classElem.name]);
413 classElem.name
414 ]);
415 return _statement([result, copyMembers]); 408 return _statement([result, copyMembers]);
416 } 409 }
417 return result; 410 return result;
418 } 411 }
419 412
420 @override 413 @override
421 JS.Statement visitEnumDeclaration(EnumDeclaration node) { 414 JS.Statement visitEnumDeclaration(EnumDeclaration node) {
422 var element = node.element; 415 var element = node.element;
423 var type = element.type; 416 var type = element.type;
424 var name = js.string(type.name); 417 var name = js.string(type.name);
(...skipping 18 matching lines...) Expand all
443 var toStringF = new JS.Method(js.string('toString'), 436 var toStringF = new JS.Method(js.string('toString'),
444 js.call('function() { return #[this.index]; }', nameMap) as JS.Fun); 437 js.call('function() { return #[this.index]; }', nameMap) as JS.Fun);
445 438
446 // Create enum class 439 // Create enum class
447 var classExpr = new JS.ClassExpression( 440 var classExpr = new JS.ClassExpression(
448 id, _classHeritage(element), [constructor, toStringF]); 441 id, _classHeritage(element), [constructor, toStringF]);
449 var result = <JS.Statement>[js.statement('#', classExpr)]; 442 var result = <JS.Statement>[js.statement('#', classExpr)];
450 443
451 // Create static fields for each enum value 444 // Create static fields for each enum value
452 for (var i = 0; i < fields.length; ++i) { 445 for (var i = 0; i < fields.length; ++i) {
453 result.add(js.statement('#.# = dart.const(new #(#));', [ 446 result.add(js.statement('#.# = dart.const(new #(#));',
454 id, 447 [id, fields[i].name, id, js.number(i)]));
455 fields[i].name,
456 id,
457 js.number(i)
458 ]));
459 } 448 }
460 449
461 // Create static values list 450 // Create static values list
462 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( 451 var values = new JS.ArrayInitializer(new List<JS.Expression>.from(
463 fields.map((f) => js.call('#.#', [id, f.name])))); 452 fields.map((f) => js.call('#.#', [id, f.name]))));
464 result.add(js.statement('#.values = dart.const(dart.list(#, #));', [ 453 result.add(js.statement('#.values = dart.const(dart.list(#, #));',
465 id, 454 [id, values, _emitTypeName(type)]));
466 values,
467 _emitTypeName(type)
468 ]));
469 455
470 return _statement(result); 456 return _statement(result);
471 } 457 }
472 458
473 /// Given a class element and body, complete the class declaration. 459 /// Given a class element and body, complete the class declaration.
474 /// This handles generic type parameters, laziness (in library-cycle cases), 460 /// This handles generic type parameters, laziness (in library-cycle cases),
475 /// and ensuring dependencies are loaded first. 461 /// and ensuring dependencies are loaded first.
476 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { 462 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) {
477 var name = type.name; 463 var name = type.name;
478 var genericName = '$name\$'; 464 var genericName = '$name\$';
479 465
480 JS.Statement genericDef = null; 466 JS.Statement genericDef = null;
481 if (type.typeParameters.isNotEmpty) { 467 if (type.typeParameters.isNotEmpty) {
482 genericDef = _emitGenericClassDef(type, body); 468 genericDef = _emitGenericClassDef(type, body);
483 } 469 }
484 470
485 // The base class and all mixins must be declared before this class. 471 // The base class and all mixins must be declared before this class.
486 if (!_loader.isLoaded(type.element)) { 472 if (!_loader.isLoaded(type.element)) {
487 // TODO(jmesserly): the lazy class def is a simple solution for now. 473 // TODO(jmesserly): the lazy class def is a simple solution for now.
488 // We may want to consider other options in the future. 474 // We may want to consider other options in the future.
489 475
490 if (genericDef != null) { 476 if (genericDef != null) {
491 return js.statement( 477 return js.statement(
492 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }', [ 478 '{ #; dart.defineLazyClassGeneric(#, #, { get: # }); }',
493 genericDef, 479 [genericDef, _exportsVar, _propertyName(name), genericName]);
494 _exportsVar,
495 _propertyName(name),
496 genericName
497 ]);
498 } 480 }
499 481
500 return js.statement( 482 return js.statement(
501 'dart.defineLazyClass(#, { get #() { #; return #; } });', [ 483 'dart.defineLazyClass(#, { get #() { #; return #; } });',
502 _exportsVar, 484 [_exportsVar, _propertyName(name), body, name]);
503 _propertyName(name),
504 body,
505 name
506 ]);
507 } 485 }
508 486
509 if (isPublic(name)) _addExport(name); 487 if (isPublic(name)) _addExport(name);
510 488
511 if (genericDef != null) { 489 if (genericDef != null) {
512 var dynType = fillDynamicTypeArgs(type, types); 490 var dynType = fillDynamicTypeArgs(type, types);
513 var genericInst = _emitTypeName(dynType, lowerGeneric: true); 491 var genericInst = _emitTypeName(dynType, lowerGeneric: true);
514 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 492 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]);
515 } 493 }
516 return body; 494 return body;
517 } 495 }
518 496
519 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { 497 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
520 var name = type.name; 498 var name = type.name;
521 var genericName = '$name\$'; 499 var genericName = '$name\$';
522 var typeParams = type.typeParameters.map((p) => p.name); 500 var typeParams = type.typeParameters.map((p) => p.name);
523 if (isPublic(name)) _exports.add(genericName); 501 if (isPublic(name)) _exports.add(genericName);
524 return js.statement('let # = dart.generic(function(#) { #; return #; });', [ 502 return js.statement('let # = dart.generic(function(#) { #; return #; });',
525 genericName, 503 [genericName, typeParams, body, name]);
526 typeParams,
527 body,
528 name
529 ]);
530 } 504 }
531 505
532 JS.Expression _classHeritage(ClassElement element) { 506 JS.Expression _classHeritage(ClassElement element) {
533 var type = element.type; 507 var type = element.type;
534 if (type.isObject) return null; 508 if (type.isObject) return null;
535 509
536 // Assume we can load eagerly, until proven otherwise. 510 // Assume we can load eagerly, until proven otherwise.
537 _loader.startTopLevel(element); 511 _loader.startTopLevel(element);
538 512
539 JS.Expression heritage = _emitTypeName(type.superclass); 513 JS.Expression heritage = _emitTypeName(type.superclass);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 // If a parent had an `iterator` (concrete or abstract) or implements 580 // If a parent had an `iterator` (concrete or abstract) or implements
607 // Iterable, we know the adapter is already there, so we can skip it as a 581 // Iterable, we know the adapter is already there, so we can skip it as a
608 // simple code size optimization. 582 // simple code size optimization.
609 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library); 583 var parent = t.lookUpGetterInSuperclass('iterator', t.element.library);
610 if (parent != null) return null; 584 if (parent != null) return null;
611 var parentType = findSupertype(t, _implementsIterable); 585 var parentType = findSupertype(t, _implementsIterable);
612 if (parentType != null) return null; 586 if (parentType != null) return null;
613 587
614 // Otherwise, emit the adapter method, which wraps the Dart iterator in 588 // Otherwise, emit the adapter method, which wraps the Dart iterator in
615 // an ES6 iterator. 589 // an ES6 iterator.
616 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( 590 return new JS.Method(
617 'function() { return new dart.JsIterator(this.#); }', 591 js.call('$_SYMBOL.iterator'),
618 [_emitMemberName('iterator', type: t)]) as JS.Fun); 592 js.call('function() { return new dart.JsIterator(this.#); }',
593 [_emitMemberName('iterator', type: t)]) as JS.Fun);
619 } 594 }
620 595
621 JS.Expression _instantiateAnnotation(Annotation node) { 596 JS.Expression _instantiateAnnotation(Annotation node) {
622 var element = node.element; 597 var element = node.element;
623 if (element is ConstructorElement) { 598 if (element is ConstructorElement) {
624 return _emitInstanceCreationExpression(element, element.returnType, 599 return _emitInstanceCreationExpression(element, element.returnType,
625 node.constructorName, node.arguments, true); 600 node.constructorName, node.arguments, true);
626 } else { 601 } else {
627 return _visit(node.name); 602 return _visit(node.name);
628 } 603 }
629 } 604 }
630 605
631 /// Emit class members that need to come after the class declaration, such 606 /// Emit class members that need to come after the class declaration, such
632 /// as static fields. See [_emitClassMethods] for things that are emitted 607 /// as static fields. See [_emitClassMethods] for things that are emitted
633 /// inside the ES6 `class { ... }` node. 608 /// inside the ES6 `class { ... }` node.
634 JS.Statement _finishClassMembers(ClassElement classElem, 609 JS.Statement _finishClassMembers(
635 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, 610 ClassElement classElem,
636 List<FieldDeclaration> fields, List<MethodDeclaration> methods, 611 JS.ClassExpression cls,
637 List<Annotation> metadata, String jsPeerName) { 612 List<ConstructorDeclaration> ctors,
613 List<FieldDeclaration> fields,
614 List<MethodDeclaration> methods,
615 List<Annotation> metadata,
616 String jsPeerName) {
638 var name = classElem.name; 617 var name = classElem.name;
639 var body = <JS.Statement>[]; 618 var body = <JS.Statement>[];
640 619
641 if (_extensionTypes.contains(classElem)) { 620 if (_extensionTypes.contains(classElem)) {
642 var dartxNames = <JS.Expression>[]; 621 var dartxNames = <JS.Expression>[];
643 for (var m in methods) { 622 for (var m in methods) {
644 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 623 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
645 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); 624 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
646 } 625 }
647 } 626 }
648 if (dartxNames.isNotEmpty) { 627 if (dartxNames.isNotEmpty) {
649 body.add(js.statement('dart.defineExtensionNames(#)', 628 body.add(js.statement('dart.defineExtensionNames(#)',
650 [new JS.ArrayInitializer(dartxNames, multiline: true)])); 629 [new JS.ArrayInitializer(dartxNames, multiline: true)]));
651 } 630 }
652 } 631 }
653 632
654 body.add(new JS.ClassDeclaration(cls)); 633 body.add(new JS.ClassDeclaration(cls));
655 634
656 // TODO(jmesserly): we should really just extend native Array. 635 // TODO(jmesserly): we should really just extend native Array.
657 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { 636 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) {
658 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [ 637 body.add(js.statement('dart.setBaseClass(#, dart.global.#);',
659 classElem.name, 638 [classElem.name, _propertyName(jsPeerName)]));
660 _propertyName(jsPeerName)
661 ]));
662 } 639 }
663 640
664 // Interfaces 641 // Interfaces
665 if (classElem.interfaces.isNotEmpty) { 642 if (classElem.interfaces.isNotEmpty) {
666 body.add(js.statement('#[dart.implements] = () => #;', [ 643 body.add(js.statement('#[dart.implements] = () => #;', [
667 name, 644 name,
668 new JS.ArrayInitializer(new List<JS.Expression>.from( 645 new JS.ArrayInitializer(new List<JS.Expression>.from(
669 classElem.interfaces.map(_emitTypeName))) 646 classElem.interfaces.map(_emitTypeName)))
670 ])); 647 ]));
671 } 648 }
672 649
673 // Named constructors 650 // Named constructors
674 for (ConstructorDeclaration member in ctors) { 651 for (ConstructorDeclaration member in ctors) {
675 if (member.name != null && member.factoryKeyword == null) { 652 if (member.name != null && member.factoryKeyword == null) {
676 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ 653 body.add(js.statement('dart.defineNamedConstructor(#, #);',
677 name, 654 [name, _emitMemberName(member.name.name, isStatic: true)]));
678 _emitMemberName(member.name.name, isStatic: true)
679 ]));
680 } 655 }
681 } 656 }
682 657
683 // Instance fields, if they override getter/setter pairs 658 // Instance fields, if they override getter/setter pairs
684 for (FieldDeclaration member in fields) { 659 for (FieldDeclaration member in fields) {
685 for (VariableDeclaration fieldDecl in member.fields.variables) { 660 for (VariableDeclaration fieldDecl in member.fields.variables) {
686 var field = fieldDecl.element as FieldElement; 661 var field = fieldDecl.element as FieldElement;
687 if (_fieldsNeedingStorage.contains(field)) { 662 if (_fieldsNeedingStorage.contains(field)) {
688 body.add(_overrideField(field)); 663 body.add(_overrideField(field));
689 } 664 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 _collectExtensions(m, types); 787 _collectExtensions(m, types);
813 } 788 }
814 for (var i in type.interfaces) { 789 for (var i in type.interfaces) {
815 _collectExtensions(i, types); 790 _collectExtensions(i, types);
816 } 791 }
817 _collectExtensions(type.superclass, types); 792 _collectExtensions(type.superclass, types);
818 } 793 }
819 794
820 JS.Statement _overrideField(FieldElement e) { 795 JS.Statement _overrideField(FieldElement e) {
821 var cls = e.enclosingElement; 796 var cls = e.enclosingElement;
822 return js.statement('dart.virtualField(#, #)', [ 797 return js.statement('dart.virtualField(#, #)',
823 cls.name, 798 [cls.name, _emitMemberName(e.name, type: cls.type)]);
824 _emitMemberName(e.name, type: cls.type)
825 ]);
826 } 799 }
827 800
828 /// Generates the implicit default constructor for class C of the form 801 /// Generates the implicit default constructor for class C of the form
829 /// `C() : super() {}`. 802 /// `C() : super() {}`.
830 JS.Method _emitImplicitConstructor( 803 JS.Method _emitImplicitConstructor(
831 ClassDeclaration node, List<FieldDeclaration> fields) { 804 ClassDeclaration node, List<FieldDeclaration> fields) {
832 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); 805 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty);
833 806
834 // If we don't have a method body, skip this. 807 // If we don't have a method body, skip this.
835 var superCall = _superConstructorCall(node.element); 808 var superCall = _superConstructorCall(node.element);
836 if (fields.isEmpty && superCall == null) return null; 809 if (fields.isEmpty && superCall == null) return null;
837 810
838 dynamic body = _initializeFields(node, fields); 811 dynamic body = _initializeFields(node, fields);
839 if (superCall != null) body = [[body, superCall]]; 812 if (superCall != null) body = [
813 [body, superCall]
814 ];
840 var name = _constructorName(node.element.unnamedConstructor); 815 var name = _constructorName(node.element.unnamedConstructor);
841 return new JS.Method(name, js.call('function() { #; }', body) as JS.Fun); 816 return new JS.Method(name, js.call('function() { #; }', body) as JS.Fun);
842 } 817 }
843 818
844 JS.Method _emitConstructor(ConstructorDeclaration node, InterfaceType type, 819 JS.Method _emitConstructor(ConstructorDeclaration node, InterfaceType type,
845 List<FieldDeclaration> fields, bool isObject) { 820 List<FieldDeclaration> fields, bool isObject) {
846 if (_externalOrNative(node)) return null; 821 if (_externalOrNative(node)) return null;
847 822
848 var name = _constructorName(node.element); 823 var name = _constructorName(node.element);
849 824
850 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz; 825 // Wacky factory redirecting constructors: factory Foo.q(x, y) = Bar.baz;
851 var redirect = node.redirectedConstructor; 826 var redirect = node.redirectedConstructor;
852 if (redirect != null) { 827 if (redirect != null) {
853 var newKeyword = redirect.staticElement.isFactory ? '' : 'new'; 828 var newKeyword = redirect.staticElement.isFactory ? '' : 'new';
854 // Pass along all arguments verbatim, and let the callee handle them. 829 // Pass along all arguments verbatim, and let the callee handle them.
855 // TODO(jmesserly): we'll need something different once we have 830 // TODO(jmesserly): we'll need something different once we have
856 // rest/spread support, but this should work for now. 831 // rest/spread support, but this should work for now.
857 var params = _visit(node.parameters); 832 var params = _visit(node.parameters);
858 var fun = js.call('function(#) { return $newKeyword #(#); }', [ 833 var fun = js.call('function(#) { return $newKeyword #(#); }',
859 params, 834 [params, _visit(redirect), params,]) as JS.Fun;
860 _visit(redirect),
861 params,
862 ]) as JS.Fun;
863 return new JS.Method(name, fun, isStatic: true)..sourceInformation = node; 835 return new JS.Method(name, fun, isStatic: true)..sourceInformation = node;
864 } 836 }
865 837
866 // Factory constructors are essentially static methods. 838 // Factory constructors are essentially static methods.
867 if (node.factoryKeyword != null) { 839 if (node.factoryKeyword != null) {
868 var body = <JS.Statement>[]; 840 var body = <JS.Statement>[];
869 var init = _emitArgumentInitializers(node, constructor: true); 841 var init = _emitArgumentInitializers(node, constructor: true);
870 if (init != null) body.add(init); 842 if (init != null) body.add(init);
871 body.add(_visit(node.body)); 843 body.add(_visit(node.body));
872 var fun = new JS.Fun( 844 var fun = new JS.Fun(
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 // available for use by top-level constant initializers. 908 // available for use by top-level constant initializers.
937 ClassDeclaration cls = node.parent; 909 ClassDeclaration cls = node.parent;
938 if (node.constKeyword != null) _loader.startTopLevel(cls.element); 910 if (node.constKeyword != null) _loader.startTopLevel(cls.element);
939 var init = _emitArgumentInitializers(node, constructor: true); 911 var init = _emitArgumentInitializers(node, constructor: true);
940 if (node.constKeyword != null) _loader.finishTopLevel(cls.element); 912 if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
941 if (init != null) body.add(init); 913 if (init != null) body.add(init);
942 914
943 // Redirecting constructors: these are not allowed to have initializers, 915 // Redirecting constructors: these are not allowed to have initializers,
944 // and the redirecting ctor invocation runs before field initializers. 916 // and the redirecting ctor invocation runs before field initializers.
945 var redirectCall = node.initializers.firstWhere( 917 var redirectCall = node.initializers.firstWhere(
946 (i) => i is RedirectingConstructorInvocation, orElse: () => null); 918 (i) => i is RedirectingConstructorInvocation,
919 orElse: () => null);
947 920
948 if (redirectCall != null) { 921 if (redirectCall != null) {
949 body.add(_visit(redirectCall)); 922 body.add(_visit(redirectCall));
950 return new JS.Block(body); 923 return new JS.Block(body);
951 } 924 }
952 925
953 // Generate field initializers. 926 // Generate field initializers.
954 // These are expanded into each non-redirecting constructor. 927 // These are expanded into each non-redirecting constructor.
955 // In the future we may want to create an initializer function if we have 928 // In the future we may want to create an initializer function if we have
956 // multiple constructors, but it needs to be balanced against readability. 929 // multiple constructors, but it needs to be balanced against readability.
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 body.add(js.statement('let # = # && # in # ? #.# : #;', [ 1096 body.add(js.statement('let # = # && # in # ? #.# : #;', [
1124 jsParam, 1097 jsParam,
1125 _namedArgTemp, 1098 _namedArgTemp,
1126 paramName, 1099 paramName,
1127 _namedArgTemp, 1100 _namedArgTemp,
1128 _namedArgTemp, 1101 _namedArgTemp,
1129 paramName, 1102 paramName,
1130 _defaultParamValue(param), 1103 _defaultParamValue(param),
1131 ])); 1104 ]));
1132 } else if (param.kind == ParameterKind.POSITIONAL) { 1105 } else if (param.kind == ParameterKind.POSITIONAL) {
1133 body.add(js.statement('if (# === void 0) # = #;', [ 1106 body.add(js.statement('if (# === void 0) # = #;',
1134 jsParam, 1107 [jsParam, jsParam, _defaultParamValue(param)]));
1135 jsParam,
1136 _defaultParamValue(param)
1137 ]));
1138 } 1108 }
1139 1109
1140 // TODO(jmesserly): various problems here, see: 1110 // TODO(jmesserly): various problems here, see:
1141 // https://github.com/dart-lang/dev_compiler/issues/161 1111 // https://github.com/dart-lang/dev_compiler/issues/161
1142 var paramType = param.element.type; 1112 var paramType = param.element.type;
1143 if (!constructor && _hasTypeParameter(paramType)) { 1113 if (!constructor && _hasTypeParameter(paramType)) {
1144 body.add(js.statement( 1114 body.add(js.statement(
1145 'dart.as(#, #);', [jsParam, _emitTypeName(paramType)])); 1115 'dart.as(#, #);', [jsParam, _emitTypeName(paramType)]));
1146 } 1116 }
1147 } 1117 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 return _emitFunctionTagged(clos, type, 1246 return _emitFunctionTagged(clos, type,
1277 topLevel: _executesAtTopLevel(node)); 1247 topLevel: _executesAtTopLevel(node));
1278 } 1248 }
1279 return clos; 1249 return clos;
1280 } 1250 }
1281 } 1251 }
1282 1252
1283 JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body) { 1253 JS.Fun _emitFunctionBody(List<JS.Parameter> params, FunctionBody body) {
1284 // sync*, async, async* 1254 // sync*, async, async*
1285 if (body.isAsynchronous || body.isGenerator) { 1255 if (body.isAsynchronous || body.isGenerator) {
1286 return new JS.Fun(params, js.statement( 1256 return new JS.Fun(
1287 '{ return #; }', [_emitGeneratorFunctionBody(params, body)])); 1257 params,
1258 js.statement(
1259 '{ return #; }', [_emitGeneratorFunctionBody(params, body)]));
1288 } 1260 }
1289 // normal function (sync) 1261 // normal function (sync)
1290 return new JS.Fun(params, _visit(body)); 1262 return new JS.Fun(params, _visit(body));
1291 } 1263 }
1292 1264
1293 JS.Expression _emitGeneratorFunctionBody( 1265 JS.Expression _emitGeneratorFunctionBody(
1294 List<JS.Parameter> params, FunctionBody body) { 1266 List<JS.Parameter> params, FunctionBody body) {
1295 var kind = body.isSynchronous ? 'sync' : 'async'; 1267 var kind = body.isSynchronous ? 'sync' : 'async';
1296 if (body.isGenerator) kind += 'Star'; 1268 if (body.isGenerator) kind += 'Star';
1297 1269
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 _asyncStarController = null; 1307 _asyncStarController = null;
1336 jsParams = params; 1308 jsParams = params;
1337 } 1309 }
1338 JS.Expression gen = new JS.Fun(jsParams, _visit(body), isGenerator: true); 1310 JS.Expression gen = new JS.Fun(jsParams, _visit(body), isGenerator: true);
1339 if (JS.This.foundIn(gen)) { 1311 if (JS.This.foundIn(gen)) {
1340 gen = js.call('#.bind(this)', gen); 1312 gen = js.call('#.bind(this)', gen);
1341 } 1313 }
1342 _asyncStarController = savedController; 1314 _asyncStarController = savedController;
1343 1315
1344 var T = _emitTypeName(rules.getExpectedReturnType(body)); 1316 var T = _emitTypeName(rules.getExpectedReturnType(body));
1345 return js.call('dart.#(#)', [kind, [gen, T]..addAll(params)]); 1317 return js.call('dart.#(#)', [
1318 kind,
1319 [gen, T]..addAll(params)
1320 ]);
1346 } 1321 }
1347 1322
1348 @override 1323 @override
1349 JS.Statement visitFunctionDeclarationStatement( 1324 JS.Statement visitFunctionDeclarationStatement(
1350 FunctionDeclarationStatement node) { 1325 FunctionDeclarationStatement node) {
1351 var func = node.functionDeclaration; 1326 var func = node.functionDeclaration;
1352 if (func.isGetter || func.isSetter) { 1327 if (func.isGetter || func.isSetter) {
1353 return js.comment('Unimplemented function get/set statement: $node'); 1328 return js.comment('Unimplemented function get/set statement: $node');
1354 } 1329 }
1355 1330
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 } 1466 }
1492 1467
1493 /// Emits a Dart [type] into code. 1468 /// Emits a Dart [type] into code.
1494 /// 1469 ///
1495 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a 1470 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a
1496 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form 1471 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form
1497 /// will be used instead of `List`. These flags are used when generating 1472 /// will be used instead of `List`. These flags are used when generating
1498 /// the definitions for typedefs and generic types, respectively. 1473 /// the definitions for typedefs and generic types, respectively.
1499 JS.Expression _emitTypeName(DartType type, 1474 JS.Expression _emitTypeName(DartType type,
1500 {bool lowerTypedef: false, bool lowerGeneric: false}) { 1475 {bool lowerTypedef: false, bool lowerGeneric: false}) {
1501
1502 // The void and dynamic types are not defined in core. 1476 // The void and dynamic types are not defined in core.
1503 if (type.isVoid) { 1477 if (type.isVoid) {
1504 return js.call('dart.void'); 1478 return js.call('dart.void');
1505 } else if (type.isDynamic) { 1479 } else if (type.isDynamic) {
1506 return js.call('dart.dynamic'); 1480 return js.call('dart.dynamic');
1507 } else if (type.isBottom) { 1481 } else if (type.isBottom) {
1508 return js.call('dart.bottom'); 1482 return js.call('dart.bottom');
1509 } 1483 }
1510 1484
1511 _loader.declareBeforeUse(type.element); 1485 _loader.declareBeforeUse(type.element);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 if (DynamicInvoke.get(target)) { 1638 if (DynamicInvoke.get(target)) {
1665 code = 'dart.$DSEND(#, #, #)'; 1639 code = 'dart.$DSEND(#, #, #)';
1666 } else if (DynamicInvoke.get(node.methodName)) { 1640 } else if (DynamicInvoke.get(node.methodName)) {
1667 // This is a dynamic call to a statically know target. For example: 1641 // This is a dynamic call to a statically know target. For example:
1668 // class Foo { Function bar; } 1642 // class Foo { Function bar; }
1669 // new Foo().bar(); // dynamic call 1643 // new Foo().bar(); // dynamic call
1670 code = 'dart.$DCALL(#.#, #)'; 1644 code = 'dart.$DCALL(#.#, #)';
1671 } else if (_requiresStaticDispatch(target, name)) { 1645 } else if (_requiresStaticDispatch(target, name)) {
1672 assert(rules.objectMembers[name] is FunctionType); 1646 assert(rules.objectMembers[name] is FunctionType);
1673 // Object methods require a helper for null checks. 1647 // Object methods require a helper for null checks.
1674 return js.call('dart.#(#, #)', [ 1648 return js.call('dart.#(#, #)',
1675 memberName, 1649 [memberName, _visit(target), _visit(node.argumentList)]);
1676 _visit(target),
1677 _visit(node.argumentList)
1678 ]);
1679 } else { 1650 } else {
1680 code = '#.#(#)'; 1651 code = '#.#(#)';
1681 } 1652 }
1682 1653
1683 return js.call( 1654 return js.call(
1684 code, [_visit(target), memberName, _visit(node.argumentList)]); 1655 code, [_visit(target), memberName, _visit(node.argumentList)]);
1685 } 1656 }
1686 1657
1687 /// Emits code for the `JS(...)` builtin. 1658 /// Emits code for the `JS(...)` builtin.
1688 _emitForeignJS(MethodInvocation node) { 1659 _emitForeignJS(MethodInvocation node) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1779 // becomes: 1750 // becomes:
1780 // 1751 //
1781 // if (stream.add(e)) return; 1752 // if (stream.add(e)) return;
1782 // yield; 1753 // yield;
1783 // 1754 //
1784 // `yield* e` becomes: 1755 // `yield* e` becomes:
1785 // 1756 //
1786 // if (stream.addStream(e)) return; 1757 // if (stream.addStream(e)) return;
1787 // yield; 1758 // yield;
1788 var helperName = star ? 'addStream' : 'add'; 1759 var helperName = star ? 'addStream' : 'add';
1789 return js.statement('{ if(#.#(#)) return; #; }', [ 1760 return js.statement('{ if(#.#(#)) return; #; }',
1790 _asyncStarController, 1761 [_asyncStarController, helperName, jsExpr, new JS.Yield(null)]);
1791 helperName,
1792 jsExpr,
1793 new JS.Yield(null)
1794 ]);
1795 } 1762 }
1796 // A normal yield in a sync* 1763 // A normal yield in a sync*
1797 return jsExpr.toYieldStatement(star: star); 1764 return jsExpr.toYieldStatement(star: star);
1798 } 1765 }
1799 1766
1800 @override 1767 @override
1801 JS.Expression visitAwaitExpression(AwaitExpression node) { 1768 JS.Expression visitAwaitExpression(AwaitExpression node) {
1802 return new JS.Yield(_visit(node.expression)); 1769 return new JS.Yield(_visit(node.expression));
1803 } 1770 }
1804 1771
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 body.add(_emitLazyFields(_lazyFields)); 1867 body.add(_emitLazyFields(_lazyFields));
1901 _lazyFields.clear(); 1868 _lazyFields.clear();
1902 } 1869 }
1903 1870
1904 JS.Statement _emitLazyFields(List<VariableDeclaration> fields) { 1871 JS.Statement _emitLazyFields(List<VariableDeclaration> fields) {
1905 var methods = []; 1872 var methods = [];
1906 for (var node in fields) { 1873 for (var node in fields) {
1907 var name = node.name.name; 1874 var name = node.name.name;
1908 var element = node.element; 1875 var element = node.element;
1909 var access = _emitMemberName(name, type: element.type, isStatic: true); 1876 var access = _emitMemberName(name, type: element.type, isStatic: true);
1910 methods.add(new JS.Method(access, js.call( 1877 methods.add(new JS.Method(
1911 'function() { return #; }', _visit(node.initializer)) as JS.Fun, 1878 access,
1879 js.call('function() { return #; }', _visit(node.initializer))
1880 as JS.Fun,
1912 isGetter: true)); 1881 isGetter: true));
1913 1882
1914 // TODO(jmesserly): use a dummy setter to indicate writable. 1883 // TODO(jmesserly): use a dummy setter to indicate writable.
1915 if (!node.isFinal) { 1884 if (!node.isFinal) {
1916 methods.add(new JS.Method(access, js.call('function(_) {}') as JS.Fun, 1885 methods.add(new JS.Method(access, js.call('function(_) {}') as JS.Fun,
1917 isSetter: true)); 1886 isSetter: true));
1918 } 1887 }
1919 } 1888 }
1920 1889
1921 JS.Expression objExpr = _exportsVar; 1890 JS.Expression objExpr = _exportsVar;
1922 var target = _lazyFields[0].element.enclosingElement; 1891 var target = _lazyFields[0].element.enclosingElement;
1923 if (target is ClassElement) { 1892 if (target is ClassElement) {
1924 objExpr = new JS.Identifier(target.type.name); 1893 objExpr = new JS.Identifier(target.type.name);
1925 } 1894 }
1926 1895
1927 return js.statement( 1896 return js.statement(
1928 'dart.defineLazyProperties(#, { # });', [objExpr, methods]); 1897 'dart.defineLazyProperties(#, { # });', [objExpr, methods]);
1929 } 1898 }
1930 1899
1931 void _flushLibraryProperties(List<JS.Statement> body) { 1900 void _flushLibraryProperties(List<JS.Statement> body) {
1932 if (_properties.isEmpty) return; 1901 if (_properties.isEmpty) return;
1933 body.add(js.statement('dart.copyProperties(#, { # });', [ 1902 body.add(js.statement('dart.copyProperties(#, { # });',
1934 _exportsVar, 1903 [_exportsVar, _properties.map(_emitTopLevelProperty)]));
1935 _properties.map(_emitTopLevelProperty)
1936 ]));
1937 _properties.clear(); 1904 _properties.clear();
1938 } 1905 }
1939 1906
1940 JS.Expression _emitConstructorName( 1907 JS.Expression _emitConstructorName(
1941 ConstructorElement element, DartType type, SimpleIdentifier name) { 1908 ConstructorElement element, DartType type, SimpleIdentifier name) {
1942 var typeName = _emitTypeName(type); 1909 var typeName = _emitTypeName(type);
1943 if (name != null || element.isFactory) { 1910 if (name != null || element.isFactory) {
1944 var namedCtor = _constructorName(element); 1911 var namedCtor = _constructorName(element);
1945 return new JS.PropertyAccess(typeName, namedCtor); 1912 return new JS.PropertyAccess(typeName, namedCtor);
1946 } 1913 }
1947 return typeName; 1914 return typeName;
1948 } 1915 }
1949 1916
1950 @override 1917 @override
1951 visitConstructorName(ConstructorName node) { 1918 visitConstructorName(ConstructorName node) {
1952 return _emitConstructorName(node.staticElement, node.type.type, node.name); 1919 return _emitConstructorName(node.staticElement, node.type.type, node.name);
1953 } 1920 }
1954 1921
1955 JS.Expression _emitInstanceCreationExpression(ConstructorElement element, 1922 JS.Expression _emitInstanceCreationExpression(
1956 DartType type, SimpleIdentifier name, ArgumentList argumentList, 1923 ConstructorElement element,
1924 DartType type,
1925 SimpleIdentifier name,
1926 ArgumentList argumentList,
1957 bool isConst) { 1927 bool isConst) {
1958 JS.Expression emitNew() { 1928 JS.Expression emitNew() {
1959 JS.Expression ctor; 1929 JS.Expression ctor;
1960 bool isFactory = false; 1930 bool isFactory = false;
1961 // var element = node.staticElement; 1931 // var element = node.staticElement;
1962 if (element == null) { 1932 if (element == null) {
1963 // TODO(jmesserly): this only happens if we had a static error. 1933 // TODO(jmesserly): this only happens if we had a static error.
1964 // Should we generate a throw instead? 1934 // Should we generate a throw instead?
1965 ctor = _emitTypeName(type); 1935 ctor = _emitTypeName(type);
1966 if (name != null) { 1936 if (name != null) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
2096 return _emitSend(left, op.lexeme, [right]); 2066 return _emitSend(left, op.lexeme, [right]);
2097 } else { 2067 } else {
2098 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; 2068 var bang = op.type == TokenType.BANG_EQ ? '!' : '';
2099 code = '${bang}dart.equals(#, #)'; 2069 code = '${bang}dart.equals(#, #)';
2100 } 2070 }
2101 return js.call(code, [_visit(left), _visit(right)]); 2071 return js.call(code, [_visit(left), _visit(right)]);
2102 } 2072 }
2103 2073
2104 if (binaryOperationIsPrimitive(leftType, rightType) || 2074 if (binaryOperationIsPrimitive(leftType, rightType) ||
2105 rules.isStringType(leftType) && op.type == TokenType.PLUS) { 2075 rules.isStringType(leftType) && op.type == TokenType.PLUS) {
2106
2107 // special cases where we inline the operation 2076 // special cases where we inline the operation
2108 // these values are assumed to be non-null (determined by the checker) 2077 // these values are assumed to be non-null (determined by the checker)
2109 // TODO(jmesserly): it would be nice to just inline the method from core, 2078 // TODO(jmesserly): it would be nice to just inline the method from core,
2110 // instead of special cases here. 2079 // instead of special cases here.
2111 if (op.type == TokenType.TILDE_SLASH) { 2080 if (op.type == TokenType.TILDE_SLASH) {
2112 // `a ~/ b` is equivalent to `(a / b).truncate()` 2081 // `a ~/ b` is equivalent to `(a / b).truncate()`
2113 var div = AstBuilder.binaryExpression(left, '/', right) 2082 var div = AstBuilder.binaryExpression(left, '/', right)
2114 ..staticType = node.staticType; 2083 ..staticType = node.staticType;
2115 return _emitSend(div, 'truncate', []); 2084 return _emitSend(div, 'truncate', []);
2116 } else { 2085 } else {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2173 /// 2142 ///
2174 /// If the expression does not end up using `x1` or `x2` more than once, or 2143 /// If the expression does not end up using `x1` or `x2` more than once, or
2175 /// if those expressions can be treated as stateless (e.g. they are 2144 /// if those expressions can be treated as stateless (e.g. they are
2176 /// non-mutated variables), then the resulting code will be simplified 2145 /// non-mutated variables), then the resulting code will be simplified
2177 /// automatically. 2146 /// automatically.
2178 /// 2147 ///
2179 /// [scope] can be mutated to contain any new temporaries that were created, 2148 /// [scope] can be mutated to contain any new temporaries that were created,
2180 /// unless [expr] is a SimpleIdentifier, in which case a temporary is not 2149 /// unless [expr] is a SimpleIdentifier, in which case a temporary is not
2181 /// needed. 2150 /// needed.
2182 Expression _bindLeftHandSide( 2151 Expression _bindLeftHandSide(
2183 Map<String, JS.Expression> scope, Expression expr, {Expression context}) { 2152 Map<String, JS.Expression> scope, Expression expr,
2153 {Expression context}) {
2184 Expression result; 2154 Expression result;
2185 if (expr is IndexExpression) { 2155 if (expr is IndexExpression) {
2186 IndexExpression index = expr; 2156 IndexExpression index = expr;
2187 result = new IndexExpression.forTarget( 2157 result = new IndexExpression.forTarget(
2188 _bindValue(scope, 'o', index.target, context: context), 2158 _bindValue(scope, 'o', index.target, context: context),
2189 index.leftBracket, 2159 index.leftBracket,
2190 _bindValue(scope, 'i', index.index, context: context), 2160 _bindValue(scope, 'i', index.index, context: context),
2191 index.rightBracket); 2161 index.rightBracket);
2192 } else if (expr is PropertyAccess) { 2162 } else if (expr is PropertyAccess) {
2193 PropertyAccess prop = expr; 2163 PropertyAccess prop = expr;
2194 result = new PropertyAccess( 2164 result = new PropertyAccess(
2195 _bindValue(scope, 'o', _getTarget(prop), context: context), 2165 _bindValue(scope, 'o', _getTarget(prop), context: context),
2196 prop.operator, prop.propertyName); 2166 prop.operator,
2167 prop.propertyName);
2197 } else if (expr is PrefixedIdentifier) { 2168 } else if (expr is PrefixedIdentifier) {
2198 PrefixedIdentifier ident = expr; 2169 PrefixedIdentifier ident = expr;
2199 result = new PrefixedIdentifier(_bindValue(scope, 'o', ident.prefix, 2170 result = new PrefixedIdentifier(
2200 context: context) as SimpleIdentifier, ident.period, 2171 _bindValue(scope, 'o', ident.prefix, context: context)
2172 as SimpleIdentifier,
2173 ident.period,
2201 ident.identifier); 2174 ident.identifier);
2202 } else { 2175 } else {
2203 return expr as SimpleIdentifier; 2176 return expr as SimpleIdentifier;
2204 } 2177 }
2205 result.staticType = expr.staticType; 2178 result.staticType = expr.staticType;
2206 DynamicInvoke.set(result, DynamicInvoke.get(expr)); 2179 DynamicInvoke.set(result, DynamicInvoke.get(expr));
2207 return result; 2180 return result;
2208 } 2181 }
2209 2182
2210 /// Creates a temporary to contain the value of [expr]. The temporary can be 2183 /// Creates a temporary to contain the value of [expr]. The temporary can be
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 Expression target, String name, List<Expression> args) { 2384 Expression target, String name, List<Expression> args) {
2412 var type = getStaticType(target); 2385 var type = getStaticType(target);
2413 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type); 2386 var memberName = _emitMemberName(name, unary: args.isEmpty, type: type);
2414 if (DynamicInvoke.get(target)) { 2387 if (DynamicInvoke.get(target)) {
2415 // dynamic dispatch 2388 // dynamic dispatch
2416 var dynamicHelper = const {'[]': DINDEX, '[]=': DSETINDEX}[name]; 2389 var dynamicHelper = const {'[]': DINDEX, '[]=': DSETINDEX}[name];
2417 if (dynamicHelper != null) { 2390 if (dynamicHelper != null) {
2418 return js.call( 2391 return js.call(
2419 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]); 2392 'dart.$dynamicHelper(#, #)', [_visit(target), _visitList(args)]);
2420 } 2393 }
2421 return js.call('dart.$DSEND(#, #, #)', [ 2394 return js.call('dart.$DSEND(#, #, #)',
2422 _visit(target), 2395 [_visit(target), memberName, _visitList(args)]);
2423 memberName,
2424 _visitList(args)
2425 ]);
2426 } 2396 }
2427 2397
2428 // Generic dispatch to a statically known method. 2398 // Generic dispatch to a statically known method.
2429 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]); 2399 return js.call('#.#(#)', [_visit(target), memberName, _visitList(args)]);
2430 } 2400 }
2431 2401
2432 @override 2402 @override
2433 visitIndexExpression(IndexExpression node) { 2403 visitIndexExpression(IndexExpression node) {
2434 var target = _getTarget(node); 2404 var target = _getTarget(node);
2435 if (_useNativeJsIndexer(target.staticType)) { 2405 if (_useNativeJsIndexer(target.staticType)) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2536 // TODO(jmesserly): we may want a helper if these become common. For now the 2506 // TODO(jmesserly): we may want a helper if these become common. For now the
2537 // full desugaring seems okay. 2507 // full desugaring seems okay.
2538 var context = compiler.context; 2508 var context = compiler.context;
2539 var dart_async = context 2509 var dart_async = context
2540 .computeLibraryElement(context.sourceFactory.forUri('dart:async')); 2510 .computeLibraryElement(context.sourceFactory.forUri('dart:async'));
2541 var T = node.loopVariable.element.type; 2511 var T = node.loopVariable.element.type;
2542 var StreamIterator_T = 2512 var StreamIterator_T =
2543 dart_async.getType('StreamIterator').type.substitute4([T]); 2513 dart_async.getType('StreamIterator').type.substitute4([T]);
2544 2514
2545 var createStreamIter = _emitInstanceCreationExpression( 2515 var createStreamIter = _emitInstanceCreationExpression(
2546 StreamIterator_T.element.unnamedConstructor, StreamIterator_T, null, 2516 StreamIterator_T.element.unnamedConstructor,
2547 AstBuilder.argumentList([node.iterable]), false); 2517 StreamIterator_T,
2518 null,
2519 AstBuilder.argumentList([node.iterable]),
2520 false);
2548 var iter = _visit(_createTemporary('it', StreamIterator_T)); 2521 var iter = _visit(_createTemporary('it', StreamIterator_T));
2549 2522
2550 var init = _visit(node.identifier); 2523 var init = _visit(node.identifier);
2551 if (init == null) { 2524 if (init == null) {
2552 init = js.call( 2525 init = js.call(
2553 'let # = #.current', [node.loopVariable.identifier.name, iter]); 2526 'let # = #.current', [node.loopVariable.identifier.name, iter]);
2554 } else { 2527 } else {
2555 init = js.call('# = #.current', [init, iter]); 2528 init = js.call('# = #.current', [init, iter]);
2556 } 2529 }
2557 return js.statement('{' 2530 return js.statement(
2531 '{'
2558 ' let # = #;' 2532 ' let # = #;'
2559 ' try {' 2533 ' try {'
2560 ' while (#) { #; #; }' 2534 ' while (#) { #; #; }'
2561 ' } finally { #; }' 2535 ' } finally { #; }'
2562 '}', [ 2536 '}',
2537 [
2563 iter, 2538 iter,
2564 createStreamIter, 2539 createStreamIter,
2565 new JS.Yield(js.call('#.moveNext()', iter)), 2540 new JS.Yield(js.call('#.moveNext()', iter)),
2566 init, 2541 init,
2567 _visit(node.body), 2542 _visit(node.body),
2568 new JS.Yield(js.call('#.cancel()', iter)) 2543 new JS.Yield(js.call('#.cancel()', iter))
2569 ]); 2544 ]);
2570 } 2545 }
2571 2546
2572 @override 2547 @override
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 } 2587 }
2613 2588
2614 JS.Statement _catchClauseGuard(CatchClause clause, JS.Statement otherwise) { 2589 JS.Statement _catchClauseGuard(CatchClause clause, JS.Statement otherwise) {
2615 var then = visitCatchClause(clause); 2590 var then = visitCatchClause(clause);
2616 2591
2617 // Discard following clauses, if any, as they are unreachable. 2592 // Discard following clauses, if any, as they are unreachable.
2618 if (clause.exceptionType == null) return then; 2593 if (clause.exceptionType == null) return then;
2619 2594
2620 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which 2595 // TODO(jmesserly): this is inconsistent with [visitIsExpression], which
2621 // has special case for typeof. 2596 // has special case for typeof.
2622 return new JS.If(js.call('dart.is(#, #)', [ 2597 return new JS.If(
2623 _visit(_catchParameter), 2598 js.call('dart.is(#, #)', [
2624 _emitTypeName(clause.exceptionType.type), 2599 _visit(_catchParameter),
2625 ]), then, otherwise); 2600 _emitTypeName(clause.exceptionType.type),
2601 ]),
2602 then,
2603 otherwise);
2626 } 2604 }
2627 2605
2628 JS.Statement _statement(List<JS.Statement> statements) { 2606 JS.Statement _statement(List<JS.Statement> statements) {
2629 // TODO(jmesserly): empty block singleton? 2607 // TODO(jmesserly): empty block singleton?
2630 if (statements.length == 0) return new JS.Block([]); 2608 if (statements.length == 0) return new JS.Block([]);
2631 if (statements.length == 1) return statements[0]; 2609 if (statements.length == 1) return statements[0];
2632 return new JS.Block(statements); 2610 return new JS.Block(statements);
2633 } 2611 }
2634 2612
2635 /// Visits the catch clause body. This skips the exception type guard, if any. 2613 /// Visits the catch clause body. This skips the exception type guard, if any.
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
2883 /// 2861 ///
2884 /// This follows the same pattern as EcmaScript 6 Map: 2862 /// This follows the same pattern as EcmaScript 6 Map:
2885 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map> 2863 /// <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_ Objects/Map>
2886 /// 2864 ///
2887 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed 2865 /// Unary minus looks like: `x['unary-']()`. Note that [unary] must be passed
2888 /// for this transformation to happen, otherwise binary minus is assumed. 2866 /// for this transformation to happen, otherwise binary minus is assumed.
2889 /// 2867 ///
2890 /// Equality is a bit special, it is generated via the Dart `equals` runtime 2868 /// Equality is a bit special, it is generated via the Dart `equals` runtime
2891 /// helper, that checks for null. The user defined method is called '=='. 2869 /// helper, that checks for null. The user defined method is called '=='.
2892 /// 2870 ///
2893 JS.Expression _emitMemberName(String name, {DartType type, bool unary: false, 2871 JS.Expression _emitMemberName(String name,
2894 bool isStatic: false, bool allowExtensions: true}) { 2872 {DartType type,
2895 2873 bool unary: false,
2874 bool isStatic: false,
2875 bool allowExtensions: true}) {
2896 // Static members skip the rename steps. 2876 // Static members skip the rename steps.
2897 if (isStatic) return _propertyName(name); 2877 if (isStatic) return _propertyName(name);
2898 2878
2899 if (name.startsWith('_')) { 2879 if (name.startsWith('_')) {
2900 return _privateNames.putIfAbsent( 2880 return _privateNames.putIfAbsent(
2901 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId); 2881 name, () => _initSymbol(new JS.TemporaryId(name)) as JS.TemporaryId);
2902 } 2882 }
2903 2883
2904 if (name == '[]') { 2884 if (name == '[]') {
2905 name = 'get'; 2885 name = 'get';
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2999 2979
3000 /// A special kind of element created by the compiler, signifying a temporary 2980 /// A special kind of element created by the compiler, signifying a temporary
3001 /// variable. These objects use instance equality, and should be shared 2981 /// variable. These objects use instance equality, and should be shared
3002 /// everywhere in the tree where they are treated as the same variable. 2982 /// everywhere in the tree where they are treated as the same variable.
3003 class TemporaryVariableElement extends LocalVariableElementImpl { 2983 class TemporaryVariableElement extends LocalVariableElementImpl {
3004 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2984 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3005 2985
3006 int get hashCode => identityHashCode(this); 2986 int get hashCode => identityHashCode(this);
3007 bool operator ==(Object other) => identical(this, other); 2987 bool operator ==(Object other) => identical(this, other);
3008 } 2988 }
OLDNEW
« no previous file with comments | « lib/src/codegen/html_codegen.dart ('k') | lib/src/codegen/js_metalet.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698