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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
new file mode 100644
index 0000000000000000000000000000000000000000..91196c868d543ef130858c1038324495e4543140
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE.md file.
+
+import 'package:front_end/src/base/instrumentation.dart';
+import 'package:front_end/src/dependency_walker.dart' as dependencyWalker;
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
+import 'package:kernel/ast.dart' show DartType, DynamicType;
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+
+/// Data structure for tracking dependencies between fields that require type
+/// inference.
+///
+/// TODO(paulberry): see if it's possible to make this class more lightweight
+/// by changing the API so that the walker is passed to computeDependencies().
+/// (This should allow us to drop the _typeInferenceEngine field).
+class FieldNode<F> extends dependencyWalker.Node<FieldNode<F>> {
+ final TypeInferenceEngineImpl _typeInferenceEngine;
+
+ final F _field;
+
+ final dependencies = <FieldNode<F>>[];
+
+ FieldNode(this._typeInferenceEngine, this._field);
+
+ @override
+ bool get isEvaluated => _typeInferenceEngine.isFieldInferred(_field);
+
+ @override
+ List<FieldNode<F>> computeDependencies() {
+ return dependencies;
+ }
+}
+
+/// Keeps track of the global state for the type inference that occurs outside
+/// of method bodies and initalizers.
+///
+/// This class abstracts away the representation of the underlying AST using
+/// generic parameters. TODO(paulberry): would it make more sense to abstract
+/// away the representation of types as well?
+///
+/// Derived classes should set F to the class they use to represent field
+/// declarations.
+///
+/// This class describes the interface for use by clients of type inference
+/// (e.g. DietListener). Derived classes should derive from
+/// [TypeInferenceEngineImpl].
+abstract class TypeInferenceEngine<F> {
+ ClassHierarchy get classHierarchy;
+
+ CoreTypes get coreTypes;
+
+ /// Creates a type inferrer for use inside of a method body declared in a file
+ /// with the given [uri].
+ TypeInferrer<dynamic, dynamic, dynamic, F> createLocalTypeInferrer(Uri uri);
+
+ /// Creates a [TypeInferrer] object which is ready to perform type inference
+ /// on the given [field].
+ TypeInferrer<dynamic, dynamic, dynamic, F> createTopLevelTypeInferrer(
+ F field);
+
+ /// Performs the second phase of top level initializer inference, which is to
+ /// visit all fields and top level variables that were passed to [recordField]
+ /// in topologically-sorted order and assign their types.
+ void finishTopLevel();
+
+ /// Gets the list of top level type inference dependencies of the given
+ /// [field].
+ List<FieldNode<F>> getFieldDependencies(F field);
+
+ /// Gets ready to do top level type inference for the program having the given
+ /// [hierarchy], using the given [coreTypes].
+ void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy);
+
+ /// Records that the given [field] will need top level type inference.
+ void recordField(F field);
+}
+
+/// Derived class containing generic implementations of
+/// [TypeInferenceEngineImpl].
+///
+/// This class contains as much of the implementation of type inference as
+/// possible without knowing the identity of the type parameter. It defers to
+/// abstract methods for everything else.
+abstract class TypeInferenceEngineImpl<F> extends TypeInferenceEngine<F> {
+ final Instrumentation instrumentation;
+
+ final bool strongMode;
+
+ final fieldNodes = <FieldNode<F>>[];
+
+ @override
+ CoreTypes coreTypes;
+
+ @override
+ ClassHierarchy classHierarchy;
+
+ TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
+
+ /// Cleares the initializer of [field].
+ void clearFieldInitializer(F field);
+
+ /// Creates a [FieldNode] to track dependencies of the given [field].
+ FieldNode<F> createFieldNode(F field);
+
+ /// Queries whether the given [field] has an initializer.
+ bool fieldHasInitializer(F field);
+
+ @override
+ void finishTopLevel() {
+ for (var fieldNode in fieldNodes) {
+ if (fieldNode.isEvaluated) continue;
+ new _FieldWalker<F>().walk(fieldNode);
+ }
+ }
+
+ /// Gets the declared type of the given [field], or `null` if the type is
+ /// implicit.
+ DartType getFieldDeclaredType(F field);
+
+ /// Gets the character offset of the declaration of [field] within its
+ /// compilation unit.
+ int getFieldOffset(F field);
+
+ /// Retrieve the [TypeInferrer] for the given [field], which was created by
+ /// a previous call to [createTopLevelTypeInferrer].
+ TypeInferrerImpl<dynamic, dynamic, dynamic, F> getFieldTypeInferrer(F field);
+
+ /// Gets the URI of the compilation unit the [field] is declared in.
+ /// TODO(paulberry): can we remove this?
+ String getFieldUri(F field);
+
+ /// Performs type inference on the given [field].
+ void inferField(F field) {
+ if (fieldHasInitializer(field)) {
+ var typeInferrer = getFieldTypeInferrer(field);
+ var type = getFieldDeclaredType(field);
+ var inferredType =
+ typeInferrer.inferFieldInitializer(field, type, type == null);
+ if (type == null && strongMode) {
+ instrumentation?.record(
+ 'topType',
+ Uri.parse(typeInferrer.uri),
+ getFieldOffset(field),
+ new InstrumentationValueForType(inferredType));
+ setFieldInferredType(field, inferredType);
+ }
+ // TODO(paulberry): if type != null, then check that the type of the
+ // initializer is assignable to it.
+ // TODO(paulberry): the following is a hack so that outlines don't contain
+ // initializers. But it means that we rebuild the initializers when doing
+ // a full compile. There should be a better way.
+ clearFieldInitializer(field);
+ }
+ }
+
+ /// Makes a note that the given [field] is part of a circularity, so its type
+ /// can't be inferred.
+ void inferFieldCircular(F field) {
+ // TODO(paulberry): report the appropriate error.
+ if (getFieldDeclaredType(field) == null) {
+ var uri = getFieldTypeInferrer(field).uri;
+ instrumentation?.record('topType', Uri.parse(uri), getFieldOffset(field),
+ const InstrumentationValueLiteral('circular'));
+ setFieldInferredType(field, const DynamicType());
+ }
+ }
+
+ /// Determines if top level type inference has been completed for [field].
+ bool isFieldInferred(F field);
+
+ @override
+ void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
+ this.coreTypes = coreTypes;
+ this.classHierarchy = classHierarchy;
+ }
+
+ @override
+ void recordField(F field) {
+ fieldNodes.add(createFieldNode(field));
+ }
+
+ /// Stores [inferredType] as the inferred type of [field].
+ void setFieldInferredType(F field, DartType inferredType);
+}
+
+/// Subtype of [dependencyWalker.DependencyWalker] which is specialized to
+/// perform top level type inference.
+class _FieldWalker<F> extends dependencyWalker.DependencyWalker<FieldNode<F>> {
+ _FieldWalker();
+
+ @override
+ void evaluate(FieldNode<F> f) {
+ f._typeInferenceEngine.inferField(f._field);
+ }
+
+ @override
+ void evaluateScc(List<FieldNode<F>> scc) {
+ for (var f in scc) {
+ f._typeInferenceEngine.inferFieldCircular(f._field);
+ }
+ for (var f in scc) {
+ f._typeInferenceEngine.inferField(f._field);
+ }
+ }
+}
« 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