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

Unified Diff: pkg/front_end/lib/src/fasta/builder/shadow_ast.dart

Issue 2768533002: Fasta type inference prototype #2
Patch Set: Rework atop 415c868589d02e98eb839f48150f4203d5cecdb0 Created 3 years, 9 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/builder/shadow_ast.dart
diff --git a/pkg/front_end/lib/src/fasta/builder/shadow_ast.dart b/pkg/front_end/lib/src/fasta/builder/shadow_ast.dart
index 6976d7bc62fc3af3d3aefd939544c46e5c6e5da7..914380725dc31efc86060fb5419c569a53bcfe10 100644
--- a/pkg/front_end/lib/src/fasta/builder/shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/builder/shadow_ast.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:front_end/src/fasta/type_inference/local_type_inferrer.dart';
+
/// This file declares mixins which can be used to create a shadow hierarchy
/// of either the kernel or the analyzer AST representations.
///
@@ -14,19 +16,27 @@
/// Note that the analyzer AST representation closely parallels Dart syntax,
/// whereas the kernel AST representation is desugared. The classes in the
/// shadow hierarchy represent the full language (prior to desugaring).
-import 'package:kernel/ast.dart' show DartType;
+import 'package:kernel/ast.dart' show DartType, DynamicType, InterfaceType;
+import 'package:kernel/core_types.dart';
/// Shadow mixin representing a statement block.
abstract class ShadowBlock implements ShadowStatement {
/// Iterates through the statements contained in the block.
Iterable<ShadowStatement> get shadowStatements;
+
+ @override
+ void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
+ for (var statement in shadowStatements) {
+ statement.shadowInfer(inferrer, context);
+ }
+ }
}
/// Common interface for shadow mixins representing expressions.
-///
-/// TODO(paulberry): add an abstract `shadowInfer` method here to do type
-/// inference.
-abstract class ShadowExpression {}
+abstract class ShadowExpression {
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded);
+}
/// Shadow mixin representing a function expression.
abstract class ShadowFunctionExpression implements ShadowExpression {
@@ -52,10 +62,49 @@ abstract class ShadowFunctionExpression implements ShadowExpression {
///
/// Intended for use by type inference.
void set shadowReturnType(DartType type);
+
+ @override
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
+ // TODO(paulberry): infer argument types and type parameters.
+ // TODO(paulberry): full support for generators.
+ var body = shadowBody;
+ // TODO(paulberry): Dart 1.0 rules say we only need to set the function
+ // node's return type if it uses expression syntax. Does that make sense
+ // for Dart 2.0?
+ bool needToSetReturnType = shadowIsExpressionFunction;
+ bool returnTypeNeeded = typeNeeded || needToSetReturnType;
+ bool isAsync = shadowIsAsync;
+ var functionContext = new FunctionContext(
+ inferrer, returnTypeNeeded, isAsync, shadowIsGenerator);
+ body.shadowInfer(inferrer, functionContext);
+ DartType inferredReturnType;
+ if (needToSetReturnType || typeNeeded) {
+ inferredReturnType = functionContext.inferredReturnType;
+ if (isAsync) {
+ inferredReturnType = new InterfaceType(
+ inferrer.coreTypes.futureClass, <DartType>[inferredReturnType]);
+ }
+ }
+ if (needToSetReturnType) {
+ this.shadowReturnType = inferredReturnType;
+ }
+ if (typeNeeded) {
+ return shadowFunctionType;
+ } else {
+ return null;
+ }
+ }
}
/// Shadow mixin representing an integer literal.
-abstract class ShadowIntLiteral implements ShadowExpression {}
+abstract class ShadowIntLiteral implements ShadowExpression {
+ @override
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
+ return typeNeeded ? inferrer.coreTypes.intClass.rawType : null;
+ }
+}
/// Shadow mixin representing a list literal.
abstract class ShadowListLiteral implements ShadowExpression {
@@ -71,23 +120,92 @@ abstract class ShadowListLiteral implements ShadowExpression {
///
/// Intended for use by type inference.
void set shadowTypeArgument(DartType type);
+
+ @override
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
+ DartType declaredTypeArgument = shadowTypeArgument;
+ DartType typeArgumentContext = declaredTypeArgument;
+ if (typeArgumentContext == null) {
+ if (context is InterfaceType &&
+ context.classNode == inferrer.coreTypes.listClass &&
+ context.typeArguments.length == 1) {
+ typeArgumentContext = context.typeArguments[0];
+ } else if (context != null) {
+ // TODO(paulberry): report an error?
+ throw new UnimplementedError('$context');
+ }
+ }
+ DartType inferredTypeArgument = typeArgumentContext;
+ bool typeArgumentNeeded = inferredTypeArgument == null;
+ for (ShadowExpression e in shadowExpressions) {
+ DartType t =
+ e.shadowInfer(inferrer, typeArgumentContext, typeArgumentNeeded);
+ if (typeArgumentNeeded) {
+ inferredTypeArgument = inferrer.union(inferredTypeArgument, t);
+ }
+ }
+ if (inferredTypeArgument == null) {
+ // Empty list.
+ throw new UnimplementedError();
+ }
+ if (declaredTypeArgument == null) {
+ this.shadowTypeArgument = inferredTypeArgument;
+ }
+ if (typeNeeded) {
+ return new InterfaceType(
+ inferrer.coreTypes.listClass, <DartType>[inferredTypeArgument]);
+ } else {
+ return null;
+ }
+ }
}
/// Shadow mixin representing a null literal.
-abstract class ShadowNullLiteral implements ShadowExpression {}
+abstract class ShadowNullLiteral implements ShadowExpression {
+ @override
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
+ return typeNeeded ? inferrer.coreTypes.nullClass.rawType : null;
+ }
+}
/// Shadow mixin representing a return statement.
abstract class ShadowReturnStatement implements ShadowStatement {
/// Gets the expression being returned, or `null` if this is a bare "return"
/// statement.
ShadowExpression get shadowExpression;
+
+ @override
+ void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
+ DartType expressionContext = null; // TODO(paulberry): probably wrong.
+ bool expressionTypeNeeded =
+ context.returnTypeNeeded && !context.isGenerator;
+ DartType expressionType = shadowExpression.shadowInfer(
+ inferrer, expressionContext, expressionTypeNeeded);
+ if (expressionTypeNeeded) {
+ if (context.isAsync) {
+ expressionType = _unwrapFuture(inferrer.coreTypes, expressionType);
+ }
+ context.recordReturnType(expressionType);
+ }
+ }
+
+ DartType _unwrapFuture(CoreTypes coreTypes, DartType type) {
+ // TODO(paulberry): replace with a full implementation of what's in the spec
+ // (e.g. handle types derived from Future). Also probably move to Kernel.
+ if (type is InterfaceType && type.classNode == coreTypes.futureClass) {
+ return type.typeArguments[0];
+ } else {
+ return type;
+ }
+ }
}
/// Common interface for shadow mixins representing statements.
-///
-/// TODO(paulberry): add an abstract `shadowInfer` method here to do type
-/// inference.
-abstract class ShadowStatement {}
+abstract class ShadowStatement {
+ void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context);
+}
/// Shadow mixin representing a declaration of a single variable.
abstract class ShadowVariableDeclaration implements ShadowStatement {
@@ -103,10 +221,31 @@ abstract class ShadowVariableDeclaration implements ShadowStatement {
///
/// Intended for use by type inference.
void set shadowType(DartType type);
+
+ @override
+ void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
+ var initializer = shadowInitializer;
+ if (initializer != null) {
+ var type = shadowType;
+ var inferredType = initializer.shadowInfer(inferrer, type, type == null);
+ if (type == null) {
+ this.shadowType = inferredType;
+ }
+ }
+ }
}
/// Shadow mixin representing a "read" reference to a variable.
abstract class ShadowVariableGet implements ShadowExpression {
/// Gets the variable declaration which is being referenced.
ShadowVariableDeclaration get shadowDeclaration;
+
+ @override
+ DartType shadowInfer(
+ LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
+ // TODO(paulberry): make the "?? const DynamicType()" unnecessary.
+ return typeNeeded
+ ? (shadowDeclaration.shadowType ?? const DynamicType())
+ : null;
+ }
}
« no previous file with comments | « pkg/front_end/lib/src/fasta/builder/ast_factory.dart ('k') | pkg/front_end/lib/src/fasta/kernel/body_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698