chore(legacy): remove unused legacy plugin loader and C-ABI nyash-file plugin; unify plugin headers to TypeBox v2

This commit is contained in:
Selfhosting Dev
2025-09-17 22:32:38 +09:00
parent d93595ab83
commit b420929f53
314 changed files with 52595 additions and 535 deletions

View File

@ -0,0 +1,59 @@
# Async Task System — Phased Plan (P1P3)
## Phase 1: Foundations (stabilize + timeouts)
- FutureBox: switch to Mutex+Condvar (done).
- Await: poll scheduler + timeout gate in VM and JIT (done; unify to Result.Err in P3).
- env.future.spawn_instance: enqueue via Scheduler; fallback sync if no scheduler (done).
- Safepoint: ensure env.runtime.checkpoint is emitted around await (Lowerer rule).
- Smokes: async-await-min; async-spawn-instance (safe form, no env).
- Acceptance:
- No hangs (await respects timeout); CPU near idle while waiting.
- VM/JIT pass basic smokes; lingering processes do not remain.
## Phase 2: TaskGroup & CancellationToken
- Types:
- CancellationToken { cancel(), is_cancelled() } idempotent; parent→child propagation only.
- TaskGroup Box { spawn(fn)->Future, cancelAll(), joinAll() }, owns token; fini enforces cancel→join.
- API:
- nowait sugar targets current TaskGroup.
- Unsafe detached spawn hidden behind unsafe_spawn_detached() and verifier checks.
- VM implementation:
- Extend scheduler to accept token; tasks periodically check token or are cancelled at await.
- Group registry per scope; insert fini hooks in function epilogues and Main.
- JIT/EXE:
- NyRT shims accept optional token handle; if missing, use current groups token.
- Smokes:
- spawn_cancel_on_scope_exit; nested_groups; lifo_join_order.
- Acceptance:
- Parent exit cancels and joins children deterministically (LIFO); no leaks per leak tracker.
## Phase 3: Error Semantics & Unification
- Future.await returns Result<T, Err> (Timeout/Cancelled/Panic) consistently (VM/JIT).
- Remove 0/None fallbacks; map shims to Result at Nyash layer.
- Lowerer verifies checkpoints around await; add verifier rule.
- Observability: minimal counters and optional traces.
- Smokes:
- await_timeout distinct from cancel; panic_propagation; wakeup_race (no double resolve).
- Acceptance:
- Consistent error surface; result handling identical across VM/JIT/EXE.
## Test Matrix & CI
- Backends: {vm, jit, aot} × Modes: {default, strict}.
- Smokes kept minimal; timebounded via timeout(1) wrapper.
- CPU spin test: ensure idle waiting; measured via time/ps (besteffort).
## Migration & Compatibility
- Keep env.future.spawn_instance during transition; TaskGroup.spawn preferred.
- nowait sugar remains; mapped to TaskGroup.spawn.
- Document flags: NYASH_AWAIT_MAX_MS, NYASH_SCHED_*.
## Files & Ownership
- Spec & Plan live here; updates linked from CURRENT_TASK.md.
- Code changes limited to runtime/{scheduler,global_hooks}, boxes/future, jit/extern/async, lowerer await rules.

View File

@ -0,0 +1,14 @@
# Async Task System (Structured Concurrency) — Overview
Goal: A safe, structured, and portable async task system that runs endtoend across Nyash code → MIR → VM → JIT/EXE.
- Default is safe: tasks are scoped to an owning group; when the owner ends, children cancel and join.
- Everything is Box: TaskGroup and Future are Boxes; user APIs are Box methods; MIR uses BoxCall.
- No new MIR ops required: use BoxCall/PluginInvoke consistently; safepoints are inserted around await.
- Deterministic exits: parent exit triggers cancelAll → joinAll on children (LIFO), eliminating leaks.
This folder contains the spec, phase plan, and test plan:
- SPEC.md: User API, Box contracts, MIR/VM/JIT mapping, ABI, error semantics.
- PLAN.md: Phased rollout (P1P3), acceptance gates and checklists.

