Commit Graph

1366 Commits

Author SHA1 Message Date
ffd49ece91 docs(joinir): L-2.2 Step-5 - Verify Stage-B stability with generic ON
Verified NYASH_JOINIR_LOWER_GENERIC=1 does not break Stage-B:
- generic OFF: joinir_json 10 PASS, joinir_stageb 6 PASS
- generic ON: joinir_json 10 PASS, joinir_stageb 6 PASS,
  auto_lowering 2 PASS
- No guard additions needed - existing code is stable
- Stage-B execution remains on VM Route A (JoinIR as canary only)

L-2.2 is now fully complete (Step-1 through Step-5).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 12:02:29 +09:00
eddc4e6035 docs(joinir): L-2.2 Step-4 - Update JoinIR VM bridge documentation
Phase 32 README:
- Expand VM Bridge table with "JoinIR 利用範囲" column
- Add L-2.2 progress summary table (Step-1~5 status)
- Add developer notes for Stage-B JoinIR observation

environment-variables.md:
- Add detailed descriptions for NYASH_JOINIR_* variables
- Clarify scope and limitations (Stage-B = lowering only)
- Add Stage-B JoinIR observation example

CURRENT_TASK:
- Update L-2.2 status to Step-1~4 complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 11:55:04 +09:00
1eea40454f test(joinir): L-2.2 Step-3 - Add Stage-B JoinIR→MIR structure tests
- Expose `convert_joinir_to_mir` as `pub(crate)` for test access
- Add `joinir_stageb_body_structure_test` and
  `joinir_stageb_funcscanner_structure_test` to `joinir_json_min.rs`
- Verify: JoinIR lowering succeeds, JoinIR→MIR conversion succeeds,
  function count matches, each function has >= 1 block
- Result: Both Stage-B functions produce 2 JoinIR functions
  (entry + loop_step) with appropriate block counts
- Note: Current tests verify handwritten JoinIR→MIR bridge layer,
  not full MIR→JoinIR roundtrip (future improvement)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 11:38:45 +09:00
e61e7a2be6 feat(joinir): L-2.2 Step-2 - Add Stage-B to VM bridge dispatch
Add Stage-B BodyExtractor and FuncScanner to JoinIR VM bridge dispatch:
- Import stageb_body and stageb_funcscanner lowering functions
- Add routing for StageBBodyExtractorBox.build_body_src/2
- Add routing for StageBFuncScannerBox.scan_all_boxes/1
- Add try_run_stageb_body() and try_run_stageb_funcscanner() (lowering verification only)

Also cleanup unused imports in funcscanner_trim.rs and stage1_using_resolver.rs

Note: Stage-B functions use lowering verification pattern (like Stage-1)
because ArrayBox/MapBox args are not yet supported in JoinValue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 11:02:21 +09:00
9d769e9217 refactor(joinir): L-2.2 Step-1 - Unify Stage-B lowering via LoopToJoinLowerer
Stage-B minimal JoinIR lowering統一化:

1. Add Case-A helpers to loop_to_join.rs:
   - lower_case_a_for_stageb_body (StageBBodyExtractorBox.build_body_src/2)
   - lower_case_a_for_stageb_funcscanner (StageBFuncScannerBox.scan_all_boxes/1)

2. Update stageb_body.rs and stageb_funcscanner.rs:
   - Replace manual LoopForm construction with construct_simple_while_loopform
   - Route through LoopToJoinLowerer like other Case-A functions
   - Remove unused imports (LoopForm, MirQuery)

Now all 6 JoinIR lowering modules use the same unified pattern:
- skip_ws, trim, append_defs, stage1_resolver, stageb_body, stageb_funcscanner
All route through LoopToJoinLowerer for consistency.

Test results: JSON snapshot 6/6 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:47:35 +09:00
853cb36800 refactor(joinir): L-1.3 - Rename minimal helpers to Case-A helpers
LoopToJoinLowerer API cleanup:

1. Rename methods to reflect their purpose as Case-A helpers:
   - lower_minimal_skip_ws_case_a → lower_case_a_for_skip_ws
   - lower_minimal_trim_case_a → lower_case_a_for_trim
   - lower_minimal_append_defs_case_a → lower_case_a_for_append_defs
   - lower_minimal_stage1_case_a → lower_case_a_for_stage1_resolver

2. Update comments to clarify these are thin wrappers over `lower()`
   - "Case-A 汎用 lowerer の薄いラッパー"
   - Actual logic is centralized in `lower` method

3. Update all 4 call sites:
   - skip_ws.rs
   - funcscanner_trim.rs
   - funcscanner_append_defs.rs
   - stage1_using_resolver.rs

Test results: standalone (2/2), JSON snapshot (6/6) PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:28:03 +09:00
51ff558904 feat(phase32): L-2.1 Stage-1 UsingResolver JoinIR integration + cleanup
Phase 32 L-2.1 complete implementation:

1. Stage-1 UsingResolver main line JoinIR connection
   - CFG-based LoopForm construction for resolve_for_source/5
   - LoopToJoinLowerer integration with handwritten fallback
   - JSON snapshot tests 6/6 PASS

