Files
hakorune/docs/development/current/main/phase230-expr-lowering-inventory.md
nyash-codex d4f90976da refactor(joinir): Phase 244 - ConditionLoweringBox trait unification
Unify condition lowering logic across Pattern 2/4 with trait-based API.

New infrastructure:
- condition_lowering_box.rs: ConditionLoweringBox trait + ConditionContext (293 lines)
- ExprLowerer implements ConditionLoweringBox trait (+51 lines)

Pattern migrations:
- Pattern 2 (loop_with_break_minimal.rs): Use trait API
- Pattern 4 (loop_with_continue_minimal.rs): Use trait API

Benefits:
- Unified condition lowering interface
- Extensible for future lowering strategies
- Clean API boundary between patterns and lowering logic
- Zero code duplication

Test results: 911/911 PASS (+2 new tests)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 02:35:31 +09:00

120 lines
6.9 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.

# Phase 230: Expr Lowering Inventory
このメモは、既存の式 lowering がどこに散らばっているかを棚卸しするためのインベントリだよ。
Phase 230 では「コードをいじらずに把握だけする」のが目的。
---
## 1. condition_to_joinir.rs / condition_lowerer.rs
- 役割:
- ループの条件式header 条件 / break 条件)を AST → JoinIR の Compare/BinOp/UnaryOp 列に落とす高レベル入口。
- `ConditionEnv` を使って「変数名 → JoinIR ValueId」の解決を行う。
- 主な機能:
- `lower_condition_to_joinir(ast, alloc_value, &ConditionEnv)`:
- 二項比較(`var < literal`, `var == var`)を JoinIR Compare に lowering。
- `ConditionPatternBox` による正規化後の単純条件を対象。
- `lower_value_expression(ast, alloc_value, &ConditionEnv, &mut instructions)`:
- 条件式の内部で出てくるサブ式(`i+1`, `s.length()`, `digits.indexOf(ch)` など)を JoinIR 値に潰す。
- `MethodCallLowerer` を経由してメソッド呼び出しを BoxCall に変換。
- 制約:
- JoinIR 専用MirBuilder には触らない)。
- 変数解決は ConditionEnv に限定LoopBodyLocalEnv や UpdateEnv には直接アクセスしない)。
- support 対象外の AST ノードは Fail-Fast`Result::Err`)で返す。
---
## 2. bool_expr_lowerer.rs
- 役割:
- 「MIR 向け」の boolean 式 loweringAST → MirBuilder / SSAを行う旧来の箱。
- OR チェーンや `&&`/`||`/`!` を MIR の Compare / BinOp / UnaryOp に展開する。
- 主な機能:
- `BoolExprLowerer::lower_condition(&ASTNode) -> Result<ValueId, String>`:
- BinaryOp比較演算子 + `&&`/`||`を再帰的に潰し、MirInstruction を emit。
- 変数・リテラル・メソッド呼び出しなどは MirBuilder の `build_expression` に委譲。
- 制約:
- MirBuilder 前提の API で、JoinIR condition_to_joinir とは別ライン。
- 現時点では「ほぼ未使用(テストもコメントアウト)」扱いの歴史的モジュール。
- condition_to_joinir 側と直接の接点はなく、将来 ExprLowerer に統合する際の候補。
---
## 3. loop_body_local_init.rsLoopBodyLocalInitLowerer
- 役割:
- ループ本体の `local` 宣言の初期化式を AST → JoinIR に落として `LoopBodyLocalEnv` に格納する。
- 「body-local 変数の定義側init」専用の lowering。
- 主な機能:
- `lower_inits_for_loop(body_ast, &mut LoopBodyLocalEnv)`:
- ループ本体 AST から `ASTNode::Local` をスキャンし、各変数の init 式を順番に処理。
- `lower_init_expr(expr, &LoopBodyLocalEnv) -> Result<ValueId, String>`:
- リテラル(整数/文字列)→ Const
- 変数参照 → ConditionEnv 経由で解決
- 二項演算(`+ - * /`)→ BinOp
- MethodCall`s.substring`, `digits.indexOf`)→ `emit_method_call_init` 経由で MethodCallLowerer に委譲
- 制約:
- 変数解決は ConditionEnv + 既存の LoopBodyLocalEnvcascadingのみ。
- サポート外のリテラル種別・演算子・複雑な式は Fail-Fast。
- lowering 対象は「init 式」だけで、更新式UpdateExprは別の箱CarrierUpdateEmitterが担当。
---
## 4. method_call_lowerer.rsMethodCallLowerer
- 役割:
- MethodCall AST ノードを CoreMethodId メタデータに基づいて JoinIR BoxCall に lowering する箱。
- 同じメソッド呼び出しでも「条件文から使うか」「init から使うか」でホワイトリストを分けている。
- 主な機能:
- `lower_for_condition(recv_val, method_name, args, alloc, &ConditionEnv, &mut instructions)`:
- `allowed_in_condition()` に通る CoreMethodId だけ許可(例: `length`, 一部の `indexOf`)。
- 引数は `condition_lowerer::lower_value_expression` で JoinIR 値に lowering。
- `lower_for_init(recv_val, method_name, args, alloc, &ConditionEnv, &LoopBodyLocalEnv, &mut instructions)`:
- `allowed_in_init()` に通るメソッド(`substring`, `indexOf` など)を body-local init 用に lowering。
- 引数の変数は LoopBodyLocalEnv → ConditionEnv の優先順で解決cascading local をサポート)。
- `lower_arg_with_cascading`:
- 引数用の小さなヘルパー。変数なら LoopBodyLocalEnv/ConditionEnv を見て、それ以外は condition_lowerer に委譲。
- 制約:
- CoreMethodId メタデータが前提(メソッド名や Box 名のハードコード禁止)。
- 文脈condition/initごとに別 API で呼び分ける必要がある。
- 型情報は暗黙的CoreMethodId 側に埋め込まれており、TypeContext のような統一ビューはまだない)。
---
## 5. carrier_update_emitter.rsCarrierUpdateEmitter
- 役割:
- LoopUpdateAnalyzer で分類された UpdateExpr`sum = sum + digit` など)を JoinIR 命令列に変換する。
- 「キャリア更新の右辺式」を安全なパターンだけ受理して lowering するホワイトリスト箱。
- 主な機能:
- `emit_carrier_update_with_env(carrier, &UpdateExpr, alloc, &UpdateEnv, &mut instructions)`:
- `UpdateRhs::Const` → Const + BinOp(Add/Mul)。
- `UpdateRhs::Variable` → UpdateEnv.resolve(name) 経由で条件変数・body-local を横断解決。
- `UpdateRhs::StringLiteral` → Const(String)。
- `UpdateRhs::NumberAccumulation` → base/digit 組み合わせを Mul + Add の2段構成で emit。
- `emit_carrier_update`(レガシー):
- ConditionEnv ベースの旧 APIbody-local 非対応)を後方互換のために残している。
- 制約:
- lowering 対象は「UpdateExpr に正規化済みの式」に限る(生 AST は扱わない)。
- `UpdateRhs::Other` や method call を含む複雑な更新は can_lower() 側で reject される前提。
- 型は整数/String の一部パターンに限定TypeContext への統合は未実施)。
---
## 6. 小まとめPhase 230 時点の散らばり方)
- 「条件式」と「init/body-local」と「UpdateExpr」が、それぞれ別の箱で AST / 中間表現を潰している:
- 条件式: `condition_to_joinir` + `condition_lowerer`+ 一部 BoolExprLowerer/MIR 側)
- body-local init: `LoopBodyLocalInitLowerer` + `MethodCallLowerer(lower_for_init)`
- carrier 更新: `CarrierUpdateEmitter` + `UpdateEnv`UpdateExpr ベース)
- 変数解決も 3 系統に分かれている:
- `ConditionEnv`loop param / captured / condition-only
- `LoopBodyLocalEnv`body 内 `local`
- `UpdateEnv`ConditionEnv + LoopBodyLocalEnv の合成ビュー)
- 将来の ExprLowerer/ScopeManager では、これらを
- 「式 lowering の SSOT」として ExprLowerer
- 「名前解決の SSOT」として ScopeManager
に段階統合していくのがターゲット、という整理になっているよ。
Status: Active
Scope: Expr Lowering 在庫JoinIR/ExprLowerer ライン)