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

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

Issue 1177563003: Generate metadata (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 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 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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 356
357 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), 357 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name),
358 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); 358 _classHeritage(classElem), _emitClassMethods(node, ctors, fields));
359 359
360 String jsPeerName; 360 String jsPeerName;
361 var jsPeer = findAnnotation(classElem, _isJsPeerInterface); 361 var jsPeer = findAnnotation(classElem, _isJsPeerInterface);
362 if (jsPeer != null) { 362 if (jsPeer != null) {
363 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); 363 jsPeerName = getConstantField(jsPeer, 'name', types.stringType);
364 } 364 }
365 365
366 var body = _finishClassMembers( 366 var body = _finishClassMembers(classElem, classExpr, ctors, fields, methods,
367 classElem, classExpr, ctors, fields, methods, jsPeerName); 367 node.metadata, jsPeerName);
368 368
369 var result = _finishClassDef(type, body); 369 var result = _finishClassDef(type, body);
370 370
371 if (jsPeerName != null) { 371 if (jsPeerName != null) {
372 // This class isn't allowed to be lazy, because we need to set up 372 // This class isn't allowed to be lazy, because we need to set up
373 // the native JS type eagerly at this point. 373 // the native JS type eagerly at this point.
374 // If we wanted to support laziness, we could defer the hookup until 374 // If we wanted to support laziness, we could defer the hookup until
375 // the end of the Dart library cycle load. 375 // the end of the Dart library cycle load.
376 assert(_loader.isLoaded(classElem)); 376 assert(_loader.isLoaded(classElem));
377 377
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 var parentType = findSupertype(t, _implementsIterable); 534 var parentType = findSupertype(t, _implementsIterable);
535 if (parentType != null) return null; 535 if (parentType != null) return null;
536 536
537 // Otherwise, emit the adapter method, which wraps the Dart iterator in 537 // Otherwise, emit the adapter method, which wraps the Dart iterator in
538 // an ES6 iterator. 538 // an ES6 iterator.
539 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( 539 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call(
540 'function() { return new dart.JsIterator(this.#); }', 540 'function() { return new dart.JsIterator(this.#); }',
541 [_emitMemberName('iterator', type: t)])); 541 [_emitMemberName('iterator', type: t)]));
542 } 542 }
543 543
544 JS.Expression _instantiateAnnotation(Annotation node) {
545 var element = node.element;
546 if (element is ConstructorElement) {
547 return _emitInstanceCreationExpression(
548 element, element.returnType, node.constructorName, node.arguments, tru e);
Jennifer Messerly 2015/06/09 23:29:53 ./tool/format.sh ? :)
vsm 2015/06/10 13:28:27 Done. Sorry - uploaded too early.
549 } else {
550 return _visit(node.name);
551 }
552 }
553
544 /// Emit class members that need to come after the class declaration, such 554 /// Emit class members that need to come after the class declaration, such
545 /// as static fields. See [_emitClassMethods] for things that are emitted 555 /// as static fields. See [_emitClassMethods] for things that are emitted
546 /// inside the ES6 `class { ... }` node. 556 /// inside the ES6 `class { ... }` node.
547 JS.Statement _finishClassMembers(ClassElement classElem, 557 JS.Statement _finishClassMembers(ClassElement classElem,
548 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, 558 JS.ClassExpression cls, List<ConstructorDeclaration> ctors,
549 List<FieldDeclaration> fields, List<MethodDeclaration> methods, 559 List<FieldDeclaration> fields, List<MethodDeclaration> methods,
550 String jsPeerName) { 560 List<Annotation> metadata, String jsPeerName) {
551 var name = classElem.name; 561 var name = classElem.name;
552 var body = <JS.Statement>[]; 562 var body = <JS.Statement>[];
553 563
554 if (jsPeerName != null) { 564 if (jsPeerName != null) {
555 var dartxNames = []; 565 var dartxNames = [];
556 for (var m in methods) { 566 for (var m in methods) {
557 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { 567 if (!m.isAbstract && !m.isStatic && m.element.isPublic) {
558 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); 568 dartxNames.add(_elementMemberName(m.element, allowExtensions: false));
559 } 569 }
560 } 570 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 var property = 630 var property =
621 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 631 new JS.Property(memberName, new JS.ArrayInitializer(parts));
622 if (node.isStatic) { 632 if (node.isStatic) {
623 tStatics.add(property); 633 tStatics.add(property);
624 sNames.add(memberName); 634 sNames.add(memberName);
625 } else { 635 } else {
626 tMethods.add(property); 636 tMethods.add(property);
627 } 637 }
628 } 638 }
629 } 639 }
640
630 var tCtors = []; 641 var tCtors = [];
631 for (ConstructorDeclaration node in ctors) { 642 for (ConstructorDeclaration node in ctors) {
632 var memberName = _constructorName(node.element); 643 var memberName = _constructorName(node.element);
633 var element = node.element; 644 var element = node.element;
634 var parts = 645 var parts =
635 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); 646 _emitFunctionTypeParts(element.type, dynamicIsBottom: false);
636 var property = 647 var property =
637 new JS.Property(memberName, new JS.ArrayInitializer(parts)); 648 new JS.Property(memberName, new JS.ArrayInitializer(parts));
638 tCtors.add(property); 649 tCtors.add(property);
639 } 650 }
651
640 build(name, elements) { 652 build(name, elements) {
641 var o = 653 var o =
642 new JS.ObjectInitializer(elements, multiline: elements.length > 1); 654 new JS.ObjectInitializer(elements, multiline: elements.length > 1);
643 var e = js.call('() => #', o); 655 var e = js.call('() => #', o);
644 var p = new JS.Property(_propertyName(name), e); 656 var p = new JS.Property(_propertyName(name), e);
645 return p; 657 return p;
646 } 658 }
647 var sigFields = []; 659 var sigFields = [];
648 if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors)); 660 if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors));
649 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); 661 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods));
(...skipping 18 matching lines...) Expand all
668 var methodNames = []; 680 var methodNames = [];
669 for (var e in extensions) { 681 for (var e in extensions) {
670 methodNames.add(_elementMemberName(e)); 682 methodNames.add(_elementMemberName(e));
671 } 683 }
672 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ 684 body.add(js.statement('dart.defineExtensionMembers(#, #);', [
673 name, 685 name,
674 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) 686 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4)
675 ])); 687 ]));
676 } 688 }
677 689
690 // Metadata
691 if (metadata.isNotEmpty) {
692 body.add(js.statement('#[dart.metadata] = () => #;', [
693 name,
694 new JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList())
695 ]));
696 }
697
678 return _statement(body); 698 return _statement(body);
679 } 699 }
680 700
681 List<ExecutableElement> _extensionsToImplement(ClassElement element) { 701 List<ExecutableElement> _extensionsToImplement(ClassElement element) {
682 var members = <ExecutableElement>[]; 702 var members = <ExecutableElement>[];
683 if (_extensionTypes.contains(element)) return members; 703 if (_extensionTypes.contains(element)) return members;
684 704
685 // Collect all extension types we implement. 705 // Collect all extension types we implement.
686 var type = element.type; 706 var type = element.type;
687 var types = new Set<ClassElement>(); 707 var types = new Set<ClassElement>();
(...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after
1736 1756
1737 void _flushLibraryProperties(List<JS.Statement> body) { 1757 void _flushLibraryProperties(List<JS.Statement> body) {
1738 if (_properties.isEmpty) return; 1758 if (_properties.isEmpty) return;
1739 body.add(js.statement('dart.copyProperties(#, { # });', [ 1759 body.add(js.statement('dart.copyProperties(#, { # });', [
1740 _exportsVar, 1760 _exportsVar,
1741 _properties.map(_emitTopLevelProperty) 1761 _properties.map(_emitTopLevelProperty)
1742 ])); 1762 ]));
1743 _properties.clear(); 1763 _properties.clear();
1744 } 1764 }
1745 1765
1746 @override 1766 _emitConstructorName(ConstructorElement element, DartType type, SimpleIdentifi er name) {
Jennifer Messerly 2015/06/09 23:29:53 return type?
vsm 2015/06/10 13:28:27 Done.
1747 visitConstructorName(ConstructorName node) { 1767 var typeName = _emitTypeName(type);
1748 var typeName = _visit(node.type); 1768 if (name != null || element.isFactory) {
1749 var element = node.staticElement;
1750 if (node.name != null || element.isFactory) {
1751 var namedCtor = _constructorName(element); 1769 var namedCtor = _constructorName(element);
1752 return new JS.PropertyAccess(typeName, namedCtor); 1770 return new JS.PropertyAccess(typeName, namedCtor);
1753 } 1771 }
1754 return typeName; 1772 return typeName;
1755 } 1773 }
1756 1774
1757 @override 1775 @override
1776 visitConstructorName(ConstructorName node) {
1777 return _emitConstructorName(node.staticElement, node.type.type, node.name);
1778 }
1779
1780 _emitInstanceCreationExpression(ConstructorElement element, DartType type, Sim pleIdentifier name,
1781 ArgumentList argumentList, bool isConst) {
1782 emitNew() {
1783 JS.Expression ctor;
1784 bool isFactory = false;
1785 // var element = node.staticElement;
1786 if (element == null) {
1787 // TODO(jmesserly): this only happens if we had a static error.
1788 // Should we generate a throw instead?
1789 ctor = _emitTypeName(type);
1790 if (name != null) {
1791 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name));
1792 }
1793 } else {
1794 ctor = _emitConstructorName(element, type, name);
1795 isFactory = element.isFactory;
1796 }
1797 var args = _visit(argumentList);
1798 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args);
1799 }
1800 if (isConst) return _emitConst(emitNew);
1801 return emitNew();
1802 }
1803
1804 @override
1758 visitInstanceCreationExpression(InstanceCreationExpression node) { 1805 visitInstanceCreationExpression(InstanceCreationExpression node) {
1759 emitNew() { 1806 var element = node.staticElement;
1760 JS.Expression ctor; 1807 var constructor = node.constructorName;
1761 bool isFactory = false; 1808 var name = constructor.name;
1762 var element = node.staticElement; 1809 var type = constructor.type.type;
1763 if (element == null) { 1810 return _emitInstanceCreationExpression(
1764 // TODO(jmesserly): this only happens if we had a static error. 1811 element, type, name, node.argumentList, node.isConst);
1765 // Should we generate a throw instead?
1766 ctor = _visit(node.constructorName.type);
1767 var ctorName = node.constructorName.name;
1768 if (ctorName != null) {
1769 ctor = new JS.PropertyAccess(ctor, _propertyName(ctorName.name));
1770 }
1771 } else {
1772 ctor = _visit(node.constructorName);
1773 isFactory = element.isFactory;
1774 }
1775 var args = _visit(node.argumentList);
1776 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args);
1777 }
1778 if (node.isConst) return _emitConst(node, emitNew);
1779 return emitNew();
1780 } 1812 }
1781 1813
1782 /// True if this type is built-in to JS, and we use the values unwrapped. 1814 /// True if this type is built-in to JS, and we use the values unwrapped.
1783 /// For these types we generate a calling convention via static 1815 /// For these types we generate a calling convention via static
1784 /// "extension methods". This allows types to be extended without adding 1816 /// "extension methods". This allows types to be extended without adding
1785 /// extensions directly on the prototype. 1817 /// extensions directly on the prototype.
1786 bool _isJSBuiltinType(DartType t) => 1818 bool _isJSBuiltinType(DartType t) =>
1787 typeIsPrimitiveInJS(t) || rules.isStringType(t); 1819 typeIsPrimitiveInJS(t) || rules.isStringType(t);
1788 1820
1789 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) || 1821 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) ||
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1869 var jsExpr = _visit(expr); 1901 var jsExpr = _visit(expr);
1870 if (_isNonNullableExpression(expr)) return jsExpr; 1902 if (_isNonNullableExpression(expr)) return jsExpr;
1871 return js.call('dart.notNull(#)', jsExpr); 1903 return js.call('dart.notNull(#)', jsExpr);
1872 } 1904 }
1873 1905
1874 @override 1906 @override
1875 JS.Expression visitBinaryExpression(BinaryExpression node) { 1907 JS.Expression visitBinaryExpression(BinaryExpression node) {
1876 var op = node.operator; 1908 var op = node.operator;
1877 var left = node.leftOperand; 1909 var left = node.leftOperand;
1878 var right = node.rightOperand; 1910 var right = node.rightOperand;
1911
1879 var leftType = getStaticType(left); 1912 var leftType = getStaticType(left);
1880 var rightType = getStaticType(right); 1913 var rightType = getStaticType(right);
1881 1914
1882 var code; 1915 var code;
1883 if (op.type.isEqualityOperator) { 1916 if (op.type.isEqualityOperator) {
1884 // If we statically know LHS or RHS is null we can generate a clean check. 1917 // If we statically know LHS or RHS is null we can generate a clean check.
1885 // We can also do this if both sides are the same primitive type. 1918 // We can also do this if both sides are the same primitive type.
1886 if (_canUsePrimitiveEquality(left, right)) { 1919 if (_canUsePrimitiveEquality(left, right)) {
1887 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; 1920 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #';
1888 } else { 1921 } else {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1938 // LocalVariableElementImpl, so we could repurpose to mean "temp". 1971 // LocalVariableElementImpl, so we could repurpose to mean "temp".
1939 // * add a new property to LocalVariableElementImpl. 1972 // * add a new property to LocalVariableElementImpl.
1940 // * create a new subtype of LocalVariableElementImpl to mark a temp. 1973 // * create a new subtype of LocalVariableElementImpl to mark a temp.
1941 var id = 1974 var id =
1942 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); 1975 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1));
1943 id.staticElement = new TemporaryVariableElement.forNode(id); 1976 id.staticElement = new TemporaryVariableElement.forNode(id);
1944 id.staticType = type; 1977 id.staticType = type;
1945 return id; 1978 return id;
1946 } 1979 }
1947 1980
1948 JS.Expression _emitConst(Expression node, JS.Expression expr()) { 1981 JS.Expression _emitConst(JS.Expression expr()) {
1949 // TODO(jmesserly): emit the constants at top level if possible. 1982 // TODO(jmesserly): emit the constants at top level if possible.
1950 // This wasn't quite working, so disabled for now. 1983 // This wasn't quite working, so disabled for now.
1951 return js.call('dart.const(#)', expr()); 1984 return js.call('dart.const(#)', expr());
1952 } 1985 }
1953 1986
1954 /// Returns a new expression, which can be be used safely *once* on the 1987 /// Returns a new expression, which can be be used safely *once* on the
1955 /// left hand side, and *once* on the right side of an assignment. 1988 /// left hand side, and *once* on the right side of an assignment.
1956 /// For example: `expr1[expr2] += y` can be compiled as 1989 /// For example: `expr1[expr2] += y` can be compiled as
1957 /// `expr1[expr2] = expr1[expr2] + y`. 1990 /// `expr1[expr2] = expr1[expr2] + y`.
1958 /// 1991 ///
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
2429 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); 2462 visitNullLiteral(NullLiteral node) => new JS.LiteralNull();
2430 2463
2431 @override 2464 @override
2432 visitSymbolLiteral(SymbolLiteral node) { 2465 visitSymbolLiteral(SymbolLiteral node) {
2433 emitSymbol() { 2466 emitSymbol() {
2434 // TODO(vsm): When we canonicalize, we need to treat private symbols 2467 // TODO(vsm): When we canonicalize, we need to treat private symbols
2435 // correctly. 2468 // correctly.
2436 var name = js.string(node.components.join('.'), "'"); 2469 var name = js.string(node.components.join('.'), "'");
2437 return new JS.New(_emitTypeName(types.symbolType), [name]); 2470 return new JS.New(_emitTypeName(types.symbolType), [name]);
2438 } 2471 }
2439 return _emitConst(node, emitSymbol); 2472 return _emitConst(emitSymbol);
2440 } 2473 }
2441 2474
2442 @override 2475 @override
2443 visitListLiteral(ListLiteral node) { 2476 visitListLiteral(ListLiteral node) {
2444 emitList() { 2477 emitList() {
2445 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); 2478 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements));
2446 ParameterizedType type = node.staticType; 2479 ParameterizedType type = node.staticType;
2447 var elementType = type.typeArguments.single; 2480 var elementType = type.typeArguments.single;
2448 if (elementType != types.dynamicType) { 2481 if (elementType != types.dynamicType) {
2449 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); 2482 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]);
2450 } 2483 }
2451 return list; 2484 return list;
2452 } 2485 }
2453 if (node.constKeyword != null) return _emitConst(node, emitList); 2486 if (node.constKeyword != null) return _emitConst(emitList);
2454 return emitList(); 2487 return emitList();
2455 } 2488 }
2456 2489
2457 @override 2490 @override
2458 visitMapLiteral(MapLiteral node) { 2491 visitMapLiteral(MapLiteral node) {
2459 // TODO(jmesserly): we can likely make these faster. 2492 // TODO(jmesserly): we can likely make these faster.
2460 emitMap() { 2493 emitMap() {
2461 var entries = node.entries; 2494 var entries = node.entries;
2462 var mapArguments = null; 2495 var mapArguments = null;
2463 if (entries.isEmpty) { 2496 if (entries.isEmpty) {
(...skipping 11 matching lines...) Expand all
2475 var values = []; 2508 var values = [];
2476 for (var e in entries) { 2509 for (var e in entries) {
2477 values.add(_visit(e.key)); 2510 values.add(_visit(e.key));
2478 values.add(_visit(e.value)); 2511 values.add(_visit(e.value));
2479 } 2512 }
2480 mapArguments = new JS.ArrayInitializer(values); 2513 mapArguments = new JS.ArrayInitializer(values);
2481 } 2514 }
2482 // TODO(jmesserly): add generic types args. 2515 // TODO(jmesserly): add generic types args.
2483 return js.call('dart.map(#)', [mapArguments]); 2516 return js.call('dart.map(#)', [mapArguments]);
2484 } 2517 }
2485 if (node.constKeyword != null) return _emitConst(node, emitMap); 2518 if (node.constKeyword != null) return _emitConst(emitMap);
2486 return emitMap(); 2519 return emitMap();
2487 } 2520 }
2488 2521
2489 @override 2522 @override
2490 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => 2523 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
2491 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); 2524 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"');
2492 2525
2493 @override 2526 @override
2494 JS.Expression visitAdjacentStrings(AdjacentStrings node) => 2527 JS.Expression visitAdjacentStrings(AdjacentStrings node) =>
2495 _visitListToBinary(node.strings, '+'); 2528 _visitListToBinary(node.strings, '+');
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2738 2771
2739 /// A special kind of element created by the compiler, signifying a temporary 2772 /// A special kind of element created by the compiler, signifying a temporary
2740 /// variable. These objects use instance equality, and should be shared 2773 /// variable. These objects use instance equality, and should be shared
2741 /// everywhere in the tree where they are treated as the same variable. 2774 /// everywhere in the tree where they are treated as the same variable.
2742 class TemporaryVariableElement extends LocalVariableElementImpl { 2775 class TemporaryVariableElement extends LocalVariableElementImpl {
2743 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 2776 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
2744 2777
2745 int get hashCode => identityHashCode(this); 2778 int get hashCode => identityHashCode(this);
2746 bool operator ==(Object other) => identical(this, other); 2779 bool operator ==(Object other) => identical(this, other);
2747 } 2780 }
OLDNEW
« lib/runtime/dart/_interceptors.js ('K') | « lib/runtime/dart_runtime.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698