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

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

Issue 1070453002: Refactor reifier to make it less dart_codegen specific. (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Created 5 years, 8 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.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
Jennifer Messerly 2015/04/08 20:28:16 nit: triple slash for doc comment style: /// If n
32 // a type parameter, or a special type like void, dynamic, etc)
33 LibraryElement importedFrom;
34 // True => use/def in same library
vsm 2015/04/08 15:31:02 Does class this describe one specific use? If not
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
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 CoercionManager _cm;
90 final TypeManager _tm; 101 TypeManager _tm;
91 final VariableManager _vm; 102 VariableManager _vm;
103 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 _Inference _inferrer;
96 108
97 UnitCoercionReifier(this._tm, this._vm, this._rules) { 109 CoercionReifier(this._library, this._rules) {
110 _vm = new VariableManager();
Jennifer Messerly 2015/04/08 20:28:16 if you want to keep final fields, it could be done
111 _tm = new TypeManager(_library.library.element.enclosingElement, _vm);
98 _cm = new CoercionManager(_vm, _tm, _rules); 112 _cm = new CoercionManager(_vm, _tm, _rules);
99 _inferrer = new _Inference(_rules, _tm); 113 _inferrer = new _Inference(_rules, _tm);
100 } 114 }
101 115
102 // This should be the entry point for this class. Entering via the 116 // This should be the entry point for this class. Entering via the
103 // visit functions directly may not do the right thing with respect 117 // visit functions directly may not do the right thing with respect
104 // to discharging the collected definitions. 118 // to discharging the collected definitions.
105 void reify(CompilationUnit unit) { 119 // Returns the set of new type identifiers added by the reifier
120 Map<Identifier, NewTypeIdDesc> reify() {
121 for (var unit in _library.partsThenLibrary) {
Jennifer Messerly 2015/04/08 20:28:16 _library.partsThenLibrary.forEach(generateUnit); ?
122 generateUnit(unit);
123 }
124 return _tm.addedTypes;
125 }
126
127 void generateUnit(CompilationUnit unit) {
106 _file = new SourceFile(unit.element.source.contents.data, 128 _file = new SourceFile(unit.element.source.contents.data,
107 url: unit.element.source.uri); 129 url: unit.element.source.uri);
108 visitCompilationUnit(unit); 130 visitCompilationUnit(unit);
131 _file = null;
109 } 132 }
110 133
111 ///////////////// Private ////////////////////////////////// 134 ///////////////// Private //////////////////////////////////
112 135
113 String _locationInfo(Expression e) { 136 String _locationInfo(Expression e) {
114 if (_file != null) { 137 if (_file != null) {
115 final begin = e is AnnotatedNode 138 final begin = e is AnnotatedNode
116 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset 139 ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
117 : e.offset; 140 : e.offset;
118 if (begin != 0) { 141 if (begin != 0) {
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 } 542 }
520 543
521 // A class for managing the interaction between the DartType hierarchy 544 // A class for managing the interaction between the DartType hierarchy
522 // and the AST type representation. It provides utilities to translate 545 // 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 546 // 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 547 // 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. 548 // 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 549 // Note that in order to hoist the typedefs out of parameterized classes
527 // we must close over any type variables. 550 // we must close over any type variables.
528 class TypeManager { 551 class TypeManager {
529 VariableManager _vm; 552 final VariableManager _vm;
530 Set<TypeName> _newTypes = new Set<TypeName>(); 553 final LibraryElement _currentLibrary;
554 final Map<Identifier, NewTypeIdDesc> addedTypes =
vsm 2015/04/08 15:31:02 Omit the type on the left?
555 new Map<Identifier, NewTypeIdDesc>();
531 556
532 /// A map containing new function typedefs to be introduced at the top level 557 /// A map containing new function typedefs to be introduced at the top level
533 /// This uses LinkedHashMap to emit code in a consistent order. 558 /// This uses LinkedHashMap to emit code in a consistent order.
534 final Map<FunctionType, FunctionTypeAlias> _typedefs = 559 final Map<FunctionType, FunctionTypeAlias> _typedefs =
535 new Map<FunctionType, FunctionTypeAlias>(); 560 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) 606 // TODO(leafp): The inner conditional (testing FunctionType, etc)
584 // can be eliminated after the roll to the next analyzer which fixes 607 // can be eliminated after the roll to the next analyzer which fixes
585 // a bug in how they resolve type names. 608 // a bug in how they resolve type names.
586 if (type.name != null && type.name != "") { 609 if (type.name != null && type.name != "") {
587 if (type is! FunctionType || 610 if (type is! FunctionType ||
588 (type.element != null && type.element is FunctionTypeAlias)) { 611 (type.element != null && type.element is FunctionTypeAlias)) {
vsm 2015/04/08 18:27:09 BTW, shouldn't this be: type is FunctionTypeAlias
589 _ftList(type.typeArguments); 612 _ftList(type.typeArguments);
590 return; 613 return;
591 } 614 }
592 } 615 }
593 if (type is FunctionType) { 616 if (type is FunctionType) {
594 _ftMap(type.namedParameterTypes); 617 _ftMap(type.namedParameterTypes);
595 _ftList(type.normalParameterTypes); 618 _ftList(type.normalParameterTypes);
596 _ftList(type.optionalParameterTypes); 619 _ftList(type.optionalParameterTypes);
597 _ft(type.returnType); 620 _ft(type.returnType);
598 return; 621 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 666
644 NormalFormalParameter _typedFormal(Identifier v, DartType type) { 667 NormalFormalParameter _typedFormal(Identifier v, DartType type) {
645 if (type is FunctionType) { 668 if (type is FunctionType) {
646 return _functionTypedFormal(v, type); 669 return _functionTypedFormal(v, type);
647 } 670 }
648 assert(type.name != null); 671 assert(type.name != null);
649 TypeName t = typeNameFromDartType(type); 672 TypeName t = typeNameFromDartType(type);
650 return AstBuilder.simpleFormal(v, t); 673 return AstBuilder.simpleFormal(v, t);
651 } 674 }
652 675
676 Identifier freshTypeDefVariable() {
677 var t = _vm.freshTypeIdentifier("t");
678 var desc = new NewTypeIdDesc(
679 fromCurrent: true, importedFrom: _currentLibrary, synthetic: true);
680 addedTypes[t] = desc;
681 return t;
682 }
683
684 Identifier typeParameterFromString(String name) =>
685 AstBuilder.identifierFromString(name);
686
687 Identifier freshReferenceToNamedType(DartType type) {
688 var name = type.name;
689 assert(name != null);
690 var id = AstBuilder.identifierFromString(name);
691 var element = type.element;
692 id.staticElement = element;
693 var library = null;
694 // This can happen for types like (e.g.) void
695 if (element != null) library = element.library;
696 var desc = new NewTypeIdDesc(
697 fromCurrent: _currentLibrary == library,
698 importedFrom: library,
699 synthetic: false);
700 addedTypes[id] = desc;
701 return id;
702 }
703
653 // I think we can avoid alpha-varying type parameters, since 704 // I think we can avoid alpha-varying type parameters, since
654 // the binding forms are so limited, so we just re-use the 705 // the binding forms are so limited, so we just re-use the
655 // the original names for the formals and the actuals. 706 // the original names for the formals and the actuals.
656 TypeName _typeNameFromFunctionType(FunctionType type) { 707 TypeName _typeNameFromFunctionType(FunctionType type) {
657 if (_typedefs.containsKey(type)) { 708 if (_typedefs.containsKey(type)) {
658 var alias = _typedefs[type]; 709 var alias = _typedefs[type];
659 var ts = null; 710 var ts = null;
660 var tpl = alias.typeParameters; 711 var tpl = alias.typeParameters;
661 if (tpl != null) { 712 if (tpl != null) {
662 var ltp = tpl.typeParameters; 713 var ltp = tpl.typeParameters;
663 ts = new List<TypeName>.from( 714 ts = new List<TypeName>.from(
664 ltp.map((t) => _mkNewTypeName(t.name, null))); 715 ltp.map((t) => _mkNewTypeName(t.name, null)));
665 } 716 }
666 var name = alias.name; 717 var name = alias.name;
667 return _mkNewTypeName(name, ts); 718 return _mkNewTypeName(name, ts);
668 } 719 }
669 720
670 List<TypeParameterType> ftvs = _freeTypeVariables(type); 721 List<TypeParameterType> ftvs = _freeTypeVariables(type);
671 Identifier t = _vm.freshTypeIdentifier("t"); 722 Identifier t = freshTypeDefVariable();
672 723
673 Iterable<Identifier> tNames = 724 Iterable<Identifier> tNames =
674 ftvs.map((x) => AstBuilder.identifierFromString(x.name)); 725 ftvs.map((x) => typeParameterFromString(x.name));
675 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList(); 726 List<TypeParameter> tps = tNames.map(AstBuilder.typeParameter).toList();
676 List<FormalParameter> fps = _formalParameterListForFunctionType(type); 727 List<FormalParameter> fps = _formalParameterListForFunctionType(type);
677 TypeName ret = _typeNameFromDartType(type.returnType); 728 TypeName ret = _typeNameFromDartType(type.returnType);
678 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps); 729 FunctionTypeAlias alias = AstBuilder.functionTypeAlias(ret, t, tps, fps);
679 730
680 _typedefs[type] = alias; 731 _typedefs[type] = alias;
681 732
682 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList(); 733 List<TypeName> args = ftvs.map(_typeNameFromDartType).toList();
683 TypeName namedType = _mkNewTypeName(t, args); 734 TypeName namedType = _mkNewTypeName(t, args);
684 735
685 return namedType; 736 return namedType;
686 } 737 }
687 738
688 TypeName _typeNameFromDartType(DartType dType) { 739 TypeName _typeNameFromDartType(DartType dType) {
689 // TODO(leafp) This doesn't re-use the name when the function type
690 // is derived from a typedef, since I've moved it above the check
691 // for a name. I think there's a bug in the resolver here: I
692 // sometimes see function types named not with a typedef name,
693 // but rather with the name of the function that they classify.
694 if (dType is FunctionType) return _typeNameFromFunctionType(dType);
695 String name = dType.name; 740 String name = dType.name;
696 if (name == null || name == "" || dType.isBottom) { 741 if (name == null || name == "" || dType.isBottom) {
742 if (dType is FunctionType) return _typeNameFromFunctionType(dType);
Leaf 2015/04/07 22:29:58 This is the only thing that changes the output cod
697 _log.severe("No name for type, casting through dynamic"); 743 _log.severe("No name for type, casting through dynamic");
698 var d = AstBuilder.identifierFromString("dynamic"); 744 var d = AstBuilder.identifierFromString("dynamic");
699 var t = _mkNewTypeName(d, null); 745 var t = _mkNewTypeName(d, null);
700 t.type = dType; 746 t.type = dType;
701 return t; 747 return t;
702 } 748 }
703 SimpleIdentifier id = AstBuilder.identifierFromString(name); 749 SimpleIdentifier id = freshReferenceToNamedType(dType);
704 id.staticElement = dType.element;
705 List<TypeName> args = null; 750 List<TypeName> args = null;
706 if (dType is ParameterizedType) { 751 if (dType is ParameterizedType) {
707 List<DartType> targs = dType.typeArguments; 752 List<DartType> targs = dType.typeArguments;
708 args = targs.map(_typeNameFromDartType).toList(); 753 args = targs.map(_typeNameFromDartType).toList();
709 } 754 }
710 var t = _mkNewTypeName(id, args); 755 var t = _mkNewTypeName(id, args);
711 t.type = dType; 756 t.type = dType;
712 return t; 757 return t;
713 } 758 }
714 759
715 TypeName _mkNewTypeName(Identifier id, List<TypeName> args) { 760 TypeName _mkNewTypeName(Identifier id, List<TypeName> args) {
716 var t = AstBuilder.typeName(id, args); 761 var t = AstBuilder.typeName(id, args);
717 _newTypes.add(t);
718 return t; 762 return t;
719 } 763 }
720 764
721 Expression _typeExpression(TypeName t) { 765 Expression _typeExpression(TypeName t) {
722 if (t.typeArguments != null && t.typeArguments.length > 0) { 766 if (t.typeArguments != null && t.typeArguments.length > 0) {
723 var w = AstBuilder.identifierFromString("_"); 767 var w = AstBuilder.identifierFromString("_");
724 var fp = AstBuilder.simpleFormal(w, t); 768 var fp = AstBuilder.simpleFormal(w, t);
725 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]); 769 var f = AstBuilder.blockFunction(<FormalParameter>[fp], <Statement>[]);
726 return new RuntimeOperation("type", <Expression>[f]); 770 return new RuntimeOperation("type", <Expression>[f]);
727 } 771 }
728 return t.name; 772 return t.name;
729 } 773 }
730 } 774 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698