Phase 259 P0: Pattern8 (BoolPredicateScan) 完全完了 is_integer/1 を Pattern8 で受理し、VM/LLVM EXE 両方で動作確認完了。 次の大工事(block-parameterized CFG への移行)前のマイルストーンとして記録。 ## Key Fixes Applied 1. **skipped_entry_redirects** (instruction_rewriter.rs) - k_exit のスキップ時、entry block 参照を exit_block_id へリダイレクト - BasicBlockId not found エラーを根治 2. **loop_var_name** (pattern8_scan_bool_predicate.rs) - merge_entry_block 選択に使用(`Some(parts.loop_var.clone())`) - 未設定時の誤った entry block 選択を修正 3. **loop_invariants** (pattern8_scan_bool_predicate.rs) - PHI-free 不変量パラメータ(`[(me, me_host), (s, s_host)]`) - loop_var_name 設定時、BoundaryInjector が join_inputs Copy を全スキップするため必要 - Pattern6 と同じ設計(header PHI で不変量を保持) 4. **expr_result** (pattern8_scan_bool_predicate.rs) - k_exit からの返り値を明示設定(`Some(join_exit_value)`) - Pattern7 style(推測ではなく明示) 5. **Smoke test scripts** - set +e パターンで exit code 7 をキャプチャ - LLVM EXE スクリプトにコメント追加(tools/build_llvm.sh 経由の明記) ## Contract Documentation - join-explicit-cfg-construction.md に Pattern8 契約の具体例を追加 - "pattern増でも推測増にしない" の実例として記録 - loop_var_name / loop_invariants / expr_result / jump_args_layout の契約を明示 - 20-Decisions.md に正規化(Semantic/Plumbing)の分離方針を追記 - DOCS_LAYOUT.md に重要ドキュメントへの参照を追加 ## Test Results - ✅ VM smoke test: `[PASS] phase259_p0_is_integer_vm` (exit 7) - ✅ LLVM EXE: tools/build_llvm.sh 経由で exit 7 確認 - ✅ --verify: PASS ## Next FAIL (Phase 260+) - Function: `Main.main/0` in `apps/examples/json_lint/main.hako` - Error: `[cf_loop/pattern2] Failed to extract break condition from loop body` - Pattern: Nested loop(外側 loop + 内側 loop with break) 🚀 次の大工事: block-parameterized CFG への移行を開始します。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
57 KiB
Self Current Task — Now (main)
Next (planned)
- Phase 259:
StringUtils.is_integer/1(nested-if + loop)を JoinIR で受理して--profile quickを進める - Phase 260: block-parameterized CFG へ向けた “edge-args terminator 併存導入”(大工事 / Strangler)
- Phase 259.x: Me receiver SSOT(
variable_map["me"])を API 化して"this"/"me"混同を構造で潰す - Phase 141 P2+: Call/MethodCall 対応(effects + typing を分離して段階投入、ANF を前提に順序固定)
- Phase 143-loopvocab P3+: 条件スコープ拡張(impure conditions 対応)
- 詳細:
docs/development/current/main/30-Backlog.md
Phase 260(大工事)ロードマップ(要約)
- P0: edge-args を MIR terminator operand として 併存導入(Branch を含むので参照点は
out_edges()系に一本化) - P1: terminator更新APIを一本化し、successors/preds 同期漏れを構造で潰す
- P2:
BasicBlock.jump_argsを削除(terminator operand を SSOT 化) - P3: spans を
Vec<Spanned<_>>に収束(段階導入)
Current First FAIL (SSOT)
- Before Phase 259 P0:
json_lint_vm / StringUtils.is_integer/1 - After Phase 259 P0:
json_lint_vm / Main.main/0 nested-loop with break
Next FAIL Details
- Test:
json_lint_vm - Function:
Main.main/0 - Error:
[cf_loop/pattern2] Failed to extract break condition from loop body - Pattern: Nested loop(外側
loop(i < cases.length())内で内側loop(j < valid.length())+ break) - Reproduce:
./target/release/hakorune --backend vm apps/examples/json_lint/main.hako - Note: is_integer/1 自体は Pattern8 で解決済み。残りは nested-loop 処理の問題(Phase 260+)
2025-12-21:Phase 259 P0(Pattern8 BoolPredicateScan)✅
- Phase 259 README:
docs/development/current/main/phases/phase-259/README.md - Result:
StringUtils.is_integer/1を Pattern8(新規)で受理 - Fixtures:
apps/tests/phase259_p0_is_integer_min.hako(expected exit 7)
- Smokes:
tools/smokes/v2/profiles/integration/apps/phase259_p0_is_integer_vm.sh✅ PASStools/smokes/v2/profiles/integration/apps/phase259_p0_is_integer_llvm_exe.sh(LLVM harness 要設定)
- Key Implementation:
src/mir/builder/control_flow/joinir/patterns/pattern8_scan_bool_predicate.rs(新規)src/mir/join_ir/lowering/scan_bool_predicate_minimal.rs(新規)
- Design Decision: Pattern8 を新設(Pattern6 拡張ではなく分離)
- Pattern6: "見つける" scan(返り値: Integer)
- Pattern8: "全部検証する" predicate scan(返り値: Boolean)
- Note: json_lint_vm はまだ FAIL だが、is_integer 自体は解決済み。残りは nested-loop with break パターン(Pattern2 の別問題)
2025-12-20:Phase 258(index_of_string/2 dynamic window scan)✅
- Phase 258 README:
docs/development/current/main/phases/phase-258/README.md - Result:
index_of_string/2を JoinIR で受理し、quick の first FAIL をis_integer/1へ進めた
2025-12-20:Phase 257(Pattern6 reverse scan + PHI/CFG stabilization)✅
- Phase 257 README:
docs/development/current/main/phases/phase-257/README.md - Result:
last_index_of/2を Pattern6(reverse scan)で受理し、PHI predecessor mismatch を fail-fast + 自動補正で根治
2025-12-19:Phase 146/147 完了 ✅
- Phase 146 README:
docs/development/current/main/phases/phase-146/README.md - Fixtures:
apps/tests/phase146_p0_if_cond_unified_min.hako(P0: pure cond, expected exit 7)apps/tests/phase146_p1_if_cond_intrinsic_min.hako(P1:s.length() == 3, expected exit 7)
- Smokes:
tools/smokes/v2/profiles/integration/apps/phase146_p0_if_cond_unified_vm.shtools/smokes/v2/profiles/integration/apps/phase146_p0_if_cond_unified_llvm_exe.shtools/smokes/v2/profiles/integration/apps/phase146_p1_if_cond_intrinsic_vm.shtools/smokes/v2/profiles/integration/apps/phase146_p1_if_cond_intrinsic_llvm_exe.sh
- Flags:
HAKO_ANF_DEV=1(dev-only: ANF routing 有効化)HAKO_ANF_ALLOW_PURE=1(dev-only: PureOnly scope で ANF 有効化)
2025-12-19:Phase 251 Fix(JoinIR 条件変数抽出 / デバッグ出力整理)✅
- Phase 251 README:
docs/development/current/main/phases/phase-251/README.md - Fix:
collect_variables_recursive()を拡張し、MethodCall/FieldAccess/Index/Callの基底変数を ConditionEnv に登録できるようにしたloop_with_if_phi_if_sum.rsの無条件eprintln!をis_joinir_debug()ガードに移した(デフォルトは clean output)
- Status:
- 元の回帰(
arr.length()のarrが ConditionEnv に入らない): 解決 --profile quickのjson_lint_vmは別件で失敗が残る(JoinIR Pattern2 の break 条件でMethodCallが未対応)
- 元の回帰(
2025-12-19:Phase 252 P0/P1(Pattern2 break 条件: this.methodcall)✅
- Phase 252 README:
docs/development/current/main/phases/phase-252/README.md - Status:
cargo checkは通過(0 errors)--profile quickは次の FAIL が残る → Phase 253([joinir/mutable-acc-spec])
2025-12-19:Phase 255(Multi-param loop wiring)✅
- Phase 255 README:
docs/development/current/main/phases/phase-255/README.md - Status:
- Pattern6/index_of が VM/LLVM で PASS
loop_invariantsを導入して ConditionOnly 誤用を根治
2025-12-19:Phase 256(StringUtils.split/2 可変 step ループ)✅
- Phase 256 README:
docs/development/current/main/phases/phase-256/README.md - Status:
StringUtils.split/2は VM--verify/ integration smoke まで PASS--profile quickの最初の FAIL は Phase 257(StringUtils.last_index_of/2)へ移動- 設計SSOT:
docs/development/current/main/design/join-explicit-cfg-construction.md
- 直近の主要fix:
ValueId(57)undefined は根治(原因はconst_1未初期化)。- SSA undef(
%49/%67)は P1.7 で根治(continuation 関数名の SSOT 不一致)。 - P1.8で ExitLine/jump_args の余剰許容と関数名マッピングを整流。
- P1.9で
JoinInst::Jumpを tail call として bridge に落とし、jump_argsを SSOT として保持。 - P1.10で DCE が
jump_argsを used 扱いし、instruction_spansを同期(SPAN MISMATCH 根治)。 - P1.11で ExitArgsCollector の expr_result slot 判定を明確化し、split が
--verify/ integration smoke まで PASS。 - P1.5-DBG: boundary entry params の契約チェックを追加(VM実行前 fail-fast)。
- P1.6: 契約チェックの薄い集約
run_all_pipeline_checks()を導入(pipeline の責務を縮退)。 - P1.13: Pattern2 boundary entry params を
join_module.entry.paramsSSOT へ寄せた(ValueId 推測生成の撤去)。 - P1.13.5(= Phase 256.8.5): Boundary SSOT 統一(Pattern4/6/7 横展開 + hardcoded ValueId/PARAM_MIN 撤去)。
- Known issue(非ブロッカー): Pattern7 integration smoke の
phi predecessor mismatchは残存(今回の修正とは独立)。
2025-12-20:Phase 257(last_index_of early return loop)🔜
- Phase 257 README:
docs/development/current/main/phases/phase-257/README.md - Goal:
StringUtils.last_index_of/2を JoinIR で受理し、--profile quickを緑に戻す- Investigation(最小再現/論点):
docs/development/current/main/investigations/phase-257-last-index-of-loop-shape.md - Status: Pattern6 reverse scan + PHI/CFG 安定化は完了(最初の FAIL は次へ移動)
- Current first FAIL:
json_lint_vm / StringUtils.index_of_string/2(dynamic window scan, unsupported)
- Investigation(最小再現/論点):
2025-12-20:Phase 258(is_integer nested-if + loop)🔜
- Phase 258 README:
docs/development/current/main/phases/phase-258/README.md- Status:
index_of_string/2を対象(dynamic window scan)
- Status:
2025-12-20:Phase 259(is_integer nested-if + loop)🔜
- Phase 259 README:
docs/development/current/main/phases/phase-259/README.md
2025-12-19:Phase 254(index_of loop pattern)✅ 完了(Blocked by Phase 255)
- Phase 254 README:
docs/development/current/main/phases/phase-254/README.md - Status: Pattern 6 実装完了、ただし実行失敗(Phase 255 で unblock)
- 完了項目:
- ✅ Pattern 6 DetectorBox 実装(
Pattern6_ScanWithInit MATCHED) - ✅ extract_scan_with_init_parts() - 構造抽出
- ✅ scan_with_init_minimal.rs - JoinIR lowerer(main/loop_step/k_exit 生成)
- ✅ MirBuilder 統合 - boundary 構築と merge 実行
- ✅ substring を BoxCall として init-time に emit
- ✅ Pattern 6 DetectorBox 実装(
- ブロッカー:
- JoinIR→MIR merge/boundary が複数ループ変数(s, ch, i)に未対応
- PHI ノードが 1つしか作られず、undefined value エラー
- Phase 254 の受け入れ境界: Pattern 6 検出+JoinIR 生成まで ✅
- 実行 PASS は Phase 255 の範囲
2025-12-19:Phase 253(mutable-acc-spec)✅
- Phase 253 README:
docs/development/current/main/phases/phase-253/README.md - Goal:
--profile quickを緑に戻す(対処療法なし、analyzer 契約の整理で直す)
2025-12-19:Phase 145-anf P0/P1/P2 完了 ✅
- SSOT docs:
docs/development/current/main/phases/phase-145-anf/README.mddocs/development/current/main/phases/phase-144-anf/INSTRUCTIONS.md
- 実装 SSOT:
src/mir/control_tree/normalized_shadow/anf/- 入口(接続箇所 SSOT):
src/mir/control_tree/normalized_shadow/common/expr_lowerer_box.rs
- 環境変数:
HAKO_ANF_DEV=1(dev-only: ANF 有効化)HAKO_ANF_STRICT=1(dev-only: ANF fail-fast)
- Fixtures & smokes(VM/LLVM EXE parity):
apps/tests/phase145_p1_anf_length_min.hako→ exit 12apps/tests/phase145_p2_compound_expr_binop_min.hako→ exit 18apps/tests/phase145_p2_compound_expr_double_intrinsic_min.hako→ exit 5
2025-12-19:Phase 143-loopvocab P2 完了 ✅
- 対象: else 対称化(B-C / C-B)
- Fixtures & smokes(VM/LLVM EXE parity):
apps/tests/phase143_p2_loop_true_if_bc_min.hako→ exit 8apps/tests/phase143_p2_loop_true_if_cb_min.hako→ exit 9
2025-12-19:Phase 143 実行系契約修正 ✅
問題: normalized_helpers が env params を ValueId(1,2...) で割り当てていた(PHI Reserved 領域 0-99)。
根本原因: JoinValueSpace 契約では Param 領域は 100-999。4つの normalized shadow モジュールが全て間違った領域に params を割り当てていた。
修正:
NormalizedHelperBox::alloc_env_params_param_region()新規追加(100+ 開始)- 4 ファイルの normalized shadow 生成を更新:
loop_true_if_break_continue.rsloop_true_break_once.rsif_as_last_join_k.rspost_if_post_k.rs
instruction_rewriter.rs型ミスマッチ修正(func.signature.params→func.params)
検証:
- VM exit=7 ✅(phase143_loop_true_if_break_vm.sh PASS)
- LLVM EXE exit=7 ✅(phase143_loop_true_if_break_llvm_exe.sh PASS、timeout 解消)
- Unit tests: 69/69 PASS
ValueId Space Contract (Phase 201):
| Region | Range | Purpose |
|---|---|---|
| PHI Reserved | 0-99 | Loop header PHI dst |
| Param | 100-999 | env params (flag, counter, etc.) |
| Local | 1000+ | Const, BinOp, condition results |
2025-12-19:Phase 143.5 + P1 完了 ✅
Phase 143.5: NormalizedHelperBox 箱化(リファクタリング)
- 目的: 120+ 行のヘルパー関数重複を消去(4 ファイル共通化)
- 実装:
src/mir/control_tree/normalized_shadow/common/normalized_helpers.rs(151行+6テスト) - 効果: 136行追加 - 149行削除 = -13行(保守性大幅向上)
- 統計: 67/67 tests PASS(新規テスト 6個含む)
- 検証: cargo check 0 errors, cargo test 100% green
Phase 143 P1: Continue Support(条件付きループ継続)
- 目的:
loop(true) { if(cond_pure) continue }パターン追加 - 実装: Loop-If-Exit contract enum 駆動(break/continue 弁別)
- 変更:
extract_pattern_shape(): Err-based pattern matching to LoopIfExitShapeextract_exit_action(): Break/Continue を enum variant として識別loop_cond_check: match shape.then で Jump target を動的決定
- Fixtures & Tests:
apps/tests/phase143_loop_true_if_continue_min.hakotools/smokes/v2/profiles/integration/apps/phase143_loop_true_if_continue_vm.shtools/smokes/v2/profiles/integration/apps/phase143_loop_true_if_continue_llvm_exe.sh
- 検証: 契約ベース(shape.validate_for_p1() で P1 制約チェック)
- 注記: Phase 131 Pattern matching Issue 既知(ルーティング層の pre-existing failure)
2025-12-19:Phase 143-loopvocab P0 完了 ✅
Phase 143-loopvocab P0: Conditional Break Vocabulary Extension
- 目的:
loop(true) { if(cond_pure) break }パターンを Normalized shadow で実装(Phase 131 の条件付き拡張) - 仕様:
- Loop条件:
trueリテラルのみ - ループ本体: 単一 if statement(else なし)
- If then:
breakのみ(no continue, no nested if) - 条件: pure expression のみ(変数/リテラル/算術/比較、Method call なし)
- Out-of-scope は
Ok(None)で graceful fallback
- Loop条件:
- 実装 SSOT:
src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs- 6-function JoinModule(main → loop_step → loop_cond_check → Jump/Call → k_exit → Ret)
- Jump: if true → k_exit, if false → fall through to Call(loop_step)
- Fixtures:
apps/tests/phase143_loop_true_if_break_min.hako(expected exit code 7)
- Smoke tests:
- VM:
tools/smokes/v2/profiles/integration/apps/phase143_loop_true_if_break_vm.sh✅ PASS - LLVM EXE:
tools/smokes/v2/profiles/integration/apps/phase143_loop_true_if_break_llvm_exe.sh✅ PASS
- VM:
- Regression: Phase 131-142 green(no regressions)
- 統計: +400 lines(loop_true_if_break_continue.rs), 0 change to existing code
- 入口:
docs/development/current/main/phases/phase-143-loopvocab/README.md
2025-12-19:Phase 142-loopstmt P0 完了 ✅
Phase 142-loopstmt P0: Statement-Level Loop Normalization
- 目的: 正規化単位を "block suffix" から "statement (loop 1個)" へ寄せてパターン爆発を防ぐ
- 変更:
- PlanBox: loop(true) に対して常に loop_only() を返す(consumed=1)
- SuffixRouter: LoopOnly を受け入れて実行
- build_block: consumed 後も後続文を処理(break 削除)
- 実装 SSOT:
src/mir/builder/control_flow/normalization/plan_box.rssrc/mir/builder/control_flow/joinir/patterns/policies/normalized_shadow_suffix_router_box.rssrc/mir/builder/stmts.rs
- Refactoring:
- LoopWithPost variant を deprecated(4 commits)
- suffix_router コメント更新
- README 更新
- Tests:
- Fixture:
apps/tests/phase142_loop_stmt_only_then_return_length_min.hako(exit code 3) - VM smoke: ✅ PASS
- Unit tests: ✅ 10/10 passed
- Regression: ✅ Phase 131, 141 green
- Fixture:
- 統計: -38 lines net (code reduction success!)
- 入口:
docs/development/current/main/phases/phase-142-loopstmt/README.md
⚠️ Note: Phase 142 (Canonicalizer Pattern Extension) とは別物。SSOT 衝突回避のため phase-142-loopstmt として独立管理。
2025-12-19:Phase 141 P1.5 完了 ✅
Phase 141 P1.5: KnownIntrinsic registry + available_inputs 3-source merge + diagnostics
- 目的: “既知 intrinsic だけ” を SSOT 化しつつ、suffix 正規化が prefix の変数を見失わないようにする(既定挙動不変)。
- Task B(バグ修正):
AvailableInputsCollectorBox::collect(.., prefix_variables)を追加し、Function params > Prefix variables > CapturedEnv の 3-source merge に変更 - Task A(SSOT化):
KnownIntrinsicRegistryBoxを追加し、intrinsic の metadata(name/arity/type_hint)をknown_intrinsics.rsに集約 - Task C(診断):
OutOfScopeReason::IntrinsicNotWhitelistedを追加し、Call/MethodCall の out-of-scope 理由を精密化 - 実装 SSOT:
src/mir/control_tree/normalized_shadow/available_inputs_collector.rssrc/mir/control_tree/normalized_shadow/common/known_intrinsics.rssrc/mir/control_tree/normalized_shadow/common/expr_lowerer_box.rssrc/mir/control_tree/normalized_shadow/common/expr_lowering_contract.rssrc/mir/builder/control_flow/normalization/execute_box.rs
- 設計 SSOT:
docs/development/current/main/design/normalized-expr-lowering.md
2025-12-19:Phase 141 P1 完了 ✅
Phase 141 P1: KnownIntrinsicOnly (length0)
- 目的: impure 導入の安全なオンランプとして、既知 intrinsic(小さな allowlist)のみを ExprLowerer に追加
- 仕様:
ExprLoweringScope::WithImpure(ImpurePolicy::KnownIntrinsicOnly)でのみreceiver.length()を lowering- それ以外の Call/MethodCall は引き続き
Ok(None)(既定挙動不変)
- Fixture:
apps/tests/phase141_p1_if_only_post_k_return_length_min.hako(expected exit code 3)
- Smoke tests:
- VM:
tools/smokes/v2/profiles/integration/apps/phase141_p1_if_only_post_k_return_length_vm.sh - LLVM EXE:
tools/smokes/v2/profiles/integration/apps/phase141_p1_if_only_post_k_return_length_llvm_exe.sh
- VM:
- 入口:
docs/development/current/main/phases/phase-141/README.md
2025-12-19:Phase 141 P0 完了 ✅
Phase 141 P0: Impure Extension Contract (Call/MethodCall stays out-of-scope)
- 目的: 次フェーズの Call/MethodCall 導入に向けて、pure/impure 境界の contract(SSOT)を型で固定
- SSOT:
src/mir/control_tree/normalized_shadow/common/expr_lowering_contract.rssrc/mir/control_tree/normalized_shadow/common/expr_lowerer_box.rs
- 仕様: Call/MethodCall は引き続き
Ok(None)(既定挙動不変) - 入口:
docs/development/current/main/phases/phase-141/README.md
2025-12-19:Phase 140 完了 ✅
Phase 140: NormalizedExprLowererBox (pure expressions)
- 目的: “return の形追加” をやめて、pure expression を AST walker で一般化して収束させる
- SSOT:
src/mir/control_tree/normalized_shadow/common/expr_lowerer_box.rssrc/mir/control_tree/normalized_shadow/common/return_value_lowerer_box.rs
- 仕様:
- pure のみ(Variable / Integer&Bool literal / unary(not,-) / arith(+,-,*,/) / compare(==,!=,<,<=,>,>=))
- Call/MethodCall など impure は
Ok(None)(Phase 141+)
- 入口:
docs/development/current/main/phases/phase-140/README.md
2025-12-19:Phase 139 完了 ✅
Phase 139: post-if post_k Return Lowering Unification
- 目的: if-only
post_k側の return lowering をReturnValueLowererBoxに統一し、loop/if の出口を一本化 - 実装:
src/mir/control_tree/normalized_shadow/post_if_post_k.rsの return lowering をReturnValueLowererBox::lower_to_value_id()に委譲- out-of-scope は
Ok(None)でフォールバック(既定挙動不変・dev-only)
- Fixture:
apps/tests/phase139_if_only_post_k_return_add_min.hako(expected exit code 4)
- Smoke tests:
- VM:
tools/smokes/v2/profiles/integration/apps/phase139_if_only_post_k_return_add_vm.sh - LLVM EXE:
tools/smokes/v2/profiles/integration/apps/phase139_if_only_post_k_return_add_llvm_exe.sh
- VM:
- 入口:
docs/development/current/main/phases/phase-139/README.md
2025-12-18:Phase 138 完了 ✅
Phase 138: ReturnValueLowererBox - Return Lowering SSOT
- 目的: Return lowering logic を共有 Box として抽出し SSOT を確立
- 実装:
- Created
common/return_value_lowerer_box.rs(~300 lines) - Migrated
loop_true_break_once.rsto use Box (2 call sites) - 5 comprehensive unit tests for all patterns
- Code reduction: ~115 lines removed from loop_true_break_once.rs
- Created
- SSOT:
ReturnValueLowererBox::lower_to_value_id()- Supported: Variable, Integer literal, Add expression (x + 2, 5 + 3)
- Fallback: Out-of-scope patterns return
Ok(None)
- Tests:
- 5 new unit tests: variable, integer literal, add (var+int), add (int+int), fallback (subtract)
- All regressions PASS: Phase 137/97/131/135/136
- Design Decision:
- Phase 138 P0 migrated loop paths only
- Phase 139 P0 will unify post_if_post_k.rs for complete SSOT
- Architecture Impact:
- Single location for return lowering improvements
- Isolated unit tests for return lowering logic
- Easy to add new return patterns in one location
- 入口:
docs/development/current/main/phases/phase-138/README.md
2025-12-18:Phase 137 完了 ✅
Phase 137: loop(true) break-once with return add expression
- 目的: Phase 136 を拡張し、return 時に最小 add 式をサポート
- 仕様:
return x + 2(variable + integer literal)→ exit code 3return 5 + 3(integer literal + integer literal)→ exit code 8loop(true) { x = 1; break }; x = x + 10; return x + 2→ exit code 13
- 実装:
src/mir/control_tree/normalized_shadow/loop_true_break_once.rs(lower_return_value_to_vid()行 638-743, BinaryOp Add at 行 673)- BinaryOp Add パターン追加(LHS: Variable or Integer literal, RHS: Integer literal only)
- Ok(None) fallback for out-of-scope patterns(
return x + y,return x - 2等)
- Return Value Lowering SSOT:
- Documentation:
loop_true_break_once.rs(行 29-46, module-level comment) - Boxification trigger: 2+ files で同一 return lowering logic が必要になった時
- Documentation:
- Fixtures:
phase137_loop_true_break_once_return_add_min.hako(期待: exit code 3)phase137_loop_true_break_once_return_add_const_min.hako(期待: exit code 8)phase137_loop_true_break_once_post_return_add_min.hako(期待: exit code 13)
- Smoke tests:
- VM: 3/3 PASS
- LLVM EXE: 3/3 PASS
- Regression:
- Phase 97: 2/2 PASS(next_non_ws, json_loader_escape)
- Phase 131/135/136: 3/3 PASS
- 設計判断(Approach A 採用):
- 直接拡張(boxification なし)、変更スコープ小
- post_if_post_k.rs は未変更(責任分離)
- 入口:
docs/development/current/main/phases/phase-137/README.md
2025-12-18:Phase 136 完了 ✅
Phase 136: loop(true) break-once with return literal
- 目的: Phase 131-135 を拡張し、return integer literal をサポート
- 仕様:
loop(true) { x = 1; break }; return 7→ exit code 7loop(true) { x = 1; break }; x = x + 2; return 7→ exit code 7- PHI禁止維持、dev-only、既定挙動不変
- 実装:
src/mir/control_tree/normalized_shadow/loop_true_break_once.rs(lower_return_value_to_vid()行 638-743, Integer literal at 行 661)- Integer literal パターン: Const generation(Phase 123 パターン再利用)
- Ok(None) fallback for out-of-scope patterns(
return "hello",return 3.14等)
- Fixtures:
phase136_loop_true_break_once_return_literal_min.hako(期待: exit code 7)phase136_loop_true_break_once_post_return_literal_min.hako(期待: exit code 7)
- Smoke tests:
- VM: 2/2 PASS
- LLVM EXE: 2/2 PASS
- Regression:
- Phase 131: 2/2 PASS
- Phase 135: 2/2 PASS
- 入口:
docs/development/current/main/phases/phase-136/README.md
2025-12-18:Phase 135 P0 完了 ✅
Phase 135 P0: Normalization Plan Suffix Detection Generalization
- 目的: NormalizationPlanBox の suffix 検出を一般化し、post-loop assign が 0 回でも OK に
- 背景:
- Phase 133 までは
loop + assign+ + return(assign 1回以上必須) - Phase 131 は
loopのみ(return なし) - ギャップ:
loop + return(0 assign)が別経路
- Phase 133 までは
- 改善:
loop + assign* + return(N >= 0 assignments)を統一パターンとして検出- Phase 131 と Phase 132-133 を
LoopWithPost { post_assign_count }enum で統一 - Phase 131 (loop-only, no return) は
PlanKind::LoopOnlyとして独立維持
- 実装:
src/mir/builder/control_flow/normalization/plan_box.rs(検出ロジック修正のみ)post_assign_count >= 1チェックを削除 →>= 0を許容execute_box.rsは変更なし(既存ロジックが 0 assigns を自然にサポート)
- Fixture:
apps/tests/phase135_loop_true_break_once_post_empty_return_min.hako(期待: exit code 1) - Smoke tests:
phase135_loop_true_break_once_post_empty_return_vm.shPASSphase135_loop_true_break_once_post_empty_return_llvm_exe.shPASS
- Regression:
- Phase 131: 2/2 PASS(VM + LLVM EXE)
- Phase 133: 2/2 PASS(VM + LLVM EXE)
- Unit tests: 9/9 PASS(plan_box module)
- 設計原則:
- 最小変更: plan_box.rs の検出条件のみ変更
- SSOT 維持: 検出ロジックは plan_box.rs に集約
- Box-First: PlanBox(what)と ExecuteBox(how)の責任分離維持
- 入口:
src/mir/builder/control_flow/normalization/README.md(Phase 135 セクション追加)
2025-12-18:Phase 133 完了 ✅
Phase 133: loop(true) break-once + multiple post-loop assigns(dev-only)
- 目的: Phase 132 を拡張し、post-loop で複数の assign を受理(PHI-free 維持)
- 仕様:
loop(true) { x = 1; break }; x = x + 2; x = x + 3; return xは exit code6(VM/LLVM EXE parity)- post_nodes 検出を
len() == 2からlen() >= 2に拡張 - 複数 assign を iterative に lower(LegacyLowerer::lower_assign_stmt 再利用)
- 実装:
src/mir/control_tree/normalized_shadow/loop_true_break_once.rs(3箇所編集、~30行追加)- Pattern detection: all_assigns + ends_with_return
- Post-loop lowering: for loop で複数 assign 処理
- SSOT: env_post_k が最終値を保持(ExitMeta に反映)
- Fixture:
apps/tests/phase133_loop_true_break_once_post_multi_add_min.hako(期待: 6) - Smoke:
phase133_loop_true_break_once_post_multi_add_vm.shPASSphase133_loop_true_break_once_post_multi_add_llvm_exe.shPASS
- Regression: Phase 132/131/97 維持確認(全 PASS)
- Unit tests: 1176/1176 PASS
- 入口:
docs/development/current/main/phases/phase-133/README.md
2025-12-18:Phase 130 完了 ✅
Phase 130: if-only Normalized "Small Expr/Assign" Expansion(dev-only)
- 目的: post_k 内の最小 post-if 計算(
x = x + 3; return x)を Normalized で通す(PHI禁止) - 実装:
- P1: Assign(Variable) -
x = yサポート(env map 直接更新) - P2: Assign(Add) -
x = x + <int literal>サポート(Const + BinOp Add) - P3: Verifier - env map が env layout(writes + inputs)外の変数を導入しないことを検証
src/mir/control_tree/normalized_shadow/legacy/mod.rs(lower_assign_stmt 拡張)src/mir/control_tree/normalized_shadow/normalized_verifier.rs(verify_env_writes_discipline 追加)
- P1: Assign(Variable) -
- Fixture:
apps/tests/phase130_if_only_post_if_add_min.hako(期待出力: 5\n4) - Smoke:
phase130_if_only_post_if_add_vm.shPASS - LLVM EXE smoke:
phase130_if_only_post_if_add_llvm_exe.sh(LLVM 前提が無い環境では SKIP) - Regression: Phase 129/128 維持確認(全 PASS)
- Unit tests: 1155/1155 PASS
- 入口:
docs/development/current/main/phases/phase-130/README.md
2025-12-18:Phase 129-C 完了 ✅
Phase 129-C: post-if / post_k continuation(dev-only)
- post-if(
if { x=2 }; return x)を post_k continuation で表現 - join_k が env merge → TailCall(post_k, merged_env)
- post_k が post-if statements 実行 → Ret
- PHI禁止: Normalized IR 内に PHI 相当を入れず env 引数で合流
- 実装:
src/mir/control_tree/normalized_shadow/post_if_post_k.rs(392行、新規)builder.rsに PostIfPostKBuilderBox 統合normalized_verifier.rsに post_k 構造検証追加parity_contract.rsに StructureMismatch 追加
- Fixture:
apps/tests/phase129_if_only_post_if_return_var_min.hako - Smoke:
phase129_if_only_post_if_return_var_vm.shPASS - Regression: Phase 129-B, 128 維持確認(全 PASS)
- Unit tests: 1155/1155 PASS
- 入口:
docs/development/current/main/phases/phase-129/README.md
2025-12-18:Phase 132 完了 ✅
Phase 132: loop(true) break-once + post-loop minimal(dev-only)
- 目的: Phase 131 を拡張し、ループ後の最小 post 計算まで Normalized shadow で固定(PHI-free 維持)
- 仕様:
loop(true) { x = 1; break }; x = x + 2; return xは exit code3(VM/LLVM EXE parity)- post_k continuation で post-loop statements を処理
- 実装:
- P0: post_k 生成(loop_true_break_once.rs 拡張)
- P0.5: StepTree が post-loop statements を保持(suffix router box 追加)
- P1: k_exit continuation 分類修正(構造ベースの判定)
- R0: Continuation SSOT 一本化 + legacy 隔離 + docs 整備
- SSOT:
JoinInlineBoundary::default_continuations()- continuation ID の集約src/mir/builder/control_flow/joinir/merge/README.md- merge 契約明文化src/mir/builder/control_flow/joinir/legacy/README.md- legacy 撤去条件
- テスト配置:
src/mir/builder/control_flow/joinir/merge/tests/continuation_contract.rs - 検証:
bash tools/smokes/v2/profiles/integration/apps/phase132_loop_true_break_once_post_add_vm.shbash tools/smokes/v2/profiles/integration/apps/phase132_loop_true_break_once_post_add_llvm_exe.sh
- 回帰: Phase 131/97 維持確認(全 PASS)
- 入口:
docs/development/current/main/phases/phase-132/README.md
2025-12-18:Phase 131 P2 完了 ✅
Phase 131: loop(true) break-once Normalized(dev-only)
- 目的: Normalized shadow の最小ループを VM/LLVM EXE 両方で動かし、更新値が外に見えることまで固定
- 仕様:
loop(true) { x = 1; break }; return xは exit code1- DirectValue mode(PHI-free)で exit 値を
variable_mapに再接続
- 検証:
bash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_vm.shbash tools/smokes/v2/profiles/integration/apps/phase131_loop_true_break_once_llvm_exe.sh
- 環境: WSL の一時的な EXDEV(
Invalid cross-device link)はwsl --shutdown再起動で解消、上記 +phase97_next_non_ws_llvm_exe.shまで PASS - 入口:
docs/development/current/main/phases/phase-131/README.md
2025-12-18:Phase 127 完了 ✅
Phase 127: unknown-read strict Fail-Fast(dev-only)
- unknown-read = reads - (writes ∪ inputs) を検出
- strict:
freeze_with_hint("phase127/unknown_read/<name>", ...)で即停止(hint必須) - dev-only non-strict: 理由ログ(tag + count + 先頭数件)
- 入口:
docs/development/current/main/phases/phase-127/README.md
2025-12-18:Phase 128 完了 ✅
Phase 128: if-only partial assign keep/merge in Normalized (dev-only)
- StepStmtKind::Assign に value_ast 追加(Phase 128)
- Normalized builder に Assign(int literal) 対応(env 更新)
- Fixture: phase128_if_only_partial_assign_normalized_min.hako(簡易版)
- Smoke: phase128_if_only_partial_assign_normalized_vm.sh(PASS)
- Regression: Phase 121-126, 118 維持確認(全 PASS)
- Unit tests: 1165/1165 PASS
- 入口:
docs/development/current/main/phases/phase-128/README.md - 実装:
src/mir/control_tree/step_tree.rs(value_ast 追加、14行追加)src/mir/control_tree/normalized_shadow/builder.rs(Assign lowering、87行追加)
- Note: 完全な join_k continuation は future work(Phase 128 は基本構造確立)
2025-12-18:Phase 126 完了 ✅
Phase 126: available_inputs SSOT wiring (dev-only)
- AvailableInputsCollectorBox 実装(function params + CapturedEnv 収集)
- try_lower_if_only() に available_inputs 配線(dev-only)
- EnvLayout.inputs が実際に使用されるようになった
- Fixture 強化: reads-only 変数の return 解決を確認
- Regression: Phase 121-125, 118 維持確認(全 PASS)
- Unit tests: 28/28 PASS (including 5 new AvailableInputsCollectorBox tests)
- Integration smoke: PASS (phase125_if_only_return_input_vm.sh, exit code 7)
- 入口:
docs/development/current/main/phases/phase-126/README.md - 実装:
src/mir/control_tree/normalized_shadow/available_inputs_collector.rs(143行、新規)src/mir/control_tree/normalized_shadow/builder.rs(available_inputs 配線)src/mir/builder/calls/lowering.rs(AvailableInputsCollectorBox::collect() 呼び出し)
2025-12-18:Phase 125 P2-P5 完了 ✅
Phase 125 P2-P5: Reads-Only Env Inputs (dev-only, structure)
- EnvLayout 導入(writes + inputs の 2 レーン化)
- from_contract: reads ∩ available_inputs で inputs を決定(決定的順序)
- Return(Variable) 解決拡張: writes or inputs から解決
- Fail-Fast with hint: env に無い変数は構造化エラー
- Unit tests: 18/18 PASS (including new test_return_variable_from_inputs_stub)
- Integration smoke: PASS (phase125_if_only_return_input_vm.sh, exit code 7)
- Regression: Phase 121-124, 118 維持確認(全 PASS)
- 入口:
docs/development/current/main/phases/phase-125/README.md - 実装:
src/mir/control_tree/normalized_shadow/builder.rs(EnvLayout, 186行追加)
- Note: P3 (available_inputs wiring) 未実装、inputs は空(structure-only)
2025-12-18:Phase 124 完了 ✅
Phase 124: Normalized reads facts + Return(Variable from env)(dev-only)
- StepTreeFacts に reads 追加(Variable 参照を AST から抽出)
- StepTreeContract signature に reads 反映(決定性維持)
- env マッピング(変数名 → ValueId)を writes から生成
- Return(Variable) サポート: env にある変数のみ(writes 由来)
- env に無い Variable は Fail-Fast エラー(phase124 error → Ok(None) fallback)
- Box-first modularization: extract_variables_from_ast() で SSOT 化
- Unit tests: 1159 tests PASS (including test_return_variable_from_env)
- Integration smoke: PASS (
phase124_if_only_return_var_vm.sh, exit code 7 許容) - 回帰: Phase 121/123/118 維持確認
- 入口:
docs/development/current/main/phases/phase-124/README.md - 実装:
src/mir/control_tree/step_tree_facts.rs(reads 追加、76行)src/mir/control_tree/step_tree_contract_box.rs(reads 反映、101行)src/mir/control_tree/step_tree.rs(extract_variables_from_ast 追加、612行)src/mir/control_tree/normalized_shadow/builder.rs(env マッピング追加、837行)
2025-12-18:Phase 123 完了 ✅
Phase 123: if-only Normalized semantics(dev-only)
- Return(Integer literal) →
Const + Ret(Some(vid))生成 - Return(Variable) →
Ok(None)(graceful degradation, Phase 124 で対応) - If(minimal compare) → Variable vs Integer literal のみ対応
- Graceful degradation: Phase 123 制限は
Ok(None)で legacy に fallback - Structured error codes:
[phase123/...]prefix で明示的エラー - Box-first modularization: parse/verify/lower 責務分離
- Unit tests: 8 tests PASS (including graceful degradation test)
- Integration smoke: PASS (
phase123_if_only_normalized_semantics_vm.sh) - 入口:
docs/development/current/main/phases/phase-123/README.md
2025-12-18:Phase 121 完了 ✅
Phase 121: StepTree→Normalized Shadow Lowering (if-only, dev-only)
- 箱化モジュール化: normalized_shadow/{contracts,builder,parity}.rs (508行、新規)
- Shadow lowering: StepTree → JoinModule (Normalized方言、if-only限定)
- Capability guard: Loop/Break/Continue を明示的拒否(SSOT)
- Parity 検証: exit contracts + writes 比較(dev ログ / strict fail-fast)
- Dev-only wiring:
joinir_dev_enabled()のときのみ shadow 生成 - Strict fail-fast:
freeze_with_hintで mismatch を即座に検出(hint必須) - Smoke tests: VM 3/3 PASS、LLVM スタブ(ハーネス設定必要)
- 回帰: Phase 120 維持確認、全テスト PASS
- 入口:
docs/development/current/main/phases/phase-121/README.md - 設計:
docs/development/current/main/design/control-tree.md(Phase 121章)
2025-12-18:Phase 120 完了 ✅
Phase 120: StepTree "Facts→Decision→Emit" 箱化モジュール化
- 箱化モジュール化: StepTreeFacts / StepTreeContractBox の責務分離
- StepTreeBuilderBox: 構造 + facts 抽出まで(意思決定・整形・署名生成はしない)
- StepTreeContractBox: facts → contract の整形のみ(idempotent, deterministic)
- BTreeSet で順序決定性保証(facts は順序に依存しない)
- signature_basis_string() の決定性維持(既定挙動不変)
- 回帰: Phase 103/118 維持確認、全 1142 テスト PASS
- 入口:
docs/development/current/main/design/control-tree.md - 実装:
src/mir/control_tree/step_tree_facts.rs(63行、新規)src/mir/control_tree/step_tree_contract_box.rs(168行、新規)src/mir/control_tree/step_tree.rs(262→411行、リファクタリング)
2025-12-18:Phase 119 完了 ✅
Phase 119: StepTree cond SSOT(AST handle)
- StepNode::If / StepNode::Loop に cond_ast (AstNodeHandle) を追加
- SSOT: cond は AST 参照を保持、cond_sig は派生(署名/ログ/差分検知)
- 不変条件: cond_ast は signature_basis_string() に混ぜない(決定性維持)
- 実装: Box clone(dev-only なので許容)
- 回帰: Phase 103/104/118 維持確認
- 入口:
docs/development/current/main/design/control-tree.md
2025-12-18:Phase 118 完了 ✅
Phase 118: loop + if-only merge parity
- loop + if-only で条件付き変数更新 merge を VM/LLVM で固定
- Fixture: phase118_loop_nested_if_merge_min.hako (expected: 2)
- Pattern3 (if-sum) 活用
- Smoke: VM + LLVM EXE parity 検証済み
- Follow-up: Pattern3 carrier PHI contract(expected: 12)
- Fixture: phase118_pattern3_if_sum_min.hako
- Smoke: phase118_pattern3_if_sum_{vm,llvm_exe}.sh
- 回帰: Phase 117 維持確認
- 入口:
docs/development/current/main/phases/phase-118/README.md
2025-12-18:Phase 117 完了 ✅
Phase 117: if-only nested-if + call merge parity
- ネストしたif-only(内側if + 外側else)で call 結果 merge を VM/LLVM で固定
- Fixture: phase117_if_only_nested_if_call_merge_min.hako (expected: 2, 3, 4)
- Smoke: VM + LLVM EXE parity 検証済み
- 回帰: Phase 116 維持確認
- 入口:
docs/development/current/main/phases/phase-117/README.md
2025-12-18:Phase 116 完了 ✅
Phase 116: if-only keep+call merge parity
- if-only で片側が元値保持、片側が call 結果のパターンを VM/LLVM で固定
- Fixture: phase116_if_only_keep_plus_call_min.hako (expected: 10, 2)
- Smoke: VM + LLVM EXE parity 検証済み
- 回帰: Phase 115 維持確認
- 入口:
docs/development/current/main/phases/phase-116/README.md
2025-12-18:Phase 115 完了 ✅
Phase 115: if-only call result merge parity
- if-only で関数呼び出し結果を merge するパターンを VM/LLVM で固定
- Fixture: phase115_if_only_call_merge_min.hako (expected: 2, 3)
- Smoke: VM + LLVM EXE parity 検証済み
- 回帰: Phase 103/113/114 維持確認
- 入口:
docs/development/current/main/phases/phase-115/README.md
2025-12-18:Phase 114 完了 ✅
Phase 114: if-only return+post parity
- if-only で early return + post-if statements パターンを VM/LLVM で固定
- Fixture: phase114_if_only_return_then_post_min.hako (expected: 7, 2)
- Smoke: VM + LLVM EXE parity 検証済み
- 回帰: Phase 103/113 維持確認
- 入口:
docs/development/current/main/phases/phase-114/README.md
2025-12-18:Phase 113 完了 ✅
Phase 113: if-only partial assign parity
- if-only(else なし)の片側代入で「保持 merge」パターンを VM/LLVM で固定
- Fixture: phase113_if_only_partial_assign_min.hako
- Smoke: VM + LLVM EXE parity 検証済み
2025-12-18:Phase 112 完了 ✅
Phase 112: StepTree Capability Guard (strict-only)
- StepTree の required_caps を strict mode でチェック
- Allowlist: If, NestedIf, Loop, Return, Break, Continue
- Deny (strict): NestedLoop, TryCatch, Throw, Lambda, While, ForRange, Match, Arrow
- Error format:
[joinir/control_tree/cap_missing/<Cap>] <msg> Hint: <hint> - Default behavior unchanged (strict=false always Ok)
- 入口:
docs/development/current/main/design/control-tree.md - 実装:
src/mir/builder/control_flow/joinir/control_tree_capability_guard.rssrc/mir/builder/calls/lowering.rs(wired into lower_function_body)
2025-12-18:Phase 111 完了 ✅
Phase 111: StepTreeContract + StepTreeSignature(dev-only)
- StepTreeContract を追加(
exits/writes/required_caps/cond_sig) - StepTreeSignature を追加(
signature_basis_string()を安定 hash、Span は含めない) - dev-only parity を break/continue に加えて return まで拡張
- 入口:
docs/development/current/main/design/control-tree.md - 実装:
src/mir/control_tree/step_tree.rs
2025-12-18:Phase 110 完了 ✅
Phase 110: ControlTree / StepTree(構造SSOT・dev-only観測)
- StepTree の語彙(Block/If/Loop/Stmt)と Feature を pure AST で実装(ValueId/PHI/CFG を混ぜない)
- joinir routing 側で extractor との “分類矛盾” を dev-only で検出(strict のみ Fail-Fast)
- 関数本体の StepTree を dev-only でダンプ(既定挙動不変)
- 入口:
docs/development/current/main/design/control-tree.md - 実装:
src/mir/control_tree/step_tree.rssrc/mir/builder/calls/lowering.rssrc/mir/builder/control_flow/joinir/routing.rs
2025-12-17:Phase 109 完了 ✅
Phase 109: error_tags hints SSOT
- policy/validator エラーを "tag + message + hint" 形式に統一
- freeze_with_hint() API 追加(hint 必須、空なら panic)
- Phase 107/104/100 の代表3箱を hint 対応に移行
- 入口:
docs/development/current/main/phases/phase-109/README.md
2025-12-17:Phase 104 完了 ✅
Phase 104: loop(true) + break-only digits(read_digits 系)
- read_digits_from 形の
loop(true)を Pattern2 で受理(loop var 抽出 + break cond 正規化) - fixture:
apps/tests/phase104_read_digits_loop_true_min.hako(expected:2,1) - smoke:
tools/smokes/v2/profiles/integration/apps/phase104_read_digits_vm.sh/tools/smokes/v2/profiles/integration/apps/phase104_read_digits_llvm_exe.sh - P2: json_cur 由来の回帰面を追加(fixture+VM/LLVM EXE smoke)
2025-12-17:Phase 107 完了 ✅
Phase 107: json_cur find_balanced_ depth scan(VM + LLVM EXE parity)*
- depth scan + nested if + return-in-loop を Pattern2 policy で受理(hardcode なし)
- fixture:
apps/tests/phase107_find_balanced_array_end_min.hako(expected:1,3)apps/tests/phase107_find_balanced_object_end_min.hako(expected:1,3)
- smoke(integration):
- VM:
tools/smokes/v2/profiles/integration/apps/phase107_find_balanced_array_end_vm.sh/tools/smokes/v2/profiles/integration/apps/phase107_find_balanced_object_end_vm.sh - LLVM EXE:
tools/smokes/v2/profiles/integration/apps/phase107_find_balanced_array_end_llvm_exe.sh/tools/smokes/v2/profiles/integration/apps/phase107_find_balanced_object_end_llvm_exe.sh
- VM:
- 入口:
docs/development/current/main/phases/phase-107/README.md
2025-12-17:Phase 108 完了 ✅
Phase 108: Pattern2 policy router SSOT(薄い入口の固定)
- post-loop early return を一般 plan(
cond/ret_expr)として独立し、Pattern2Inputs の依存を解消 - ApplyPolicyStepBox から “直叩き” を撤去し、policy router 1本に集約(入口SSOT)
- 入口:
docs/development/current/main/phases/phase-108/README.md
2025-12-17:Phase 103 P0 完了 ✅
Phase 103: if-only regression baseline
- if-only(loop無し)の nested if + merge を fixture 化し、VM/LLVM EXE parity を integration smoke で固定
2025-12-17:Phase 100 P3 完了 ✅
Phase 100 P3: String Accumulator Captures
- String accumulator(
out = out + ch)を最小形で固定し、VM/LLVM EXE parity を smoke で検証 - LLVM EXE 側の stringish 伝播(PHI/copy/binop)を修正し、concat の意味論を安定化
2025-12-17:Phase 100 P2 完了 ✅
Phase 100 P2: Mutable Accumulator Captures
- Mutable accumulator pattern (
out = out + ch) を Pattern2 carrier で対応 - ScopeManager 委譲により read-only check を回避
- Numeric output validation (count=3) で fixture 固定
- VM/LLVM EXE parity 完了(smoke 追加)
2025-12-17:Phase 100 P1 完了 ✅
Phase 100 P1: Pinned Local Captures
- CapturedEnv に CapturedKind (Explicit/Pinned) 拡張
- PinnedLocalAnalyzer で loop-outer read-only locals を識別
- Pinned receiver (例: s.substring()) が loop 内で使用可能に
- Fixture/smoke で動作確認済み
2025‑12‑17:Phase 99 完了 ✅
Phase 99: Trim/escape 実コード寄り強化(VM+LLVM EXE)
- next_non_ws を3ケース固定(
2,-1,3)— 改行/CR/Tab混在パターン追加 - escape 末尾バックスラッシュを best-effort として固定(
hello\そのまま出力) - VM+LLVM EXE parity 完全対応、integration smoke で検証済み
関連(設計/実装の入口):
- Phase 100:
docs/development/current/main/phases/phase-100/README.md
2025‑12‑15:Phase 132 完了 ✅
Phase 132: LLVM Exit PHI=0 根治修正 完了!
- ループ exit PHI が 0 を返す問題を根治解決
- 原因(2層): (1) JoinIR/Boundary が exit 値を境界に渡していない、(2) LLVM Python が PHI を落とす/上書きする
- 修正: Pattern 1 で exit 値を明示的に渡す +
predeclared_ret_phis使用 +builder.vmapの PHI 保護 - 結果:
/tmp/p1_return_i.hakoが 3 を返す(VM 一致) - 詳細:
investigations/phase132-llvm-exit-phi-wrong-result.md
追加(Phase 132-P2): Case C の Exit PHI ValueId 衝突を修正
- 原因:
exit_phi_builder.rsが module-level allocator を使い、同一関数内で ValueId が衝突し得た - 修正:
func.next_value_id()(function-level)へ統一(bd07b7f4) - 結果:
apps/tests/llvm_stage3_loop_only.hakoが LLVM EXE でもResult: 3(VM 一致) - 詳細:
investigations/phase132-case-c-llvm-exe.md
追加(Phase 132-P3): Exit PHI collision の早期検出(debug-only)
verify_exit_phi_no_collision()をcontract_checks.rsに追加し、ValueId 衝突を JoinIR merge の段階で Fail-Fast する
2025‑12‑15:Phase 133–136(短報)
- Phase 133: promoted carrier(Trim)の
join_id解決を SSOT に寄せて修正(smoke は compile-only)。 - Phase 134: plugin loader best-effort loading を導入(決定的順序 + failure 集約 + 継続)。
- Phase 135: ConditionLoweringBox が allocator SSOT を無視して ValueId 衝突を起こす問題を根治。
- 詳細:
docs/development/current/main/phases/phase-135/README.md
- 詳細:
- Phase 136: MirBuilder の Context 分割を完了し、状態の SSOT を Context に一本化。
- 詳細:
docs/development/current/main/phases/phase-136/README.md
- 詳細:
2025‑12‑16:Phase 137‑141(短報)
- Loop Canonicalizer(前処理 SSOT)は Phase 141 まで完了(既定挙動は不変、dev-only 観測/strict parity あり)。
- 設計 SSOT:
docs/development/current/main/design/loop-canonicalizer.md - 実装:
src/mir/loop_canonicalizer/mod.rs(+ 観測:src/mir/builder/control_flow/joinir/routing.rs) - Phase 記録:
docs/development/current/main/phases/phase-137/README.md
- 設計 SSOT:
2025‑12‑16:Phase 92(短報)
- Phase 92(ConditionalStep / P5b escape の lowering 基盤)は完了。
- 条件付き更新(
ConditionalStep)のJoinIR表現 + Pattern2 側の委譲(emitter 箱化) - 条件式での body-local 参照(
ConditionEnv → LoopBodyLocalEnv)+ 最小E2E smoke 固定 - Phase 記録(SSOT入口):
docs/development/current/main/phases/phase-92/README.md - 残: P5b の “完全E2E” は body-local promotion 拡張後(スコープ外で保留)
- 条件付き更新(
2025‑12‑16:Phase 93(短報)
- Trim の
is_ch_matchなど「ConditionOnly(PHIで運ばない派生値)」を Derived Slot として毎イテレーション再計算できるようにした。- SSOT:
ConditionOnlyRecipe(運搬禁止)+ConditionOnlyEmitter - schedule:
body-init → derived → breakを評価順SSOTとして強制 - Phase 記録(入口):
docs/development/current/main/phases/phase-93/README.md
- SSOT:
2025‑12‑16:Phase 94(短報)
- P5b escape(
ch再代入 +iの +1/+2)を “derived(Select)” として扱い、VM E2E を固定。- 新箱:
BodyLocalDerivedEmitter+ 明示ポリシー(strict で理由付き Fail-Fast) - integration smoke:
tools/smokes/v2/profiles/integration/apps/phase94_p5b_escape_e2e.sh - Phase 記録(入口):
docs/development/current/main/phases/phase-94/README.md
- 新箱:
2025‑12‑16:Phase 95(短報)
- MiniJsonLoader の escape ループを Phase 94 基盤で固定(派生 body-local + 条件付き skip)。
- フィクスチャ:
apps/tests/phase95_json_loader_escape_min.hako - smoke:
tools/smokes/v2/profiles/integration/apps/phase95_json_loader_escape_vm.sh - Phase 記録(入口):
docs/development/current/main/phases/phase-95/README.md
- フィクスチャ:
2025‑12‑16:Phase 96(短報)
- Trim系 policy 化を開始し、MiniJsonLoader の next_non_ws ループを fixtures/smoke に追加。
- フィクスチャ:
apps/tests/phase96_json_loader_next_non_ws_min.hako - smoke:
tools/smokes/v2/profiles/integration/apps/phase96_json_loader_next_non_ws_vm.sh - Phase 記録(入口):
docs/development/current/main/phases/phase-96/README.md
- フィクスチャ:
2025‑12‑16:Phase 97(短報)
- Phase 95/96 の MiniJsonLoader fixture を LLVM EXE ラインでも固定し、JoinIR/Trim の退行検出を強化。
- smoke:
tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh(next_non_ws) - smoke:
tools/smokes/v2/profiles/integration/apps/phase97_json_loader_escape_llvm_exe.sh(escape) - Phase 記録(入口):
docs/development/current/main/phases/phase-97/README.md
- smoke:
2025‑12‑17:Phase 98(短報)
- plugin loader に strict fail-fast を導入し(HAKO_JOINIR_STRICT=1)、FileBox/MapBox の LLVM EXE parity を持続可能に。
- smoke:
tools/smokes/v2/profiles/integration/apps/phase97_next_non_ws_llvm_exe.sh - smoke:
tools/smokes/v2/profiles/integration/apps/phase97_json_loader_escape_llvm_exe.sh - Phase 記録(入口):
docs/development/current/main/phases/phase-98/README.md
- smoke:
2025‑12‑17:Phase 102(短報)
- real-app(MiniJsonLoader.read_quoted_from)の loop を最小抽出し、VM + LLVM EXE で regression を固定(期待: length=4)。
- フィクスチャ:
apps/tests/phase102_realapp_read_quoted_min.hako - smoke:
tools/smokes/v2/profiles/integration/apps/phase102_realapp_read_quoted_vm.sh - smoke:
tools/smokes/v2/profiles/integration/apps/phase102_realapp_read_quoted_llvm_exe.sh - Phase 記録(入口):
docs/development/current/main/phases/phase-102/README.md
- フィクスチャ:
2025‑12‑14:現状サマリ
(補足)docs が増えて迷子になったときの「置き場所ルール(SSOT)」:
docs/development/current/main/DOCS_LAYOUT.md
JoinIR / Loop / If ライン
- LoopBuilder は Phase 186‑187 で完全削除済み。JoinIR が唯一の loop lowering 経路。
- LoopPattern 系は Pattern1–4 まで実装・本線化済み:
- Pattern1: Simple While
- Pattern2: Loop with Break
- Pattern3: Loop with If‑Else PHI(break/continue なし)
- Pattern4: Loop with Continue(multi‑carrier 対応)
- Exit/Carrier/Boundary ラインは次の箱で SSOT 化:
CarrierInfo/ExitMeta/ExitBindingBuilderJoinInlineBoundary+LoopExitBinding
- If lowering は IfSelectLowerer/IfMergeLowerer を中心に整理済み。Select/PHI の扱いも Phase 189 系で橋渡し済み。
- 残課題(JoinIR ライン):
- JoinIR→MIR merge の一般化(複雑な Select/PHI パターンの統合)
- JsonParserBox など実アプリ側での長期運用テスト
- Phase 86–90(Loop frontends)まとめ(1枚):
docs/development/current/main/phase86-90-loop-frontends-summary.md
Phase 86–90: Loop frontends(要約)
- Phase 86–90 は “dev-only fixtures + shape guard + fail-fast” で段階的に固定済み。
- 具体の fixture / shape / 未検証は
docs/development/current/main/phase86-90-loop-frontends-summary.mdを SSOT とする。
Scope / BindingId(dev-only の段階移行ライン)
- MIR builder 側で lexical scope / shadowing を実在化し、言語仕様の “local はブロック境界で分離” を SSOT に揃えた。
- JoinIR lowering 側は name-based から BindingId-based へ段階移行中:
ScopeManager.lookup_with_binding()/ConditionEnv.binding_id_mapを導入し、shadowing を壊さずに解決できる足場を作った。- promoted carriers(DigitPos/Trim)については
BindingId(original) → BindingId(promoted) → ValueId(join)の鎖を dev-only で整備中。 - Phase 86 で
carrier_init_builder/error_tagsを SSOT 化し、段階移行ラインの基盤(ValueId 生成とエラー語彙)が確立した。 - これにより、BindingId dual-path の拡張・統合時に「生成」と「表示」の責務が混ざらない構造が固定された。
- Phase 81 で Pattern2(DigitPos/Trim)の ExitLine 契約(ConditionOnly を exit PHI から除外、LoopState のみを reconnect)を E2E で固定した。
- 参照:
docs/development/current/main/phase73-scope-manager-design.mddocs/development/current/main/phase78-bindingid-promoted-carriers.mddocs/development/current/main/phase80-bindingid-p3p4-plan.mddocs/development/current/main/phase81-pattern2-exitline-contract.mddocs/development/current/main/phase78-85-boxification-feedback.md
JsonParser / Selfhost depth‑2 ライン
selfhost_build.sh --jsonで Program JSON v0 emit は安定。
.hako側から env 経由で JSON を読む最小ループ(program_read_min.hako)は動作確認済み。- JsonParserBox / BundleResolver のループ 21 本のうち:
- 18 本は Pattern1–4 で JoinIR 対応済み(Phase 162–165)。
_trimを含む一部の複合ループは、ValueId 境界や Box 登録など残課題あり。
- BoolExprLowerer / condition_to_joinir で OR/AND/NOT 付き条件式の lowering は実装完了(Phase 168–169)。
- 残課題(JsonParser/selfhost depth‑2):
- JoinIR→MIR ValueId boundary の完全一般化(条件用 ValueId を含める)
- JsonParserBox の using / Box 登録(Rust VM 側での認識)
- Program JSON v0 を JsonParserBox 経由でフル解析する line の仕上げ
Ring0 / Runtime / CoreServices ライン
- Ring0Context + Ring0Registry で OS API 抽象化レイヤ完成:
- MemApi / IoApi / TimeApi / LogApi / FsApi / ThreadApi
- RuntimeProfile(Default / NoFs) で条件付き必須を制御。
- CoreServices(ring1‑core)として次を実装済み:
- StringService / IntegerService / BoolService
- ArrayService / MapService / ConsoleService
- PluginHost 統合 + UnifiedBoxRegistry からの自動初期化
- FileBox / FileHandleBox ライン:
- Ring0FsFileIo 経由で read / write / append / metadata 完全対応
- Default プロファイルでは必須、NoFs プロファイルでは disabled。
- Logging ライン:
- ConsoleService(user‑facing)
- Ring0.log(internal/dev)
- println!(test 専用)
の 3 層が
logging_policy.mdで整理済み。JoinIR/Loop trace も同ドキュメントに集約。
- VM backend の Box 解決(UnifiedBoxRegistry / BoxFactoryRegistry)の経路図:
docs/development/current/main/phase131-2-box-resolution-map.md
- LLVM(Python llvmlite)lowering の棚卸し(Phase 131-3..10):
docs/development/current/main/phase131-3-llvm-lowering-inventory.md- 状態: Case B(Pattern1/loop_min_while)は EMIT/LINK/RUN まで復旧済み。Phase 132 で
return iの VM/LLVM parity を固定。 - Case C は別途 “Case C docs” を SSOT にして追跡する(状況は更新されるので、この箇所では断定しない)
- Case C の調査と実装計画:
docs/development/current/main/phase131-11-case-c-summary.mddocs/development/current/main/case-c-infinite-loop-analysis.md
2025‑09‑08:旧スナップショット(参考)
- LLVM 側 P0 完了(BitOps/Array/Echo/Map 緑)。VInvoke(by‑name/by‑id vector) は戻り値マッピングの暫定課題を確認中(Decisions 参照)。
- selfhosting-dev の作業を main に順次取り込み。VM/MIR 基盤は main で先に整える方針。
直近タスク(当時)
- continue/break の lowering(Builder 修正のみで表現)
- ループ文脈スタック {head, exit} を導入。
- continue に遭遇 → head(または latch)へ br を emit し終端。
- break に遭遇 → exit へ br を emit し終端。
- post‑terminated 後に emit しない制御を徹底。
- ループ CFG の厳密化
- 単一 exit ブロックの徹底。
- Phi はヘッダでキャリー変数を合流(SSA/支配関係が崩れない形)。
- 検証とスモーク
- Verifier 緑(dominance/SSA)。
- VM のループ代表(単純/ネスト/早期継続・脱出)。
- LLVM/Cranelift EXE に綺麗に降りる(br/phi ベースで問題なし)。
代表コマンド(例)
- ビルド:
cargo build --release - LLVM smoke:
LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) NYASH_LLVM_BITOPS_SMOKE=1 ./tools/llvm_smoke.sh release - VInvoke 調査:
NYASH_LLVM_VINVOKE_TRACE=1 NYASH_LLVM_VINVOKE_SMOKE=1 ./tools/llvm_smoke.sh release