2. JoinIR/VM Bridge improvements
   - Simplified join_ir_vm_bridge.rs dispatch logic
   - Enhanced json.rs serialization
   - PHI core boxes cleanup (local_scope_inspector, loop_exit_liveness, loop_var_classifier)

3. Stage-1 CLI enhancements
   - Extended args.rs, groups.rs, mod.rs for new options
   - Improved stage1_bridge module (args, env, mod)
   - Updated stage1_cli.hako

4. MIR builder cleanup
   - Simplified if_form.rs control flow
   - Removed dead code from loop_builder.rs
   - Enhanced phi_merge.rs

5. Runner module updates
   - json_v0_bridge/lowering.rs improvements
   - dispatch.rs, selfhost.rs, modes/vm.rs cleanup

6. Documentation updates
   - CURRENT_TASK.md, AGENTS.md
   - Various docs/ updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:17:37 +09:00
7d0581c9a4 refactor(joinir): Extract construct_simple_while_loopform helper, delete legacy code
Phase 32 cleanup:

1. Delete legacy is_supported_case_a_loop function from loop_to_join.rs
   - Replaced by is_supported_case_a_loop_view() in Phase 32 Step 3

2. Extract construct_simple_while_loopform helper to common.rs
   - Unified LoopForm construction for simple while loops
   - Parameters: entry_is_preheader (trim=true, stage1=false)
                 has_break (trim=true, stage1=false)
   - Sets latch=body to satisfy is_simple_case_a_loop check

3. Update lowering modules to use the common helper:
   - funcscanner_trim.rs: entry_is_preheader=true, has_break=true
   - stage1_using_resolver.rs: entry_is_preheader=false, has_break=false

Test results: JSON snapshot 6/6 PASS, VM bridge trim 2/2 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:15:31 +09:00
ec69b49446 feat(mir): Phase 32 Step 0-3B - LoopRegion/LoopControlShape view methods
Phase 32 introduces a "view pattern" for loop structures, enabling
gradual migration without breaking existing code.

Changes:
- control_form.rs: Add new ID types (LoopId, ExitEdgeId, ContinueEdgeId)
  and structures (LoopRegion, LoopControlShape, ExitEdge, ContinueEdge)
- control_form.rs: Add view methods on LoopShape:
  - to_region_view() - returns LoopRegion
  - to_control_view() - returns LoopControlShape
  - to_exit_edges() - returns Vec<ExitEdge>
  - to_continue_edges() - returns Vec<ContinueEdge>
- loop_scope_shape.rs: Use views in from_existing_boxes_legacy()
- loop_to_join.rs: Add debug logging with Phase 32 views

All 4 minimal lowerers (skip_ws/trim/append_defs/stage1) now use
view-based block ID extraction via shared from_existing_boxes_legacy().

Tests: joinir_runner_standalone_*, joinir_vm_bridge_trim_* PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 08:01:32 +09:00
b35b477c9c feat(phase32): L-1 - Enable JoinIR by default for FuncScannerBox.trim/1
Phase 32 L-1: Make JoinIR the default execution path for verified targets.

- Added is_default_joinir_target() function to check default-enabled functions
- FuncScannerBox.trim/1 is now enabled by default (break=[], Case-A verified)
- Main.skip/1 excluded from default (break=[2], needs Case-B support)
- Environment variable NYASH_JOINIR_VM_BRIDGE=1 still works for other targets

Test results:
- trim: Route C (JoinIR) returns correct value "abc"
- trim: Route A (VM) returns "void" due to PHI bug
- JoinIR correctly handles PHI issues that affect direct VM path

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 06:23:07 +09:00
acffd9974b feat(phase31): Step 3-A/B - Add early return and structure checks to LoopToJoinLowerer
Phase 31 Step 3-A: Add early return using is_case_a_minimal_target() filter
- Check before LoopScopeShape construction for efficiency
- Returns None immediately for non-target functions

Phase 31 Step 3-B: Add structural validation to is_supported_case_a_loop()
- Single exit check: loop_form.break_targets.len() <= 1
- Variable presence check: !carriers.is_empty() || !pinned.is_empty()
- Debug logging for rejection reasons

Also refactored lower_with_scope() from if-else chain to match expression for clarity.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 06:02:52 +09:00
7a29ebd268 refactor(phase31): Connect 4 lowerers to LoopToJoinLowerer
Phase 31 Step 2 complete:
- skip_ws.rs: use LoopToJoinLowerer::lower_minimal_skip_ws_case_a()
- funcscanner_trim.rs: use LoopToJoinLowerer::lower_minimal_trim_case_a()
- funcscanner_append_defs.rs: use LoopToJoinLowerer::lower_minimal_append_defs_case_a()
- stage1_using_resolver.rs: use LoopToJoinLowerer::lower_minimal_stage1_case_a()

Eliminates direct generic_case_a calls, routing through unified box.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 02:36:43 +09:00
ef9fd4417a feat(phase31): Add LoopToJoinLowerer unified box
Phase 31 Step 1 complete:
- Create src/mir/join_ir/lowering/loop_to_join.rs
- Add LoopToJoinLowerer struct with lower() method
- Implement lower_minimal_skip_ws_case_a() via generic_case_a
- Support for trim, append_defs, stage1 patterns
- Re-export from mod.rs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 01:18:32 +09:00
bbafd9c8b1 refactor(phi_core): Phase 30 F-2.2 delete LoopSnapshotManager (test-only)
Remove LoopSnapshotManager which was only used by its own internal tests.
No external call sites existed.

- Delete loop_snapshot_manager.rs (~458 lines)
- Update mod.rs to remove module declaration
- Update PHI_BOX_INVENTORY.md and TASKS.md

Analysis showed all other F-2.2 candidates have production dependencies
and must wait for JoinIR coverage expansion:
- PhiBuilderBox - loop_builder.rs
- LoopSnapshotMergeBox - loopform_builder.rs, json_v0_bridge
- if_phi.rs - lifecycle.rs, if_form.rs, loop_builder.rs
- if_body_local_merge.rs - phi_builder_box.rs, loop_builder.rs
- phi_invariants.rs, conservative.rs, phi_input_collector.rs - multiple

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 00:44:11 +09:00
bf3893b2cc feat(mir): Phase 30 F-3.0.7 LoopScopeShape Case-A minimal routing
Add func_name-based routing in LoopScopeShape::from_existing_boxes()
to prepare for MIR-based independent analysis:

- Add is_case_a_minimal_target() helper for 4 Case-A targets
- Add analyze_case_a() method (delegates to legacy, future MIR-based)
- Add from_existing_boxes_legacy() for backward compatibility
- Update from_existing_boxes() with func_name: Option<&str> parameter
- Update 4 production call sites with specific func_name
- Update 6 test cases with None for legacy path
- Update module documentation with routing logic diagram

Tests: 10/10 LoopScopeShape tests PASS, 6/7 JoinIR VM bridge tests PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 00:36:41 +09:00
2b47f47061 refactor(phi_core): F-2.1 - 早期グループPHI箱削除(約2,500行削減)
## 削除したファイル
- header_phi_builder.rs (~628行) - バイパス関数を loopform_builder.rs に移動
- exit_phi_builder.rs (~1000行) - バイパス関数を loopform_builder.rs に移動
- body_local_phi_builder.rs (~550行) - 依存なし
- loop_phi.rs (~288行) - LoopPhiOps実装も削除

## 移動した関数
loopform_builder.rs に以下を移動:
- get_loop_bypass_flags() / LoopBypassFlags struct
- is_joinir_header_bypass_target()
- joinir_exit_bypass_enabled()
- is_joinir_exit_bypass_target()

## 修正したファイル
- loop_builder.rs: バイパス関数の参照先変更 + LoopPhiOps impl削除
- mod.rs: モジュール宣言削除

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 23:42:35 +09:00
a898ff3f83 refactor(joinir): Phase 30 F-2.0/F-3 - PHI箱インベントリと旧APIレガシー削除
F-3 レガシー削除:
- generic_case_a.rs: 旧API関数4個削除(_with_scope 移行完了)
- loop_scope_shape.rs: CaseAContext::new() 削除(from_scope() に統一)
- mod.rs: 不要な pub use 削除
- #[allow(dead_code)] 除去(5関数)
- 未使用import削除(コード削減約150行)

F-2.0 PHI箱インベントリ:
- PHI_BOX_INVENTORY.md 作成: 13箱+11補助構造体の棚卸し
- 削除順ポリシー: 早期/中期/最終の3段階
- TASKS.md/CURRENT_TASK.md 更新

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 23:25:39 +09:00
6598cd3272 refactor(joinir): F-3 add _with_scope variant for skip_ws lowering
Phase 30 F-3: LoopScopeShape 実データ運用の一歩目

変更内容:
- lower_case_a_skip_ws_with_scope(scope) 追加
  - LoopScopeShape を直接受け取る新 API
  - CaseAContext::from_scope() 経由で ctx 構築
- lower_case_a_skip_ws_core(ctx) 抽出
  - 共通ロジックを分離
  - _for_minimal_skip_ws と _with_scope で共有

設計意図:
- lowerer が scope を明示的に構築できる API を提供
- 将来の boxes 削除時に移行しやすい構造を準備
- 既存 API は後方互換性を維持

テスト結果:
- JoinIR 関連テスト: 全 PASS
- loop_scope_shape テスト: 10/10 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 15:48:00 +09:00
f41564723d docs: Phase 30 F-1/F-3/F-4.4 preparation survey
Task A/B/C results:
- Task A: Lowerer files Case A analysis (6 files surveyed)
  - Found: all lowerers use empty LoopVarClassBox/LoopExitLivenessBox
  - stageb_body/stageb_funcscanner have placeholders only
- Task B: Add VM runner shrinkage plan to TASKS.md F-4.4
- Task C: Add bridge summary to CURRENT_TASK.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 15:30:54 +09:00
de5d5fae52 feat(mir): Phase 30 F-1 LoopScopeShape SSOT preparation
LoopScopeShape を変数分類の唯一の情報源 (SSOT) にするための準備:

F-1.1 LoopVarClassBox:
- 4分類(Pinned/Carrier/BodyLocalExit/BodyLocalInternal)の仕様を
  loop_scope_shape.rs にドキュメント化(PHI生成ルール表付き)
