blob: 4f2b698923dc17357f73ad768aa88a728fb48e46 [file] [log] [blame]
// 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/fasta/type_inference/type_inference_engine.dart';
import 'package:kernel/ast.dart';
/// Base class for [TypeInferenceListener] that defines the API for debugging.
///
/// By default no debug info is printed. To enable debug printing, mix in
/// [TypeInferenceDebugging].
class TypeInferenceBase {
void debugDependency(AccessorNode accessorNode) {}
bool debugExpressionEnter(
String expressionType, Expression expression, DartType typeContext) {
return false;
}
void debugExpressionExit(
String expressionType, Expression expression, DartType inferredType) {}
void debugInitializerEnter(String initializerType, Initializer initializer) {}
void debugInitializerExit(String initializerType, Initializer initializer) {}
void debugStatementEnter(String statementType, Statement statement) {}
void debugStatementExit(String statementType, Statement statement) {}
}
/// Mixin which can be applied to [TypeInferenceListener] to cause debug info to
/// be printed.
class TypeInferenceDebugging implements TypeInferenceBase {
void debugDependency(AccessorNode accessorNode) {
print('Dependency $accessorNode');
}
bool debugExpressionEnter(
String expressionType, Expression expression, DartType typeContext) {
print('Enter $expressionType($expression) (context=$typeContext)');
return true;
}
void debugExpressionExit(
String expressionType, Expression expression, DartType inferredType) {
print('Exit $expressionType($expression) (type=$inferredType)');
}
void debugInitializerEnter(String initializerType, Initializer initializer) {
print('Enter $initializerType($initializer)');
}
void debugInitializerExit(String initializerType, Initializer initializer) {
print('Exit $initializerType($initializer)');
}
void debugStatementEnter(String statementType, Statement statement) {
print('Enter $statementType($statement)');
}
void debugStatementExit(String statementType, Statement statement) {
print('Exit $statementType($statement)');
}
}
/// Callback interface used by [TypeInferrer] to report the results of type
/// inference to a client.
///
/// The interface is structured as a set of enter/exit methods. The enter
/// methods are called as the inferrer recurses down through the AST, and the
/// exit methods are called on the way back up. The enter methods take a
/// [DartType] argument representing the downwards inference context, and return
/// a bool indicating whether the TypeInferenceListener needs to know the final
/// inferred type; the exit methods take [DartType] argument representing the
/// final inferred type.
///
/// The default implementation (in this base class) does nothing, however it can
/// be used to debug type inference by uncommenting the
/// "with TypeInferenceDebugging" clause below.
class TypeInferenceListener
extends TypeInferenceBase // with TypeInferenceDebugging
{
bool asExpressionEnter(AsExpression expression, DartType typeContext) =>
debugExpressionEnter("asExpression", expression, typeContext);
void asExpressionExit(AsExpression expression, DartType inferredType) =>
debugExpressionExit("asExpression", expression, inferredType);
void assertStatementEnter(AssertStatement statement) =>
debugStatementEnter('assertStatement', statement);
void assertStatementExit(AssertStatement statement) =>
debugStatementExit('assertStatement', statement);
bool awaitExpressionEnter(AwaitExpression expression, DartType typeContext) =>
debugExpressionEnter("awaitExpression", expression, typeContext);
void awaitExpressionExit(AwaitExpression expression, DartType inferredType) =>
debugExpressionExit("awaitExpression", expression, inferredType);
void blockEnter(Block statement) => debugStatementEnter('block', statement);
void blockExit(Block statement) => debugStatementExit('block', statement);
bool boolLiteralEnter(BoolLiteral expression, DartType typeContext) =>
debugExpressionEnter("boolLiteral", expression, typeContext);
void boolLiteralExit(BoolLiteral expression, DartType inferredType) =>
debugExpressionExit("boolLiteral", expression, inferredType);
void breakStatementEnter(BreakStatement statement) =>
debugStatementEnter('breakStatement', statement);
void breakStatementExit(BreakStatement statement) =>
debugStatementExit('breakStatement', statement);
bool cascadeExpressionEnter(Let expression, DartType typeContext) =>
debugExpressionEnter("cascade", expression, typeContext);
void cascadeExpressionExit(Let expression, DartType inferredType) =>
debugExpressionExit("cascade", expression, inferredType);
bool conditionalExpressionEnter(
ConditionalExpression expression, DartType typeContext) =>
debugExpressionEnter("conditionalExpression", expression, typeContext);
void conditionalExpressionExit(
ConditionalExpression expression, DartType inferredType) =>
debugExpressionExit("conditionalExpression", expression, inferredType);
bool constructorInvocationEnter(
InvocationExpression expression, DartType typeContext) =>
debugExpressionEnter("constructorInvocation", expression, typeContext);
void constructorInvocationExit(
InvocationExpression expression, DartType inferredType) =>
debugExpressionExit("constructorInvocation", expression, inferredType);
void continueSwitchStatementEnter(ContinueSwitchStatement statement) =>
debugStatementEnter('continueSwitchStatement', statement);
void continueSwitchStatementExit(ContinueSwitchStatement statement) =>
debugStatementExit('continueSwitchStatement', statement);
void doStatementEnter(DoStatement statement) =>
debugStatementEnter("doStatement", statement);
void doStatementExit(DoStatement statement) =>
debugStatementExit("doStatement", statement);
bool doubleLiteralEnter(DoubleLiteral expression, DartType typeContext) =>
debugExpressionEnter("doubleLiteral", expression, typeContext);
void doubleLiteralExit(DoubleLiteral expression, DartType inferredType) =>
debugExpressionExit("doubleLiteral", expression, inferredType);
void dryRunEnter(Expression expression) =>
debugExpressionEnter("dryRun", expression, null);
void dryRunExit(Expression expression) =>
debugExpressionExit("dryRun", expression, null);
void expressionStatementEnter(ExpressionStatement statement) =>
debugStatementEnter('expressionStatement', statement);
void expressionStatementExit(ExpressionStatement statement) =>
debugStatementExit('expressionStatement', statement);
void forInStatementEnter(ForInStatement statement) =>
debugStatementEnter('forInStatement', statement);
void forInStatementExit(ForInStatement statement) =>
debugStatementExit('forInStatement', statement);
void forStatementEnter(ForStatement statement) =>
debugStatementEnter('forStatement', statement);
void forStatementExit(ForStatement statement) =>
debugStatementExit('forStatement', statement);
void functionDeclarationEnter(FunctionDeclaration statement) =>
debugStatementEnter('functionDeclaration', statement);
void functionDeclarationExit(FunctionDeclaration statement) =>
debugStatementExit('functionDeclaration', statement);
bool functionExpressionEnter(
FunctionExpression expression, DartType typeContext) =>
debugExpressionEnter("functionExpression", expression, typeContext);
void functionExpressionExit(
FunctionExpression expression, DartType inferredType) =>
debugExpressionExit("functionExpression", expression, inferredType);
bool ifNullEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter('ifNull', expression, typeContext);
void ifNullExit(Expression expression, DartType inferredType) =>
debugExpressionExit('ifNull', expression, inferredType);
void ifStatementEnter(IfStatement statement) =>
debugStatementEnter('ifStatement', statement);
void ifStatementExit(IfStatement statement) =>
debugStatementExit('ifStatement', statement);
bool indexAssignEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("indexAssign", expression, typeContext);
void indexAssignExit(Expression expression, DartType inferredType) =>
debugExpressionExit("indexAssign", expression, inferredType);
bool intLiteralEnter(IntLiteral expression, DartType typeContext) =>
debugExpressionEnter("intLiteral", expression, typeContext);
void intLiteralExit(IntLiteral expression, DartType inferredType) =>
debugExpressionExit("intLiteral", expression, inferredType);
bool isExpressionEnter(IsExpression expression, DartType typeContext) =>
debugExpressionEnter("isExpression", expression, typeContext);
void isExpressionExit(IsExpression expression, DartType inferredType) =>
debugExpressionExit("isExpression", expression, inferredType);
bool isNotExpressionEnter(Not expression, DartType typeContext) =>
debugExpressionEnter("isNotExpression", expression, typeContext);
void isNotExpressionExit(Not expression, DartType inferredType) =>
debugExpressionExit("isNotExpression", expression, inferredType);
void labeledStatementEnter(LabeledStatement statement) =>
debugStatementEnter('labeledStatement', statement);
void labeledStatementExit(LabeledStatement statement) =>
debugStatementExit('labeledStatement', statement);
bool listLiteralEnter(ListLiteral expression, DartType typeContext) =>
debugExpressionEnter("listLiteral", expression, typeContext);
void listLiteralExit(ListLiteral expression, DartType inferredType) =>
debugExpressionExit("listLiteral", expression, inferredType);
bool logicalExpressionEnter(
LogicalExpression expression, DartType typeContext) =>
debugExpressionEnter("logicalExpression", expression, typeContext);
void logicalExpressionExit(
LogicalExpression expression, DartType inferredType) =>
debugExpressionExit("logicalExpression", expression, inferredType);
bool mapLiteralEnter(MapLiteral expression, DartType typeContext) =>
debugExpressionEnter("mapLiteral", expression, typeContext);
void mapLiteralExit(MapLiteral expression, DartType typeContext) =>
debugExpressionExit("mapLiteral", expression, typeContext);
bool methodInvocationEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("methodInvocation", expression, typeContext);
void methodInvocationExit(Expression expression, DartType inferredType) =>
debugExpressionExit("methodInvocation", expression, inferredType);
bool notEnter(Not expression, DartType typeContext) =>
debugExpressionEnter("not", expression, typeContext);
void notExit(Not expression, DartType inferredType) =>
debugExpressionExit("not", expression, inferredType);
bool nullLiteralEnter(NullLiteral expression, DartType typeContext) =>
debugExpressionEnter("nullLiteral", expression, typeContext);
void nullLiteralExit(NullLiteral expression, DartType inferredType) =>
debugExpressionExit("nullLiteral", expression, inferredType);
bool propertyAssignEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("propertyAssign", expression, typeContext);
void propertyAssignExit(Expression expression, DartType inferredType) =>
debugExpressionExit("propertyAssign", expression, inferredType);
bool propertyGetEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("propertyGet", expression, typeContext);
void propertyGetExit(Expression expression, DartType inferredType) =>
debugExpressionExit("propertyGet", expression, inferredType);
bool propertySetEnter(PropertySet expression, DartType typeContext) =>
debugExpressionEnter("propertySet", expression, typeContext);
void propertySetExit(PropertySet expression, DartType inferredType) =>
debugExpressionExit("propertySet", expression, inferredType);
void recordDependency(AccessorNode accessorNode) =>
debugDependency(accessorNode);
void redirectingInitializerEnter(RedirectingInitializer initializer) =>
debugInitializerEnter("redirectingInitializer", initializer);
void redirectingInitializerExit(RedirectingInitializer initializer) =>
debugInitializerExit("redirectingInitializer", initializer);
bool rethrowEnter(Rethrow expression, DartType typeContext) =>
debugExpressionEnter('rethrow', expression, typeContext);
void rethrowExit(Rethrow expression, DartType inferredType) =>
debugExpressionExit('rethrow', expression, inferredType);
void returnStatementEnter(ReturnStatement statement) =>
debugStatementEnter('returnStatement', statement);
void returnStatementExit(ReturnStatement statement) =>
debugStatementExit('returnStatement', statement);
bool staticAssignEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("staticAssign", expression, typeContext);
void staticAssignExit(Expression expression, DartType inferredType) =>
debugExpressionExit("staticAssign", expression, inferredType);
bool staticGetEnter(StaticGet expression, DartType typeContext) =>
debugExpressionEnter("staticGet", expression, typeContext);
void staticGetExit(StaticGet expression, DartType inferredType) =>
debugExpressionExit("staticGet", expression, inferredType);
bool staticInvocationEnter(
StaticInvocation expression, DartType typeContext) =>
debugExpressionEnter("staticInvocation", expression, typeContext);
void staticInvocationExit(
StaticInvocation expression, DartType inferredType) =>
debugExpressionExit("staticInvocation", expression, inferredType);
bool stringConcatenationEnter(
StringConcatenation expression, DartType typeContext) =>
debugExpressionEnter("stringConcatenation", expression, typeContext);
void stringConcatenationExit(
StringConcatenation expression, DartType inferredType) =>
debugExpressionExit("stringConcatenation", expression, inferredType);
bool stringLiteralEnter(StringLiteral expression, DartType typeContext) =>
debugExpressionEnter("StringLiteral", expression, typeContext);
void stringLiteralExit(StringLiteral expression, DartType inferredType) =>
debugExpressionExit("StringLiteral", expression, inferredType);
void switchStatementEnter(SwitchStatement statement) =>
debugStatementEnter('switchStatement', statement);
void switchStatementExit(SwitchStatement statement) =>
debugStatementExit('switchStatement', statement);
bool symbolLiteralEnter(SymbolLiteral expression, DartType typeContext) =>
debugExpressionEnter("symbolLiteral", expression, typeContext);
void symbolLiteralExit(SymbolLiteral expression, DartType inferredType) =>
debugExpressionExit("symbolLiteral", expression, inferredType);
bool thisExpressionEnter(ThisExpression expression, DartType typeContext) =>
debugExpressionEnter("thisExpression", expression, typeContext);
void thisExpressionExit(ThisExpression expression, DartType inferredType) =>
debugExpressionExit("thisExpression", expression, inferredType);
bool throwEnter(Throw expression, DartType typeContext) =>
debugExpressionEnter('throw', expression, typeContext);
void throwExit(Throw expression, DartType inferredType) =>
debugExpressionExit('throw', expression, inferredType);
void tryCatchEnter(TryCatch statement) =>
debugStatementEnter('tryCatch', statement);
void tryCatchExit(TryCatch statement) =>
debugStatementExit('tryCatch', statement);
void tryFinallyEnter(TryFinally statement) =>
debugStatementEnter('tryFinally', statement);
void tryFinallyExit(TryFinally statement) =>
debugStatementExit('tryFinally', statement);
bool typeLiteralEnter(TypeLiteral expression, DartType typeContext) =>
debugExpressionEnter("typeLiteral", expression, typeContext);
void typeLiteralExit(TypeLiteral expression, DartType inferredType) =>
debugExpressionExit("typeLiteral", expression, inferredType);
bool variableAssignEnter(Expression expression, DartType typeContext) =>
debugExpressionEnter("variableAssign", expression, typeContext);
void variableAssignExit(Expression expression, DartType inferredType) =>
debugExpressionExit("variableAssign", expression, inferredType);
void variableDeclarationEnter(VariableDeclaration statement) =>
debugStatementEnter('variableDeclaration', statement);
void variableDeclarationExit(VariableDeclaration statement) =>
debugStatementExit('variableDeclaration', statement);
bool variableGetEnter(VariableGet expression, DartType typeContext) =>
debugExpressionEnter("variableGet", expression, typeContext);
void variableGetExit(VariableGet expression, DartType inferredType) =>
debugExpressionExit("variableGet", expression, inferredType);
bool variableSetEnter(VariableSet expression, DartType typeContext) =>
debugExpressionEnter("variableSet", expression, typeContext);
void variableSetExit(VariableSet expression, DartType inferredType) =>
debugExpressionExit("variableSet", expression, inferredType);
void whileStatementEnter(WhileStatement statement) =>
debugStatementEnter("whileStatement", statement);
void whileStatementExit(WhileStatement statement) =>
debugStatementExit("whileStatement", statement);
void yieldStatementEnter(YieldStatement statement) =>
debugStatementEnter('yieldStatement', statement);
void yieldStatementExit(YieldStatement statement) =>
debugStatementExit('yieldStatement', statement);
}