OLD | NEW |
---|---|
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 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 result.add(js.statement('#.# = dart.const(new #(#));', | 502 result.add(js.statement('#.# = dart.const(new #(#));', |
503 [id, fields[i].name, id, js.number(i)])); | 503 [id, fields[i].name, id, js.number(i)])); |
504 } | 504 } |
505 | 505 |
506 // Create static values list | 506 // Create static values list |
507 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( | 507 var values = new JS.ArrayInitializer(new List<JS.Expression>.from( |
508 fields.map((f) => js.call('#.#', [id, f.name])))); | 508 fields.map((f) => js.call('#.#', [id, f.name])))); |
509 result.add(js.statement('#.values = dart.const(dart.list(#, #));', | 509 result.add(js.statement('#.values = dart.const(dart.list(#, #));', |
510 [id, values, _emitTypeName(type)])); | 510 [id, values, _emitTypeName(type)])); |
511 | 511 |
512 if (isPublic(type.name)) _addExport(type.name); | |
512 return _statement(result); | 513 return _statement(result); |
513 } | 514 } |
514 | 515 |
515 /// Given a class element and body, complete the class declaration. | 516 /// Given a class element and body, complete the class declaration. |
516 /// This handles generic type parameters, laziness (in library-cycle cases), | 517 /// This handles generic type parameters, laziness (in library-cycle cases), |
517 /// and ensuring dependencies are loaded first. | 518 /// and ensuring dependencies are loaded first. |
518 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { | 519 JS.Statement _finishClassDef(ParameterizedType type, JS.Statement body) { |
519 var name = type.name; | 520 var name = type.name; |
520 var genericName = '$name\$'; | 521 var genericName = '$name\$'; |
521 | 522 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 } else { | 745 } else { |
745 tMethods.add(property); | 746 tMethods.add(property); |
746 } | 747 } |
747 } | 748 } |
748 } | 749 } |
749 | 750 |
750 var tCtors = <JS.Property>[]; | 751 var tCtors = <JS.Property>[]; |
751 for (ConstructorDeclaration node in ctors) { | 752 for (ConstructorDeclaration node in ctors) { |
752 var memberName = _constructorName(node.element); | 753 var memberName = _constructorName(node.element); |
753 var element = node.element; | 754 var element = node.element; |
754 var parts = _emitFunctionTypeParts(element.type); | 755 var parts = _emitFunctionTypeParts(element.type, node.parameters); |
755 var property = | 756 var property = |
756 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 757 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
757 tCtors.add(property); | 758 tCtors.add(property); |
758 } | 759 } |
759 | 760 |
760 JS.Property build(String name, List<JS.Property> elements) { | 761 JS.Property build(String name, List<JS.Property> elements) { |
761 var o = | 762 var o = |
762 new JS.ObjectInitializer(elements, multiline: elements.length > 1); | 763 new JS.ObjectInitializer(elements, multiline: elements.length > 1); |
763 var e = js.call('() => #', o); | 764 var e = js.call('() => #', o); |
764 return new JS.Property(_propertyName(name), e); | 765 return new JS.Property(_propertyName(name), e); |
(...skipping 22 matching lines...) Expand all Loading... | |
787 var methodNames = <JS.Expression>[]; | 788 var methodNames = <JS.Expression>[]; |
788 for (var e in extensions) { | 789 for (var e in extensions) { |
789 methodNames.add(_elementMemberName(e)); | 790 methodNames.add(_elementMemberName(e)); |
790 } | 791 } |
791 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ | 792 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ |
792 name, | 793 name, |
793 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) | 794 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) |
794 ])); | 795 ])); |
795 } | 796 } |
796 | 797 |
798 // TODO(vsm): Make this optional per #268. | |
797 // Metadata | 799 // Metadata |
798 if (metadata.isNotEmpty) { | 800 if (metadata.isNotEmpty) { |
799 body.add(js.statement('#[dart.metadata] = () => #;', [ | 801 body.add(js.statement('#[dart.metadata] = () => #;', [ |
800 name, | 802 name, |
801 new JS.ArrayInitializer( | 803 new JS.ArrayInitializer( |
802 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) | 804 new List<JS.Expression>.from(metadata.map(_instantiateAnnotation))) |
803 ])); | 805 ])); |
804 } | 806 } |
805 | 807 |
806 return _statement(body); | 808 return _statement(body); |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1472 return _getTemp(element, name); | 1474 return _getTemp(element, name); |
1473 } | 1475 } |
1474 } | 1476 } |
1475 | 1477 |
1476 return new JS.Identifier(name); | 1478 return new JS.Identifier(name); |
1477 } | 1479 } |
1478 | 1480 |
1479 JS.TemporaryId _getTemp(Element key, String name) => | 1481 JS.TemporaryId _getTemp(Element key, String name) => |
1480 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); | 1482 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); |
1481 | 1483 |
1482 JS.ArrayInitializer _emitTypeNames(List<DartType> types) { | 1484 // TODO(vsm): |
Jennifer Messerly
2015/08/07 18:52:59
forgot comment?
vsm
2015/08/07 19:38:30
Doh - thanks - this was the comment I "moved" to l
| |
1483 return new JS.ArrayInitializer( | 1485 List<Annotation> _parameterMetadata(FormalParameter p) => |
1484 new List<JS.Expression>.from(types.map(_emitTypeName))); | 1486 (p is NormalFormalParameter) |
1487 ? p.metadata | |
1488 : (p as DefaultFormalParameter).parameter.metadata; | |
1489 | |
1490 JS.ArrayInitializer _emitTypeNames(List<DartType> types, | |
1491 [List<FormalParameter> parameters]) { | |
1492 var result = <JS.Expression>[]; | |
1493 for (int i = 0; i < types.length; ++i) { | |
1494 var metadata = | |
1495 parameters != null ? _parameterMetadata(parameters[i]) : []; | |
1496 var typeName = _emitTypeName(types[i]); | |
1497 var value = typeName; | |
1498 // TODO(vsm): Make this optional per #268. | |
1499 if (metadata.isNotEmpty) { | |
1500 metadata = metadata.map(_instantiateAnnotation).toList(); | |
1501 value = new JS.ArrayInitializer([typeName]..addAll(metadata)); | |
1502 } | |
1503 result.add(value); | |
1504 } | |
1505 return new JS.ArrayInitializer(result); | |
1485 } | 1506 } |
1486 | 1507 |
1487 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 1508 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
1488 var properties = <JS.Property>[]; | 1509 var properties = <JS.Property>[]; |
1489 types.forEach((name, type) { | 1510 types.forEach((name, type) { |
1490 var key = _propertyName(name); | 1511 var key = _propertyName(name); |
1491 var value = _emitTypeName(type); | 1512 var value = _emitTypeName(type); |
1492 properties.add(new JS.Property(key, value)); | 1513 properties.add(new JS.Property(key, value)); |
1493 }); | 1514 }); |
1494 return new JS.ObjectInitializer(properties); | 1515 return new JS.ObjectInitializer(properties); |
1495 } | 1516 } |
1496 | 1517 |
1497 /// Emit the pieces of a function type, as an array of return type, | 1518 /// Emit the pieces of a function type, as an array of return type, |
1498 /// regular args, and optional/named args. | 1519 /// regular args, and optional/named args. |
1499 List<JS.Expression> _emitFunctionTypeParts(FunctionType type) { | 1520 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, |
1521 [FormalParameterList parameterList]) { | |
1522 var parameters = parameterList?.parameters; | |
1500 var returnType = type.returnType; | 1523 var returnType = type.returnType; |
1501 var parameterTypes = type.normalParameterTypes; | 1524 var parameterTypes = type.normalParameterTypes; |
1502 var optionalTypes = type.optionalParameterTypes; | 1525 var optionalTypes = type.optionalParameterTypes; |
1503 var namedTypes = type.namedParameterTypes; | 1526 var namedTypes = type.namedParameterTypes; |
1504 var rt = _emitTypeName(returnType); | 1527 var rt = _emitTypeName(returnType); |
1505 var ra = _emitTypeNames(parameterTypes); | 1528 var ra = _emitTypeNames(parameterTypes, parameters); |
1506 if (!namedTypes.isEmpty) { | 1529 if (!namedTypes.isEmpty) { |
1507 assert(optionalTypes.isEmpty); | 1530 assert(optionalTypes.isEmpty); |
1531 // TODO(vsm): Pass in annotations here as well. | |
1508 var na = _emitTypeProperties(namedTypes); | 1532 var na = _emitTypeProperties(namedTypes); |
1509 return [rt, ra, na]; | 1533 return [rt, ra, na]; |
1510 } | 1534 } |
1511 if (!optionalTypes.isEmpty) { | 1535 if (!optionalTypes.isEmpty) { |
1512 assert(namedTypes.isEmpty); | 1536 assert(namedTypes.isEmpty); |
1513 var oa = _emitTypeNames(optionalTypes); | 1537 var oa = _emitTypeNames( |
1538 optionalTypes, parameters?.sublist(parameterTypes.length)); | |
1514 return [rt, ra, oa]; | 1539 return [rt, ra, oa]; |
1515 } | 1540 } |
1516 return [rt, ra]; | 1541 return [rt, ra]; |
1517 } | 1542 } |
1518 | 1543 |
1519 JS.Expression _emitFunctionRTTI(FunctionType type) { | 1544 JS.Expression _emitFunctionRTTI(FunctionType type) { |
1520 var parts = _emitFunctionTypeParts(type); | 1545 var parts = _emitFunctionTypeParts(type); |
1521 return js.call('dart.definiteFunctionType(#)', [parts]); | 1546 return js.call('dart.definiteFunctionType(#)', [parts]); |
1522 } | 1547 } |
1523 | 1548 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1687 | 1712 |
1688 var type = getStaticType(target); | 1713 var type = getStaticType(target); |
1689 var name = node.methodName.name; | 1714 var name = node.methodName.name; |
1690 var element = node.methodName.staticElement; | 1715 var element = node.methodName.staticElement; |
1691 bool isStatic = element is ExecutableElement && element.isStatic; | 1716 bool isStatic = element is ExecutableElement && element.isStatic; |
1692 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); | 1717 var memberName = _emitMemberName(name, type: type, isStatic: isStatic); |
1693 | 1718 |
1694 if (DynamicInvoke.get(target)) { | 1719 if (DynamicInvoke.get(target)) { |
1695 code = 'dart.$DSEND(#, #, #)'; | 1720 code = 'dart.$DSEND(#, #, #)'; |
1696 } else if (DynamicInvoke.get(node.methodName)) { | 1721 } else if (DynamicInvoke.get(node.methodName)) { |
1697 // This is a dynamic call to a statically know target. For example: | 1722 // This is a dynamic call to a statically known target. For example: |
1698 // class Foo { Function bar; } | 1723 // class Foo { Function bar; } |
1699 // new Foo().bar(); // dynamic call | 1724 // new Foo().bar(); // dynamic call |
1700 code = 'dart.$DCALL(#.#, #)'; | 1725 code = 'dart.$DCALL(#.#, #)'; |
1701 } else if (_requiresStaticDispatch(target, name)) { | 1726 } else if (_requiresStaticDispatch(target, name)) { |
1702 assert(rules.objectMembers[name] is FunctionType); | 1727 assert(rules.objectMembers[name] is FunctionType); |
1703 // Object methods require a helper for null checks. | 1728 // Object methods require a helper for null checks. |
1704 return js.call('dart.#(#, #)', | 1729 return js.call('dart.#(#, #)', |
1705 [memberName, _visit(target), _visit(node.argumentList)]); | 1730 [memberName, _visit(target), _visit(node.argumentList)]); |
1706 } else { | 1731 } else { |
1707 code = '#.#(#)'; | 1732 code = '#.#(#)'; |
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3050 | 3075 |
3051 /// A special kind of element created by the compiler, signifying a temporary | 3076 /// A special kind of element created by the compiler, signifying a temporary |
3052 /// variable. These objects use instance equality, and should be shared | 3077 /// variable. These objects use instance equality, and should be shared |
3053 /// everywhere in the tree where they are treated as the same variable. | 3078 /// everywhere in the tree where they are treated as the same variable. |
3054 class TemporaryVariableElement extends LocalVariableElementImpl { | 3079 class TemporaryVariableElement extends LocalVariableElementImpl { |
3055 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 3080 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
3056 | 3081 |
3057 int get hashCode => identityHashCode(this); | 3082 int get hashCode => identityHashCode(this); |
3058 bool operator ==(Object other) => identical(this, other); | 3083 bool operator ==(Object other) => identical(this, other); |
3059 } | 3084 } |
OLD | NEW |