- LoopScopeShape.classify() / classify_all() メソッド追加
- LoopVarClassBox.classify_with_scope() 委譲メソッド追加
- 旧APIにPhase 30 TODOコメント追加

F-1.2 LoopExitLivenessBox:
- exit_live フィールドにSSOT説明ドキュメント追加
- get_exit_live_from_scope() 委譲メソッド追加

F-1.3 LocalScopeInspectorBox:
- Phase 30移行中のTODOコメント追加
- is_available_in_all_with_scope() 委譲メソッド追加

未使用フィールド削除:
- CaseAContext::scope フィールド削除
- LoopBypassFlags::exit フィールド削除
- PhiBuilderBox::loop_context / LoopPhiContext 削除

テスト結果: 37テスト全てPASS
- loop_scope_shape: 12 PASS (+2 new)
- loop_var_classifier: 11 PASS
- loop_exit_liveness: 3 PASS
- local_scope_inspector: 11 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 15:14:54 +09:00
e93727dd37 fix(joinir): Stage-1 string concat BinOp::Or → Add + ArrayBox support
Fixes:
1. BinOp::Or → BinOp::Add for string concatenation in Stage-1 lowering
2. ArrayBox/MapBox support via JoinValue::BoxRef (ChatGPT implementation)

Results:
- n=0: JoinIR → "init"  (VM → "void" PHI bug)
- n=3: JoinIR → "ABC"  (VM → "void" PHI bug)

Stage-1 JoinIR VM Bridge now fully working!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 13:33:01 +09:00
6d10fc45ba feat(joinir): Stage-1 Route B execution test - prove PHI fix
Add Route B execution tests for Stage-1 UsingResolver:

Results:
- n=0 (no loop): JoinIR returns "init"  vs VM returns "void" (PHI bug)
- n=3 (loop runs): JoinIR errors "IntegerBox.get" - needs ArrayBox support

This proves JoinIR can fix PHI bugs in Stage-1 loops.
Next step: JoinValue extension for ArrayBox/MapBox arguments.

Test: joinir_vm_bridge_stage1_usingresolver_route_b_*

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 12:53:12 +09:00
29ae922a57 feat(joinir): Stage-1 UsingResolver JoinIR VM Bridge A/B test
Phase 30.x: Stage-1 ループでも PHI バグが発生することを確認・JoinIR で設計根絶可能を実証

変更内容:
- src/tests/joinir_vm_bridge_stage1_usingresolver.rs: 新規作成(モジュール化・削除容易)
  - empty_entries: VM → "void" (PHI bug, expected "init")
  - with_entries: VM → "void" (PHI bug, expected "ABC")
  - lowering_sanity: 常時実行の構造検証
- src/runner/modes/vm.rs: Stage1UsingResolverBox.resolve_for_source/5 検出・JoinIR lowering 確認
- src/tests/mod.rs: モジュール追加(1行で削除可能)
- docs: Phase 30 TASKS.md に L-0.5 追加

発見:
  Stage-1 ループでも PHI バグが発生 → JoinIR で設計根絶可能を確認
  (ArrayBox/MapBox 引数対応は TODO)

テスト結果:
   empty_entries ... ok (VM="void", expected="init", PHI bug detected)
   with_entries ... ok (VM="void", expected="ABC", PHI bug detected)
   lowering_sanity ... ok (JoinIR structure: 2 functions)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 12:34:20 +09:00
ee2b3115ee feat(joinir): FuncScannerBox.trim/1 JoinIR VM Bridge A/B test
Phase 30.x: JoinIR VM Bridge でPHI問題を設計で解決できることを実証

変更内容:
- src/runner/modes/vm.rs: FuncScannerBox.trim/1 検出時にJoinIR経由実行
- src/mir/join_ir_vm_bridge.rs: Non-tail call サポート追加
  - dst=Some(id) の場合、結果を格納して次の命令へ継続
- src/tests/joinir_vm_bridge_trim.rs: A/Bテスト新規作成
  - メインテスト: Route A (VM) → "void" (PHI bug), Route C (JoinIR) → "abc" 
  - エッジケース: 5パターン全てPASS
- src/config/env.rs: joinir_vm_bridge_debug() 追加
- docs: Phase 30 TASKS.md に L-0.4 追加

テスト結果:
  Route A (MIR→VM直接):     "void"  ← PHI バグ
  Route C (MIR→JoinIR→VM):  "abc"   ← 正解 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 12:22:08 +09:00
de16ff9b7f feat(joinir): Phase 30.x jsonir v0 snapshot tests
Implement JSON snapshot testing for JoinIR regression detection.

Implementation:
- tests/fixtures/joinir/v0_*.jsonir: 6 snapshot fixtures for minimal JoinIR cases
- src/tests/joinir_json_min.rs: Added 6 snapshot comparison tests

Fixtures:
- v0_skip_ws_min.jsonir (1338 bytes)
- v0_funcscanner_trim_min.jsonir (4484 bytes)
- v0_funcscanner_append_defs_min.jsonir (988 bytes)
- v0_stage1_usingresolver_min.jsonir (987 bytes)
- v0_stageb_body_min.jsonir (1074 bytes)
- v0_stageb_funcscanner_min.jsonir (962 bytes)

