visitSwitchExpression method
Visit a SSwitchExpression.
Implementation
@override
Object? visitSwitchExpression(SSwitchExpression node) {
final switchValue = node.expression.accept<Object?>(this);
final originalEnvironment = environment; // Backup current environment
for (final caseExpr in node.cases) {
final switchCase = caseExpr;
final switchGp = switchCase.guardedPattern;
final pattern = switchGp.pattern;
final guard = switchGp.whenClause?.expression;
final body = switchCase.expression;
// Create a temporary environment for this case's pattern variables
// Enclose the *original* environment where the switch expression is evaluated
final caseEnvironment = Environment(enclosing: originalEnvironment);
try {
// Attempt to match and bind variables in the temporary environment
_matchAndBind(pattern, switchValue, caseEnvironment);
Logger.debug(
"[SwitchExpr] Pattern ${pattern.runtimeType} matched value ${switchValue?.runtimeType}",
);
// Pattern matched, now check the guard (if it exists)
bool guardPassed = true;
if (guard != null) {
final previousVisitorEnv = environment; // Backup
try {
environment = caseEnvironment; // Evaluate guard in case scope
final guardResult = guard.accept<Object?>(this);
if (guardResult is! bool) {
throw RuntimeD4rtException(
"Switch expression 'when' clause must evaluate to a boolean.",
);
}
guardPassed = guardResult;
Logger.debug("[SwitchExpr] Guard evaluated to: $guardPassed");
} finally {
environment = previousVisitorEnv; // Restore
}
}
// If guard passed (or no guard), evaluate and return the body result
if (guardPassed) {
Logger.debug("[SwitchExpr] Guard passed or absent. Evaluating body.");
final previousVisitorEnv = environment; // Backup
try {
environment = caseEnvironment; // Evaluate body in case scope
final result = body.accept<Object?>(this);
Logger.debug("[SwitchExpr] Body evaluated to: $result. Returning.");
return result; // Return the result of the matching case's body
} finally {
environment = previousVisitorEnv; // Restore
}
}
} on PatternMatchD4rtException catch (e) {
// Pattern didn't match, try the next case
Logger.debug(
"[SwitchExpr] Pattern ${pattern.runtimeType} did not match: ${e.message}. Trying next case.",
);
continue;
}
// If we reach here, it means the pattern matched but the guard failed.
Logger.debug(
"[SwitchExpr] Pattern matched but guard failed. Trying next case.",
);
} // End of loop through cases
// If no case matched and returned a value
throw RuntimeD4rtException(
"Switch expression was not exhaustive for value: $switchValue (${switchValue?.runtimeType})",
);
}