[cfe][Contexts] Split VariableDeclaration and VariableStatement

This separates VariableDeclaration from Statement. VariableDeclaration no longer implements Statement and variable declared in a block or in a for-statement are now wrapped by a VariableStatement.

Currently there are two VariableStatement implementations; LegacyVariableStatement for variables in the current model, called LegacyVariable, and VariableInitialization for variables used in the new, still experimental, encoding that supports scope computation.

This CL is a step towards realigning the AST nodes to the new model in which each kind of variable has its own distinct subclass. (LocalVariable, PositionalParameter, NamedParameter, SyntheticVariable, etc.)

Note that it is not the intent to use VariableStatement in ForStatement going forward but that will be handled in a follow-up.

TEST=existing.

Change-Id: I5b309cd62c9b138f95b74fb054686edffa49a393
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/502681
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2026-05-18 05:49:28 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 046d473d5e
commit e30cd0322c
78 changed files with 1341 additions and 1132 deletions
+34 -20
View File
@@ -91,7 +91,8 @@ class _AwaitTransformer extends Transformer {
Statement newBody = transformer.transform(body);
final List<Statement> newStatements = [
...transformer.expressionTransformer.variables,
for (final variable in transformer.expressionTransformer.variables)
VariableStatement(variable),
...transformer.statements,
];
@@ -248,13 +249,13 @@ class _AwaitTransformer extends Transformer {
List<List<Statement>> initEffects = List<List<Statement>>.generate(length, (
int i,
) {
VariableDeclaration decl = stmt.variables[i];
VariableStatement decl = stmt.variables[i];
List<Statement> statements = <Statement>[];
if (decl.initializer != null) {
decl.initializer = expressionTransformer.rewrite(
decl.initializer!,
if (decl.variable.initializer != null) {
decl.variable.initializer = expressionTransformer.rewrite(
decl.variable.initializer!,
statements,
)..parent = decl;
)..parent = decl.variable;
}
isSimple = isSimple && statements.isEmpty;
return statements;
@@ -345,23 +346,31 @@ class _AwaitTransformer extends Transformer {
List<Statement> updates = <Statement>[];
List<Statement> newBody = <Statement>[body];
for (int i = 0; i < stmt.variables.length; ++i) {
VariableDeclaration decl = stmt.variables[i];
VariableStatement decl = stmt.variables[i];
temps.add(
VariableDeclaration(null, type: decl.type, isSynthesized: true),
VariableDeclaration(
null,
type: decl.variable.type,
isSynthesized: true,
),
);
loopBody.add(decl);
if (decl.initializer != null) {
initializers.addAll(initEffects[i]);
initializers.add(
ExpressionStatement(VariableSet(decl, decl.initializer!)),
ExpressionStatement(VariableSet(decl.variable, decl.initializer!)),
);
decl.initializer = null;
}
updates.add(
ExpressionStatement(VariableSet(decl, VariableGet(temps.last))),
ExpressionStatement(
VariableSet(decl.variable, VariableGet(temps.last)),
),
);
newBody.add(
ExpressionStatement(VariableSet(temps.last, VariableGet(decl))),
ExpressionStatement(
VariableSet(temps.last, VariableGet(decl.variable)),
),
);
}
// Add the updates to their guarded list of statements.
@@ -387,7 +396,10 @@ class _AwaitTransformer extends Transformer {
loopBody.add(IfStatement(cond, Block(newBody), BreakStatement(labeled)));
labeled.body = WhileStatement(BoolLiteral(true), Block(loopBody))
..parent = labeled;
return Block(<Statement>[...temps, labeled]);
return Block(<Statement>[
for (VariableDeclaration temp in temps) VariableStatement(temp),
labeled,
]);
}
@override
@@ -537,19 +549,21 @@ class _AwaitTransformer extends Transformer {
}
return Block([
continuationVar,
exceptionVar,
stackTraceVar,
VariableStatement(continuationVar),
VariableStatement(exceptionVar),
VariableStatement(stackTraceVar),
TryFinally(body, finalizer),
]);
}
@override
TreeNode visitVariableDeclaration(VariableDeclaration stmt) {
final initializer = stmt.initializer;
TreeNode visitLegacyVariableStatement(LegacyVariableStatement stmt) {
final initializer = stmt.variable.initializer;
if (initializer != null) {
stmt.initializer = expressionTransformer.rewrite(initializer, statements)
..parent = stmt;
stmt.variable.initializer = expressionTransformer.rewrite(
initializer,
statements,
)..parent = stmt.variable;
}
return stmt;
}
@@ -1256,7 +1270,7 @@ class _ExpressionTransformer extends Transformer {
// <body's statements>
//
// and return the body's value.
statements.add(variable);
statements.add(VariableStatement(variable));
var index = nameIndex;
seenAwait = false;
variable.initializer = transform(variable.initializer!)
+4 -4
View File
@@ -1626,11 +1626,11 @@ class _CaptureFinder extends RecursiveVisitor {
}
@override
void visitVariableDeclaration(VariableDeclaration node) {
void defaultVariableDeclaration(VariableDeclaration node) {
if (depth > 0) {
variableDepth[node] = depth;
}
super.visitVariableDeclaration(node);
super.defaultVariableDeclaration(node);
}
@override
@@ -1863,7 +1863,7 @@ class _ContextCollector extends RecursiveVisitor {
}
@override
void visitVariableDeclaration(VariableDeclaration node) {
void defaultVariableDeclaration(VariableDeclaration node) {
Capture? capture = closures.captures[node];
if (capture != null) {
if (isInInitializer == capture.isInInitializer) {
@@ -1871,7 +1871,7 @@ class _ContextCollector extends RecursiveVisitor {
capture.context = currentContext!;
}
}
super.visitVariableDeclaration(node);
super.defaultVariableDeclaration(node);
}
@override
+17 -5
View File
@@ -672,6 +672,18 @@ abstract class AstCodeGenerator
}
}
void translateVariableDeclaration(VariableDeclaration node) {
final oldFileOffset = setSourceMapFileOffset(node.fileOffset);
try {
visitVariableDeclaration(node);
} catch (_) {
_printLocation(node);
rethrow;
} finally {
setSourceMapFileOffset(oldFileOffset);
}
}
void translateStatement(Statement node) {
final oldFileOffset = setSourceMapFileOffset(node.fileOffset);
try {
@@ -1266,7 +1278,7 @@ abstract class AstCodeGenerator
@override
void visitForStatement(ForStatement node) {
allocateContext(node);
for (VariableDeclaration variable in node.variables) {
for (VariableStatement variable in node.variables) {
translateStatement(variable);
}
w.Label block = b.block();
@@ -1290,8 +1302,8 @@ abstract class AstCodeGenerator
w.Local newContext = context.currentLocal;
// Copy the values of captured loop variables to the new context.
for (VariableDeclaration variable in node.variables) {
Capture? capture = closures.captures[variable];
for (VariableStatement variableDeclaration in node.variables) {
Capture? capture = closures.captures[variableDeclaration.variable];
if (capture != null) {
assert(capture.context == context);
b.local_get(newContext);
@@ -1559,7 +1571,7 @@ abstract class AstCodeGenerator
@override
w.ValueType visitLet(Let node, w.ValueType expectedType) {
translateStatement(node.variable);
translateVariableDeclaration(node.variable);
return translateExpression(node.body, expectedType);
}
@@ -4440,7 +4452,7 @@ class ConstructorInitializerCodeGenerator extends ConstructorCodeGeneratorBase {
@override
void visitLocalInitializer(LocalInitializer node) {
translateStatement(node.variable);
translateVariableDeclaration(node.variable);
}
@override
@@ -732,12 +732,15 @@ class _ReferenceDependenciesCollector extends RecursiveVisitor {
@override
void visitEmptyStatement(EmptyStatement node) => node.visitChildren(this);
@override
void visitVariableDeclaration(VariableDeclaration node) =>
void defaultVariableDeclaration(VariableDeclaration node) =>
node.visitChildren(this);
@override
void visitReturnStatement(ReturnStatement node) => node.visitChildren(this);
@override
void visitYieldStatement(YieldStatement node) => node.visitChildren(this);
@override
void visitLegacyVariableStatement(LegacyVariableStatement node) =>
node.visitChildren(this);
@override
void visitLet(Let node) => node.visitChildren(this);
@@ -151,7 +151,7 @@ class CallbackSpecializer {
),
);
body.add(argumentsLength);
body.add(VariableStatement(argumentsLength));
if (castClosureArguments.isNotEmpty) {
// Call the cast closure, but only if the arity is okay. In the case where
+4 -4
View File
@@ -495,11 +495,11 @@ class Finalizer extends _ExceptionHandler {
Finalizer._(this.codeGen, TryFinally node, this.parentFinalizer, super.target)
: _continuationVar =
(node.parent as Block).statements[0] as VariableDeclaration,
((node.parent as Block).statements[0] as VariableStatement).variable,
_exceptionVar =
(node.parent as Block).statements[1] as VariableDeclaration,
((node.parent as Block).statements[1] as VariableStatement).variable,
_stackTraceVar =
(node.parent as Block).statements[2] as VariableDeclaration;
((node.parent as Block).statements[2] as VariableStatement).variable;
@override
bool get canHandleJSExceptions => true;
@@ -869,7 +869,7 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator {
StateTarget after = afterTargets[node]!;
allocateContext(node);
for (VariableDeclaration variable in node.variables) {
for (VariableStatement variable in node.variables) {
translateStatement(variable);
}
emitTargetLabel(inner);
+15 -14
View File
@@ -278,11 +278,11 @@ class _WasmTransformer extends Transformer {
}
@override
visitVariableDeclaration(VariableDeclaration node) {
defaultVariableDeclaration(VariableDeclaration node) {
if (!node.isFinal) {
_implicitFinalVariables.add(node);
}
return super.visitVariableDeclaration(node);
return super.defaultVariableDeclaration(node);
}
@override
@@ -440,7 +440,8 @@ class _WasmTransformer extends Transformer {
resultType: elementType,
)..fileOffset = stmt.bodyOffset);
Block body = Block([variable, stmt.body])..fileOffset = stmt.fileOffset;
Block body = Block([VariableStatement(variable), stmt.body])
..fileOffset = stmt.fileOffset;
Statement forStatement = ForStatement(
const [],
@@ -479,8 +480,8 @@ class _WasmTransformer extends Transformer {
}
return Block([
iterator,
if (isAsync) jumpSentinel,
VariableStatement(iterator),
if (isAsync) VariableStatement(jumpSentinel),
forStatement,
]).accept<TreeNode>(this);
}
@@ -883,17 +884,17 @@ class _WasmTransformer extends Transformer {
return FunctionNode(
Block([
pausedVar,
cancelCompleterVar,
isDoneVar,
onCancelCallbackVar,
onResumeCallbackVar,
VariableStatement(pausedVar),
VariableStatement(cancelCompleterVar),
VariableStatement(isDoneVar),
VariableStatement(onCancelCallbackVar),
VariableStatement(onResumeCallbackVar),
// var controller = StreamController<T>(sync: true, onCancel: onCancelCallback, onResume: onResumeCallback);
controllerVar,
VariableStatement(controllerVar),
// var #body = ...;
bodyVar,
VariableStatement(bodyVar),
// controller.onListen = ...;
ExpressionStatement(setControllerOnListen),
@@ -1346,7 +1347,7 @@ class PushPopWasmArrayTransformer {
}
final List<Statement> arrayGrowStatements = [
newArrayVariable,
VariableStatement(newArrayVariable),
ExpressionStatement(newArrayCopy),
arrayFieldUpdate,
];
@@ -1475,7 +1476,7 @@ class PushPopWasmArrayTransformer {
isFinal: true,
type: elementType,
);
blockStatements.add(arrayGetVariable);
blockStatements.add(VariableStatement(arrayGetVariable));
// array[length] = null
if (elementIsNullable) {