Usage:
  # Run snapshot tests
  NYASH_JOINIR_SNAPSHOT_TEST=1 cargo test --release joinir_json_v0_

  # Regenerate fixtures (after intentional changes)
  NYASH_JOINIR_SNAPSHOT_TEST=1 NYASH_JOINIR_SNAPSHOT_GENERATE=1 cargo test --release joinir_json_v0_

Purpose:
- Fix current JoinIR shape as v0 baseline (pre-generic state)
- Detect unintended regressions during genericization
- Allow intentional fixture updates when design changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:19:02 +09:00
e9c7d27a7f feat(joinir): Phase 30.x jsonir v0 - JoinIR JSON serialization
Implement JSON serialization for JoinIR module.

Implementation:
- src/mir/join_ir/json.rs: JSON serializer (~250 lines, no external deps)
- src/tests/joinir_json_min.rs: Integration tests (8 unit + 2 integration)
- 10 tests total, all passing

Features:
- JoinModule → JSON serialization
- All instruction types: Call, Jump, Ret, Compute
- All MirLikeInst types: Const, BinOp, Compare, BoxCall
- Full ConstValue support: Integer, Bool, String, Null
- Full operator coverage: Add/Sub/Mul/Div/Or/And, Lt/Le/Gt/Ge/Eq/Ne
- JSON string escaping for special characters

Usage:
  use crate::mir::join_ir::json::join_module_to_json_string;
  let json = join_module_to_json_string(&module);

Non-goals (this phase):
- CLI flag (--emit-joinir-json)
- JSON → JoinIR reverse conversion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:53:26 +09:00
daf4f9af57 docs: CLAUDE.md にセルフホストライン追加
- 🔥 セルフホストライン セクション追加
- 環境変数の使い方とコマンド例
- タイムアウト延長、デバッグ出力のオプション
- セルフホストの価値(ビルド不要で爆速開発)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:30:48 +09:00
4120ab65c9 fix(selfhost): StringBox.get() エラー修正でセルフホスト復活!
StageBDriverBox.compile() と main() 内の2箇所に防御チェック追加:
- methods.get(mi) が null の場合スキップ
- methods.get(mi) が StringBox の場合スキップ (MapBox のみ処理)

これにより "Unknown method 'get' on StringBox" エラーが解消され、
.hako セルフホストコンパイラが再び動作するようになった。

テスト確認:
NYASH_USE_NY_COMPILER=1 ./target/release/hakorune test.hako
→ "Hello from selfhost!" RC: 0 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:18:43 +09:00
03efa13e76 docs(phase-29): JoinIR/Stage-1 環境変数棚卸し完了
Step 1: ENV_INVENTORY.md 作成 (docs/private submodule)
Step 2: 実装統一確認 - 既にhelper経由で統一済み
Step 3: environment-variables.md に JoinIRセクション追加
Step 4: スモークテスト pass
Step 5: CURRENT_TASK.md に完了記録

発見事項:
- JoinIR: env_flag_is_1() ヘルパー経由で統一済み
- Stage-1: src/config/env/stage1.rs SSOT モジュール経由で統一済み
- NYASH_RUN_JOINIR_MINIMAL は既に削除済み

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:03:28 +09:00
c479e5f527 fix(dx): Quick Win 1-3 for better error messages and API simplification
Quick Win 1: Show available boxes on "Unknown Box type" error
- vm.rs, vm_fallback.rs: Display sorted list of available user-defined boxes
- Before: "Unknown Box type: Foo"
- After:  "Unknown Box type: Foo. Available: Bar, Baz, Main"

Quick Win 2: Show stderr on child process timeout
- child.rs, selfhost_exe.rs: Capture and display stderr (up to 500 chars)
- Helps diagnose what went wrong in selfhost compiler child process

Quick Win 3: Simplify Stage-B compiler API (SSOT)
- compiler_stageb.hako: Add StageBDriverBox.compile() as single entry point
- compiler_stageb.hako: Remove StageBMain compatibility wrapper
- compiler.hako: Change from `using ... as StageBMain` to direct import
- compiler.hako: Call StageBDriverBox.compile() directly

Also includes child_env.rs NYASH_MODULES env var for module mapping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 08:44:31 +09:00
6726ee246d fix(selfhost): Phase 28.2 Ny compiler child process fixes
- Use --stage-b flag for file-based compilation (Stage-A expects source
  content, not path; Stage-B uses FileBox to read files)
- Remove redundant env overrides that conflicted with
  apply_selfhost_compiler_env() settings
- Re-enable plugins in selfhost compiler env (NYASH_DISABLE_PLUGINS=0)
  so compiler.hako can use FileBox to read source files

Note: Pipeline infrastructure now works, but compiler.hako has a MIR
SSA bug (undefined ValueId(374)) that needs separate investigation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 07:49:47 +09:00
22575aa1db refactor(selfhost): clean up selfhost.rs - remove duplicates, unify env access
## Changes

