visitYieldStatement method
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);
}