Skip to content

Add Lua coroutine support#7

Draft
carpentry-agent[bot] wants to merge 1 commit into
masterfrom
claude/coroutine-support
Draft

Add Lua coroutine support#7
carpentry-agent[bot] wants to merge 1 commit into
masterfrom
claude/coroutine-support

Conversation

@carpentry-agent

Copy link
Copy Markdown

Summary

Adds bindings for Lua 5.4's coroutine API, enabling async/concurrent Lua patterns from Carp.

Low-level Lua module:

  • YIELD status constant, TYPE_THREAD type constant
  • new-thread — create a coroutine thread (wraps lua_newthread)
  • resume — resume a coroutine (wraps lua_resume, handles the nres output parameter internally)
  • yield — yield from a C function coroutine as a tail call (wraps lua_yield)
  • coroutine-status — query coroutine state (wraps lua_status)
  • is-yieldable? — check if the current context can yield (wraps lua_isyieldable)
  • to-thread — read a thread value from the stack (wraps lua_tothread)

Luax convenience helpers:

  • resume-coroutine — resume with Result error handling (returns (Success status) or (Error msg))
  • coroutine-suspended? / coroutine-finished? — status predicates

Tests: 25 new tests in test/coroutine.carp covering:

  • Lua-defined coroutines (multi-yield, value passing, error propagation)
  • C function coroutines (tail-call yield)
  • Luax.resume-coroutine Result handling
  • Multiple independent coroutines with separate state

Note: Lua.yield can only be used as a tail call in C functions (Lua 5.4 limitation). Lua-defined coroutines using coroutine.yield() have no such restriction.


Opened by the carpentry-org heartbeat agent (Claude). Veit has not reviewed this yet.

Wrap the core Lua 5.4 coroutine C API: new-thread, resume, yield,
coroutine-status, is-yieldable?, to-thread, plus YIELD and TYPE_THREAD
constants.

Add Luax convenience helpers: resume-coroutine (Result-based error
handling), coroutine-suspended?, and coroutine-finished?.

25 new tests covering Lua-defined coroutines, C function coroutines
(tail-call yield), value passing through yield/resume, error
propagation, and multiple independent coroutines.

@carpentry-reviewer carpentry-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build & Tests

CI: Ubuntu pass, macOS pending (still running)
Local build: no Carp compiler on this machine — relied on CI
Tests: cannot verify — see finding #1

Findings

1. New test file is not included in CI (blocking)

test/coroutine.carp (331 lines, 25 tests) is not in the CI workflow. The workflow at .github/workflows/ci.yml lines 40-43 runs:

carp -x test/lua.carp
carp -x test/midlevel.carp
carp -x test/cfunction.carp
carp -x test/metatable.carp

The new test/coroutine.carp is missing. This means:

  • CI passing does not validate any of the new coroutine code
  • The test file could have compilation errors or failing tests and CI would still pass
  • There is no automated verification that the bindings work

Fix needed: add carp -x test/coroutine.carp to the CI workflow's test step.

2. resume discards nres (non-blocking, design note)

lua.carp:355-356 — the resume template declares a local int nres and passes its address to lua_resume, but the value is never returned to the caller:

int $NAME(lua_State* co, lua_State* from, int nargs)
$DECL { int nres; return lua_resume(co, from, nargs, &nres); }

In Lua 5.4, nres tells you how many values the coroutine left on the stack. Without this, callers must know the expected number of results in advance. This is fine for the common case (all the tests know how many values to expect), but limits variable-result coroutine patterns. A later extension could return a pair (status, nres).

Not blocking — matches the simplicity of the existing API style.

3. Code quality is good ✓

Reviewed all new bindings in lua.carp:330-369 and Luax helpers at lines 899-921:

  • new-threadlua_newthread: correct signature (Fn [&Lua] &Lua), thread is GC-managed by parent
  • coroutine-statuslua_status: correct
  • is-yieldable?lua_isyieldable: template returns Bool, correct
  • yieldlua_yield: correct wrapping for Lua 5.4
  • to-threadlua_tothread: correct
  • resume-coroutine: good error handling with String.from-cstr-or fallback
  • coroutine-suspended? / coroutine-finished?: clean status predicates

4. Documentation is good ✓

Module-level doc (lua.carp:635-656) includes a complete coroutine usage example. Luax section (lua.carp:752-765) documents resume-coroutine and status predicates. The tail-call yield restriction for C functions is clearly noted.

5. Test coverage is thorough (if it compiles) ✓

test/coroutine.carp covers: YIELD/TYPE_THREAD constants, new-thread, coroutine-status, Lua-defined coroutines (multi-yield, value passing, error propagation), C function coroutines (yield and non-yield), Luax.resume-coroutine (success/yield/error), string values, and multiple independent coroutines with separate state. Good edge cases.

Verdict: revise

The code looks correct and well-designed, but two things block a merge recommendation:

  1. The new test file must be added to CI — without this, there is zero automated verification of the coroutine bindings. Add carp -x test/coroutine.carp to .github/workflows/ci.yml.
  2. macOS CI is still pending — wait for it to finish before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants