visitYieldStatement method

  1. @override
Object? visitYieldStatement(
  1. SYieldStatement node
)
override

Visit a SYieldStatement.

Implementation

@override
Object? visitYieldStatement(SYieldStatement node) {
  final value = node.expression!.accept<Object?>(this);
  Logger.debug(
    "[SYieldStatement] Yielding value: $value (star: ${node.isStar})",
  );

  // If we're in an async* generator (with real async state), create a suspension
  if (currentAsyncState?.isGenerator == true) {
    final controller = currentAsyncState!.generatorStreamController!;

    if (node.isStar) {
      // yield* - handle asynchronously
      return AsyncSuspensionRequest(
        _handleYieldStarAsync(value, controller),
        currentAsyncState!,
        isYieldSuspension: true,
      );
    } else {
      // regular yield - send to stream and create minimal suspension
      controller.add(value);
      // Create a completed future suspension to continue execution
      return AsyncSuspensionRequest(
        Future.value(null),
        currentAsyncState!,
        isYieldSuspension: true,
      );
    }
  }

  // If we're in a sync* generator context, add directly to the values list
  if (syncGeneratorValues != null) {
    if (node.isStar) {
      // yield* - expand iterable
      if (value is Iterable) {
        syncGeneratorValues!.addAll(value);
      } else {
        throw RuntimeD4rtException(
          "yield* expression must be an Iterable, got ${value.runtimeType}",
        );
      }
    } else {
      syncGeneratorValues!.add(value);
    }
    return null; // Continue execution
  }

  // Lim-4/Bug-43 FIX: If we're in a lazy sync* context, throw suspension to pause
  if (isLazySyncGeneratorContext) {
    throw SyncGeneratorYieldSuspension(value, isYieldStar: node.isStar);
  }

  // Fallback for other contexts
  return YieldValue(value, isYieldStar: node.isStar);
}