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

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: Address comments, rebase 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
« no previous file with comments | « lib/src/codegen/dart_codegen.dart ('k') | test/dart_codegen/expect/_internal/iterable.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.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
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
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
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 }
OLDNEW
« no previous file with comments | « lib/src/codegen/dart_codegen.dart ('k') | test/dart_codegen/expect/_internal/iterable.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698