View File

@ -0,0 +1,83 @@
# Async Task System — SPEC
Scope: Define a structured concurrency model for Nyash with TaskGroup and Future as Boxes. Implementable across VM and JIT/EXE without adding new MIR instructions.
## UserFacing API (Everything is Box)
Box TaskGroup
- spawn(fn: () -> T) -> Future<T>
- cancelAll() -> void
- joinAll() -> void
- fini: must run cancelAll() then joinAll() (LIFO order) to ensure structured shutdown.
Box Future<T>
- await(timeout_ms?: int) -> Result<T, Err>
- Ok(value)
- Err(Timeout) | Err(Cancelled) | Err(Panic)
- cancel() -> void (idempotent)
Sugar
- nowait v = expr is sugar for: let g = current_group(); v = g.spawn(lambda: expr)
Default Ownership
- An implicit TaskGroup is created per function scope and for Main. It owns tasks spawned in that scope.
- Leaving the scope triggers cancelAll→joinAll on its group (LIFO), unless tasks were moved to a longerlived group explicitly.
Detachment (discouraged)
- unsafe_spawn_detached(fn) only in advanced modules. Verifier should disallow use in normal code paths.
## MIR Mapping
- No new MIR instructions. Use existing BoxCall/PluginInvoke forms.
- TaskGroup.spawn → BoxCall on TaskGroup Box, returns Future Box.
- Future.await → BoxCall on Future Box with optional timeout parameter.
- Lowerer inserts safepoint around await: ExternCall env.runtime.checkpoint before and after the await call.
Example Lowering (high level)
- AST: nowait fut = arr.length()
- MIR (normalized):
- recv = … (arr)
- mname = Const("length")
- fut = ExternCall iface="env.future", method="spawn_instance", args=[recv, mname]
- v = BoxCall Future.await(fut, timeout_ms?)
Note: In the final API, TaskGroup.spawn replaces env.future.spawn_instance, but the MIR contract remains BoxCall/ExternCallbased.
## VM Semantics
- Scheduler: SingleThreadScheduler initially; spawn enqueues closure in FIFO. safepoint_and_poll() runs due tasks.
- Future: implemented with Mutex+Condvar; set_result notifies; await waits with optional timeout; on cancel/timeout, returns Result.Err.
- CancellationToken: parent→child propagation only, idempotent cancel().
- TaskGroup: holds token and child registry; fini enforces cancelAll→joinAll (LIFO).
## JIT/EXE Semantics
- NyRT CABI Shims:
- nyash.future.spawn_method_h(type_id, method_id, argc, recv_h, vals*, tags*) -> i64 (Future handle)
- nyash.future.spawn_instance3_i64(a0, a1, a2, argc) -> i64 (Future handle, by name/first args)
- nyash.future.await_h(handle, timeout_ms?) -> i64/handle (Result encoding handled at Nyash layer)
- Await shim must poll safepoints and honor timeout; returns 0 or sentinel; Nyash layer maps to Result.Err.*
## Errors & Results
- Distinguish Timeout vs Cancelled vs Panic.
- Logging: concise, off by default; env flags can enable traces.
- No silent fallback: unimplemented paths error early with clear labels.
## GC & Safepoints
- Lowerer must emit env.runtime.checkpoint immediately before and after await calls.
- Scheduler.poll runs at checkpoints; long loops should explicitly insert checkpoints.
## Configuration
- NYASH_AWAIT_MAX_MS (default 5000) — global default timeout for await when not specified.
- NYASH_SCHED_POLL_BUDGET — tasks per poll, default 1.
- NYASH_SCHED_TRACE — prints poll/move/ran counts when 1.
## Security & Determinism
- Structured shutdown prevents orphan tasks after parent exit.
- LIFO joinAll reduces deadlock surfaces.
- Detached tasks are explicit and rare.