feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論

**Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring
呼び出しを通すことに成功。

## 主要変更

### 1. MethodCall 構造追加 (34-6.1)
- `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines)
  - 構造: `{ dst, receiver, method, args }`
  - 設計原則: JoinIR は構造のみ、意味論は MIR レベル

### 2. extract_value 更新 (34-6.2)
- `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines)
  - receiver/args を extract_value で再帰処理
  - ダミー Const(0) 削除 → 本物の MethodCall 生成
  - cond 処理修正: ValueId(0) ハードコード → extract_value で取得

### 3. JoinIR→MIR 変換実装 (34-6.3)
- `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines)
- `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines)
- `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines)

### 4. テスト更新 (34-6.4)
- `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造
- `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用
- テスト成功: v="hello", at=3 → "hel" 

## 成果

-  テスト全通過(1 passed; 0 failed)
-  設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル
-  Phase 33-10 原則との整合性: Method でも同じ原則適用

**ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-27 17:05:46 +09:00
parent 6a5701ead9
commit 588129db65
15 changed files with 1891 additions and 69 deletions

View File

@ -142,6 +142,44 @@ fn write_inst<W: Write>(inst: &JoinInst, out: &mut W) -> std::io::Result<()> {
write!(out, ",\"else_val\":{}", else_val.0)?;
write!(out, "}}")?;
}
// Phase 33-6: IfMerge instruction JSON serialization
JoinInst::IfMerge { cond, merges, k_next } => {
write!(out, "{{\"type\":\"if_merge\"")?;
write!(out, ",\"cond\":{}", cond.0)?;
write!(out, ",\"merges\":[")?;
for (i, merge) in merges.iter().enumerate() {
if i > 0 {
write!(out, ",")?;
}
write!(out, "{{")?;
write!(out, "\"dst\":{}", merge.dst.0)?;
write!(out, ",\"then_val\":{}", merge.then_val.0)?;
write!(out, ",\"else_val\":{}", merge.else_val.0)?;
write!(out, "}}")?;
}
write!(out, "]")?;
match k_next {
Some(k) => write!(out, ",\"k_next\":{}", k.0)?,
None => write!(out, ",\"k_next\":null")?,
}
write!(out, "}}")?;
}
// Phase 34-6: MethodCall instruction JSON serialization
JoinInst::MethodCall { dst, receiver, method, args } => {
write!(out, "{{\"type\":\"method_call\"")?;
write!(out, ",\"dst\":{}", dst.0)?;
write!(out, ",\"receiver\":{}", receiver.0)?;
write!(out, ",\"method\":\"{}\"", escape_json_string(method))?;
write!(out, ",\"args\":[")?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(out, ",")?;
}
write!(out, "{}", arg.0)?;
}
write!(out, "]")?;
write!(out, "}}")?;
}
JoinInst::Compute(mir_like) => {
write!(out, "{{\"type\":\"compute\",\"op\":")?;
write_mir_like_inst(mir_like, out)?;
@ -270,7 +308,7 @@ pub fn join_module_to_json_string(module: &JoinModule) -> String {
#[cfg(test)]
mod tests {
use super::*;
use crate::mir::join_ir::{JoinContId, JoinFuncId};
use crate::mir::join_ir::{JoinContId, JoinFuncId, MergePair};
use crate::mir::ValueId;
#[test]
@ -404,4 +442,44 @@ mod tests {
assert!(json.contains("\\n"));
assert!(json.contains("\\\""));
}
// Phase 33-6: IfMerge instruction JSON serialization test
#[test]
fn test_if_merge_instruction() {
let mut module = JoinModule::new();
let mut func = JoinFunction::new(JoinFuncId::new(0), "main".to_string(), vec![]);
// Add IfMerge instruction with 2 merge pairs
func.body.push(JoinInst::IfMerge {
cond: ValueId(1),
merges: vec![
MergePair {
dst: ValueId(10),
then_val: ValueId(20),
else_val: ValueId(30),
},
MergePair {
dst: ValueId(11),
then_val: ValueId(21),
else_val: ValueId(31),
},
],
k_next: None,
});
module.add_function(func);
let json = join_module_to_json_string(&module);
// Verify JSON structure
assert!(json.contains("\"type\":\"if_merge\""));
assert!(json.contains("\"cond\":1"));
assert!(json.contains("\"merges\":["));
assert!(json.contains("\"dst\":10"));
assert!(json.contains("\"then_val\":20"));
assert!(json.contains("\"else_val\":30"));
assert!(json.contains("\"dst\":11"));
assert!(json.contains("\"then_val\":21"));
assert!(json.contains("\"else_val\":31"));
assert!(json.contains("\"k_next\":null"));
}
}