### Duplicate code removal
- Remove nested double cli_verbose() checks (2 places)
- Remove duplicate pre_run_reset_oob_if_strict() calls
- Remove duplicate OOB strict check blocks

### Environment variable access unification
- All raw std::env::var() calls replaced with config::env functions
- Added new config::env functions:
  - ny_compiler_use_py()
  - macro_selfhost_pre_expand()
  - scopebox_enable()
  - loopform_normalize()
  - selfhost_inline_force()

### Common helper extraction
- maybe_dump_mir_verbose(): MIR dump with verbose check
- check_oob_strict_exit(): OOB strict mode check and exit
- execute_with_oob_check(): Combined run + OOB check

## Result
- Net ~11 lines reduction
- Much better code structure and maintainability
- Consistent environment variable access through config::env

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 07:18:29 +09:00
59f00db385 chore: update docs/private submodule
Updates Phase 28.2/29 documentation with Ny compiler path investigation results.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 07:08:56 +09:00
94b2bd2799 feat(selfhost): add observation logs for Ny compiler path diagnosis
Add NYASH_CLI_VERBOSE>=2 observation logs to trace the Ny compiler
child process path (NYASH_USE_NY_COMPILER=1):
- Log when spawning child process
- Log when receiving Program(JSON v0)
- Log before/after maybe_dump_mir with dump path info
- Report whether MIR dump file was created

Key finding: apps/selfhost/compiler/compiler.hako doesn't exist,
so the preferred child process route never fires. This explains
why RUST_MIR_DUMP_PATH doesn't create files in Ny compiler path.

Also update environment-variables.md with:
- NYASH_CLI_VERBOSE=2 level documentation
- Ny compiler observation template for Phase 29

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 07:08:32 +09:00
8ae5280be2 feat(joinir): promote joinir_runner_standalone_trim to mainline test
Remove #[ignore] from trim test, following skip_ws promotion pattern:
- NYASH_JOINIR_EXPERIMENT=1 toggle controls execution
- Normal cargo test skips via early return (lightweight)
- Two JoinIR standalone tests now available as PHI-independent baselines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 06:54:35 +09:00
96ce02eef4 feat(joinir): add progress carrier verification for skip_ws (Phase 29 L-5.2)
Implement zero-progress backedge detection for JoinIR loops:
- Create verify.rs module with ProgressError enum
- verify_progress_for_skip_ws() checks BinOp::Add before recursive calls
- Hook into joinir_runner_standalone_skip_ws test (NYASH_JOINIR_EXPERIMENT=1)
- Currently warning-only, will upgrade to error in Phase 30

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 06:38:43 +09:00
31e458e7fa refactor(joinir): introduce CaseAContext to consolidate common lowering logic
- Add CaseAContext struct in loop_scope_shape.rs to centralize:
  - LoopForm validation
  - intake_loop_form invocation
  - LoopScopeShape construction
  - Variable name → ValueId mapping
  - pinned_ids/carrier_ids/exit_args resolution

- Refactor all 4 generic_case_a.rs functions to use CaseAContext:
  - lower_case_a_loop_to_joinir_for_minimal_skip_ws
  - lower_case_a_loop_to_joinir_for_trim_minimal
  - lower_case_a_loop_to_joinir_for_append_defs_minimal
  - lower_case_a_loop_to_joinir_for_stage1_usingresolver_minimal

- Remove unused name_to_header_id field from LoopFormIntake
  (was duplicate of header_snapshot)

Code reduction: ~200 lines of duplicated pattern → 4 lines

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 06:32:08 +09:00
844e53d96c fix(parser): Part 5 - eliminate infinite loops in parse_string2 and scan_with_quote
Problem: Nested escape sequence processing in string parsing functions caused
infinite loops due to missing continue statements, allowing fallthrough to the
else block which corrupted the position counter.

Fixed functions:
- parser_expr_box.hako::parse_string2 (lines 22-83)
- parser_string_scan_box.hako::scan_with_quote (lines 11-101)

Changes:
- Flattened nested 'else { if ... }' chains to flat 'if' statements
- Added explicit 'continue' after each escape sequence processing
- Prevents fallthrough to position increment code

Verification:
 NYASH_USE_STAGE1_CLI=1 STAGE1_EMIT_PROGRAM_JSON=1 HAKO_VM_MAX_STEPS=2000000
   apps/tests/minimal_ssa_skip_ws.hako
 No budget exceeded
 Program JSON v0 output to stdout
 Exit code: 0

MirBuilder-friendly pattern applied consistently with Parts 1-4.
Stage-1 CLI infinite loop elimination COMPLETE!
2025-11-25 00:16:29 +09:00
b21ee3c854 fix(parser): Part 3-4 - Fix remaining infinite loops in parser subsystems
Part 3 (included):
- parser_box.hako: Fix semicolon consumption loop (lines 401-421)

Part 4 (systematic fix of 7 files):
- parser_number_scan_box.hako: Fix scan_int digit scanning loop
- parser_literal_box.hako: Fix parse_map and parse_array loops (2 loops)
- parser_peek_box.hako: Fix peek expression arms parsing loop
- parser_control_box.hako: Fix parse_block and semicolon loops (2 loops)
- parser_exception_box.hako: Fix try/catch clauses loop
- parser_stmt_box.hako: Fix using statement namespace parsing loop

