run method
Implementation
@override
FutureOr<ASTValue> run(
VMContext parentContext,
ASTRunStatus runStatus,
) async {
var context = VMScopeContext(parentContext.block, parent: parentContext);
var prevContext = VMContext.setCurrent(context);
try {
var switchValue = await expression.run(context, runStatus);
var rawSwitch = await switchValue.getValue(context);
// Find the matching case, or fall back to `default`.
var startIndex = -1;
for (var i = 0; i < cases.length; ++i) {
var c = cases[i];
if (c.isDefault) continue;
var caseValue = await c.value!.run(context, runStatus);
var rawCase = await caseValue.getValue(context);
if (rawSwitch == rawCase) {
startIndex = i;
break;
}
}
if (startIndex < 0) {
startIndex = cases.indexWhere((c) => c.isDefault);
}
if (startIndex < 0) return ASTValueVoid.instance;
if (!fallThrough) {
// Only the matched clause runs (Kotlin `when` / Python `match`).
await cases[startIndex].block.run(context, runStatus);
// `break` is implicit here, so consume any that bubbled up.
if (runStatus.broke) runStatus.broke = false;
return ASTValueVoid.instance;
}
// Fall-through: run from the matched clause onward until break/return.
for (var i = startIndex; i < cases.length; ++i) {
await cases[i].block.run(context, runStatus);
// `return`/`continue` propagate up (e.g. `continue` of an enclosing
// loop); `break` is consumed here as it targets this switch.
if (runStatus.returned || runStatus.continued) break;
if (runStatus.broke) {
runStatus.broke = false;
break;
}
}
} finally {
VMContext.setCurrent(prevContext);
}
return ASTValueVoid.instance;
}