| 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.reify_coercions; | 5 library dev_compiler.src.codegen.reify_coercions; |
| 6 | 6 |
| 7 import 'package:analyzer/analyzer.dart' as analyzer; | 7 import 'package:analyzer/analyzer.dart' as analyzer; |
| 8 import 'package:analyzer/src/generated/ast.dart'; | 8 import 'package:analyzer/src/generated/ast.dart'; |
| 9 import 'package:analyzer/src/generated/element.dart'; | 9 import 'package:analyzer/src/generated/element.dart'; |
| 10 import 'package:logging/logging.dart' as logger; | 10 import 'package:logging/logging.dart' as logger; |
| 11 import 'package:source_span/source_span.dart' show SourceFile; | 11 import 'package:source_span/source_span.dart' show SourceFile; |
| 12 | 12 |
| 13 import 'package:dev_compiler/src/checker/rules.dart'; | 13 import 'package:dev_compiler/src/checker/rules.dart'; |
| 14 import 'package:dev_compiler/src/info.dart'; | 14 import 'package:dev_compiler/src/info.dart'; |
| 15 import 'package:dev_compiler/src/utils.dart' as utils; | 15 import 'package:dev_compiler/src/utils.dart' as utils; |
| 16 | 16 |
| 17 import 'ast_builder.dart'; | 17 import 'ast_builder.dart'; |
| 18 | 18 |
| 19 final _log = new logger.Logger('dev_compiler.reify_coercions'); | 19 final _log = new logger.Logger('dev_compiler.reify_coercions'); |
| 20 | 20 |
| 21 // TODO(leafp) Factor this out or use an existing library | 21 // TODO(leafp) Factor this out or use an existing library |
| 22 class Tuple2<T0, T1> { | 22 class Tuple2<T0, T1> { |
| 23 final T0 e0; | 23 final T0 e0; |
| 24 final T1 e1; | 24 final T1 e1; |
| 25 Tuple2(this.e0, this.e1); | 25 Tuple2(this.e0, this.e1); |
| 26 } | 26 } |
| 27 | 27 |
| 28 typedef T Function1<S, T>(S _); | 28 typedef T Function1<S, T>(S _); |
| 29 | 29 |
| 30 class NewTypeIdDesc { |
| 31 /// If null, then this is not a library level identifier (i.e. it's |
| 32 /// a type parameter, or a special type like void, dynamic, etc) |
| 33 LibraryElement importedFrom; |
| 34 /// True => use/def in same library |
| 35 bool fromCurrent; |
| 36 /// True => not a source variable |
| 37 bool synthetic; |
| 38 NewTypeIdDesc({this.fromCurrent, this.importedFrom, this.synthetic}); |
| 39 } |
| 40 |
| 30 class _LocatedWrapper { | 41 class _LocatedWrapper { |
| 31 final String loc; | 42 final String loc; |
| 32 final Wrapper wrapper; | 43 final Wrapper wrapper; |
| 33 _LocatedWrapper(this.wrapper, this.loc); | 44 _LocatedWrapper(this.wrapper, this.loc); |
| 34 } | 45 } |
| 35 | 46 |
| 36 class _Inference extends DownwardsInference { | 47 class _Inference extends DownwardsInference { |
| 37 TypeManager _tm; | 48 TypeManager _tm; |
| 38 | 49 |
| 39 _Inference(TypeRules rules, this._tm) : super(rules); | 50 _Inference(TypeRules rules, this._tm) : super(rules); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 88 |
| 78 @override | 89 @override |
| 79 void annotateFunctionExpression(FunctionExpression e, DartType returnType) { | 90 void annotateFunctionExpression(FunctionExpression e, DartType returnType) { |
| 80 // Implicitly changes e.staticType | 91 // Implicitly changes e.staticType |
| 81 (e.element as ExecutableElementImpl).returnType = returnType; | 92 (e.element as ExecutableElementImpl).returnType = returnType; |
| 82 } | 93 } |
| 83 } | 94 } |
| 84 | 95 |
| 85 // This class implements a pass which modifies (in place) the ast replacing | 96 // This class implements a pass which modifies (in place) the ast replacing |
| 86 // abstract coercion nodes with their dart implementations. | 97 // abstract coercion nodes with their dart implementations. |
| 87 class UnitCoercionReifier extends analyzer.GeneralizingAstVisitor<Object> | 98 class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> |
| 88 with ConversionVisitor<Object> { | 99 with ConversionVisitor<Object> { |
| 89 CoercionManager _cm; | 100 final CoercionManager _cm; |
| 90 final TypeManager _tm; | 101 final TypeManager _tm; |
| 91 final VariableManager _vm; | 102 final VariableManager _vm; |
| 103 final LibraryUnit _library; |
| 92 SourceFile _file; | 104 SourceFile _file; |
| 93 bool _skipCoercions = false; | 105 bool _skipCoercions = false; |
| 94 final TypeRules _rules; | 106 final TypeRules _rules; |
| 95 _Inference _inferrer; | 107 final _Inference _inferrer; |
| 96 | 108 |
| 97 UnitCoercionReifier(this._tm, this._vm, this._rules) { | 109 CoercionReifier._( |
| 98 _cm = new CoercionManager(_vm, _tm, _rules); | 110 this._cm, this._tm, this._vm, this._library, this._rules, this._inferrer); |
| 99 _inferrer = new _Inference(_rules, _tm); | 111 |
| 112 factory CoercionReifier(LibraryUnit library, TypeRules rules) { |
| 113 var vm = new VariableManager(); |
| 114 var tm = new TypeManager(library.library.element.enclosingElement, vm); |
| 115 var cm = new CoercionManager(vm, tm, rules); |
| 116 var inferrer = new _Inference(rules, tm); |
| 117 return new CoercionReifier._(cm, tm, vm, library, rules, inferrer); |
| 100 } | 118 } |
| 101 | 119 |
| 102 // This should be the entry point for this class. Entering via the | 120 // This should be the entry point for this class. Entering via the |
| 103 // visit functions directly may not do the right thing with respect | 121 // visit functions directly may not do the right thing with respect |
| 104 // to discharging the collected definitions. | 122 // to discharging the collected definitions. |
| 105 void reify(CompilationUnit unit) { | 123 // Returns the set of new type identifiers added by the reifier |
| 124 Map<Identifier, NewTypeIdDesc> reify() { |
| 125 _library.partsThenLibrary.forEach(generateUnit); |
| 126 return _tm.addedTypes; |
| 127 } |
| 128 |
| 129 void generateUnit(CompilationUnit unit) { |
| 106 _file = new SourceFile(unit.element.source.contents.data, | 130 _file = new SourceFile(unit.element.source.contents.data, |
| 107 url: unit.element.source.uri); | 131 url: unit.element.source.uri); |
| 108 visitCompilationUnit(unit); | 132 visitCompilationUnit(unit); |
| 133 _file = null; |
| 109 } | 134 } |
| 110 | 135 |
| 111 ///////////////// Private ////////////////////////////////// | 136 ///////////////// Private ////////////////////////////////// |
| 112 | 137 |
| 113 String _locationInfo(Expression e) { | 138 String _locationInfo(Expression e) { |
| 114 if (_file != null) { | 139 if (_file != null) { |
| 115 final begin = e is AnnotatedNode | 140 final begin = e is AnnotatedNode |
| 116 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset | 141 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset |
| 117 : e.offset; | 142 : e.offset; |
| 118 if (begin != 0) { | 143 if (begin != 0) { |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 } | 544 } |
| 520 | 545 |
| 521 // A class for managing the interaction between the DartType hierarchy | 546 // A class for managing the interaction between the DartType hierarchy |
| 522 // and the AST type representation. It provides utilities to translate | 547 // and the AST type representation. It provides utilities to translate |
| 523 // a DartType to AST. In order to do so, it maintains a map of typedefs | 548 // a DartType to AST. In order to do so, it maintains a map of typedefs |
| 524 // naming otherwise un-named types. These must be discharged at the top | 549 // naming otherwise un-named types. These must be discharged at the top |
| 525 // level of the compilation unit in order to produce well-formed dart code. | 550 // level of the compilation unit in order to produce well-formed dart code. |
| 526 // Note that in order to hoist the typedefs out of parameterized classes | 551 // Note that in order to hoist the typedefs out of parameterized classes |
| 527 // we must close over any type variables. | 552 // we must close over any type variables. |
| 528 class TypeManager { | 553 class TypeManager { |
| 529 VariableManager _vm; | 554 final VariableManager _vm; |
| 530 Set<TypeName> _newTypes = new Set<TypeName>(); | 555 final LibraryElement _currentLibrary; |
| 556 final Map<Identifier, NewTypeIdDesc> addedTypes = {}; |
| 531 | 557 |
| 532 /// A map containing new function typedefs to be introduced at the top level | 558 /// A map containing new function typedefs to be introduced at the top level |
| 533 /// This uses LinkedHashMap to emit code in a consistent order. | 559 /// This uses LinkedHashMap to emit code in a consistent order. |
| 534 final Map<FunctionType, FunctionTypeAlias> _typedefs = | 560 final Map<FunctionType, FunctionTypeAlias> _typedefs = {}; |
| 535 new Map<FunctionType, FunctionTypeAlias>(); | |
| 536 | 561 |
| 537 TypeManager(this._vm); | 562 TypeManager(this._currentLibrary, this._vm); |
| 538 | 563 |
| 539 void enterCompilationUnit() {} | 564 void enterCompilationUnit() {} |
| 540 void exitCompilationUnit(CompilationUnit unit) { | 565 void exitCompilationUnit(CompilationUnit unit) { |
| 541 unit.declarations.addAll(_typedefs.values); | 566 unit.declarations.addAll(_typedefs.values); |
| 542 _typedefs.clear(); | 567 _typedefs.clear(); |
| 543 } | 568 } |
| 544 | 569 |
| 545 TypeName typeNameFromDartType(DartType dType) { | 570 TypeName typeNameFromDartType(DartType dType) { |
| 546 return _typeNameFromDartType(dType); | 571 return _typeNameFromDartType(dType); |
| 547 } | 572 } |
| 548 | 573 |
| 549 NormalFormalParameter typedFormal(Identifier v, DartType type) { | 574 NormalFormalParameter typedFormal(Identifier v, DartType type) { |
| 550 return _typedFormal(v, type); | 575 return _typedFormal(v, type); |
| 551 } | 576 } |
| 552 | 577 |
| 553 Expression typeExpressionFromDartType(DartType t) => | 578 Expression typeExpressionFromDartType(DartType t) => |
| 554 typeExpression(typeNameFromDartType(t)); | 579 typeExpression(typeNameFromDartType(t)); |
| 555 | 580 |
| 556 Expression typeExpression(TypeName t) => _typeExpression(t); | 581 Expression typeExpression(TypeName t) => _typeExpression(t); |
| 557 | 582 |
| 558 Set<TypeName> get addedTypes => _newTypes; | |
| 559 | |
| 560 ///////////////// Private ////////////////////////////////// | 583 ///////////////// Private ////////////////////////////////// |
| 561 List<TypeParameterType> _freeTypeVariables(DartType type) { | 584 List<TypeParameterType> _freeTypeVariables(DartType type) { |
| 562 var s = new Set<TypeParameterType>(); | 585 var s = new Set<TypeParameterType>(); |
| 563 | 586 |
| 564 void _ft(DartType type) { | 587 void _ft(DartType type) { |
| 565 void _ftMap(Map<String, DartType> m) { | 588 void _ftMap(Map<String, DartType> m) { |
| 566 if (m == null) return; | 589 if (m == null) return; |
| 567 for (var k in m.keys) _ft(m[k]); | 590 for (var k in m.keys) _ft(m[k]); |
| 568 } | 591 } |
| 569 void _ftList(List<DartType> l) { | 592 void _ftList(List<DartType> l) { |
| 570 if (l == null) return; | 593 if (l == null) return; |
| 571 for (int i = 0; i < l.length; i++) _ft(l[i]); | 594 for (int i = 0; i < l.length; i++) _ft(l[i]); |
| 572 } | 595 } |
| 573 | 596 |
| 574 if (type == null) return; | 597 if (type == null) return; |
| 575 if (type.isDynamic) return; | 598 if (type.isDynamic) return; |
| 576 if (type.isBottom) return; | 599 if (type.isBottom) return; |
| 577 if (type.isObject) return; | 600 if (type.isObject) return; |
| 578 if (type is TypeParameterType) { | 601 if (type is TypeParameterType) { |
| 579 s.add(type); | 602 s.add(type); |
| 580 return; | 603 return; |
| 581 } | 604 } |
| 582 if (type is ParameterizedType) { | 605 if (type is ParameterizedType) { |
| 583 // TODO(leafp): The inner conditional (testing FunctionType, etc) | |
| 584 // can be eliminated after the roll to the next analyzer which fixes | |
| 585 // a bug in how they resolve type names. | |
| 586 if (type.name != null && type.name != "") { | 606 if (type.name != null && type.name != "") { |
| 587 if (type is! FunctionType || | 607 _ftList(type.typeArguments); |
| 588 (type.element != null && type.element is FunctionTypeAlias)) { | 608 return; |
| 589 _ftList(type.typeArguments); | |
| 590 return; | |
| 591 } | |
| 592 } | 609 } |
| 593 if (type is FunctionType) { | 610 if (type is FunctionType) { |
| 594 _ftMap(type.namedParameterTypes); | 611 _ftMap(type.namedParameterTypes); |
| 595 _ftList(type.normalParameterTypes); | 612 _ftList(type.normalParameterTypes); |
| 596 _ftList(type.optionalParameterTypes); | 613 _ftList(type.optionalParameterTypes); |
| 597 _ft(type.returnType); | 614 _ft(type.returnType); |
| 598 return; | 615 return; |
| 599 } | 616 } |
| 600 assert(type is! InterfaceType); | 617 assert(type is! InterfaceType); |
| 601 assert(false); | 618 assert(false); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 | 659 |
| 643 NormalFormalParameter _typedFormal(Identifier v, DartType type) { | 660 NormalFormalParameter _typedFormal(Identifier v, DartType type) { |
| 644 if (type is FunctionType) { | 661 if (type is FunctionType) { |
| 645 return _functionTypedFormal(v, type); | 662 return _functionTypedFormal(v, type); |
| 646 } | 663 } |
| 647 assert(type.name != null); | 664 assert(type.name != null); |
| 648 TypeName t = typeNameFromDartType(type); | 665 TypeName t = typeNameFromDartType(type); |
| 649 return AstBuilder.simpleFormal(v, t); | 666 return AstBuilder.simpleFormal(v, t); |
| 650 } | 667 } |
| 651 | 668 |
| 669 Identifier freshTypeDefVariable() { |
| 670 var t = _vm.freshTypeIdentifier("t"); |
| 671 var desc = new NewTypeIdDesc( |
| 672 fromCurrent: true, importedFrom: _currentLibrary, synthetic: true); |
| 673 addedTypes[t] = desc; |
| 674 return t; |
| 675 } |
| 676 |
| 677 Identifier typeParameterFromString(String name) => |
| 678 AstBuilder.identifierFromString(name); |
| 679 |
| 680 Identifier freshReferenceToNamedType(DartType type) { |
| 681 var name = type.name; |
| 682 assert(name != null); |
| 683 var id = AstBuilder.identifierFromString(name); |
| 684 var element = type.element; |
| 685 id.staticElement = element; |
| 686 var library = null; |
| 687 // This can happen for types like (e.g.) void |
| 688 if (element != null) library = element.library; |
| 689 var desc = new NewTypeIdDesc( |
| 690 fromCurrent: _currentLibrary == library, |
| 691 importedFrom: library, |
| 692 synthetic: false); |
| 693 addedTypes[id] = desc; |
| 694 return id; |
| 695 } |
| 696 |
| 652 // I think we can avoid alpha-varying type parameters, since | 697 // I think we can avoid alpha-varying type parameters, since |
| 653 // the binding forms are so limited, so we just re-use the | 698 // the binding forms are so limited, so we just re-use the |
| 654 // the original names for the formals and the actuals. | 699 // the original names for the formals and the actuals. |
| 655 TypeName _typeNameFromFunctionType(FunctionType type) { | 700 TypeName _typeNameFromFunctionType(FunctionType type) { |
| 656 if (_typedefs.containsKey(type)) { | 701 if (_typedefs.containsKey(type)) { |
| 657 var alias = _typedefs[type]; | 702 var alias = _typedefs[type]; |
| 658 var ts = null; | 703 var ts = null; |
| 659 var tpl = alias.typeParameters; | 704 var tpl = alias.typeParameters; |
| 660 if (tpl != null) { | 705 if (tpl != null) { |
| 661 var ltp = tpl.typeParameters; | 706 var ltp = tpl.typeParameters; |
| 662 ts = new List<TypeName>.from( | 707 ts = new List<TypeName>.from( |
| 663 ltp.map((t) => _mkNewTypeName(t.name, null))); | 708 ltp.map((t) => _mkNewTypeName(t.name, null))); |
| 664 } | 709 } |
| 665 var name = alias.name; | 710 var name = alias.name; |
| 666 return _mkNewTypeName(name, ts); | 711 return _mkNewTypeName(name, ts); |
| 667 } | 712 } |
| 668 | 713 |
| 669 List<TypeParameterType> ftvs = _freeTypeVariables(type); | 714 List<TypeParameterType> ftvs = _freeTypeVariables(type); |
| 670 Identifier t = _vm.freshTypeIdentifier("t"); | 715 Identifier t = freshTypeDefVariable(); |
| 671 | 716 |
| 672 Iterable<Identifier> tNames = | 717 Iterable<Identifier> tNames = |
| 673 ftvs.map((x) => AstBuilder.identifierFromString(x.name)); | 718 ftvs.map((x) => typeParameterFromString(x.name)); |
| 674 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList(); | 719 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList(); |
| 675 List<FormalParameter> fps = _formalParameterListForFunctionType(type); | 720 List<FormalParameter> fps = _formalParameterListForFunctionType(type); |
| 676 TypeName ret = _typeNameFromDartType(type.returnType); | 721 TypeName ret = _typeNameFromDartType(type.returnType); |
| 677 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps); | 722 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps); |
| 678 | 723 |
| 679 _typedefs[type] = alias; | 724 _typedefs[type] = alias; |
| 680 | 725 |
| 681 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList(); | 726 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList(); |
| 682 TypeName namedType = _mkNewTypeName(t, args); | 727 TypeName namedType = _mkNewTypeName(t, args); |
| 683 | 728 |
| 684 return namedType; | 729 return namedType; |
| 685 } | 730 } |
| 686 | 731 |
| 687 TypeName _typeNameFromDartType(DartType dType) { | 732 TypeName _typeNameFromDartType(DartType dType) { |
| 688 // TODO(leafp) This doesn't re-use the name when the function type | |
| 689 // is derived from a typedef, since I've moved it above the check | |
| 690 // for a name. I think there's a bug in the resolver here: I | |
| 691 // sometimes see function types named not with a typedef name, | |
| 692 // but rather with the name of the function that they classify. | |
| 693 if (dType is FunctionType) return _typeNameFromFunctionType(dType); | |
| 694 String name = dType.name; | 733 String name = dType.name; |
| 695 if (name == null || name == "" || dType.isBottom) { | 734 if (name == null || name == "" || dType.isBottom) { |
| 735 if (dType is FunctionType) return _typeNameFromFunctionType(dType); |
| 696 _log.severe("No name for type, casting through dynamic"); | 736 _log.severe("No name for type, casting through dynamic"); |
| 697 var d = AstBuilder.identifierFromString("dynamic"); | 737 var d = AstBuilder.identifierFromString("dynamic"); |
| 698 var t = _mkNewTypeName(d, null); | 738 var t = _mkNewTypeName(d, null); |
| 699 t.type = dType; | 739 t.type = dType; |
| 700 return t; | 740 return t; |
| 701 } | 741 } |
| 702 SimpleIdentifier id = AstBuilder.identifierFromString(name); | 742 SimpleIdentifier id = freshReferenceToNamedType(dType); |
| 703 id.staticElement = dType.element; | |
| 704 List<TypeName> args = null; | 743 List<TypeName> args = null; |
| 705 if (dType is ParameterizedType) { | 744 if (dType is ParameterizedType) { |
| 706 List<DartType> targs = dType.typeArguments; | 745 List<DartType> targs = dType.typeArguments; |
| 707 args = targs.map(_typeNameFromDartType).toList(); | 746 args = targs.map(_typeNameFromDartType).toList(); |
| 708 } | 747 } |
| 709 var t = _mkNewTypeName(id, args); | 748 var t = _mkNewTypeName(id, args); |
| 710 t.type = dType; | 749 t.type = dType; |
| 711 return t; | 750 return t; |
| 712 } | 751 } |
| 713 | 752 |
| 714 TypeName _mkNewTypeName(Identifier id, List<TypeName> args) { | 753 TypeName _mkNewTypeName(Identifier id, List<TypeName> args) { |
| 715 var t = AstBuilder.typeName(id, args); | 754 var t = AstBuilder.typeName(id, args); |
| 716 _newTypes.add(t); | |
| 717 return t; | 755 return t; |
| 718 } | 756 } |
| 719 | 757 |
| 720 Expression _typeExpression(TypeName t) { | 758 Expression _typeExpression(TypeName t) { |
| 721 if (t.typeArguments != null && t.typeArguments.length > 0) { | 759 if (t.typeArguments != null && t.typeArguments.length > 0) { |
| 722 var w = AstBuilder.identifierFromString("_"); | 760 var w = AstBuilder.identifierFromString("_"); |
| 723 var fp = AstBuilder.simpleFormal(w, t); | 761 var fp = AstBuilder.simpleFormal(w, t); |
| 724 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]); | 762 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]); |
| 725 return new RuntimeOperation("type", <Expression>[f]); | 763 return new RuntimeOperation("type", <Expression>[f]); |
| 726 } | 764 } |
| 727 return t.name; | 765 return t.name; |
| 728 } | 766 } |
| 729 } | 767 } |
| OLD | NEW |