Root cause: MirBuilder bug with loop(flag == 0/1) + nested if-else
- Generated broken MIR with PHI self-references
- Caused infinite loops in VM execution

Solution: Convert all problematic loops to MirBuilder-friendly pattern:
  loop(true) { if condition { continue } else { break } }

Test results:  Stage-1 CLI now completes without timeout
- Exit code: 0
- MIR dump created successfully
- parse_program2 ws_init: 1 iteration (was infinite)

Total loops fixed across all parts: 18 loops in 11 files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 21:34:22 +09:00
54b9597af6 fix(parser): Stage-1 CLI infinite loop - fix ParserExprBox and ParserIdentScanBox (Part 2/3)
**Problem**: Multiple infinite loops in parser expression handling
- ParserIdentScanBox.scan_ident: bb985
- ParserExprBox.parse_factor2: bb1662 (2 loops)
- ParserExprBox.parse_term2: bb1704
- ParserExprBox.parse_sum2
- ParserExprBox.parse_expr2
- ParserExprBox.parse_args2

**Root Cause**: Same `loop(cont == 1)` + nested if-else pattern as Part 1
- MirBuilder generates PHI self-references
- Loop exits jump to wrong blocks

**Solution**: MirBuilder-friendly explicit continue/break pattern
```hako
// BAD:
loop(cont == 1) {
  if condition { action } else { cont = 0 }
}

// GOOD:
loop(true) {
  if condition { action; continue }
  break
}
```

**Files Modified**:
- lang/src/compiler/parser/scan/parser_ident_scan_box.hako: scan_ident explicit continue
- lang/src/compiler/parser/expr/parser_expr_box.hako: 6 loops fixed
  - parse_factor2: 2 method chaining loops (new/identifier)
  - parse_term2: */ operators
  - parse_sum2: +- operators
  - parse_expr2: &&|| operators
  - parse_args2: argument list parsing

**Progress**: 9 total loop patterns fixed (Part 1: 3, Part 2: 6)

**Remaining**: parse_program2 still has infinite loop at different location (bb2816 vs original bb2854) - investigating in Part 3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:34:43 +09:00
c6c5653ae0 fix(parser): Stage-1 CLI infinite loop - MirBuilder-friendly refactoring (Part 1/3)
**Problem**: Stage-1 CLI hits VM step budget (infinite loops) in multiple functions
- ParserBox.parse_program2: bb2853→bb2854 loop
- StringHelpers.skip_ws: bb488→bb491 loop

**Root Cause**: MirBuilder bug with `loop(cont==1)` + nested `if-else` pattern
- PHI instructions with self-references
- Loop exit blocks jumping back to header instead of continuation

**Solution**: Refactor to MirBuilder-friendly pattern
```hako
// Before (causes infinite loop):
loop(cont == 1) {
  if guard > max { return j } else { guard++ }
  if condition { action } else { cont = 0 }
}

// After (MirBuilder-friendly):
loop(j < n) {
  if condition { j++; continue }
  break
}
```

**Changes**:
1. parser_box.hako: parse_program2 main loop refactored
   - 7 sections: ws→EOF/guard→parse_stmt2→progress guard→trace→semicolons→emit
   - Unconditional parse_stmt2 execution (no nested if-else)
   - Explicit `break` for loop exits

2. string_helpers.hako: StringHelpers.skip_ws simplified
   - Removed `cont` flag and guard counter
   - Direct `loop(j < n)` with `continue/break`

3. vm.rs, vm_fallback.rs: RUST_MIR_DUMP_PATH support
   - Enables offline MIR analysis for debugging

**Progress**:
-  parse_program2: infinite loop fixed
-  StringHelpers.skip_ws: infinite loop fixed
-  ParserIdentScanBox.scan_ident: next target (bb985 loop)

