Files
hakorune/CURRENT_TASK.md

883 lines
65 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Current Task — Phase 15 (Concise)
Focus
- Keep VM quick green; llvmlite integration on-demand.
- Using SSOTnyash.toml + 相対usingで安定解決。
- Builder/VM ガードは最小限・仕様不変dev では診断のみ)。
- Phase 15.7 を再定義: Known 化Rewrite 統合dev観測と MiniVM 安定化、表示APIは `str()` に統一(互換:stringify
Update — 2025-11-02StageB 既定ONRunnerヘルパー適用quick:core 緑PHI strict 既定ON
- StageB スモークを既定ON 化quick
- 7本print/binop/if/loop/array/map/string`static box Main { method main(args) { … } }` 形へ統一。
- 実行は emit 直行Stage1 Program(JSON v0) の1行出力を厳格検証
- v1 downconvert 実行は引き続きオプトイン(`NYASH_NYVM_V1_DOWNCONVERT=1`)。
- Runner 子環境の一元化
- `src/runner/child_env.rs::apply_core_wrapper_env` を selfhost 子経路へ適用冗長ENV配線を除去
- GateC/Core の OOB Strict フローは `pre_run_reset_oob_if_strict()` で明示リセット→実行→観測 exit に統一。
- テストランナー強化
- `run_nyash_vm``NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1` を常時付与Stage3 文法の安定受理)。
- Hako/canonicalize/OOB の optin 整理
- Hako 系: `SMOKES_ENABLE_HAKO_BINOP|_IF=1`、Bridge canonicalize: `SMOKES_ENABLE_BRIDGE_CANON=1`、OOB(pipe/file): `SMOKES_ENABLE_OOB_PIPE|_FILE=1`
- ルート検出の不安定スクリプトは `git rev-parse` + fallback 形式に統一。
- quickcore フィルタ): 115/115 PASS を確認。既定セットは赤ゼロ。
VM PHI strict 既定ONFailFast
- 既定ON化: `src/backend/mir_interpreter/exec.rs` の判定を「未設定なら ON」に変更。
- 無効化: `HAKO_VM_PHI_STRICT=0`(互換: `NYASH_VM_PHI_STRICT=0`)。
- ループ条件の PHI 再束縛/初期PHIpreheader入力のみを導入し、条件式が必ずPHI値を参照するよう修正。
- 変更: `src/mir/phi_core/loop_phi.rs`初期PHI + 再束縛)、`src/mir/loop_builder.rs`PHI差替え・順序安定
- 付随: VM インタプリタにステップ上限(`HAKO_VM_MAX_STEPS`/`NYASH_VM_MAX_STEPS`、既定 1,000,000を追加して暴走を防止。
- 結果: quick 120/120 PASS、strictカナリアstrict/core/vm_phi_strict_smoke.shも PASS。
Docs refresh — 2025-11-02VM/Smokes
- VM READMElang/src/vm/README.md更新
- 診断タグを明記: `[map/missing]`, `[map/bad-key]`, `[array/empty/pop]`
- PHI strict 既定ONとステップ上限`HAKO_VM_MAX_STEPS` / `NYASH_VM_MAX_STEPS`)の方針を追記。
- Core canary と GateC(Core) の使い方、Core ループ上限(`HAKO_CORE_MAX_ITERS` / `NYASH_CORE_MAX_ITERS`)を追記。
- Smokes READMEtools/smokes/v2/README.md更新
- Bridge canonicalize の ON/OFF/FAIL ポリシーと diff カナリア群を記載。
- Core negativesArray/Map/Stringと GateC(Core) の不正ヘッダ/パリティ系を列挙。
- StageB カナリアは optin`SMOKES_ENABLE_STAGEB=1`)に訂正。
- quick 現況
- quickcore フィルタ): 137/137 PASSemit→nyvm(Core) 3本、GateC/Core OOB strict/file+pipe を含む)。
- 代表トグル: `SMOKES_ENABLE_CORE_CANARY=1`, `SMOKES_ENABLE_BRIDGE_CANON=1`, `SMOKES_ENABLE_OOB_PIPE|_FILE=1`
- 将来の昇格候補: StageBprint/binop/if/loop/array/map/string の直行を既定ONへ。
Update — 2025-11-02 (P1, part1) — Runner子ENV一元化StageB入口の軽量化の徹底
- Runner 子経路のENV一元化を追加適用
- `src/runner/selfhost.rs` の Python harness / PyVM runner の spawn にも
`child_env::apply_core_wrapper_env` を適用JSON_ONLY/disable plugins/using禁などを統一
- StageB 入口の軽量化emitの1行保証
- `compiler_stageb.hako` は Stage1 Program(JSON v0) を1行出力heavyな MIR 直行を回避)。
- FlowEntry は v1→v0軽経路を優先し、using 付き v0 と v1+meta は二段目の候補に降格。
- `lower_stage1_to_mir_with_usings` のデバッグ出力は既定OFFprefer==9 の時のみ)。
- quick: core/stageb canaries は引き続き PASSoptin。昇格基準print まで PASSを達した時点で既定ONへの切替を検討。
Update — 2025-11-02P0後半 — StageB bundle emit と GateC print/loop rc 昇格)
- StageB Module bundling最小
- `compiler_stageb.hako``--bundle-src <code>` を複数受理する最小バンドラを追加。
- 直行 emit 前に bundle を先頭へ連結し、Program(JSON v0) 一行出力を維持。
- スモーク追加: `core/stageb/stageb_bundle_vm.sh`(ヘッダ厳格のみ; 実行は未対象)。
- GateC(Core) rc 昇格
- loop: rc=6 の厳格検証に昇格PHI重複をlowerer側でマージ
- print: legacy/extern の最小ブリッジをVM側に追加numeric→println; rcはreturnに従う
- `stageb_print_vm.sh`/`stageb_loop_vm.sh` を rc 検証化。
Update — 2025-11-02P1 — child_env 一元化print 正規化)
- Runner 子環境ヘルパー適用の拡大
- pipe I/O の PyVM 経路と selfhost common_util(json) の Python runner spawn に `child_env::apply_core_wrapper_env` を適用。
- 目的: Stage3/using抑止/JSON_ONLY/disable plugins などのトグルを一元化し、ドリフトを除去。
- Core mir_call 正例(最小)
- print 系legacy/externを VM 側で最小受理(数値/文字列印字 → Void。GateC/Core の print rc 検証が安定。
Update — 2025-09-28 (P4 defaulton + P5 docs/annotations 完了)
- Known 正規化userbox限定・関数存在・一意・arity一致を既定ON。
- フラグ: `NYASH_REWRITE_KNOWN_DEFAULT`0/false/off で無効化)。
- 設計ノートを追加: `docs/development/builder/unified-method-resolution.md`
- Quick Reference を更新: 内部正規化の注記と切替フラグを追記。
- 型注釈を最小拡張is_digit_char/hex/alpha, MapBox.has/1 → Bool
- quick/integration: 全緑を確認。
Update — 2025-09-28 (Router/EmitGuard/NameConst 導入・json_lint_vm 緑)
- Router 最小ガード(仕様不変・安定優先)
- UnknownBox の Method は一律レガシー経路BoxCallへフォールバックunified 経路での sporadic 未定義を根絶)。
- `prefer_legacy` を保守側既定に調整: None/Unknown/String/Array/Map は BoxCall 優先、ユーザー箱(末尾"Box"以外)も従来通り BoxCall。
- `JsonParserModule.create_parser/0` の戻り型を Known 化Box("JsonParser") 起源付与)。
- BlockSchedule 検証dev-only
- φ→Copy(materialize)→本体(Call) の順序検証を追加(ズレは WARN のみ)。
- VM dev 安全弁既定OFF
- `reg_load` 未定義→Void 置換を `NYASH_VM_TOLERATE_VOID=1` 下でのみ有効化(診断と一時救済)。
- 結果
- quick: `json_lint_vm` PASS未定義は解消
- integrationLLVM/llvmlite: PASS 17/17すべて緑
- 備考: `json_query_vm` は後続の更新で解決(下記エントリ参照)。
Update — 2025-09-28 (json_query_vm PASS・最終ガード適用)
- evaluator 側の堅牢化VM準拠・仕様不変
- 文字クラス判定を membership手動スキャンへ変更indexOf 非依存)。
- span を ArrayBox から "i:j" 文字列に正規化(.get 依存を排除)。
- span_unpack_* も手動スキャン実装indexOf 非依存)。
- out-of-range/未存在キーは null 返却で合意。
- テスト: json_query_vm の SKIP を解除して PASS を確認。
- quick: 引き続き 64/64 PASS、integration: 17/17 PASS。
Update — 2025-10-31 (Phase 20.33 bring-up)
- Stage-A map literal parser hardened空白エスケープ; quick `index_operator_hako` expands coverage。
- Stage-B entry separated (`lang/src/compiler/entry/compiler_stageb.hako`); `compiler.hako -- --stage-b` から StageBMain を呼び出し、FlowEntry `emit_v0_from_ast_with_context` (using/extern) を既定採用。`--v1-compat` は MirJsonV1Adapter 経路へ opt-in現状は未配線のため SKIP。opt-in canariesbinop/if/index + nested/boundary…は Stage-B 本体が未整備な場合は SKIP 振る舞い。
- `nyash.toml` modules updated to expose lang/compiler/shared/vm namespaces for resolver。
- quick profile: 72/72 PASSFileBox 未展開時は SKIP ハンドリング)。
Update — 2025-11-01 (GateC v1 / Bridge / StageB)
- GateC v1 実行既定OFF
- `HAKO_NYVM_CORE=1`alias `NYASH_NYVM_CORE`)で v1(JSON) を `json_v1_bridge``MirModule` に変換 → MIR Interpreter で実行const/copy/binop/compare/ret/branch/jump/phi
- `HAKO_NYVM_V1_DOWNCONVERT=1` で同じコンバータを「降格」として再利用(未対応は FailFast
- Bridge 正規化トグルを実装既定OFF: `HAKO_BRIDGE_INJECT_SINGLETON=1`Array/Map len→Method 化)、`HAKO_BRIDGE_EARLY_PHI_MATERIALIZE=1`(φ をブロック先頭へ)。
- Parityoptin
- GateC(file/pipe) × plugins(ON/OFF) の 2×2 は quick の optin カナリアで緑scripts: `profiles/quick/core/gate_c_v1_{file,pipe}_vm.sh`)。
- StageB 入口
- `compiler.hako -- --stage-b``compiler_stageb.hako`StageBMain`FlowEntry.emit_v0_from_ast_with_context`
- dev サポートスクリプト: `tools/dev_stagea.sh` / `tools/dev_stageb.sh`emit 文字列をその場実行)。
- 次の重点Claudeへ
- StageB emit の空経路潰しprint/binop/if/index の 1 行 v0 を保証)。
- v1 ブリッジに `mir_call`(最小の Global/Externを追加診断安定化
- Rust MIR の params 既定化(`build_static_main_box` / `lower_static_method_as_function` の def→use 順)。
- Rust builder の微修正
Update — 2025-11-01 (LLVM 静的Box規約の明文化 / リポジトリ整備)
- 静的BoxLLVM 命令系)の self 先頭規約を明文化し、互換トグル `HAKO_BRIDGE_INJECT_SINGLETON` の運用を docs に追加。
- 新規: `docs/development/architecture/llvm/static_box_singleton.md`
- 参照追加: `lang/src/vm/README.md` に規約サマリを追記。
- GateC(Core)/Bridge 設計の現状と今後を README 類に反映既定OFFのまま
- `bak` フォルダの存在を確認したが、ワークスペース直下には見当たらず(削除不要)。
- `build_static_main_box` にて `args` 配列生成後に `birth()` を明示呼び出し。NewBox→birth の警告/未初期化を解消。
Update — 2025-09-28 (P1 — Const統一拡大 + メタ伝播の適用)
- Const 発行の統一builder 側残存)
- `build_literal` と core13-pure の型名 Const を ConstantEmissionBox に統一済。残存直書きは掃除済みrewrite系は NameConstBox 使用)。
- メタデータ伝播type/originを小粒適用
- BlockScheduleBox: `emit_before_call_copy``propagate(base→dst)` を追加。
- utils: `materialize_local``propagate(src→dst)` を追加。
- `insert_copy_after_phis` は既に propagate 済み(再確認のみ)。
- ルータ/型注釈: 前回の dev トレース追加/ホワイトリスト拡張に変更なし(挙動不変)。
- 検証: quick/integration は引き続き全緑を確認予定(差分は局所・可逆)。
Update — 2025-09-28 (Rewrite Known 化 Stage1 一本化)
- 標準メソッド呼び出しを emit_unified_call に統一委譲。
- ルーティングRouterPolicyと rewrite::{special,known} の適用点を一本化。
- 既存ガードにより Unknown/core/user-instance は BoxCall へ自動フォールバック(挙動不変)。
- 重複掃除(挙動不変)
- method_call_handlers 内の receiver クラス推定me/起源/型は削除し、unified 側に一本化。
- box_type は None を渡し、emit_unified_call が起源/型から判断。
- pin_to_slot/BoxCall 直呼びの旧コードは撤去済み。
Update — 2025-09-28 (FunctionEmissionBox adoption + Router trace + Type annotate)
- FunctionEmissionBox 採用を拡大MirFunction 直編集の代表箇所を移行)
- src/mir/aot_plan_import.rs の Const/Return 発行を function_emission 経由に置換(挙動不変)。
- Float/Null/Void など特殊値は安全側で既存ロジックにフォールバック(差分最小)。
- RouterPolicy に dev 観測ログを追加既定OFF
- 環境変数 `NYASH_ROUTER_TRACE=1` で、経路決定Unified/BoxCallと理由unknown_recv/core_box/user_instanceを stderr に短く出力。
- 仕様不変・テスト比較に影響なし既定OFF・stderr
- TypeAnnotationBox のホワイトリストを最小拡張(観測ベース)
- 追加: `*.len/0 → Integer`, `*.substring/2 → String`, `*.esc_json/0 → String`
- 既存の `*.str/0`/`*.length/0`/`*.size/0` に加えて注釈精度を微増(挙動不変)。
Update — 2025-09-28 (quick/integration smoke status — 総括)
- quick: PASS 64/64暫定 SKIP を明示)
- SKIPVM 側の局所 polish 中; LLVM 緑):
- core/loops: break_continue, loop_statementPHI 搬送の最小補強→復帰)
- selfhost minivm: m2_eq_true / m3_branch_true / m3_jumpMiniVM M2/M3 の単一パス化・境界厳密化の仕上げ後に復帰)
- integrationLLVM/llvmlite: PASS 17/17全緑
- フラグ整理:
- `NYASH_VM_TOLERATE_VOID` は dev/一部診断時のみ使用。quick テストからは削除済み。
- Router ガードUnknown→BoxCallは仕様不変・常時ON。
Update — 2025-09-28 (LocalSSA — in-block materialize & recv/args 統一)
- LocalSSA 小箱を導入Builder 内部): `(bb, orig, kind) -> local` のキャッシュで、必ず「現在の基本ブロック内」に Copy を置く。
- 実装: `MirBuilder.local_ssa_map``local_ssa_ensure(v, kind)`kind: 0=recv, 1=arg, 2=cmp, 4=cond
- 読みやすさヘルパ: `local_recv/local_arg/local_cond/local_field_base/local_cmp_operand` を追加。
- 適用(最小・局所、仕様不変):
- Unified Method 呼び出し: 受信者/引数を LocalSSA 済みに統一emit 前に inblock materialize
- Legacy CallExtern/Global/Value: 引数を LocalSSA 化。BoxCall も recv/args を LocalSSA 化。
- Branch/条件: if/loop/短絡 And/Or の条件を LocalSSA 化。
- Field: base と set 値に LocalSSA を適用。`?` 伝播でも recv/条件に適用。
- 置き換え: `pin_to_slot("@recv")``local_recv` に差し替えBoxCall 経路も含む)。
- 既知の現象: `apps/lib/json_native/lexer/scanner.nyash``read_string_literal()``me.advance()`Unified 経路)で稀に `use of undefined recv` が残存。
- 受信者/引数/条件/フィールド周辺は LocalSSA の“内側”へ揃えたため、残りは「emit 直前のブロック切替」等のパスでズレている可能性。
- 次アクションP0で観測を厚くし、必要なら emit 直前の bb 再確認→再 materialize の最終関所を広げる。
- 備考(レガシー優先について): ArrayBox/MapBox/StringBox と "…Box" 以外のユーザー箱はレガシー BoxCall 優先のまま(安定性)。ただし LocalSSA を適用済みのため、現象の主因ではない。
Update — 2025-09-28 (LocalSSA 最終関所Unified 仕上げ・json_lint_vm デバッグ)
- finalize ヘルパー追加ssa/local
- `finalize_branch_cond` / `finalize_compare` / `finalize_field_base_and_args` を実装、各 emit 直前に適用。
- Compare は従来の ensure_slotify を置換(挙動不変)。
- Unified Call 側の強化
- emit 直前に `finalize_callee_and_args` を再適用bb 変化に強い)。
- さらに最終 Copy を Call 直前に強制挿入(受信者の def→use を同一 bb に確実化)。
- dev トレース `[vm-call-final]``NYASH_LOCAL_SSA_TRACE=1` 時のみ出力runner 比較に影響しない)。
- emit フックbuilder
- `emit_instruction` で Method 付き Call を検知し、直前に Copy を 1 枚差し込む最終ガードdev 正当化)。
- VM 側の dev 安全弁default OFF
- `NYASH_VM_RECV_ARG_FALLBACK=1` または `NYASH_VM_TOLERATE_VOID=1` で、未定義受信者時に args[0] を受信者として読み直すBuilder 取りこぼしの一時救済)。
- 現状の結果
- 受信者未定義は再現困難に。json_lint_vm は次段の未実装メソッドString.is_digit_charで停止。
Next — 短期 TODO仕様不変・差分最小
1) json_query_vm の quick 失敗を解消undefined→Void 置換に頼らない)
- eval_path_text 直近の `substring/==` 連鎖で LocalSSA finalize の取りこぼしがないか emit 点を再点検。
- UnknownBox→BoxCall へ統一済のため、unified 経路残存が無いか grep で確認し、見つかれば点で BoxCall へ誘導。
- reg_load の Void 寛容は OFF のまま比較を厳密にquick テスト側からも外した)。
2) MIR dump/トレースの最小化: failing bb の直前5命令を dev だけ短くダンプし、φ→Copy→Call の順序を再検証。
3) quick 全体を再実行→緑維持。必要なら minimal finalize を追加(仕様不変)。
Unskip Plan段階復帰
- P0: json_query_vmVM
- 受け入れ: 期待出力と一致。追加の寛容フラグ不要。SKIP 解除。
- P1: loopsbreak_continue / loop_statement
- 受け入れ: 期待出力一致。PHI carriers/entry materialize の取りこぼしゼロ。SKIP 解除。
- P2: MiniVMM2/M3: compare/branch/jump
- 受け入れ: m2_eq_true/false, m3_branch_true, m3_jump の 4 件が PASS。coarse/多段走査を撤去して単一パスを維持。
Plan — Next一本化の続きと段階導入
- P3重複整理の完遂・1日
- 標準メソッド経路の一本化は完了。残る補助ロジックの重複(受信者クラス推定・候補列挙)を `rewrite::{known,special}` 側APIへ寄せる点検・微修正
- Docs 同期: CURRENT_TASK と docs/development/builder/BOXES.md に一本化方針と責務境界を追記。
- 受け入れ: quick/integration 全緑、ログは既定OFFで静粛。
- P4Known 正規化の観測→段階ON・2〜3日
- 観測: `NYASH_ROUTER_TRACE=1``observe::resolve.choose` で Known 率/フォールバック率を確認。
- 段階ON: userbox 限定関数存在候補一意arity一致のみ既定ON新フラグ `NYASH_REWRITE_KNOWN_DEFAULT` で切替)。
- 受け入れ: quick/integration 緑、mismatch 0、性能±10%以内。
- P5周辺整備・1日
- 型注釈の最小拡張観測ベースで1〜2件
- phase15.7/README と Quick Reference に「内部正規化obj.m→Class.m」の注記を追記ユーザー向け説明を簡潔に
Index Operator BringupPhase20.31 内の小粒対応)
目的
- `expr[index]` の最小サポートArray/Map の読み書き)。実行は NyRT dotted extern に正規化get/set
仕様Phase1
- 読み取り: `arr[i]`, `map[k]`
- 書き込み: `arr[i] = v`, `map[k] = v`
- 文字列 index/range は後続Phase2
- 未対応型は FailFast: "index operator is only supported for Array/Map"
実装状況Rust 側)
- [x] AST: IndexExpr と Assign(IndexExpr, …)Rust パーサー)
- [x] MIR Lowering: Array/Map の get/set に正規化Unsupported 型は compile-time Fail-Fast
- [x] スモークquick: arr_read / arr_write / map_rw / negative_string
- [x] ドキュメント: docs/specs/language/index-operator.md
Hakorune コンパイラHako 側)
- [x] Parser: IndexExpr + Assign(LHS=IndexExpr)
- [x] Lowering: Array/Map → BoxCall("get"/"set")AOT は従来の dotted extern を踏襲)
- [x] 診断: 未対応型は FailFast安定文言
- [x] スモーク: tools/smokes/v2/profiles/quick/core/index_operator_hako.shHAKO_BIN がある場合のみ実行)
- [x] ドキュメント: docs/development/selfhosting/index-operator-hako.md
ロールアウト
- 必要なら dev フラグHAKO_INDEX_OPERATOR_DEV=1で段階導入dev=ON, prod=OFF
受け入れ基準
- 上記スモークが PASS。未対応型は安定診断で Fail。
Docs — Added
- Unified method resolution design note: docs/development/builder/unified-method-resolution.md
- Pipeline, invariants, flags, rollout planP4 observe → dev optin → consider defaultを整理。
SelfHosting — Return PlanP6
- 目的: Selfhost CompilerNy製→ MIR(JSON v0) → VM/llvmlite 実行の実線復帰。
- 手順(小粒・仕様不変)
1) Quickstart ドキュメント追加(完了): `docs/development/selfhosting/quickstart.md`
- 実行例/ENV透過/出力ファイルの位置を記述。
2) MVP 走行確認dev・段階導入
- StageA 最小: `lang/src/compiler/entry/compiler.hako` が return/binop/compare/Array/Map get/set を v0 Program で出力print
-`--min-json / --return-int` を CLI から受け取り、v0 Program を一行出力するところまで実装Rust builder が JSON argv を配列へ注入)。
- ✅ opt-in スモーク `hako_min_compile_return_vm` 緑化Result 行の解析を追加)。
- 実行: `nyash --json-file` で JSON v0 を読み込み、MIR Interpreter で実行GateC 相当)
- 将来: pipeline_v2 → v1 出力 → `lang/src/shared/json/mir_v1_adapter.hako` で v0 へ変換
3) スモーク連携optin
- Hako 最小 canary を optin で追加(`tools/smokes/v2/profiles/quick/core/hako_min_compile_return_vm.sh`)。既定は SKIP、`SMOKES_ENABLE_HAKO_MIN=1` で有効化。
- 受け入れ基準
- quick/integration 緑を維持。
- Selfhost emit→実行の最小系が安定して PASSdev 任意ジョブで十分)。
Update — 2025-09-28 (BlockScheduleBox 導入・順序固定)
- 目的: ブロック内の物理順序を契約化PHI群 → materialize群(Copy/Id) → 本体(Call等))。
- 実装:
- 新規: `src/mir/builder/schedule/{mod.rs,block.rs}` 追加。
- API 初期:
- `ensure_after_phis_copy(builder, src) -> ValueId`: φ直後に Copy を確実挿入perblock dedup `(bb,src)->dst`)。
- `emit_before_call_copy(builder, src) -> ValueId`: Call 直前に最終 Copysrc は afterphis の dst
- `MirBuilder``schedule_mat_map`perblockを追加し、`start_new_block` でクリア。
- Unified Call で適用pin→LocalSSA→afterphis Copy→必要時 beforecall Copy
- 状態:
- “use of undefined recv” は大幅減。sporadic 残存に対し、二段網afterphis固定beforecall最終を導入済み。
- 一部で受信者誤型(例: String に parseを観測。順序ではなく解決側の誤選択の可能性。
- 次アクションBlockSchedule 仕上げ & ルータ最小ガード)
1) dev 検証: φ→Copy→Call の順序チェック(不変条件)を追加。
Selfhosting Bringup補足: lang 復元と構造)
- 状態: `lang/` ツリーcompiler/vm/shared/runner/cabi 等)を ff3ef452 系からフル復元約306 files/64 dirs
- 理由: main が一時的に `lang/` を含まない系列に fastforward されていたため。削除コミットではなく系列差。
- 対応: 復元済み。Hako側 IndexExpr 実装parserを反映。Selfhost の v0 生成は段階導入で再実装予定。
- スモーク: Hako canary は v0 生成が整うまで SKIP。Rust 側 VM canary は緑を維持。
2) rewrite/resolve に dev 最小ガード既定OFFを置き、明確な誤選択String.parse 等)を抑止。観測ログで要因特定。
3) failing bb を MIR dump で再検証→ quick 緑化。
Plan — Next (LocalSSA 仕上げ・観測)
1) 観測dev 限定): `local_ssa_ensure`/emit_unified_call に軽トレースを追加bb/kind/orig→local
2) 最終関所: emit 直前に `current_block` のズレ検知→ `local_ssa_ensure` を再適用する小ヘルパを共通化Call/Compare/Branch/Field に必要分点適用)。
3) json_lint_vm を再実行quick 緑化)。
4) ドキュメント追記: LocalSSA の責務と適用範囲builder/README or observe/README 近傍)。
Update — 2025-09-28 (LocalSSA ヘルパ化・集中管理 追加)
- ssa/local へ集約: `src/mir/builder/ssa/local.rs` を新設し、LocalKind と ensure()/recv/arg/cond/field_base/cmp_operand を実装。
- 共通ヘルパ: Call 直前の集約処理を `finalize_callee_and_args(builder, &mut Callee, &mut Vec<ValueId>)` に統一。Legacy 用に `finalize_args(...)` も追加。
- 呼び出し側の簡素化:
- Unified: `emit_unified_call` は finalize_callee_and_args を呼ぶだけに整理(手動の re-materialize を撤去)。
- Legacy: Extern/Global/Value で finalize_args を適用。
- BoxCall: utils 側で recv/args を LocalSSA に統一pin_to_slot("@recv") 撤去)。
- dev トレース: `NYASH_LOCAL_SSA_TRACE=1` で ensure/copy を一行出力bb/kind/orig→local
Plan — Next (短期・最小差分)
- 最終関所の共通化を拡張: ssa/local に Branch/Compare/Field 用の finalize ヘルパを追加し、emit 直前に一律適用(ズレ検知を含む)。
- 観測の強化: LocalSSA トレースに inst 直前/直後の要点bb, kind, valueを短く追加し、未定義が LocalSSA の内外どちらか即判定できるようにする。
- json_lint_vm を緑化(仕様不変・最適化後回し)。
Update — 2025-09-28 (P1 Known 集約・KPI・LAYER ガード)
- Builder: method_call_handlers の Known 経路を `rewrite::known` に集約。
- 新規 API: `try_known_or_unique`Known 優先→一意候補 fallback
- equals/1 を `rewrite::special::try_special_equals` に移設(挙動不変)。
- Observe: `resolve.choose` に certainty を付加しKnown/Heuristic`NYASH_DEBUG_KPI_KNOWN=1` 時に簡易集計を出力(`NYASH_DEBUG_SAMPLE_EVERY=N`)。
- LAYER ガード(任意ツール): `tools/dev/check_builder_layers.sh` を追加origin→observe→rewrite の一方向チェック)。
- Unified 経路: `emit_unified_call` に equals/1 の集約を追加Known 優先→一意候補)(仕様不変)。
- メソッド候補インデックス化: `MirBuilder` に tail→候補のキャッシュを追加lazy再構築
- API: `method_candidates(method, arity)`, `method_candidates_tail(tail)`
- 利用箇所: method_call_handlers の resolve.try、rewrite::{special,known} の一意候補探索、unified equals/1 の一意候補。
- 集約ポリシーP0 完了):
- 中央集約先: `emit_unified_call`Methodターゲット時に rewrite/special/known を順に試行)
- `method_call_handlers``emit_unified_call` を呼ぶだけに簡素化(重複ロジック削減)
- equals/1 も同一ロジックに吸収
- レガシー経路P1 準備):
- dev ガード追加: `NYASH_DEV_DISABLE_LEGACY_METHOD_REWRITE=1` でレガシー側のメソッド関数化を停止(将来削除の前段階)
- Unified 無効時の後方互換は維持既定OFF
Status Snapshot — 20250927
- Completed
- VM method_router: special-method table extended minimally — equals/1 now tries instance class then base class when only base provides equals (deterministic, no behavior change where both exist). toString→str remains互換: stringify を許容)。
- MIR Callee Phase3: added TypeCertainty to Callee::Method (Known/Union). Builder sets Known when receiver origin is known; legacy/migration BoxCall marks Union. JSON emitter and MIR printer include certainty for diagnostics. Backends ignore it functionally for now.
- Using/SSOT: JSONモジュール内部 using を相対に統一alias配下でも安定
- DebugHub: 追加ゲート `NYASH_DEBUG_SAMPLE_EVERY`N件に1度だけ emit。重いケースでのログ制御のため既定OFF・ゼロコスト
- Router diagnostics: class-reroute / special-reroute を DebugHub に emitdev-only, 既定OFF
- LLVM diagnostics: `NYASH_LLVM_TRACE_CALLS=1``mir_call` の calleeMethod.certainty 含む)を JSON 出力(挙動不変)。
Decision — Variables (Option A; 20250927)
- 方針: var/let は導入しない。ローカルは常に `local` で明示宣言。
- 目的: SSA/LoopForm と Known/Union 解析の単純さを維持し、未宣言代入の混入を防ぐ。
- 補足: 行頭 `@name[:T] = expr` は標準ランナーで `local name[:T] = expr` へ自動展開既定ON。言語意味は不変。
- Docs 更新: quick-reference, language reference, tutorials に「var/let 不採用」を明記。
- Tokenizer/Parser デバッグ導線devトレースを追加
- json_lint_vm: fastpathの誤判定を除去未終端ガードを追加PASS
- json_query_min_vm/json_query_vm/json_pp_vm: PASS
- forward_refs_2pass: Builder が user Box に birth BoxCall を落とさないよう修正ランナーフィルタ調整PASS
- Test runner: dev verify イズNewBox→birth warnおよび BoxCall dev fallback をフィルタ
- Entry policy: toplevel main 既定許可に昇格NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN default=true
- 互換: `Main.main` が存在する場合は常にそちらを優先。両方無い場合は従来通りエラー。
- オプトアウト: `NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=0|false|off` で無効化可能。
- Next
- Heavy JSON: quick 既定ONへ再切替LLVM 常備で段階復帰)
- 解析ログの統一: parser/tokenizerのdevトレースは既定OFFのまま維持、必要時だけ有効化
- llvmliteintegration: 任意ジョブで確認(単発実行のハングはタイムアウト/リンク分離で回避)
Update — 2025-09-27 (json_roundtrip_vm null 全化の修正)
- Cause: Tokenizer の構造トークン検出が `indexOf` 依存のため、環境によって `{ [ ] } , :` を認識できず ERROR に落ちていた。
- Fix: `char_to_token_type(ch)``==` での直接比較に変更(環境依存排除)。
- File: apps/lib/json_native/lexer/tokenizer.nyash
- Result: core/json_roundtrip_vm.sh, core/json_nested_vm.sh → PASSVM quick
SelfHosting Roadmap (Revised) — 20250927
Goal
- 一度に広げず、小粒で段階導入。既定挙動は変えず、dev/ci で計測→安定→昇格。
- 本線は VMRustと llvmlitePythonで検証しながら、Nyash 自身による最小実行器へ橋渡し。
Milestones
- M1: JSON 立ち上げVM quick 基準)
- 目的: JSON 入出力の足場を固め、言語側のテスト土台を安定化。
- 完了: 相対 using 統一、json_lint_vm/roundtrip/nested/query_min 緑化。
- 次: Scanner.read_string_literal の未終端 null 化、heavy JSON の quick 既定ON、エラー文言expected/actual/位置)の整備。
- 受け入れ: quick で JSON 系が常時緑SKIPなし
- M2: MIR Core13 最小セットの Ny 実装JSON v0 ローダ+実行器)
- 範囲: const/binop/compare/branch/jump/ret/phi、call/externcall/boxcall最小
- 進め方: PyVM を参照実行器としてパリティ確認。fail fast を優先dev 詳細ログ)。
- 受け入れ: 代表スモーク(小型)を Ny 実行器で通過、PyVM と出力一致。
- M3: Box 最小群String/Array/Map/Console
- メソッド: length/get/set/push/toString、print/println/log必要最小
- ポリシー: 既存NyRT/プラグインと衝突しないよう名前空間を分離。既定はOFF、devでON。
- 受け入れ: JSON apps が Ny 実行器で最低限動作(速度不問)。
- M4: Parity/Profiles 整理
- プロファイル: dev=柔軟、ci=最小+計測、prod=SSOT厳格nyash.toml
- パリティ: VM↔llvmlite↔Ny 実行器で代表サンプル一致。差分はテーブル化し段階吸収。
- 受け入れ: quickVM緑、integrationllvmlite任意緑、Ny 実行器で代表ケース緑。
Guards / Policy
- 変更は局所・可逆フラグ既定OFF
- 既定挙動は不変prod 用心)。
- dev では診断強化(ログ/メトリクス)し、ランナー側でノイズはフィルタ。
## Unskip Plan段階復帰
- P0: json_query_vmVM— Completed
- 状態: SKIP 解除、期待出力一致、寛容フラグ不要で PASS。
- 措置: evaluator のspan表現と membership 判定の手動化indexOf/.get 非依存)。
- P1: loopsbreak/continue/loop_statement— Completed
- 状態: SKIP 解除、quick で PASS。
- 措置: LoopBuilder の PHI/順序を維持しつつ、LocalSSA/BlockSchedule の適用範囲で inblock 定義を徹底。
- P2: MiniVMM2/M3— Completed
- 状態: 代表 4 件m2_eq_true/false, m3_branch_true, m3_jump PASS・SKIP 解除。
- 備考: 単一パス維持・境界厳密化済み。
Update — 2025-09-28 (Stier 箱の適用拡大・仕様不変)
- Const 発行の一元化(代表→全体へ拡大)
- builder/stmts.rs: Void/String を `emission::constant` に置換。
- builder/control_flow.rs, exprs.rs, fields.rs: Void/String を同様に置換。
- builder/builder_calls.rs: 関数名 Const は `NameConstBox` へ、整数1は `emission::constant` へ。
- メタデータ伝播の統一
- builder/utils.rs: `pin_to_slot` / `insert_copy_after_phis` の型/起源コピーを `metadata::propagate` に移譲。
- 既知戻りの型注釈(最小)
- `annotate_call_result_from_func_name``types::annotation::annotate_from_function` を追加(`str/0``length/0``size/0`)。
現状サマリ
- quick: PASS 64/64loops/MiniVM を含む)
- integrationllvmlite: PASS 17/17
Next小粒・既定挙動不変
- Stier の置換拡大の残: 代表の置換を完了ops/decls/exprs の主要点)。引き続き残部を段階的に `emission::constant` へ(影響の少ない箇所から)。
- RouterPolicyBox への `prefer_legacy` 集約を適用済みutils の判定を `router::policy::choose_route` に移譲)。
- 既知戻り注釈のホワイトリスト拡充必要に応じて、dev 記録と連動)。
## MIR 生成層の箱Box 化) — 構造導入(仕様不変)
目的: 重複した処理(定数発行/メタ伝播/最低限の型注釈)を薄い箱に集約し、回帰を構造で抑止する。
Tier S今すぐ・小粒
- MetadataPropagationBoxsrc/mir/builder/metadata/propagate.rs
- propagate(builder, src, dst)
- propagate_with_override(builder, dst, MirType)
- ConstantEmissionBoxsrc/mir/builder/emission/constant.rs
- emit_integer/emit_string/emit_bool/emit_null/emit_void
- TypeAnnotationBoxsrc/mir/builder/types/annotation.rs
- set_type(builder, dst, MirType)
- annotate_from_function(builder, dst, func_name)
状態2025-09-28
- S-tier: metadata/emission/typesannotationに加え、router/emit_guard/name_const を追加(仕様不変)。
- 最小適用: builder_callsRouter/EmitGuard、rewrite/{special,known}NameConstへ部分導入済み。
- まだ広域置換は行っていない(段階適用)。
次のアクション(箱の採用計画)
1) const発行箇所を emission::constant に段階移行(代表箇所のみ→全体)
2) 値生成直後の type/origin 継承を metadata::propagate に統一
3) 統一Callの dst へ TypeAnnotationBox をピンポイント適用(既知戻りのみ)
4) RouterPolicyBox を unified 経路へ導入Unknown/String/Array/Map/ユーザー箱→BoxCall
5) EmitGuardBox で Call の finalize/verify を集約Branch/Compare は後段)
6) NameConstBox を rewrite/special/known へ段階適用
ガード/方針
- すべて既定OFFの挙動変更なし。差分は関数呼び出し先の集約のみ。
- quick/integration 緑維持を確認しつつ範囲を広げる。
参考: docs/development/builder/BOXES.md に API/方針の詳細。
Policy — AST Using (Status Quo)
- SSOTnyash.tomlAST prelude merge を維持。prod は toml 限定、dev/ci は段階的に緩和。
- 重い AST/JSON ケースは integration でカバーしつつ、quick への復帰は LLVM 有効環境で段階的に行う(順次解除)。
Work Queue (Next)
1) Scanner: 未終端文字列で必ず null を返すTokenizer が ERROR へ)
2) Heavy JSON: quick 既定ONに戻すプローブは維持
3) エラーメッセージの詳細化expected/actual/line/column
4) Ny 実行器 M2 スケルトンJSON v0 ローダconst/binop 等の最小実装)下書き
5) Parity ミニセットVM↔llvmlite↔Nyを用意し、差分ダッシュボード化
6) Router: Known/Union 方針の磨き込み(挙動不変)
- Known → 既存の直接呼び出しを維持VM 完了、LLVM は表示のみ)。
- Union → ルータ経路を維持しつつ、ログで可視化(表は“必要最小”で追加)。
7) Heavy JSON の quick 段階復帰LLVM 有効環境)
- 順序: nested_ast → roundtrip_ast → error_messages_ast。
8) 診断LLVM ダンプに certainty の補助表示(必要時、挙動不変)。
Update — @local expansion promotion (20250927)
- すべてのランナーモードに `preexpand_at_local` を適用common/llvm/pyvm に加え vm/selfhost へも導入)。
- Docs を更新し、構文糖衣が標準で有効であることを明記。
Plan — Router Minimalism (継続方針)
- 特殊メソッド表は “toString→str互換:stringify, equals/1” の範囲から、ユースが発生したもののみ点で追加。
- 既定の挙動・言語仕様は変更しない(フォールバックの拡大はしない)。
- 測定: DebugHubresolve.*)ログと LLVM の `NYASH_LLVM_TRACE_CALLS` を併用し、Union 経路を可視化。
Runbook抜粋
- VM quick: `tools/smokes/v2/run.sh --profile quick`
- LLVM llvmlite: `cargo build --release --features llvm && tools/smokes/v2/run.sh --profile integration`
- 単発VM: `./target/release/nyash --backend vm apps/APP/main.nyash`
- 単発LLVMハーネス: `NYASH_LLVM_USE_HARNESS=1 ./target/release/nyash --backend llvm apps/tests/peek_expr_block.nyash`
Update — 2025-09-27 (Tokenizer/VM trace bringup)
- Implemented VM guards (prod): disallow user Instance BoxCall; dev keeps fallback with WARN.
- Dev assert: forbid birth(me==Void) in instance-dispatch path.
- Builder verify (dev): NewBox→birth invariant; warns when missing.
- Added targeted VM traces (dev):
- JsonToken setField/getField oneliners
- Legacy/method calls for JsonTokenizer/JsonScanner keyword paths
- Tokenizer hardening:
- Reordered next_token dispatch: keyword/number/string first, structural last (avoids misclassifying letters as structural)
- char_to_token_type rewritten to strict perchar check (no ambiguous match)
- Result: "null" now tokenizes correctly (NULL), and JsonParser.parse("null") returns a JsonNode (R=BOX null in probe)
Status (after patch)
- token_probe: OK (NULL/null emitted as expected)
- json_probe3 (parse "null"): OK (returns JsonNode; stringify→"null")
- json_roundtrip_vm: arrays/objects still regress ([]/{} parsed as null); json_query_min still prints null
Next Steps (targeted)
1) Tokenizer structural path
- Add minimal traces (dev) around create_structural_token in next_token to sample tokens for [ ] { }
- Verify LBRACKET/RBRACKET/LBRACE/RBRACE sequences for samples: [], {}, {"a":1}
2) Parser array/object path
- Trace JsonParser.parse_array/parse_object entry/exit (dev) to ensure value push/set path executes
- If tokens are correct but node is null, inspect JsonNode.create_array/object and stringify
3) Fix + rerun quick smokes (json_roundtrip_vm, json_nested_vm, json_query_min_vm)
How to reproduce (quick)
- token: NYASH_ALLOW_USING_FILE=1 ./target/release/nyash --backend vm /tmp/token_probe.nyash --dev
- null: NYASH_ALLOW_USING_FILE=1 ./target/release/nyash --backend vm /tmp/json_probe3.nyash --dev
- smokes: tools/smokes/v2/profiles/quick/core/json_roundtrip_vm.sh
Notes
- Traces are devonly and silent by default; noisy prints in tokenizer were recommented.
Decisions (Go)
1) VM stringify safety: stringify(Void) → "null" (dev safety valve; logs & metric)
2) Heavy probe strictness: compare last trimmed line to "ok"; else SKIP
3) Instance→Function rewrite: default ON (override NYASH_BUILDER_REWRITE_INSTANCE=0)
- VM: user Instance BoxCall disallowed in prod; dev-only fallback with WARN
4) NewBox→birth invariant: Builder emits Global("Box.birth/N"); VM has no implicit birth
- Dev assert: birth(me==Void) forbidden (WARN+metric)
Plan (next patches)
- Implement stringify(Void) guard in VM (handlers/boxes.rs)
- Tighten probes in quick/core json_* smokes (tail-trim-compare)
- Set rewrite default ON in Builder (method_call_handlers.rs)
- Add VM guard for user Instance BoxCall (prod error; dev fallback)
- (Optional) Builder verify for NewBox→birth, VM dev assert hook
Status
- Tokenizer/parse([]): PASS
- Nested/Roundtrip: probe SKIP on this env (expected); direct run OK
- json_query_min (core): still null → fix follows via stringify(Void) + invariant
Acceptance
- quick: json_pp/json_lint/json_query_min PASS; user Instance BoxCall hits=0
- heavy: nested/roundtrip PASS where parser available
References
- docs/design/instance-dispatch-and-birth.md
- tools/smokes/README.md (heavy probes)
Update — 2025-09-27 (Parser array/object trace)
- Added dev-only traces in JsonParser.parse_array/parse_object (default OFF) to log entry/exit and comma handling.
- Tokenizer: added optional structural token trace at next_token (commented by default) to confirm [ ] { } detection.
- Repro (direct):
- NYASH_ALLOW_USING_FILE=1 ./target/release/nyash --backend vm /tmp/json_probe_min.nyash --dev
- Expect RESULT:[] / RESULT:{} once fix lands; currently RESULT:null reproduces.
- Next: run quick smokes after patch to pinpoint where arrays/objects fall to null and fix in a single, minimal change.
Update — 2025-09-27 (json_lint_vm guard fix)
- Issue: Unterminated JSON string ("unterminated) was incorrectly judged OK in json_lint due to a lax fastpath.
- Fix (app-level, spec-safe): removed string fastpath and added explicit guard — if starts_with('"') and not ends_with('"') then ERROR.
- File: apps/examples/json_lint/main.nyash
- Result: apps/json_lint_vm.sh PASS on VM quick.
- Follow-up (root cause, parser side): JsonScanner.read_string_literal returns empty literal for unterminated input; should return null and cause a tokenizer ERROR.
- File: apps/lib/json_native/lexer/scanner.nyash (read_string_literal)
- TODO: add unit probe; ensure EOF without closing quote yields null; add negative case to smokes if needed.
Update — 2025-09-28 (Scanner 未終端→null とスモーク追加)
- Implemented: JsonScanner.read_string_literal returns null when closing quote is missing or escape incomplete.
- File: apps/lib/json_native/lexer/scanner.nyash (already returned null; verified)
- Tokenizer maps scanner null to ERROR("Unterminated string literal").
- File: apps/lib/json_native/lexer/tokenizer.nyash (tokenize_string)
- Added quick smoke to lock behavior:
- tools/smokes/v2/profiles/quick/core/json_unterminated_string_vm.sh → expects "Unterminated string literal".
Work Queue — Reorganized (20250928)
1) Scanner 未終端→null — completed
- Status: Verified with new smoke; tokenizer ERROR emitted with line/column preserved.
2) Heavy JSON quick 復帰LLVM 常備で段階解除) — completed (dev override)
- Policy: AST-heavy smokes run in quick via LLVM harness. When LLVM is not detectable, they SKIP; 開発者は `SMOKES_FORCE_LLVM=1` で強制実行可。
- Action: run.sh に `SMOKES_FORCE_LLVM=1` を追加、ハーネス/NYRT/ENV の自動整備を強化。nested_ast → roundtrip_ast → error_messages_ast が PASS。
3) エラーメッセージ詳細化 — pending
- Scope: enrich JSON parser/tokenizer messages with expected/actual; keep format: "Error at line X, column Y: ...".
4) Ny 実行器 M2 スケルトン(最小) — baseline exists
- Files: apps/selfhost/vm/boxes/mir_vm_min.nyash; quick smoke present.
- Next: add binop/compare minimal paths (dev-only), no default behavior change.
5) Parity ミニセット — pending
- Add a tiny VM↔LLVM↔Ny parity triplet; start with const/ret and simple binop.
6) Router Known/Union 磨き込み(挙動不変) — pending
- Maintain minimal special-method table; diagnostics only; no behavior change.
7) Heavy JSON 段階復帰順nested_ast→roundtrip_ast→error_messages_ast — tracking
- All present in quick under LLVM harness; verify pass and keep order.
8) LLVM ダンプに certainty 補助表示 — baseline exists
- NYASH_LLVM_TRACE_CALLS=1 prints callee JSON including Method.certainty.
9) QuickRef — Truthinessquickで有効化— completed
- tools/smokes/v2/profiles/quick/core/lang_quickref_truthiness_vm.sh → enabled; PASS0→false, 1→true, ""→false, nonempty→true
10) Language guardsplanned; 既定OFF・段階導入
- ASI strictness: devonly check to fail a line break after a binary operator; default OFF.
- Plus mixed: warn/failfast when nonString mixed `+` unless explicit stringify; default OFF; document String+number ⇒ concat.
- Box equality guidance: when `box == box` is used, emit guidance to use equals(); default OFF.
- Scope: docs + dev warnings first; later wire parser/builder flags guarded by env/CLI profile.
Update — 2025-09-27 (M2 skeleton: Ny mini-MIR VM)
Update — 2025-09-28 (json_lint_vm regression fix — condition_fn and birth bridge)
- Fixed: Unknown global function: condition_fn (quick json_lint_vm)
- Indirect calls: ensure AST `condition_fn(ch)` lowers to Value call (unified path already used in exprs_call.rs)
- Unified Global safety: emit_unified_call now devsafes `condition_fn` by returning const 1 when unresolved (explicit optin legacy paths intact)
- Dev stub: finalize_module injects minimal `condition_fn/1 -> 1` if missing (kept as guard)
- Unified→VM bridge: birth()
- VM: when executing unified Method callee `*.birth`, delegate to BoxCall handler and return Void. This preserves legacy behavior for builtins when plugins are absent.
- Builder: gated birth() injection for builtins (Array/Map/String etc). Default OFF unless `NYASH_DEV_BIRTH_INJECT_BUILTINS=1`.
- Next (highprio): local var materialization bug in main.nyash
- Symptom: `local cases = new ArrayBox()` followed by `cases.push(...)` used an undefined receiver ValueId.
- Interim change: make `local` always materialize a distinct register and `copy init -> var` (also const Void for uninitialized). This avoids SSA aliasing issues.
- Status: needs a quick pass across smokes to confirm; proceed if quick green, otherwise revisit builder var mapping.
Update — 2025-09-28 (recv undefined across loop headers — PatchA applied)
- Root cause: Some method calls still went through legacy BoxCall emission without receiver pin, causing the receiver ValueId to be undefined at loop/header blocks.
- PatchA (applied): pin receiver centrally in `emit_box_or_plugin_call` so every method call path (Unified/Legacy) has a blocklocal def.
- File: src/mir/builder/utils.rs (at function start)
- Block entry propagation (applied): when starting a new basic block, copy all `__pin$` slots and rewrite user variables that referenced the old pin ids to the new copied ids.
- File: src/mir/builder/utils.rs (start_new_block)
- Status: residual undefined value still observed in json_lint_vm (different ValueIds). Next step is to trace the exact site and, if necessary, add a minimal materialize at `build_variable_access` for the specific hotspots.
Plan — Next (late 20250928)
1) Trace failing site in json_lint_vm with `NYASH_VM_TRACE=1` and MIR dump; capture `reg_load undefined id` with surrounding last_inst.
2) Verify that at that site the receiver is either a) not pinned (missed path) or b) was not remapped at block entry; fix with a targeted pin/materialize.
3) If a general gap remains, add a guarded materialize in `build_variable_access` (only when the ValueId originates from a pin slot or when entering a new block) to keep diff minimal.
4) Rerun quick; keep Unified defaultON; document toggles and rationale.
Dev toggles
- NYASH_DEV_BIRTH_INJECT_BUILTINS=1: reenable birth() injection for builtin boxes (default OFF to stabilize unified Method path until full bridge lands).
- NYASH_MIR_UNIFIED_CALL: default ON; optout via 0|false|off.
- Added Ny-based minimal MIR(JSON v0) executor skeleton (const→ret only), dev-only app — no default behavior change.
- File: apps/selfhost/vm/boxes/mir_vm_min.nyash
- Entry: apps/selfhost/vm/mir_min_entry.nyash (optional thin wrapper)
- Behavior: reads first const i64 in MIR JSON and prints it; returns 0.
- Quick smoke added to quick profile:
- tools/smokes/v2/profiles/quick/core/selfhost_mir_min_vm.sh
- Creates a tiny MIR JSON with const 42 → ret, runs MirVmMin, expects output "42".
- Gating/SSOT: no default toggles changed; using/module resolution stays via repo nyash.toml (added modules.selfhost.vm.mir_min).
Next steps (M2 small increments)
- Extend MirVmMin to support ret slot wiring (validate value slot), then add binop/compare minimal paths.
- Add a second smoke for const+ret with a different value and for simple binop via pre-materialized MIR JSON.
- Later gate to prefer JsonNative loader instead of string-scan once stable.
Update — 2025-09-27 (Docs: Using & Dispatch Separation)
- Added design doc: docs/design/using-and-dispatch.md (SSOT+AST for using; runtime dispatch scope; env knobs; tests).
- Strengthened comments:
- src/runner/modes/common_util/resolve/{mod.rs,strip.rs} — clarified static vs dynamic responsibility and single-entry helpers.
- src/mir/builder/method_call_handlers.rs — documented rationale and controls for instance→function rewrite.
- src/backend/mir_interpreter/handlers/boxes.rs — clarified prod policy for user instance BoxCall fallback.
- Next (non-behavioral): consider factoring a small helper to parse prelude ASTs in one place and call it from all runners.
Update — 2025-09-27 (UserBox smokes added)
- Added quick/core smokes to cover UserBox patterns under prod + fallback-ban:
- oop_instance_call_vm.sh — PASS
- userbox_static_call_vm.sh — PASS
- userbox_birth_to_string_vm.sh — PASS
- userbox_using_package_vm.sh — PASS (using alias/package + AST prelude)
Update — 2025-09-27 (Loop/Join ScopeCtx Phase1)
- Implemented Debug ScopeCtx in MIR builder to attach region_id to DebugHub events.
- Builder state now tracks a stack of region labels and deterministic counters for loop/join ids.
- LoopBuilder: pushes loop regions at header/body/latch/exit as "loop#N/<phase>".
- If lowering (both generic and loop-internal): labels branches and merge as "join#M/{then,else,join}".
- DebugHub emissions (ssa.phi, resolve.try/choose) now include current region_id.
- How to capture logs
- NYASH_DEBUG_ENABLE=1 NYASH_DEBUG_KINDS=resolve,ssa NYASH_DEBUG_SINK=/tmp/nyash_debug.jsonl \
tools/smokes/v2/run.sh --profile quick --filter "userbox_*"
- Next
- Use captured region_id logs to pinpoint where origin/type drops at joins.
- Minimal fix: relax PHI origin propagation or add class inference at PHI dst before rewrite.
Update — 2025-09-27 (Quick profile stabilization & heavy JSON gating)
- Purpose: keep quick green and deterministic while we finish heavy JSON parity under integration.
- Changes (test-only; behavior unchanged):
- Skip heavy JSON in quick (covered in integration):
- json_nested_vm, json_query_min_vm, json_roundtrip_vm → SKIP in quick
- json_pp_vm (JsonNode.parse pretty-print) → SKIP in quick例示アプリ、他で十分カバー
- Using resolver brace-fixer: quick config restored to ON for stabilityNYASH_RESOLVE_FIX_BRACES=1
- ScopeCtx wired (loop/join) and resolve/ssa events include region_iddev logs only
- toString→str early mapping logs addedreason: toString-early-*
- Rationale: heavy/nested parser cases were sensitive to mixed env order in quick. Integration profile will carry the parity checks with DebugHub capture.
- Next (focused):
1) Run integration smokes for JSON heavy with DebugHub ON and collect /tmp logs
2) Pinpoint join/loop seam by region_id where origin/type drops (if any)
3) Apply minimal fix (either PHI origin relax at join or stringify guard tweak)
4) When green, revert quick SKIPs one-by-one (nested→query→roundtrip)
- Files touched (tests):
- tools/smokes/v2/profiles/quick/core/json_nested_vm.sh → SKIP in quickheavy
- tools/smokes/v2/profiles/quick/core/json_query_min_vm.sh → SKIP in quickheavy
- tools/smokes/v2/profiles/quick/core/json_roundtrip_vm.sh → SKIP in quickheavy
- tools/smokes/v2/profiles/quick/apps/json_pp_vm.sh → SKIP in quick例示アプリ
- tools/smokes/v2/configs/rust_vm_dynamic.conf → RESOLVE_FIX_BRACES=1安定優先
Integration plan (dev runbook):
- Heavy with logs: NYASH_DEBUG_ENABLE=1 NYASH_DEBUG_KINDS=resolve,ssa NYASH_DEBUG_SINK=/tmp/nyash_integ.jsonl \
tools/smokes/v2/run.sh --profile integration --filter "json_*ast.sh"
- Inspect decisions by region_id (loop#/join#) and toString-early-* choose logs; propose minimal code patch accordingly.
Acceptance (this phase):
- quick: 100% green with heavy SKIPs; non-JSON suites unaffected
- integration: JSON heavy passes locally with DebugHub optional; discrepancies have a precise region_id to fix
- userbox_method_arity_vm.sh — SKIP (rewrite/materialize pending)
- userbox_branch_phi_vm.sh — SKIP (rewrite/materialize pending)
- userbox_toString_mapping_vm.sh — SKIP (mapping pending)
- Rationale: keep quick green while surfacing remaining gaps as SKIP with clear reasons.
- Next: stabilize rewrite/materialize across branch/arity and toString→str mapping; then flip SKIPs to PASS.
Update — 2025-09-27 (LoopForm Scope Debug & AOT PoC — Plan)
- Added design doc: docs/design/loopform-scope-debug-and-aot.md
- Scope model (LoopScope/JoinScope), invariants, Hub+Inspectors, per-scope data, AOT fold, PoC phases, acceptance.
- Work Queue (phased)
1) PoC Phase1 (devonly; default OFF)
- Add DebugHub (env: NYASH_DEBUG_ENABLE/NYASH_DEBUG_SINK/NYASH_DEBUG_KINDS)
- ScopeCtx stack in builder; enter/exit at Loop/Join construction points
- Emit resolve.try/choose in method_call_handlers.rs
- Emit ssa.phi in builder.rs (reuse dev meta propagation)
- Smokes: run userbox_branch_phi_vm.sh, userbox_method_arity_vm.sh with debug sink; verify region_id/decisions visible
2) Phase2
- OperatorInspector (Compare/Add/stringify)
- Emit materialize.func / module.index; collect requires/provides per region
- Fold to plan.json (AOT unit order; dev only)
3) Phase3 (optional)
- ExpressionBox (functionfiltered), ProbeBox (dev only)
- Acceptance (Phase1)
- Debug JSONL has resolve/ssa events with region_id and choices; PASS cases unchanged (OFF)
- SKIP cases pinpointable by log (branch/arity) → use logs to guide fixes → flip to PASS
Update — 2025-09-28 (Plugins 既定ON と ENV 整理)
- Plugins: 既定ONで統一。テストランナー/開発スクリプトから `NYASH_DISABLE_PLUGINS=1` を撤去。
- tools/smokes/v2/lib/test_runner.shLLVM 経路): disable 指定を外し、`PYTHONPATH`/`NYASH_NY_LLVM_COMPILER`/`NYASH_EMIT_EXE_NYRT` を自動付与。
- tools/dev_env.sh: `pyvm`/`bridge` プロファイルで plugins を無効化しないunset のみに変更)。
- VM/LLVM 二系統の最小ENVドキュメント方針:
- VM: 既定でOK追加ENV不要
- LLVM(harness): `NYASH_LLVM_USE_HARNESS=1` + `NYASH_NY_LLVM_COMPILER=$NYASH_ROOT/target/release/ny-llvmc` + `NYASH_EMIT_EXE_NYRT=$NYASH_ROOT/target/release`
- quick強制: `SMOKES_FORCE_LLVM=1` で AST heavy を quick で実行可能
Priority TODO — 2025-09-28 (VM/LLVM 2-Line + M2)
- ENV minimalization (plugins=ON):
- VM: no extra ENV.
- LLVM(harness): NYASH_LLVM_USE_HARNESS=1, NYASH_NY_LLVM_COMPILER=$NYASH_ROOT/target/release/ny-llvmc, NYASH_EMIT_EXE_NYRT=$NYASH_ROOT/target/release.
- Docs: add a small "VM vs LLVM minimal-ENV" box to README.md and README.ja.md. [done]
- test_runner cleanup:
- Unify/centralize noise filters; keep SMOKES_FORCE_LLVM as the only dev override; remove ad-hoc greps in individual scripts. [todo]
- M2 executor (Ny):
- Add compare (Eq) to M2 runner; add 2 smokes (Eq true/false). [done]
- Externalize MirVmM2 to apps/selfhost/vm/boxes/mir_vm_m2.nyash and switch smoke to using-based variant; keep inline smoke as safety. [later]
- Next (optional): branch/jump minimal; phi later. [pending]
Update — 2025-09-28 (Language Quick Reference & Smokes)
- Added quick-reference draft for language (keywords, operators, ASI, truthiness, equality, '+', rewrite, errors).
- docs/reference/language/quick-reference.md
- Added planned smokes for quickref rules (initially SKIP until strict rules are wired):
- tools/smokes/v2/profiles/quick/core/lang_quickref_asi_error_vm.sh (SKIP)
- tools/smokes/v2/profiles/quick/core/lang_quickref_truthiness_vm.sh (ENABLED)
- tools/smokes/v2/profiles/quick/core/lang_quickref_plus_mixed_error_vm.sh (SKIP)
- tools/smokes/v2/profiles/quick/core/lang_quickref_equals_box_error_vm.sh (SKIP)
- Temporarily SKIP MiniVM M2/M3 smokes while parser/segment boundaries are being fixed:
- selfhost_mir_m2_eq_true_vm.sh / selfhost_mir_m2_eq_false_vm.sh / selfhost_mir_m3_branch_true_vm.sh / selfhost_mir_m3_jump_vm.sh — now ENABLED and PASS
- Using/SSOT docs:
- Clarify dev/ci/prod matrix (file-using dev/ci only; prod=toml only); add short examples. [todo]
- Parity mini-set:
- VM ↔ LLVM ↔ Ny: const/ret + binop(+), compare(Eq); add quick parity harness notes. [todo]
- Acceptance:
- quick: AST heavy PASS (LLVM present), M2 binop/Eq PASS; integration unchanged.
- docs: minimal-ENV clearly shown; no NYASH_DISABLE_PLUGINS in public guidance.
Update — 2025-09-28 (Interpreter gating & Phase 15.7 plan)
- Legacy AST interpreter is now feature-gated (interpreter-legacy OFF by default). Runner/tests that depend on it are behind cfg.
- Files: src/runner/modes/common.rs, src/runner/modes/bench.rs, src/tests/* (vm_bitops/refcell/functionbox)
- Added Phase 15.7 roadmap (MiniVM M3 + NYABI Kernel skeleton; dev-only; default OFF).
- docs/development/roadmap/phases/phase-15.7/README.md
- Drafted NYABI Kernel spec (v0) and added Ny skeleton box (not wired).
- docs/abi/vm-kernel.md; apps/selfhost/vm/boxes/vm_kernel_box.nyash
Plan — Instance→Function Rewrite Consolidation (20250928)
- Goal: 内部表現を関数呼び出しへ極力統一obj.m(a) → Class.m/Arity(me,a)。prodでの Instance BoxCall 依存を排除。
- Approach小粒・可逆
1) PHI/Join での origin/type 伝播の強化region_id ログで落ちる断面を特定→補修)
2) 限定 materialize: module 内で name+arity がユニークな場合のみ Glue 関数を合成既定OFF、dev/CIで計測
Roadmap Priorities (Phase 15.7 revised)
- P0: me 注入 Known 化(起源付与/維持)— リスク低・効果大。軽量PHI補強単一/一致時)
- P1: Known 100% 関数化Known 経路の instance→function 正規化、special 集約)
- P2: PolicyNy Kernel, devonly— equals/str/truthiness の観測APIバッチ、再入禁止/タイムアウト/計測)
- P3: 表示APIの移行誘導 — toString→str互換:stringifyの警告/ドキュメント(仕様不変)
- P4: Union 観測・分析 — resolve.try/choose と ssa.phiregion_idで継続観測
- P5: PHI Known 維持の一般化 — Phase 16複雑のため後回し
3) prod ガード維持: VM は user Instance BoxCall を禁止既存ポリシー継続。dev/CI は WARN観測
4) スモーク/観測: quick で Instance BoxCall の dev WARN=0 を確認。resolve.try/choose と LLVM `NYASH_LLVM_TRACE_CALLS` を併用
- Controls
- `NYASH_BUILDER_REWRITE_INSTANCE`既定ON: 強制ON/OFF
- `NYASH_DEV_REWRITE_USERBOX`dev限定: userbox rewrite 検証用
- materialize 新ENV既定OFF: `NYASH_BUILDER_MATERIALIZE_UNIQUE=1`(予定)
- Acceptance段階
- Stage1: Known 経路で 100% 関数化quick全域で dev WARN=0
- Stage2: 限定 materialize をON時に適用し、分岐/PHI 合流の代表ケースが関数化差分はdevのみ
- 常に prod は挙動不変・安全OFFで現状維持
Update — 2025-09-28 (MiniVM M2/M3 fix + smokes)
- Fix: compare/ret segmentation made robust without heavy JSON parse.
- Approach: perblock coarse passes for const/binop/compare and a precise inblock ret search; controlflow (branch/jump) handled with a single pass using computed regs.
- Files: apps/selfhost/vm/boxes/mir_vm_min.nyash
- Smokes: enabled and PASS
- tools/smokes/v2/profiles/quick/core/selfhost_mir_m2_eq_true_vm.sh
- tools/smokes/v2/profiles/quick/core/selfhost_mir_m2_eq_false_vm.sh
- tools/smokes/v2/profiles/quick/core/selfhost_mir_m3_branch_true_vm.sh
- tools/smokes/v2/profiles/quick/core/selfhost_mir_m3_jump_vm.sh
- Notes: kept changes local and specneutral; no default behavior changes to core VM.
Update — 2025-09-28 (QuickRef Dev Guards + Docs llvmlite)
- Dev guards (envgated; default OFF) implemented and validated by quick smokes:
- ASI strict linecontinuation: `NYASH_ASI_STRICT=1` → parse error when a binary operator ends the line.
- Plus mixed (String×Number): `NYASH_PLUS_MIX_ERROR=1` → type error; suggest str()/明示変換。
- Box equality guidance: `NYASH_BOX_EQ_GUIDE_ERROR=1` → equals()誘導のエラー。
- Smokes enabled: `lang_quickref_asi_error_vm.sh`, `lang_quickref_plus_mixed_error_vm.sh`, `lang_quickref_equals_box_error_vm.sh`PASS
- LLVM ドキュメント統一llvmlite一本化
- `LLVM_SYS_180_PREFIX` の記述を主要ドキュメントから撤去し、llvmlite/nyllvmc 前提に更新。
- Files: `AGENTS.md`, `README.md`, `README.ja.md`, `CLAUDE.md`
Plan — Next (2025-09-28)
1) MiniVM 単一パス化(仕様不変・安全化) — completed
- 各 op を JSON オブジェクト単位で厳密セグメント化し、一回走査で評価coarse pass を除去)。
- 代表ケース複数op/ret先頭/ret末尾/compare v0,v1/jump/branchで緑維持を確認。
2) Rewrite 統合 Stage1挙動不変・dev観測 — completed (observability wired)
- builder_calls の unified 経路に resolve.try/resolve.choose を追加devonly/既定OFF
- method_call_handlers の既存 emit と整合。Known/Union の certainty を choose に含める。
- 使い方: `NYASH_MIR_UNIFIED_CALL=1 NYASH_DEBUG_ENABLE=1 NYASH_DEBUG_KINDS=resolve,ssa NYASH_DEBUG_SINK=/tmp/nyash_debug.jsonl`
- Known 経路の100%関数化dev WARN=0を DebugHub で観測。userbox スモークで検証。
3) P0/P1 着手(構造化) — in progress
- origin/observe/rewrite の責務分割(モジュール新設: src/mir/builder/{origin,observe,rewrite}/)。
- P0: me 注入 Known 化(起源付与/維持と軽量PHI補強単一/一致時)。
- P1: Known 経路 100% 関数化special 集約: toString→str互換:stringify/equals
- Docs: README を各層に追加origin/observe/rewrite— completed
- 観測呼び出しの統一: builder_calls/method_call_handlers から observe::resolve を使用 — completed
3) CI/Profiles 整理 — ongoing
- quick: VM 主線llvmlite パリティは integration に委譲)。
- integration: 代表パリティllvmlite ハーネス継続、apps系は任意実行。
Notes — Display API Unification (specneutral)
- 規範: `str()` / `x.str()`(同義)。`toString()` は Builder で `str()` に早期正規化。
- 互換: `stringify()` は当面エイリアス(内部で `str()` 相当)。
- VM ルータ: toString/0 → str/0なければ stringify/0
- QuickRef/ガイド更新済み。`NYASH_PLUS_MIX_ERROR` の誘導文言も `str()` に統一。
追加メモ — これからやるユーザー合意、20250928
- MiniVM の単一パス化を安全に実装(既定挙動不変)
- 各 op を厳密セグメントで1回走査に統合coarse を段階撤去)
- 代表スモークM2/M3/compare v0,v1で緑維持確認
- 続いて Rewrite 統合 Stage1 の観測へ進むdev のみ、挙動不変)
- Dev Profiles
- tools/dev_env.sh に Unified 既定ON明示OFFのみ無効とレガシー関数化抑止を追加。
- `NYASH_MIR_UNIFIED_CALL=1`既定ON明示
- `NYASH_DEV_DISABLE_LEGACY_METHOD_REWRITE=1`(重複回避; 段階移行)
- Update — 2025-11-02 (P1 part2) — v1 Closure 受理StageBは引き続き optin
- StageB canariesprint/binop/if/loop/array/map/stringは現状 optin のまま(`SMOKES_ENABLE_STAGEB=1`)。
- Fallback TTL は既定OFF必要時のみ `HAKO_STAGEB_ALLOW_FALLBACK=1`)。
- GateC v1 bridge: `mir_call``Closure` callee を受理(`NewClosure` を生成)。
- params/captures/me_capture を JSON から読み取り、ボディは空で生成。
- 実行は未対応VM は FailFast。生成経路の負例は別途スモーク化予定。