feat(compiler): dynamic system registration + --emit-module for binary packages (#64)
The runtime + compiler foundation for prebuilt binary packages, over the existing reflection C-ABI (EV0–EV8 already gives dynamic components via ludic_register_prop). - ludic_register_system(fn, phase) + a registry the frame loop dispatches after each phase's own handlers — the systems analogue of ludic_register_prop, mirroring the EV6 foreign event-listener array. Emitted for every ECS program; a zero-length registry means a non-hosting game is output-identical. - --emit-module: compile a package to a position-independent module — no main, no world table — that declares the host reflection ABI it calls and carries a load-time constructor which registers its @System(Phase) functions and runs module_init (where it registers its dynamic components). Built as a dylib with -undefined dynamic_lookup, it binds ludic_* back to the host image at load. - @System(Phase) annotation marks a module function as a runtime-registered system; the compiler supplies its address (Ludic source cannot take one). - The reflection ABI (world table) is now emitted for every ECS program, so any game can host binary modules with no flag; unused defs dead-strip at -O2, so golden renders stay byte-identical and the C-free bootstrap fixpoint holds. Proven end-to-end: a module dylib registers a component + an Update system; a host game that never saw its source links it and the system mutates the shared world each frame. Full suite 87/0, test-tools 30/0, fixpoint intact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
035e6dfe41
commit
e1537d2d45
7 changed files with 18543 additions and 17872 deletions
|
|
@ -166,7 +166,7 @@ function emit_program() -> void {
|
|||
i = i + 1
|
||||
}
|
||||
if len(g_events) > 0 { emit_event_fns() } # EV0: @ev_<E> event-dispatch functions
|
||||
if has_ecs() and (len(g_events) > 0 or g_uses_query or g_uses_reflect or g_uses_esys) { emit_world_table() } # EV2/EV8: the mod reflection ABI (also powers Query.* / Reflect.* / engine systems)
|
||||
if has_ecs() { emit_world_table() } # EV2/EV8: the mod reflection ABI (powers Query.* / Reflect.* / engine systems, and lets a binary module (#64) link against a shared world). Unused defs dead-strip at -O2, so a game that touches none is output-identical.
|
||||
if has_ecs() { emit_ecs_allocator(); emit_snapshot() }
|
||||
if has_ecs() { emit_net() } # N2/N3: @Sync serializers + @Owned storage (gated internally)
|
||||
if has_ui() { emit_ui_build() }
|
||||
|
|
@ -208,6 +208,7 @@ function emit_program() -> void {
|
|||
if g_uses_result { emith("%Result = type { i32, i32, ptr }\n") } # issue #46: ok/err/try value
|
||||
if g_uses_option { emith("%Option = type { i32, i32 }\n") } # issue #53: some/none value
|
||||
emit_cov_runtime() # issue #45: --coverage tables + exit dump
|
||||
if g_emit_module { emit_module_glue() } # issue #64: binary-module host-ABI declares + load-time registration ctor
|
||||
}
|
||||
|
||||
# issue #45: the line-coverage runtime. Emits the static line table, a parallel
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue