feat: Phase 8.3 true non-blocking async/await with stackful coroutines

- C runtime: ucontext-based coroutines (bux_async_spawn/yield/await/run)
- Round-robin scheduler in bux_async_run() manages ready queue
- spawn Func() without args → bux_async_spawn() creates coroutine
- await → blocks/yields until coroutine completes
- async func → emitted as regular C function, runs on dedicated stack
- Interleaved execution: multiple coroutines yield cooperatively
- Example: examples/async.bux demonstrates WorkA/WorkB interleaving
- All 20 examples pass, selfhost build works
This commit is contained in:
2026-06-01 01:06:46 +03:00
parent d337ada4d6
commit 5ec755743d
4 changed files with 168 additions and 22 deletions
+4 -4
View File
@@ -253,14 +253,14 @@ proc emitExpr(be: var CBackend, node: HirNode): string =
return &"sizeof({typ})"
of hSpawn:
var argsStr = ""
if node.spawnArgs.len > 0:
# Package arguments into a heap-allocated struct (simplified: single arg)
# Fallback to OS thread spawn for functions with arguments
var argsStr = ""
let arg = be.emitExpr(node.spawnArgs[0])
argsStr = &"(void*){arg}"
return &"bux_task_spawn({node.spawnCallee}, {argsStr})"
else:
argsStr = "NULL"
return &"bux_task_spawn({node.spawnCallee}, {argsStr})"
return &"bux_async_spawn({node.spawnCallee})"
of hIf:
# Ternary expression
+1 -1
View File
@@ -770,7 +770,7 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
of ekAwait:
let lowered = ctx.lowerExpr(expr.exprAwaitOperand)
return hirCall("bux_task_join", @[lowered], makeVoid(), loc)
return hirCall("bux_async_await", @[lowered], makeVoid(), loc)
else:
return HirNode(kind: hLit, litToken: Token(kind: tkIntLiteral, text: "0", loc: loc),