d1af4b0f8b
Introduces Go-style channels as El's mid-flight communication primitive, completing the threading model: threads can now not only spawn/join but also communicate while running. Part 1 — seed layer (el_runtime.c / el_runtime.h): - Add __thread_create/__thread_join/__mutex_new/__mutex_lock/__mutex_unlock as C seed primitives (dlsym-based thread dispatch, pthread mutex table) - Add __channel_new/__channel_send/__channel_recv/__channel_try_recv/__channel_close as MPMC channel seed primitives backed by mutex + condvar + circular buffer - Bounded channels (cap > 0): circular buffer, sender blocks when full - Unbounded channels (cap == 0): dynamic array, grows on demand, never blocks - channel_close wakes all blocked recvers/senders; recv drains then returns "" Part 2 — El API (runtime/channel.el): - channel_new/send/recv/try_recv/close — thin wrappers over seed layer - channel_pipeline — spawn N worker threads reading from in_ch, applying fn_name, writing to out_ch; workers exit on "" sentinel from close - channel_drain — collect all messages from a closed channel into [String] - channel_fan_out — send a [String] list into a channel then close it Part 3 — codegen.el: - Register all 10 seed builtins (__thread_* + __channel_*) in builtin_arity so the arity checker validates call sites at compile time