visitIfStatement method

  1. @override
Object? visitIfStatement(
  1. SIfStatement node
)
override

Visit a SIfStatement.

Implementation

@override
Object? visitIfStatement(SIfStatement node) {
  // Evaluate the expression
  final expressionValue = node.condition!.accept<Object?>(this);

  // If the evaluation returns an AsyncSuspensionRequest, return it immediately
  if (expressionValue is AsyncSuspensionRequest) {
    Logger.debug(
      "[SIfStatement] Expression suspended (AsyncSuspensionRequest). Propagating.",
    );
    return expressionValue;
  }

  // Check if this is an if-case statement (pattern matching)
  final caseClause = node.caseClause;
  if (caseClause != null) {
    // This is an if-case statement: if (expr case Pattern when guard) { ... }
    final cc = caseClause;
    final gp = cc.guardedPattern;
    final pattern = gp.pattern;
    final guard = gp.whenClause?.expression;

    // Create a temporary environment for pattern variable bindings
    final caseEnvironment = Environment(enclosing: environment);

    try {
      // Attempt to match the pattern against the expression value
      _matchAndBind(pattern, expressionValue, caseEnvironment);
      Logger.debug(
        "[SIfStatement] Pattern ${pattern.runtimeType} matched value ${expressionValue?.runtimeType}",
      );

      // Pattern matched, now check the guard (if it exists)
      bool guardPassed = true;
      if (guard != null) {
        final previousVisitorEnv = environment;
        try {
          environment = caseEnvironment; // Evaluate guard in case scope
          final guardResult = guard.accept<Object?>(this);
          if (guardResult is! bool) {
            throw RuntimeD4rtException(
              "If-case 'when' clause must evaluate to a boolean.",
            );
          }
          guardPassed = guardResult;
          Logger.debug("[SIfStatement] Guard evaluated to: $guardPassed");
        } finally {
          environment = previousVisitorEnv;
        }
      }

      // If pattern matched and guard passed, execute thenStatement
      if (guardPassed) {
        final previousVisitorEnv = environment;
        try {
          environment = caseEnvironment; // Execute body in case scope
          node.thenStatement!.accept<Object?>(this);
        } finally {
          environment = previousVisitorEnv;
        }
      } else if (node.elseStatement != null) {
        // Guard failed, execute elseStatement
        node.elseStatement!.accept<Object?>(this);
      }
    } on PatternMatchD4rtException {
      // Pattern didn't match, execute elseStatement if present
      Logger.debug(
        "[SIfStatement] Pattern ${pattern.runtimeType} did not match. Executing else if present.",
      );
      if (node.elseStatement != null) {
        node.elseStatement!.accept<Object?>(this);
      }
    }

    return null;
  }

  // Regular boolean condition if statement
  bool conditionResult;
  final bridgedInstance = toBridgedInstance(expressionValue);
  if (expressionValue is bool) {
    conditionResult = expressionValue;
  } else if (bridgedInstance.$2 && bridgedInstance.$1?.nativeObject is bool) {
    conditionResult = bridgedInstance.$1!.nativeObject as bool;
  } else {
    throw RuntimeD4rtException(
      "The condition of an 'if' must be a boolean, but was ${expressionValue?.runtimeType}.",
    );
  }

  if (conditionResult) {
    node.thenStatement!.accept<Object?>(this);
  } else if (node.elseStatement != null) {
    node.elseStatement!.accept<Object?>(this);
  }

  return null; // The If instruction normally ends with null
}