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

Side by Side Diff: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart

Issue 2830313002: Split up TypeInferrer class. (Closed)
Patch Set: Created 3 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
(Empty)
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
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.md file.
4
5 import 'package:front_end/src/base/instrumentation.dart';
6 import 'package:front_end/src/dependency_walker.dart' as dependencyWalker;
7 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
8 import 'package:kernel/ast.dart' show DartType, DynamicType;
9 import 'package:kernel/class_hierarchy.dart';
10 import 'package:kernel/core_types.dart';
11
12 /// Data structure for tracking dependencies between fields that require type
13 /// inference.
14 ///
15 /// TODO(paulberry): see if it's possible to make this class more lightweight
16 /// by changing the API so that the walker is passed to computeDependencies().
17 /// (This should allow us to drop the _typeInferenceEngine field).
18 class FieldNode<F> extends dependencyWalker.Node<FieldNode<F>> {
19 final TypeInferenceEngineImpl _typeInferenceEngine;
20
21 final F _field;
22
23 final dependencies = <FieldNode<F>>[];
24
25 FieldNode(this._typeInferenceEngine, this._field);
26
27 @override
28 bool get isEvaluated => _typeInferenceEngine.isFieldInferred(_field);
29
30 @override
31 List<FieldNode<F>> computeDependencies() {
32 return dependencies;
33 }
34 }
35
36 /// Keeps track of the global state for the type inference that occurs outside
37 /// of method bodies and initalizers.
38 ///
39 /// This class abstracts away the representation of the underlying AST using
40 /// generic parameters. TODO(paulberry): would it make more sense to abstract
41 /// away the representation of types as well?
42 ///
43 /// Derived classes should set F to the class they use to represent field
44 /// declarations.
45 ///
46 /// This class describes the interface for use by clients of type inference
47 /// (e.g. DietListener). Derived classes should derive from
48 /// [TypeInferenceEngineImpl].
49 abstract class TypeInferenceEngine<F> {
50 ClassHierarchy get classHierarchy;
51
52 CoreTypes get coreTypes;
53
54 /// Creates a type inferrer for use inside of a method body declared in a file
55 /// with the given [uri].
56 TypeInferrer<dynamic, dynamic, dynamic, F> createLocalTypeInferrer(Uri uri);
57
58 /// Creates a [TypeInferrer] object which is ready to perform type inference
59 /// on the given [field].
60 TypeInferrer<dynamic, dynamic, dynamic, F> createTopLevelTypeInferrer(
61 F field);
62
63 /// Performs the second phase of top level initializer inference, which is to
64 /// visit all fields and top level variables that were passed to [recordField]
65 /// in topologically-sorted order and assign their types.
66 void finishTopLevel();
67
68 /// Gets the list of top level type inference dependencies of the given
69 /// [field].
70 List<FieldNode<F>> getFieldDependencies(F field);
71
72 /// Gets ready to do top level type inference for the program having the given
73 /// [hierarchy], using the given [coreTypes].
74 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy);
75
76 /// Records that the given [field] will need top level type inference.
77 void recordField(F field);
78 }
79
80 /// Derived class containing generic implementations of
81 /// [TypeInferenceEngineImpl].
82 ///
83 /// This class contains as much of the implementation of type inference as
84 /// possible without knowing the identity of the type parameter. It defers to
85 /// abstract methods for everything else.
86 abstract class TypeInferenceEngineImpl<F> extends TypeInferenceEngine<F> {
87 final Instrumentation instrumentation;
88
89 final bool strongMode;
90
91 final fieldNodes = <FieldNode<F>>[];
92
93 @override
94 CoreTypes coreTypes;
95
96 @override
97 ClassHierarchy classHierarchy;
98
99 TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
100
101 /// Cleares the initializer of [field].
102 void clearFieldInitializer(F field);
103
104 /// Creates a [FieldNode] to track dependencies of the given [field].
105 FieldNode<F> createFieldNode(F field);
106
107 /// Queries whether the given [field] has an initializer.
108 bool fieldHasInitializer(F field);
109
110 @override
111 void finishTopLevel() {
112 for (var fieldNode in fieldNodes) {
113 if (fieldNode.isEvaluated) continue;
114 new _FieldWalker<F>().walk(fieldNode);
115 }
116 }
117
118 /// Gets the declared type of the given [field], or `null` if the type is
119 /// implicit.
120 DartType getFieldDeclaredType(F field);
121
122 /// Gets the character offset of the declaration of [field] within its
123 /// compilation unit.
124 int getFieldOffset(F field);
125
126 /// Retrieve the [TypeInferrer] for the given [field], which was created by
127 /// a previous call to [createTopLevelTypeInferrer].
128 TypeInferrerImpl<dynamic, dynamic, dynamic, F> getFieldTypeInferrer(F field);
129
130 /// Gets the URI of the compilation unit the [field] is declared in.
131 /// TODO(paulberry): can we remove this?
132 String getFieldUri(F field);
133
134 /// Performs type inference on the given [field].
135 void inferField(F field) {
136 if (fieldHasInitializer(field)) {
137 var typeInferrer = getFieldTypeInferrer(field);
138 var type = getFieldDeclaredType(field);
139 var inferredType =
140 typeInferrer.inferFieldInitializer(field, type, type == null);
141 if (type == null && strongMode) {
142 instrumentation?.record(
143 'topType',
144 Uri.parse(typeInferrer.uri),
145 getFieldOffset(field),
146 new InstrumentationValueForType(inferredType));
147 setFieldInferredType(field, inferredType);
148 }
149 // TODO(paulberry): if type != null, then check that the type of the
150 // initializer is assignable to it.
151 // TODO(paulberry): the following is a hack so that outlines don't contain
152 // initializers. But it means that we rebuild the initializers when doing
153 // a full compile. There should be a better way.
154 clearFieldInitializer(field);
155 }
156 }
157
158 /// Makes a note that the given [field] is part of a circularity, so its type
159 /// can't be inferred.
160 void inferFieldCircular(F field) {
161 // TODO(paulberry): report the appropriate error.
162 if (getFieldDeclaredType(field) == null) {
163 var uri = getFieldTypeInferrer(field).uri;
164 instrumentation?.record('topType', Uri.parse(uri), getFieldOffset(field),
165 const InstrumentationValueLiteral('circular'));
166 setFieldInferredType(field, const DynamicType());
167 }
168 }
169
170 /// Determines if top level type inference has been completed for [field].
171 bool isFieldInferred(F field);
172
173 @override
174 void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
175 this.coreTypes = coreTypes;
176 this.classHierarchy = classHierarchy;
177 }
178
179 @override
180 void recordField(F field) {
181 fieldNodes.add(createFieldNode(field));
182 }
183
184 /// Stores [inferredType] as the inferred type of [field].
185 void setFieldInferredType(F field, DartType inferredType);
186 }
187
188 /// Subtype of [dependencyWalker.DependencyWalker] which is specialized to
189 /// perform top level type inference.
190 class _FieldWalker<F> extends dependencyWalker.DependencyWalker<FieldNode<F>> {
191 _FieldWalker();
192
193 @override
194 void evaluate(FieldNode<F> f) {
195 f._typeInferenceEngine.inferField(f._field);
196 }
197
198 @override
199 void evaluateScc(List<FieldNode<F>> scc) {
200 for (var f in scc) {
201 f._typeInferenceEngine.inferFieldCircular(f._field);
202 }
203 for (var f in scc) {
204 f._typeInferenceEngine.inferField(f._field);
205 }
206 }
207 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/source/source_loader.dart ('k') | pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698