| Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
|
| diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
|
| index 0b6af073e67b018e7e24b006aecd0719b9b6f6ef..c61fe0bb5a2db33dab7c98bd626c7711a8b17f38 100644
|
| --- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
|
| +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
|
| @@ -20,6 +20,7 @@
|
| import 'package:front_end/src/base/instrumentation.dart';
|
| import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
|
| import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
|
| +import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
|
| import 'package:kernel/ast.dart';
|
|
|
| /// Concrete shadow object representing a statement block in kernel form.
|
| @@ -43,6 +44,17 @@ abstract class KernelExpression implements Expression {
|
| KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded);
|
| }
|
|
|
| +/// Concrete shadow object representing an expression statement in kernel form.
|
| +class KernelExpressionStatement extends ExpressionStatement
|
| + implements KernelStatement {
|
| + KernelExpressionStatement(Expression expression) : super(expression);
|
| +
|
| + @override
|
| + void _inferStatement(KernelTypeInferrer inferrer) {
|
| + inferrer.inferExpressionStatement(expression);
|
| + }
|
| +}
|
| +
|
| /// Concrete shadow object representing a field in kernel form.
|
| class KernelField extends Field {
|
| bool _implicitlyTyped = true;
|
| @@ -83,8 +95,32 @@ class KernelFunctionExpression extends FunctionExpression
|
| @override
|
| DartType _inferExpression(
|
| KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| - // TODO(paulberry): implement.
|
| - return typeNeeded ? const DynamicType() : null;
|
| + var asyncMarker = function.asyncMarker;
|
| + bool isAsync = asyncMarker == AsyncMarker.Async ||
|
| + asyncMarker == AsyncMarker.AsyncStar;
|
| + bool isGenerator = asyncMarker == AsyncMarker.SyncStar ||
|
| + asyncMarker == AsyncMarker.AsyncStar;
|
| + return inferrer.inferFunctionExpression(
|
| + typeContext,
|
| + typeNeeded,
|
| + function.body,
|
| + function.body is ReturnStatement,
|
| + isAsync,
|
| + isGenerator,
|
| + fileOffset, (type) {
|
| + function.returnType = type;
|
| + }, () => function.functionType);
|
| + }
|
| +}
|
| +
|
| +/// Concrete shadow object representing an if statement in kernel form.
|
| +class KernelIfStatement extends IfStatement implements KernelStatement {
|
| + KernelIfStatement(Expression condition, Statement then, Statement otherwise)
|
| + : super(condition, then, otherwise);
|
| +
|
| + @override
|
| + void _inferStatement(KernelTypeInferrer inferrer) {
|
| + inferrer.inferIfStatement(condition, then, otherwise);
|
| }
|
| }
|
|
|
| @@ -99,6 +135,31 @@ class KernelIntLiteral extends IntLiteral implements KernelExpression {
|
| }
|
| }
|
|
|
| +/// Concrete shadow object representing a non-inverted "is" test in kernel form.
|
| +class KernelIsExpression extends IsExpression implements KernelExpression {
|
| + KernelIsExpression(Expression operand, DartType type) : super(operand, type);
|
| +
|
| + @override
|
| + DartType _inferExpression(
|
| + KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| + return inferrer.inferIsExpression(typeContext, typeNeeded, operand);
|
| + }
|
| +}
|
| +
|
| +/// Concrete shadow object representing an inverted "is" test in kernel form.
|
| +class KernelIsNotExpression extends Not implements KernelExpression {
|
| + KernelIsNotExpression(Expression operand, DartType type, int charOffset)
|
| + : super(new IsExpression(operand, type)..fileOffset = charOffset);
|
| +
|
| + @override
|
| + DartType _inferExpression(
|
| + KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| + IsExpression isExpression = this.operand;
|
| + return inferrer.inferIsExpression(
|
| + typeContext, typeNeeded, isExpression.operand);
|
| + }
|
| +}
|
| +
|
| /// Concrete shadow object representing a list literal in kernel form.
|
| class KernelListLiteral extends ListLiteral implements KernelExpression {
|
| KernelListLiteral(List<KernelExpression> expressions,
|
| @@ -226,7 +287,10 @@ class KernelTypeInferenceEngine extends TypeInferenceEngineImpl<KernelField> {
|
| /// Concrete implementation of [TypeInferrer] specialized to work with kernel
|
| /// objects.
|
| class KernelTypeInferrer extends TypeInferrerImpl<Statement, Expression,
|
| - KernelVariableDeclaration, KernelField> {
|
| + VariableDeclaration, KernelField> {
|
| + @override
|
| + final typePromoter = new KernelTypePromoter();
|
| +
|
| KernelTypeInferrer._(KernelTypeInferenceEngine engine, String uri)
|
| : super(engine, uri);
|
|
|
| @@ -287,12 +351,83 @@ class KernelTypeInferrer extends TypeInferrerImpl<Statement, Expression,
|
| }
|
| }
|
|
|
| +/// Concrete implementation of [TypePromoter] specialized to work with kernel
|
| +/// objects.
|
| +///
|
| +/// Note: the second type parameter really ought to be
|
| +/// KernelVariableDeclaration, but we can't do that yet because BodyBuilder
|
| +/// still uses raw VariableDeclaration objects sometimes.
|
| +/// TODO(paulberry): fix this.
|
| +class KernelTypePromoter
|
| + extends TypePromoterImpl<Expression, VariableDeclaration> {
|
| + @override
|
| + int getVariableFunctionNestingLevel(VariableDeclaration variable) {
|
| + if (variable is KernelVariableDeclaration) {
|
| + return variable._functionNestingLevel;
|
| + } else {
|
| + // Hack to deal with the fact that BodyBuilder still creates raw
|
| + // VariableDeclaration objects sometimes.
|
| + // TODO(paulberry): get rid of this once the type parameter is
|
| + // KernelVariableDeclaration.
|
| + return 0;
|
| + }
|
| + }
|
| +
|
| + @override
|
| + bool sameExpressions(Expression a, Expression b) {
|
| + return identical(a, b);
|
| + }
|
| +
|
| + @override
|
| + void setVariableMutatedAnywhere(VariableDeclaration variable) {
|
| + if (variable is KernelVariableDeclaration) {
|
| + variable._mutatedAnywhere = true;
|
| + } else {
|
| + // Hack to deal with the fact that BodyBuilder still creates raw
|
| + // VariableDeclaration objects sometimes.
|
| + // TODO(paulberry): get rid of this once the type parameter is
|
| + // KernelVariableDeclaration.
|
| + }
|
| + }
|
| +
|
| + @override
|
| + void setVariableMutatedInClosure(VariableDeclaration variable) {
|
| + if (variable is KernelVariableDeclaration) {
|
| + variable._mutatedInClosure = true;
|
| + } else {
|
| + // Hack to deal with the fact that BodyBuilder still creates raw
|
| + // VariableDeclaration objects sometimes.
|
| + // TODO(paulberry): get rid of this once the type parameter is
|
| + // KernelVariableDeclaration.
|
| + }
|
| + }
|
| +
|
| + @override
|
| + bool wasVariableMutatedAnywhere(VariableDeclaration variable) {
|
| + if (variable is KernelVariableDeclaration) {
|
| + return variable._mutatedAnywhere;
|
| + } else {
|
| + // Hack to deal with the fact that BodyBuilder still creates raw
|
| + // VariableDeclaration objects sometimes.
|
| + // TODO(paulberry): get rid of this once the type parameter is
|
| + // KernelVariableDeclaration.
|
| + return true;
|
| + }
|
| + }
|
| +}
|
| +
|
| /// Concrete shadow object representing a variable declaration in kernel form.
|
| class KernelVariableDeclaration extends VariableDeclaration
|
| implements KernelStatement {
|
| final bool _implicitlyTyped;
|
|
|
| - KernelVariableDeclaration(String name,
|
| + final int _functionNestingLevel;
|
| +
|
| + bool _mutatedInClosure = false;
|
| +
|
| + bool _mutatedAnywhere = false;
|
| +
|
| + KernelVariableDeclaration(String name, this._functionNestingLevel,
|
| {Expression initializer,
|
| DartType type,
|
| bool isFinal: false,
|
| @@ -304,6 +439,8 @@ class KernelVariableDeclaration extends VariableDeclaration
|
| isFinal: isFinal,
|
| isConst: isConst);
|
|
|
| + DartType get _declaredType => _implicitlyTyped ? null : type;
|
| +
|
| @override
|
| void _inferStatement(KernelTypeInferrer inferrer) {
|
| inferrer.inferVariableDeclaration(
|
| @@ -315,13 +452,33 @@ class KernelVariableDeclaration extends VariableDeclaration
|
|
|
| /// Concrete shadow object representing a read from a variable in kernel form.
|
| class KernelVariableGet extends VariableGet implements KernelExpression {
|
| - KernelVariableGet(VariableDeclaration variable, [DartType promotedType])
|
| - : super(variable, promotedType);
|
| + final TypePromotionFact<VariableDeclaration> _fact;
|
| +
|
| + final TypePromotionScope _scope;
|
| +
|
| + KernelVariableGet(VariableDeclaration variable, this._fact, this._scope)
|
| + : super(variable);
|
|
|
| @override
|
| DartType _inferExpression(
|
| KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| - // TODO(paulberry): implement.
|
| - return typeNeeded ? const DynamicType() : null;
|
| + bool mutatedInClosure;
|
| + DartType declaredType;
|
| + var variable = this.variable;
|
| + if (variable is KernelVariableDeclaration) {
|
| + mutatedInClosure = variable._mutatedInClosure;
|
| + declaredType = variable._declaredType;
|
| + } else {
|
| + // Hack to deal with the fact that BodyBuilder still creates raw
|
| + // VariableDeclaration objects sometimes.
|
| + // TODO(paulberry): get rid of this once the type parameter is
|
| + // KernelVariableDeclaration.
|
| + mutatedInClosure = true;
|
| + declaredType = variable.type;
|
| + }
|
| + return inferrer.inferVariableGet(typeContext, typeNeeded, mutatedInClosure,
|
| + _fact, _scope, fileOffset, declaredType, (type) {
|
| + promotedType = type;
|
| + });
|
| }
|
| }
|
|
|