**Testing**:
- MIR dumps generated successfully (116K+ lines)
- ws_init loop completes
- parse_program2 progresses further
- Still hits infinite loop in scan_ident (Part 2 needed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 18:19:31 +09:00
6885235145 Factor JSON v0 bridge globals/throw into small helpers 2025-11-24 15:21:49 +09:00
da1a5558e5 Normalize passes keep spans and clean warnings 2025-11-24 15:02:51 +09:00
466e636af6 Span trace utilities and runner source hint 2025-11-24 14:17:02 +09:00
3154903121 docs: S-5.4 GC統合&A/Bテスト完了 (submodule update)
 Phase 27-shortterm S-5 全タスク完了
- GC統合: Arc<dyn NyashBox> 参照カウント管理
- standalone テスト完全成功 (skip_ws/trim PASS)
- VM統合実証済み (execute_box_call経由)

Submodule commits: ba0cc24, 02e57a1
2025-11-24 11:47:25 +09:00
98dadf446f feat(joinir): S-5.2-improved - VM完全意味論統合完了
Phase 27-shortterm S-5.2-improved 実装完了:

## 実装内容
1. **execute_box_call() ラッパー追加**:
   - src/backend/mir_interpreter/mod.rs に公開 API 実装
   - 1_000_000 番台レジスタで一時値管理
   - 適切なクリーンアップ処理実装

2. **handle_box_call 可視性変更**:
   - src/backend/mir_interpreter/handlers/boxes.rs を pub に変更
   - JoinIR Runner からアクセス可能に

3. **JoinIR Runner BoxCall 統合**:
   - src/mir/join_ir_runner.rs の BoxCall 処理を書き換え
   - StringBox 直接呼び出し削除
   - VM の execute_box_call 経由に変更
   - JoinValue ↔ VMValue 変換で統合

4. **不要な関数削除**:
   - expect_str(), expect_int(), box_to_join_value() 削除
   - VMValue 変換に一本化

5. **テスト更新**:
   - joinir_runner_standalone.rs: VM インスタンス追加
   - joinir_runner_min.rs: VM 再利用

## 期待される効果
 Void guards 完全対応 (Void.length() → 0)
 PluginBox/InstanceBox 将来対応可能
 VM の完全な BoxCall 意味論統一
 VM 2号機回避(ガードレール設計成功)

## テスト結果
 joinir_runner_standalone_skip_ws ... ok
 joinir_runner_standalone_trim ... ok
 ビルド成功(0エラー)

## 完了タスク
- [x] MirInterpreter::execute_box_call() 実装
- [x] 1_000_000 レジスタ帯域割り当て
- [x] regs クリーンアップ実装
- [x] JoinIR Runner BoxCall 書き換え
- [x] テスト更新&PASS確認

🎉 VM 完全意味論統合完了!
2025-11-24 08:37:59 +09:00
a8555e67d5 feat(joinir): S-5.2完了 - BoxCall → VM method_router 経由実装
実装内容:
- box_to_join_value() ヘルパー関数追加(VM Box → JoinValue 変換)
- StringBox.length/substring を VM 実装経由で呼び出し(hardcoded削除)
- safe_substring() 削除(不要になった)

技術的成果:
- ガードレール設計実現: 制御フローは JoinIR Runner、Box実装は VM に委譲
- VM 2号機 回避: Box実装の重複なし
- テスト全 PASS: joinir_runner_standalone_skip_ws/trim 両方成功

Phase 27-shortterm S-5.2 完了 
2025-11-24 08:01:56 +09:00
03cb0a49c7 feat(joinir): Phase 27-shortterm S-5.1 完了 - JoinValue を VMValue ベースに統合
## 実装内容

### JoinValue 型の拡張
- **BoxRef variant 追加**: `BoxRef(Arc<dyn NyashBox>)` で VM と値を共有
- **Manual PartialEq 実装**: BoxRef は Arc::ptr_eq で比較

### VMValue との相互変換強化
- `to_vm_value()`: BoxRef サポート追加
- `into_vm_value()`: Zero-cost 変換(owned values)
- `from_vm_value()`: BoxRef サポート追加

### 後方互換性
- 既存の Int/Bool/Str/Unit variant は変更なし
- すべての既存コードがそのまま動作
- 16個の unit test 全て PASS 

### S-5.2 への準備
- BoxRef を method_router 経由で使用する準備完了
- 「VM 2号機」を避けるための基盤確立

## テスト結果
- join_ir_ops unit tests: 16 passed / 0 failed
2025-11-24 07:31:34 +09:00
790c8381fb chore: Update docs/private submodule (S-4 完了記録) 2025-11-24 07:24:59 +09:00
bff223eff9 feat(joinir): Phase 27-shortterm S-4 完了 - JoinIR → Rust VM ブリッジ参考実装
## 実装内容

### S-4.1: VM インターフェース調査
- VMValue 定義調査(Integer/Float/Bool/String/Future/Void/BoxRef)
- execute_module() API 調査

### S-4.2: JoinValue ↔ VMValue 変換関数実装
- src/mir/join_ir_ops.rs に変換関数追加(+121行)
- to_vm_value()/from_vm_value() 実装
- Float/Future/BoxRef は非対応エラー

### S-4.3: join_ir_vm_bridge.rs 基本構造実装
- src/mir/join_ir_vm_bridge.rs 新規作成(362行)
- run_joinir_via_vm() API 実装
- convert_join_function_to_mir() 実装
- 7つのコンパイルエラー修正完了

### S-4.4-A: Call/Jump 命令実装(skip_ws パターンのみ)
- Call: 末尾呼び出しのみサポート
- Jump: Multi-block CFG 生成(Branch + Return)
- 非対応パターンは unimplemented!() で落とす

### S-4.4-B: A/B テスト作成
- src/tests/joinir_vm_bridge_skip_ws.rs 作成(104行)
- Route A: 直接 VM 実行
- Route C: JoinIR → VM bridge 経由
- skip_ws("   abc") → 3 の A/B 比較実装

## 戦略転換

ChatGPT 先生 + Task 先生の分析により、**Approach 2 (JoinIR Runner 本線化 + ガードレール)** への移行が決定。

本ブリッジ実装は参考実装として保持し、これ以上は太らせない方針。次フェーズで JoinIR Runner を method_router 経由で Rust VM と統合する。
2025-11-24 07:24:42 +09:00