smokes: add curated LLVM runner; archive legacy smokes; PHI-off unified across Bridge/Builder; LLVM resolver tracing; minimal Throw lowering; config env getters; dev profile and root cleaner; docs updated; CI workflow runs curated LLVM (PHI-on/off)
This commit is contained in:
@ -13,6 +13,37 @@ Guiding Principles
|
||||
- Short-circuit semantics are already mirrored via logical nodes; Stage-3 should reuse the same block-building infrastructure (Bridge/VM/JIT) to avoid special cases.
|
||||
- Continue the "degrade to expression" approach when code generation is not ready (e.g. throw/try) so that Stage-2 tests stay green while the full implementation is developed.
|
||||
|
||||
Current Status (Phase 15.3 – 2025-09-16)
|
||||
- ParserBox / Selfhost compiler expose `stage3_enable` and `--stage3` CLI flag, defaulting to the safe Stage-2 surface.
|
||||
- Break/Continue JSON emission and Bridge lowering are implemented. Bridge now emits `Jump` to loop exit/head and records instrumentation events.
|
||||
- Throw/Try nodes are emitted when the gate is on, but still degrade to expression/no-op during lowering; runtime semantics remain TBD.
|
||||
- Documentation for JSON v0 (Stage-3 nodes) is updated; remaining runtime work is tracked in CURRENT_TASK.md.
|
||||
|
||||
Runtime snapshot
|
||||
- MIR Builder already lowers `ASTNode::Throw` into `MirInstruction::Throw` (unless disabled via `NYASH_BUILDER_DISABLE_THROW`) and has a provisional `build_try_catch_statement` that emits `Catch`/`Jump` scaffolding with env flags controlling fallback.
|
||||
- Rust VM (`interpreter::ControlFlow::Throw`) supports catch/finally semantics and rethrows unhandled exceptions.
|
||||
- Bridge degradation prevents these MIR paths from activating unless `NYASH_BRIDGE_THROW_ENABLE=1`;既定では Const0 を出し、フラグONで実際に `Throw` を生成する。
|
||||
|
||||
PyVM plan
|
||||
- Current PyVM runner treats Stage-3 constructs as no-ops because JSON v0 never emits MIR throws; once Bridge emits them, PyVM must mirror Rust VM semantics:
|
||||
- Introduce a lightweight `exception` representation (reuse ErrorBox JSON form) and propagate via structured returns.
|
||||
- Implement try/catch/finally execution order identical to Rust VM (catch matches first, finally always runs, rethrow on miss).
|
||||
- Add minimal smoke tests under `tools/pyvm_stage2_smoke.sh` (gated) to ensure PyVM and LLVM stay in sync when Stage-3 is enabled.
|
||||
|
||||
LLVM plan
|
||||
- Short term: continue degrading throw/try to keep LLVM pipeline green while implementation lands (Stage-3 smoke ensures awareness).
|
||||
- Implementation steps once runtime semantics are ready:
|
||||
1. Ensure MIR output contains `Throw`/`Catch` instructions; update LLVM codegen to treat `Throw` as a call to a runtime helper (`nyash.rt.throw`) that unwinds or aborts.
|
||||
2. Model catch/finally blocks using landing pads or structured IR (likely via `invoke`/`landingpad` in LLVM); document minimal ABI expected from NyRT.
|
||||
3. Add gated smoke (`NYASH_LLVM_STAGE3_SMOKE`) that expects non-degraded behaviour (distinct exit codes or printed markers) once helper is active.
|
||||
- Until landing pad support exists, document that Stage-3 throw/try is unsupported in LLVM release mode and falls back to interpreter/PyVM.
|
||||
|
||||
Testing plan
|
||||
- JSON fixtures: create `tests/json_v0_stage3/{break_continue,throw_basic,try_catch_finally}.json` to lock parser/bridge output and allow regression diffs.
|
||||
- PyVM/VM: extend Stage-3 smoke scripts with throw/try cases (under gate) to ensure runtime consistency before enabling by default.
|
||||
- LLVM: `NYASH_LLVM_STAGE3_SMOKE=1` は `NYASH_BRIDGE_THROW_ENABLE=1` / `NYASH_BRIDGE_TRY_ENABLE=1` と組み合わせて実際の例外経路を確認。将来的に常時ONへ移行予定。
|
||||
- CI gating: add optional job that runs Stage-3 smokes (PyVM + LLVM) nightly to guard against regressions while feature is still experimental.
|
||||
|
||||
JSON v0 Additions
|
||||
| Construct | JSON v0 Node | Notes |
|
||||
|------------|-------------------------------------------------|-------|
|
||||
@ -29,7 +60,11 @@ Lowering Strategy (Bridge)
|
||||
|
||||
2. **Throw/Try**
|
||||
- Phase 15 MVP keeps them syntax-only to avoid VM/JIT churn. Parser/Emitter produce nodes; Bridge either degrades (Expr) or logs a structured event for future handling.
|
||||
- Document expectation: once runtime exception model is defined, nodes become non-degrading.
|
||||
- Bridge helper `lower_throw` respects `NYASH_BRIDGE_THROW_ENABLE=1`; defaultは Const i64 0 のデグレード、フラグONで `MirInstruction::Throw` を実際に生成。
|
||||
- Try lowering plan:
|
||||
1. Parse-time JSON already includes `catches`/`finally`. Bridge should map `try` body into a fresh region, emit basic blocks for each `catch`, and wire `finally` as a postamble block.
|
||||
2. MIR needs explicit instructions/metadata for exception edges. Evaluate whether existing `MirInstruction::Throw` + `ControlFlow::Throw` is sufficient or if `Catch` terminators are required.
|
||||
3. Until runtime implementation lands, keep current degrade path but log a structured event to flag unhandled try/catch.
|
||||
|
||||
3. **Metadata Events**
|
||||
- Augment `crate::jit::observe` with `lower_shortcircuit`/`lower_try` stubs so instrumentation remains coherent when full support is wired.
|
||||
@ -37,14 +72,14 @@ Lowering Strategy (Bridge)
|
||||
Testing Plan
|
||||
- Extend selfhost Stage-2 smoke file with guard cases (`return break` etc.) once lowering is live.
|
||||
- Create dedicated JSON fixtures under `tests/json_v0_stage3/` for break/continue/try once behaviour stabilises.
|
||||
- Update `tools/ny_stage2_shortcircuit_smoke.sh` to ensure Stage-3 constructs do not regress Stage-2 semantics (break/continue degrade). Timing: after lowering is implemented.
|
||||
- Update `tools/ny_stage2_shortcircuit_smoke.sh` to ensure Stage-3 constructs do not regress Stage-2 semantics (break/continue degrade when gate off, jump when on).
|
||||
|
||||
Migration Checklist
|
||||
1. ParserBox emits Stage-3 nodes under `NYASH_PARSER_STAGE3=1` gate to allow gradual rollout.
|
||||
2. Emitter attaches Stage-3 JSON when gate is enabled (otherwise degrade to existing Stage-2 forms).
|
||||
3. Bridge honours Stage-3 nodes when gate is on; degrade with warning when off.
|
||||
4. PyVM/VM/JIT semantics gradually enabled (throw/try remain degrade until corresponding runtime support is merged).
|
||||
5. Documentation kept in sync (`CURRENT_TASK.md`, release notes).
|
||||
1. ParserBox emits Stage-3 nodes under `stage3_enable` gate to allow gradual rollout. ✅
|
||||
2. Emitter attaches Stage-3 JSON when gate is enabled (otherwise degrade to existing Stage-2 forms). ✅
|
||||
3. Bridge honours Stage-3 nodes when gate is on; break/continue lowering implemented, throw/try still degrade. ✅ (partial)
|
||||
4. PyVM/VM/JIT semantics gradually enabled (throw/try remain degrade until corresponding runtime support is merged). 🔄 Pending runtime work.
|
||||
5. Documentation kept in sync (`CURRENT_TASK.md`, release notes). ✅ (break/continue) / 🔄 (throw/try runtime notes).
|
||||
|
||||
References
|
||||
- Stage-2 design (`parser_mvp_stage2.md`)
|
||||
|
||||
@ -14,6 +14,9 @@ Statements (`StmtV0`)
|
||||
- `Local { name, expr }` (Stage‑2)
|
||||
- `If { cond, then: Stmt[], else?: Stmt[] }` (Stage‑2)
|
||||
- `Loop { cond, body: Stmt[] }` (Stage‑2; while(cond) body)
|
||||
- `Break` (Stage‑3; exits current loop)
|
||||
- `Continue` (Stage‑3; jumps to loop head)
|
||||
- `Try { try: Stmt[], catches?: Catch[], finally?: Stmt[] }` (Stage‑3 skeleton; currently lowered as sequential `try` body only when runtime support is absent)
|
||||
|
||||
Expressions (`ExprV0`)
|
||||
- `Int { value }` where `value` is JSON number or digit string
|
||||
@ -26,6 +29,7 @@ Expressions (`ExprV0`)
|
||||
- `Method { recv: Expr, method: string, args[] }` (box method)
|
||||
- `New { class: string, args[] }` (construct Box)
|
||||
- `Var { name: string }`
|
||||
- `Throw { expr }` (Stage‑3; currently degrades to expression statement when runtime semantics are disabled)
|
||||
|
||||
CFG conventions (lowered by the bridge)
|
||||
- If: create `then_bb`, `else_bb`, `merge_bb`. Both branches jump to merge if unterminated.
|
||||
@ -33,12 +37,10 @@ CFG conventions (lowered by the bridge)
|
||||
- Short‑circuit Logical: create `rhs_bb`, `fall_bb`, `merge_bb` with constants on fall path.
|
||||
- All blocks end with a terminator (branch/jump/return).
|
||||
|
||||
PHI merging (current behavior)
|
||||
- If: locals updated in `then`/`else` merge at `merge_bb` via `phi`.
|
||||
- Else欠落時は else 側に分岐前(base)を採用。
|
||||
- 片側にしか存在しない新規変数はスコープ外として外へ未伝播。
|
||||
- Loop: `cond_bb` にヘッダ PHI を先置き(preheader/base と latch/body end を合流)。
|
||||
- 目的: Stage‑2 を早期に安定化させるための橋渡し。将来(LoopForm= MIR18)では LoopForm からの逆Loweringで PHI を自動化予定。
|
||||
PHI merging(Phase‑15 終盤の方針)
|
||||
- MIR 生成層は PHI を生成しない(MIR13 運用)。If/Loop の合流は LLVM 層(llvmlite/Resolver)が PHI を合成。
|
||||
- ループは既存 CFG(preheader→cond→{body|exit}; body→cond)の検出により、ヘッダ BB で搬送値の PHI を構築。
|
||||
- 将来(LoopForm= MIR18)では LoopForm 占位命令から逆 Lowering で PHI を自動化予定。
|
||||
|
||||
Type meta (emitter/LLVM harness cooperation)
|
||||
- `+` with any string operand → string concat path(handle固定)。
|
||||
@ -78,3 +80,5 @@ If with local + PHI merge
|
||||
{"type":"Return","expr":{"type":"Var","name":"x"}}
|
||||
]}
|
||||
```
|
||||
- `Break` / `Continue` are emitted when Stage‑3 gate is enabled. When the bridge is compiled without Stage‑3 lowering, frontends may degrade them into `Expr(Int(0))` as a safety fallback.
|
||||
- `Try` nodes include optional `catches` entries of the form `{ param?: string, typeHint?: string, body: Stmt[] }`. Until runtime exception semantics land, downstream lowers only the `try` body and ignores handlers/finally.
|
||||
|
||||
Reference in New Issue
Block a user