[kernel,vm] Change async transformer to extend RemovingTransformer

Since some of the async transformers return `null`, signaling that they
remove nodes, they must extend the RemovingTransformer in order to
migrate to null safety where arbitrary node removal is not possible.

Change-Id: I8e20e2c61ce23699fe32c7450aacdd15467da5f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/191923
Reviewed-by: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
Johnni Winther
2021-04-07 08:30:47 +00:00
committed by commit-bot@chromium.org
parent 9db78a3b49
commit a26a140d88
2 changed files with 95 additions and 84 deletions
+2 -2
View File
@@ -530,7 +530,7 @@ class ExpressionLifter extends Transformer {
visitFunctionNode(FunctionNode node) {
var nestedRewriter = new RecursiveContinuationRewriter(
continuationRewriter.helper, _staticTypeContext);
return node.accept(nestedRewriter);
return nestedRewriter.transform(node);
}
TreeNode visitBlockExpression(BlockExpression expr) {
@@ -561,7 +561,7 @@ class ExpressionLifter extends Transformer {
List<Statement> savedOuter = continuationRewriter.statements;
statements = <Statement>[];
continuationRewriter.statements = <Statement>[];
stmt.accept(continuationRewriter);
continuationRewriter.transform(stmt);
List<Statement> results = continuationRewriter.statements;
statements = savedInner;
@@ -77,10 +77,10 @@ Procedure transformProcedure(
new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
var rewriter = new RecursiveContinuationRewriter(
helper, new StatefulStaticTypeContext.stacked(typeEnvironment));
return rewriter.visitProcedure(procedure);
return rewriter.transform(procedure);
}
class RecursiveContinuationRewriter extends Transformer {
class RecursiveContinuationRewriter extends RemovingTransformer {
final HelperNodes helper;
final VariableDeclaration awaitJumpVariable = new VariableDeclaration(
@@ -94,49 +94,50 @@ class RecursiveContinuationRewriter extends Transformer {
RecursiveContinuationRewriter(this.helper, this.staticTypeContext);
Component rewriteComponent(Component node) {
return node.accept<TreeNode>(this);
return transform(node);
}
Library rewriteLibrary(Library node) {
return node.accept<TreeNode>(this);
return transform(node);
}
visitField(Field node) {
visitField(Field node, TreeNode removalSentinel) {
staticTypeContext.enterMember(node);
final result = super.visitField(node);
final result = super.visitField(node, removalSentinel);
staticTypeContext.leaveMember(node);
return result;
}
visitConstructor(Constructor node) {
visitConstructor(Constructor node, TreeNode removalSentinel) {
staticTypeContext.enterMember(node);
final result = super.visitConstructor(node);
final result = super.visitConstructor(node, removalSentinel);
staticTypeContext.leaveMember(node);
return result;
}
@override
visitProcedure(Procedure node) {
visitProcedure(Procedure node, TreeNode removalSentinel) {
staticTypeContext.enterMember(node);
final result = node.isAbstract ? node : super.visitProcedure(node);
final result =
node.isAbstract ? node : super.visitProcedure(node, removalSentinel);
staticTypeContext.leaveMember(node);
return result;
}
@override
visitLibrary(Library node) {
visitLibrary(Library node, TreeNode removalSentinel) {
staticTypeContext.enterLibrary(node);
Library result = super.visitLibrary(node);
Library result = super.visitLibrary(node, removalSentinel);
staticTypeContext.leaveLibrary(node);
return result;
}
@override
visitFunctionNode(FunctionNode node) {
visitFunctionNode(FunctionNode node, TreeNode removalSentinel) {
switch (node.asyncMarker) {
case AsyncMarker.Sync:
case AsyncMarker.SyncYielding:
node.transformChildren(
node.transformOrRemoveChildren(
new RecursiveContinuationRewriter(helper, staticTypeContext));
return node;
case AsyncMarker.SyncStar:
@@ -154,9 +155,9 @@ class RecursiveContinuationRewriter extends Transformer {
}
@override
TreeNode visitForInStatement(ForInStatement stmt) {
TreeNode visitForInStatement(ForInStatement stmt, TreeNode removalSentinel) {
if (stmt.isAsync) {
return super.visitForInStatement(stmt);
return super.visitForInStatement(stmt, removalSentinel);
}
// Transform
@@ -217,8 +218,8 @@ class RecursiveContinuationRewriter extends Transformer {
final Block body = Block([variable, stmt.body]);
return Block([syncForIterator, ForStatement([], condition, [], body)])
.accept<TreeNode>(this);
return transform(
Block([syncForIterator, ForStatement([], condition, [], body)]));
}
}
@@ -277,30 +278,30 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
return new YieldStatement(value, isNative: true);
}
TreeNode visitTryCatch(TryCatch node) {
TreeNode visitTryCatch(TryCatch node, TreeNode removalSentinel) {
if (node.body != null) {
++currentTryDepth;
node.body = node.body.accept<TreeNode>(this);
node.body = transform(node.body);
node.body?.parent = node;
--currentTryDepth;
}
++currentCatchDepth;
transformList(node.catches, node);
transformCatchList(node.catches, node);
--currentCatchDepth;
return node;
}
TreeNode visitTryFinally(TryFinally node) {
TreeNode visitTryFinally(TryFinally node, TreeNode removalSentinel) {
if (node.body != null) {
++currentTryDepth;
node.body = node.body.accept<TreeNode>(this);
node.body = transform(node.body);
node.body?.parent = node;
--currentTryDepth;
}
if (node.finalizer != null) {
++currentCatchDepth;
node.finalizer = node.finalizer.accept<TreeNode>(this);
node.finalizer = transform(node.finalizer);
node.finalizer?.parent = node;
--currentCatchDepth;
}
@@ -477,14 +478,14 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
// :iterator.isYieldEach=
// and return `true` as long as it did something and `false` when it's done.
return new Block(<Statement>[
enclosingFunction.body.accept<TreeNode>(this),
transform(enclosingFunction.body),
new ReturnStatement(new BoolLiteral(false))
..fileOffset = enclosingFunction.fileEndOffset
]);
}
visitYieldStatement(YieldStatement node) {
Expression transformedExpression = node.expression.accept<TreeNode>(this);
visitYieldStatement(YieldStatement node, TreeNode removalSentinel) {
Expression transformedExpression = transform(node.expression);
var statements = <Statement>[];
if (node.isYieldStar) {
@@ -506,7 +507,8 @@ class SyncStarFunctionRewriter extends ContinuationRewriterBase {
return new Block(statements);
}
TreeNode visitReturnStatement(ReturnStatement node) {
TreeNode visitReturnStatement(
ReturnStatement node, TreeNode removalSentinel) {
// sync* functions cannot return a value.
assert(node.expression == null || node.expression is NullLiteral);
node.expression = new BoolLiteral(false)..parent = node;
@@ -643,41 +645,43 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
List<Statement> statements = <Statement>[];
TreeNode visitExpressionStatement(ExpressionStatement stmt) {
TreeNode visitExpressionStatement(
ExpressionStatement stmt, TreeNode removalSentinel) {
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
..parent = stmt;
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitBlock(Block stmt) {
TreeNode visitBlock(Block stmt, TreeNode removalSentinel) {
var saved = statements;
statements = <Statement>[];
for (var statement in stmt.statements) {
statement.accept<TreeNode>(this);
transform(statement);
}
saved.add(new Block(statements));
statements = saved;
return null;
return removalSentinel;
}
TreeNode visitEmptyStatement(EmptyStatement stmt) {
TreeNode visitEmptyStatement(EmptyStatement stmt, TreeNode removalSentinel) {
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitAssertBlock(AssertBlock stmt) {
TreeNode visitAssertBlock(AssertBlock stmt, TreeNode removalSentinel) {
var saved = statements;
statements = <Statement>[];
for (var statement in stmt.statements) {
statement.accept<TreeNode>(this);
transform(statement);
}
saved.add(new Block(statements));
statements = saved;
return null;
return removalSentinel;
}
TreeNode visitAssertStatement(AssertStatement stmt) {
TreeNode visitAssertStatement(
AssertStatement stmt, TreeNode removalSentinel) {
var condEffects = <Statement>[];
var cond = expressionRewriter.rewrite(stmt.condition, condEffects);
if (stmt.message == null) {
@@ -686,7 +690,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
// statements, ensure they are guarded by whether asserts are enabled.
statements.add(
condEffects.isEmpty ? stmt : new AssertBlock(condEffects..add(stmt)));
return null;
return removalSentinel;
}
// The translation depends on the translation of the message, by cases.
@@ -733,31 +737,32 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
result = new AssertBlock(condEffects);
}
statements.add(result);
return null;
return removalSentinel;
}
Statement visitDelimited(Statement stmt) {
var saved = statements;
statements = <Statement>[];
stmt.accept<TreeNode>(this);
transform(stmt);
Statement result =
statements.length == 1 ? statements.first : new Block(statements);
statements = saved;
return result;
}
Statement visitLabeledStatement(LabeledStatement stmt) {
Statement visitLabeledStatement(
LabeledStatement stmt, TreeNode removalSentinel) {
stmt.body = visitDelimited(stmt.body)..parent = stmt;
statements.add(stmt);
return null;
return removalSentinel;
}
Statement visitBreakStatement(BreakStatement stmt) {
Statement visitBreakStatement(BreakStatement stmt, TreeNode removalSentinel) {
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitWhileStatement(WhileStatement stmt) {
TreeNode visitWhileStatement(WhileStatement stmt, TreeNode removalSentinel) {
Statement body = visitDelimited(stmt.body);
List<Statement> effects = <Statement>[];
Expression cond = expressionRewriter.rewrite(stmt.condition, effects);
@@ -783,10 +788,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
stmt.body = new Block(effects)..parent = stmt;
statements.add(labeled);
}
return null;
return removalSentinel;
}
TreeNode visitDoStatement(DoStatement stmt) {
TreeNode visitDoStatement(DoStatement stmt, TreeNode removalSentinel) {
Statement body = visitDelimited(stmt.body);
List<Statement> effects = <Statement>[];
stmt.condition = expressionRewriter.rewrite(stmt.condition, effects)
@@ -802,10 +807,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
}
stmt.body = body..parent = stmt;
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitForStatement(ForStatement stmt) {
TreeNode visitForStatement(ForStatement stmt, TreeNode removalSentinel) {
// Because of for-loop scoping and variable capture, it is tricky to deal
// with await in the loop's variable initializers or update expressions.
bool isSimple = true;
@@ -859,7 +864,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
stmt.body = new Block(condEffects)..parent = stmt;
statements.add(labeled);
}
return null;
return removalSentinel;
}
// If the rewrite of the initializer or update expressions produces a
@@ -946,10 +951,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
statements.add(new Block(<Statement>[]
..addAll(temps)
..add(labeled)));
return null;
return removalSentinel;
}
TreeNode visitForInStatement(ForInStatement stmt) {
TreeNode visitForInStatement(ForInStatement stmt, TreeNode removalSentinel) {
if (stmt.isAsync) {
// Transform
//
@@ -1058,15 +1063,16 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
var block = new Block(
<Statement>[streamVariable, forIteratorVariable, tryFinally]);
block.accept<TreeNode>(this);
return null;
transform(block);
return removalSentinel;
} else {
super.visitForInStatement(stmt);
return null;
super.visitForInStatement(stmt, removalSentinel);
return removalSentinel;
}
}
TreeNode visitSwitchStatement(SwitchStatement stmt) {
TreeNode visitSwitchStatement(
SwitchStatement stmt, TreeNode removalSentinel) {
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
..parent = stmt;
for (var switchCase in stmt.cases) {
@@ -1075,15 +1081,16 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
switchCase.body = visitDelimited(switchCase.body)..parent = switchCase;
}
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitContinueSwitchStatement(ContinueSwitchStatement stmt) {
TreeNode visitContinueSwitchStatement(
ContinueSwitchStatement stmt, TreeNode removalSentinel) {
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitIfStatement(IfStatement stmt) {
TreeNode visitIfStatement(IfStatement stmt, TreeNode removalSentinel) {
stmt.condition = expressionRewriter.rewrite(stmt.condition, statements)
..parent = stmt;
stmt.then = visitDelimited(stmt.then)..parent = stmt;
@@ -1091,10 +1098,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
stmt.otherwise = visitDelimited(stmt.otherwise)..parent = stmt;
}
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitTryCatch(TryCatch stmt) {
TreeNode visitTryCatch(TryCatch stmt, TreeNode removalSentinel) {
++currentTryDepth;
stmt.body = visitDelimited(stmt.body)..parent = stmt;
--currentTryDepth;
@@ -1105,10 +1112,10 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
}
--currentCatchDepth;
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitTryFinally(TryFinally stmt) {
TreeNode visitTryFinally(TryFinally stmt, TreeNode removalSentinel) {
++currentTryDepth;
stmt.body = visitDelimited(stmt.body)..parent = stmt;
--currentTryDepth;
@@ -1116,33 +1123,36 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
stmt.finalizer = visitDelimited(stmt.finalizer)..parent = stmt;
--currentCatchDepth;
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitYieldStatement(YieldStatement stmt) {
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode removalSentinel) {
stmt.expression = expressionRewriter.rewrite(stmt.expression, statements)
..parent = stmt;
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitVariableDeclaration(VariableDeclaration stmt) {
TreeNode visitVariableDeclaration(
VariableDeclaration stmt, TreeNode removalSentinel) {
if (stmt.initializer != null) {
stmt.initializer = expressionRewriter.rewrite(
stmt.initializer, statements)
..parent = stmt;
}
statements.add(stmt);
return null;
return removalSentinel;
}
TreeNode visitFunctionDeclaration(FunctionDeclaration stmt) {
stmt.function = stmt.function.accept<TreeNode>(this)..parent = stmt;
TreeNode visitFunctionDeclaration(
FunctionDeclaration stmt, TreeNode removalSentinel) {
stmt.function = transform(stmt.function)..parent = stmt;
statements.add(stmt);
return null;
return removalSentinel;
}
defaultExpression(TreeNode node) => throw 'unreachable $node';
defaultExpression(TreeNode node, TreeNode removalSentinel) =>
throw 'unreachable $node';
}
class AsyncStarFunctionRewriter extends AsyncRewriterBase {
@@ -1235,7 +1245,7 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
]);
}
TreeNode visitYieldStatement(YieldStatement stmt) {
TreeNode visitYieldStatement(YieldStatement stmt, TreeNode removalSentinel) {
Expression expr = expressionRewriter.rewrite(stmt.expression, statements);
var addExpression = new MethodInvocation(
@@ -1251,15 +1261,16 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
addExpression,
new ReturnStatement(new NullLiteral()),
createContinuationPoint()..fileOffset = stmt.fileOffset));
return null;
return removalSentinel;
}
TreeNode visitReturnStatement(ReturnStatement node) {
TreeNode visitReturnStatement(
ReturnStatement node, TreeNode removalSentinel) {
// Async* functions cannot return a value.
assert(node.expression == null || node.expression is NullLiteral);
statements
.add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset);
return null;
return removalSentinel;
}
}
@@ -1369,14 +1380,14 @@ class AsyncFunctionRewriter extends AsyncRewriterBase {
]);
}
visitReturnStatement(ReturnStatement node) {
visitReturnStatement(ReturnStatement node, TreeNode removalSentinel) {
var expr = node.expression == null
? new NullLiteral()
: expressionRewriter.rewrite(node.expression, statements);
statements.add(new ExpressionStatement(
new VariableSet(returnVariable, expr)..fileOffset = node.fileOffset));
statements.add(new BreakStatement(labeledBody));
return null;
return removalSentinel;
}
}