merge: resolve conflicts (prefer cranelift-dev for Core-13 defaults; drop modules/using, add env.local/env.box shims)
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
# MIR step‑50: Final Reference Sync after Core Flip
|
||||
|
||||
Status: Planned
|
||||
Status: Done
|
||||
|
||||
Purpose: After the Core‑15→Core‑13 flip is complete in code/tests, perform a last wave of documentation alignment across top‑level entry points and user‑facing docs.
|
||||
|
||||
@ -13,13 +13,13 @@ Purpose: After the Core‑15→Core‑13 flip is complete in code/tests, perform
|
||||
- DEV quickstart and contributor docs: link to Core‑13 reference and validation tests.
|
||||
|
||||
## Preconditions
|
||||
- Tests enforce Core‑13 instruction count and legacy‑op forbiddance.
|
||||
- Tests enforce Core‑13 instruction count and legacy‑op forbiddance (see `src/mir/instruction_introspection.rs` and `src/tests/mir_core13_normalize.rs`).
|
||||
- VM/JIT/AOT backends accept the reduced set (or have shims documented if not yet).
|
||||
|
||||
## Validation
|
||||
- `cargo test` green with Core‑13 enforcement.
|
||||
- `tests/mir_instruction_set_sync.rs` asserts exactly 13 instructions.
|
||||
- `src/mir/instruction_introspection.rs` asserts exactly 13 in `core13_instruction_count_is_13`.
|
||||
- `src/tests/mir_core13_normalize.rs` validates Array/Ref normalization to BoxCall.
|
||||
|
||||
## Rollback Plan
|
||||
- Keep the Core‑15 reference/notes in `docs/development/roadmap/` (archive) for historical context.
|
||||
|
||||
|
||||
72
docs/development/roadmap/phases/phase-17/BLUEPRINT_MIN.md
Normal file
72
docs/development/roadmap/phases/phase-17/BLUEPRINT_MIN.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Phase 17 — Minimal, Clean, Small (Blueprint)
|
||||
|
||||
Purpose: ship a tiny, beautiful vertical slice that runs Core‑13 IR end‑to‑end, is observable, and easy to extend. Keep everything additive and simple.
|
||||
|
||||
1) Scope (MVP)
|
||||
- IR: Core‑13 only (Loop IR placeholder only).
|
||||
- Exec: Wrap existing VM with a tiny `ExecEngine` adapter.
|
||||
- Remote: One transport only — NDJSON over stdio (`nyash-engine-core13`).
|
||||
- CLI: `run`, `ir-emit`, `ir-run`. Trace: Enter/Exit only.
|
||||
|
||||
2) ExecEngine (tiny)
|
||||
- Value: `Int(i64) | Bool(bool) | Str(String) | Box(u64) | None`.
|
||||
- Trait:
|
||||
- `load(&Core13Module) -> ModuleHandle`
|
||||
- `get(&ModuleHandle, func: &str) -> FuncHandle`
|
||||
- `call(&FuncHandle, args: &[Value]) -> Result<Value>`
|
||||
- Adapter: `VMEngine` delegates to existing VM (`execute_module`), converts Value <-> NyashBox.
|
||||
|
||||
3) Core‑13 IR JSON (minimal)
|
||||
- module: `{ schema:1, name:"m", funcs:[ { name, params:[], ret:"i64|bool|string|box|void", blocks:[...] } ] }`
|
||||
- block: `{ id:0, inst:[...], term:{...} }`
|
||||
- inst (13 only): `Const, BinOp, Compare, Jump, Branch, Return, Phi, Call, BoxCall, ExternCall, TypeOp, Safepoint, Barrier`.
|
||||
- example Const: `{ op:"Const", dst:1, ty:"i64", value:42 }`
|
||||
- example Return: `{ term:"Return", value:1 }`
|
||||
|
||||
4) NDJSON protocol (stdio)
|
||||
- Common: every request has `op,id,schema(=1)`; every response `{ok:true|false,id,...}`; unknown keys ignored.
|
||||
- Ops (MVP): `load_module`, `call`, `ping`, `trace_sub` (Enter/Exit only).
|
||||
- Requests:
|
||||
- load_module: `{op:"load_module",id:1,ir:"core13",format:"json",bytes:"<base64>"}`
|
||||
- call: `{op:"call",id:2,module_id:1,func:"main",args:[]}`
|
||||
- ping: `{op:"ping",id:3}`
|
||||
- trace_sub: `{op:"trace_sub",id:4,mask:["EnterFunc","ExitFunc"],flush_ms:50?}`
|
||||
- Responses:
|
||||
- `{ok:true,id:1,module_id:1,features:["interp","trace"],ir:"core13"}`
|
||||
- `{ok:true,id:2,value:42,events_dropped:0}`
|
||||
- `{ok:true,id:3,now:1725600000}`
|
||||
- `{ok:true,id:4}` (events then stream as separate lines)
|
||||
- Events (lines): `{"event":"EnterFunc","func":"main"}` / `{"event":"ExitFunc","func":"main"}`.
|
||||
|
||||
5) CLI UX
|
||||
- `nyash run --engine=vm apps/hello.nyash`
|
||||
- `nyash run --engine=remote --exe ./nyash-engine-core13 apps/hello.nyash`
|
||||
- `nyash ir-emit --ir=core13 --format=json apps/hello.nyash > out.json`
|
||||
- `nyash ir-run --engine=vm < out.json`
|
||||
|
||||
6) Milestones
|
||||
- M1: ExecEngine + VMAdapter + `run --engine=vm` (tests: add/if/string.length)
|
||||
- M2: Core‑13 serde/verify + `ir-emit`/`ir-run` (round‑trip + 1 exec test)
|
||||
- M3: `nyash-engine-core13` NDJSON (load/call/ping/trace_sub) + `run --engine=remote` parity
|
||||
|
||||
7) Design rules (beauty & simplicity)
|
||||
- Additive evolution only: version fields present (`schema`), unknown keys ignored.
|
||||
- Deterministic JSON: stable key order where practical to make diffs readable.
|
||||
- Naming: short, explicit; avoid redundancy; keep method ids optional.
|
||||
- Observability first: ship with Enter/Exit trace; branch/extern later.
|
||||
|
||||
Appendix: Two request/response examples
|
||||
1) Load then call
|
||||
REQ: `{ "op":"load_module", "id":1, "schema":1, "ir":"core13", "format":"json", "bytes":"<base64>" }`
|
||||
RESP:`{ "ok":true, "id":1, "module_id":1, "features":["interp","trace"], "ir":"core13" }`
|
||||
REQ: `{ "op":"call", "id":2, "schema":1, "module_id":1, "func":"main", "args":[] }`
|
||||
RESP:`{ "ok":true, "id":2, "value":42, "events_dropped":0 }`
|
||||
|
||||
2) Trace subscribe and ping
|
||||
REQ: `{ "op":"trace_sub", "id":10, "schema":1, "mask":["EnterFunc","ExitFunc"] }`
|
||||
RESP:`{ "ok":true, "id":10 }`
|
||||
EVT: `{ "event":"EnterFunc", "func":"main" }`
|
||||
EVT: `{ "event":"ExitFunc", "func":"main" }`
|
||||
REQ: `{ "op":"ping", "id":11, "schema":1 }`
|
||||
RESP:`{ "ok":true, "id":11, "now":1725600000 }`
|
||||
|
||||
128
docs/development/roadmap/phases/phase-17/README.md
Normal file
128
docs/development/roadmap/phases/phase-17/README.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Phase 17: 二本立てIR実行系とモジュール分割(AST共有 → MIR13 / Loop MIR 分岐)
|
||||
|
||||
## 目的(Why)
|
||||
- 文法・予約語・ASTまでは完全共有し、その後のIR層で分岐(MIR13/Core‑13 と LoopForm/Loop MIR)する設計に再編する。
|
||||
- 解釈器(interp)を各IRに対して同型で用意し、変換を挟まずに意味・性能をA/B比較できるようにする。
|
||||
- VM/JIT/AOTは共通の実行インタフェース(ExecEngine)で差し替え可能にし、分散開発を容易にする。
|
||||
|
||||
## スコープ(Scope)
|
||||
- 共有フロントエンド: Lexer/Parser/AST/Resolver は現行仕様(文法・予約語を変えない)。
|
||||
- 二系統IR: Core‑13 MIR(= MIR13)と Loop MIR(= LoopForm IR)。
|
||||
- 同型解釈層: core13→core13(interp)、loop→loop(interp)。変換は後段。
|
||||
- 安定IR ABI: 各IRをシリアライズ/デシリアライズ可能にし、CLI/ツールと疎結合化。
|
||||
- CLI統合: `--engine` と `ir-emit/ir-run/trace` の導線。
|
||||
|
||||
## 全体アーキテクチャ(High‑level)
|
||||
- frontend
|
||||
- grammar(文法)/ lexer / parser / AST builder
|
||||
- semantic resolver(必要なら)
|
||||
- lowering
|
||||
- `lower_core13(ast) -> Core13Module`
|
||||
- `lower_loop(ast) -> LoopModule`
|
||||
- ir
|
||||
- `nyash-ir-core13`: 型・検証(verify)・正規化(normalize)・serde(json/bin)
|
||||
- `nyash-ir-loop`: 型・検証(verify)・serde(json/bin)
|
||||
- exec (共通トレイト)
|
||||
- `nyash-exec-traits`: `ExecEngine`, `TraceSink`, `Value`, `EffectMask`, `Event`
|
||||
- `nyash-interp-core13`: Core‑13インタプリタ
|
||||
- `nyash-interp-loop`: Loop MIRインタプリタ
|
||||
- `nyash-vm` / `nyash-jit` / `nyash-aot`(将来/既存統合)
|
||||
- runtime
|
||||
- `nyash-rt`: BoxCall/ExternCall/GC/FFI等の実体
|
||||
- cli
|
||||
- `nyash`: `run`, `dump-ir`, `exec --engine`, `trace`, `bench`
|
||||
|
||||
## AST共有 → IR分岐(設計原則)
|
||||
- 文法・予約語・AST構造は単一実装で共有(差分なし)。
|
||||
- AST→MIRはインタフェース分岐のみ:
|
||||
- `LoweringFacade` が `LowerCore13` と `LowerLoop` を注入可能な形で生成
|
||||
- ASTノード毎に `emit_*` を両実装で提供(if/while/for/return/break/continue/try 等)
|
||||
- エラー/位置情報: AST→IRの間で `dbg.origin` と `scope_id` を保持し、IR間比較・デバッグに使う。
|
||||
|
||||
## ExecEngine インタフェース(安定境界)
|
||||
- 型
|
||||
- `Value`: int/float/bool/ptr/box/none
|
||||
- `EffectMask`: R/W/IO/GC/FFI などのビット
|
||||
- `Event`: Enter/Exit/Block/PhiMerge/LoopIter/Branch/ExternCall/Safepoint/Barrier/GC/Jit
|
||||
- トレイト
|
||||
- `load_module(ir) -> ModuleHandle`
|
||||
- `get_func(m, name) -> FuncHandle`
|
||||
- `call(ctx, f, args) -> Result<Value>`
|
||||
- `set_tracer(TraceSink)` / `features() -> FeatureMask`
|
||||
- 切替
|
||||
- `nyash run --engine=interp-core13|interp-loop|vm|jit`(同一AST/IRに対し差し替え)
|
||||
|
||||
## IR ABI(シリアライズ)
|
||||
- 目的: ブランチや外部プロセス間でIRを受け渡しし、分散開発・ツール連携を容易に。
|
||||
- 形式: `json`(可読) + `bin`(MessagePack/bincode 等)。
|
||||
- バージョン: `schema_version`, `features` を明示。後方互換は“追加のみ”。
|
||||
- CLI:
|
||||
- `nyash ir-emit --ir=core13|loop --format=json|bin -o out`
|
||||
- `nyash ir-run --engine=... < in.ir`
|
||||
- `nyash trace --engine=...`(イベント列のダンプ/比較)
|
||||
|
||||
## Core‑13 MIR(MIR13)概要
|
||||
- 命令: Const, BinOp, Compare, Jump, Branch, Return, Phi, Call, BoxCall, ExternCall, TypeOp, Safepoint, Barrier(固定13)
|
||||
- verify: `phi`配置、効果マスクと`safepoint/barrier`の規則、レガシー命令の禁止
|
||||
- normalize: クリティカルエッジ分割、可換演算正規化、不要ジャンプ除去、`phi`順序安定化
|
||||
|
||||
## Loop MIR(LoopForm IR)概要
|
||||
- プリミティブ: `loop.begin`, `loop.iter`, `loop.branch`, `loop.end`, `loop.signal(Next|Break|Return|Yield?)`
|
||||
- 状態: ループキャリア値は `state tuple` として管理、合流は `loop.branch` に集約
|
||||
- verify: 単一エントリ/単一点帰還、`signal`の終端性、state↔phi対応、例外/非局所脱出はSignal表現
|
||||
|
||||
## 2つの解釈器(変換なしで比較)
|
||||
- `interp-core13`: 基本ブロック/PC/SSA環境、`phi`合流、Box/Extern/Type/Safepoint/Barrier 実装
|
||||
- `interp-loop`: LoopFrame(state, pc, hdr), `loop.iter/branch/signal` を直接実行
|
||||
- 共通計測: `steps, blocks, phi_merges, loop_iter, branch_taken, extern_calls, box_allocs, safepoints`
|
||||
- トレース一致: 同一プログラムで I/O/ExternCall列/Effect可視イベント列が一致することを自動検証
|
||||
|
||||
## モジュールとファイル案(例)
|
||||
- `crates/nyash-ir-core13/`(schema, verify, normalize, serde)
|
||||
- `crates/nyash-ir-loop/`(schema, verify, serde)
|
||||
- `crates/nyash-exec-traits/`(Value, EffectMask, Event, ExecEngine, TraceSink)
|
||||
- `crates/nyash-interp-core13/`(ExecEngine実装)
|
||||
- `crates/nyash-interp-loop/`(ExecEngine実装)
|
||||
- `crates/nyash-rt/`(ランタイム)
|
||||
- `crates/nyash-front/`(lexer/parser/AST/resolver/lowering-facade)
|
||||
- `apps/nyash-cli/`(サブコマンド: run, dump-ir, ir-run, trace, bench)
|
||||
|
||||
## ブランチ運用
|
||||
- `feature/mir-core13-interp-refactor`: 既存Core‑13実行をExecEngineでラップ、計測/トレース導入
|
||||
- `experiment/loopform-interp-poc`: Loop IR定義+verify+loop→loop解釈器
|
||||
- `infra/exec-switch-cli`: CLIに `--engine` と IR入出力/トレース差分
|
||||
- (後段)`feature/loopform-lowering`: 変換器(Core‑13⇄Loop)— デフォルトOFF
|
||||
|
||||
## マイルストーン
|
||||
1. ExecEngineトレイト雛形を追加(ビルド通る最小)
|
||||
2. Core‑13解釈器をトレイト実装化(既存コード最小改修でアダプタ挟み)
|
||||
3. Core‑13 IRのserde/verify/normalize + `ir-emit/ir-run`
|
||||
4. Loop IRのschema/verify/serde + `interp-loop` 最小実装
|
||||
5. A/Bトレース一致(代表: if/while/break/early return/副作用混在)
|
||||
6. ベンチ3種(算術核/ループ核/副作用核)で `--engine` 差し替え比較
|
||||
7. CI: 双経路の意味同値・形式同値(α同値は後段)テストを追加
|
||||
|
||||
## 受入れ基準(Definition of Done)
|
||||
- 同一入力で `interp-core13` と `interp-loop` の I/O と外部呼び出しトレースが一致
|
||||
- 代表3ベンチでイベント内訳が収集可能、差分が説明可能
|
||||
- IRのシリアライズ/デシリアライズ→verify が双系統とも成功
|
||||
- CLIの `--engine` / `ir-emit` / `ir-run` / `trace` が動作
|
||||
|
||||
## リスクと対策
|
||||
- 変換せず比較するため構文上の差異は見えにくい → AST→IRで `dbg.origin/scope_id` を保持し比較用に活用
|
||||
- ExecEngineの型進化 → 予約タグ/ビット・schema_versionで後方互換を担保
|
||||
- デバッグ難度 → `trace-diff` と `ir-dump` に高レベル再構成表示(while/loop切替)を用意
|
||||
|
||||
## タスクリスト(最小)
|
||||
- [ ] `nyash-exec-traits` 作成(Value/Effect/Event/ExecEngine/TraceSink)
|
||||
- [ ] Core‑13実行器のトレイトラップ(最小アダプタ)
|
||||
- [ ] `nyash-ir-core13` serde/verify/normalize + CLI `ir-emit/ir-run`
|
||||
- [ ] `nyash-ir-loop` schema/verify/serde
|
||||
- [ ] `nyash-interp-loop` 最小実装(begin/iter/branch/signal)
|
||||
- [ ] CLI `--engine` 切替 + `trace` サブコマンド
|
||||
- [ ] ベンチ3種 + 共通計測 + CSV出力
|
||||
- [ ] CI: A/Bトレース一致テスト
|
||||
|
||||
## 備考
|
||||
- 文法・予約語・ASTは完全共有(このフェーズでは変更しない)。
|
||||
- 変換(Core‑13⇄Loop)は次フェーズ以降。まずは“同型解釈”で比較と観測に集中する。
|
||||
@ -0,0 +1,92 @@
|
||||
# Phase 17 接続モデル(最小): JSON NDJSON over stdio, exe↔exe
|
||||
|
||||
目的: まずは「簡単・見える・壊れない」。単一の接続モデル(JSONを1行ずつ、標準入出力でやり取り)で、エンジンを別プロセスの小さな実行ファイルとして積み上げる。
|
||||
|
||||
## 方針
|
||||
- 1接続モデルのみ: NDJSON(1メッセージ=1行のJSON)。
|
||||
- 1トランスポートのみ: 標準入出力(子プロセス起動)。パイプ/ソケットは後回し。
|
||||
- 1エンジン=1 exe: `nyash-engine-core13`, `nyash-engine-loop`など。役割ごとに小さく分割。
|
||||
- 可視化容易: すべてのトレースをNDJSONで出力し、そのまま保存・比較・変換(jq/簡易スクリプト)。
|
||||
|
||||
## メッセージ共通フィールド
|
||||
- `op`: 操作名(例: "load_module", "call", "trace_sub")
|
||||
- `id`: リクエストID(数値/文字列)。応答に同じ`id`を返す。
|
||||
- `schema`: プロトコル版(整数, 例: 1)。
|
||||
- `ts`: 送信者時刻(オプション, ns/μs/ms表現は自由)。
|
||||
|
||||
応答の共通:
|
||||
- `ok`: true/false
|
||||
- `id`: リクエストと同一
|
||||
- `err`: 失敗時のみ `{code, message, data?}`
|
||||
|
||||
## 操作一覧(最小)
|
||||
1) load_module
|
||||
- 要求: `{op:"load_module", id:1, schema:1, ir:"core13|loop", format:"json|bin", bytes:"<base64>"}`
|
||||
- 応答: `{ok:true, id:1, module_id:1, features:["interp","trace"], ir:"core13"}`
|
||||
|
||||
2) call
|
||||
- 要求: `{op:"call", id:2, module_id:1, func:"main", args:[1,2,3], timeout_ms:5000?}`
|
||||
- 応答: `{ok:true, id:2, value:3, events_dropped:0}`
|
||||
|
||||
3) trace_sub(トレース購読)
|
||||
- 要求: `{op:"trace_sub", id:3, mask:["EnterFunc","ExitFunc","LoopIter","Branch","ExternCall"], flush_ms:50?}`
|
||||
- 応答: `{ok:true, id:3}`
|
||||
- イベントストリーム: 別行で `{"event":"EnterFunc", "func":"main", ...}` を逐次出力(応答行とは独立)
|
||||
|
||||
4) unload(任意)
|
||||
- 要求: `{op:"unload", id:4, module_id:1}`
|
||||
- 応答: `{ok:true, id:4}`
|
||||
|
||||
5) ping(ヘルスチェック)
|
||||
- 要求: `{op:"ping", id:5}`
|
||||
- 応答: `{ok:true, id:5, now: 1725600000}`
|
||||
|
||||
エラー例:
|
||||
- 応答: `{ok:false, id:2, err:{code:"E_NO_FUNC", message:"function not found", data:{func:"main"}}}`
|
||||
|
||||
## トレースイベント(NDJSON)
|
||||
- 例: `{"event":"EnterFunc","func":"main","args":[1],"ts":...}`
|
||||
- 最小セット: `EnterFunc, ExitFunc, Block, PhiMerge, LoopIter, Branch, ExternCall, Safepoint, Barrier`
|
||||
- フィールドの原則: `event`必須、その他は柔軟に拡張し未知キーは無視可能。
|
||||
|
||||
## エンジンexeの約束
|
||||
- 起動直後にバナー等を出力しない(標準出力は完全にプロトコル専用)。
|
||||
- 標準エラーは自由(ログ用)。
|
||||
- 読み込みは行単位でJSONをパース、応答は必ず1行。
|
||||
- イベントは応答と独立行で流してよい(trace_sub済みのとき)。
|
||||
- 大きなIRバイナリは `bytes` を base64。JSON IRはそのまま文字列可。
|
||||
|
||||
## クライアント側(nyash-cli)
|
||||
- `nyash run --engine=remote --exe ./nyash-engine-core13 --ir=core13 -- program.ny`
|
||||
- 実装は単純: 子プロセスspawn → stdin/stdoutにNDJSON → `load_module`→`call`。
|
||||
- `--trace`で `trace_sub` を投げてNDJSONログをファイル保存(そのまま可視化可能)。
|
||||
|
||||
## 可視化(最小)
|
||||
- NDJSON→Markdown表: `jq -r` で列抽出, `|`区切りでテーブル化。
|
||||
- NDJSON→CSV: `jq -r '[.event, .func, .block, .ts] | @csv'`。
|
||||
- 差分: 2つのトレースを event+順序でzip比較。簡易Python/nyashツールは後続で追加可。
|
||||
|
||||
## バージョニングと互換
|
||||
- `schema` は整数で宣言、互換性は「追加のみ」原則。意味変更や削除は `schema+1`。
|
||||
- 不明キーは無視。必須キー欠落は `E_SCHEMA`。
|
||||
|
||||
## タイムアウト/健全性
|
||||
- `call.timeout_ms` を受付。内部でキャンセル/中断可能な範囲で対応。
|
||||
- ハートビート: `ping` を定期送信して固まり検出。
|
||||
|
||||
## セキュリティ
|
||||
- ローカル実行のみを想定(最小)。ネットワーク露出はしない。
|
||||
- 外部からのファイルアクセス/実行はプロトコルに含めない(エンジンはIR実行に限定)。
|
||||
|
||||
## 最小試験手順(手動)
|
||||
1) エンジンを起動(手動で別ターミナル)。`cat`でNDJSONを流せるならなお良い。
|
||||
2) `load_module` を送信(小さなIR)。
|
||||
3) `trace_sub` を送信。
|
||||
4) `call` を送信 → 応答とイベント列を保存。
|
||||
5) jqでCSV化して目視。
|
||||
|
||||
## 将来拡張(後回し)
|
||||
- 長期接続(ソケット/名前付きパイプ)
|
||||
- バイナリMessagePack/bincode実装(速度重視)
|
||||
- 圧縮(gzip)
|
||||
- ストリーム再同期(途中から読み直し)
|
||||
Reference in New Issue
Block a user