visitSwitchExpression method

  1. @override
Object? visitSwitchExpression(
  1. SSwitchExpression node
)
override

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})",
  );
}