ast_lowerer.rs → ast_lowerer/ (10 files): - mod.rs: public surface + entry dispatch - context.rs: ExtractCtx helpers - expr.rs: expression-to-JoinIR extraction - if_return.rs: simple if→Select lowering - loop_patterns.rs: loop variants (simple/break/continue) - read_quoted.rs: read_quoted_from lowering (Phase 45-46) - nested_if.rs: NestedIfMerge lowering - analysis.rs: loop if-var analysis + metadata helpers - tests.rs: frontend lowering tests - README.md: module documentation join_ir_vm_bridge.rs → join_ir_vm_bridge/ (5 files): - mod.rs: public surface + shared helpers - convert.rs: JoinIR→MIR lowering - runner.rs: VM execution entry (run_joinir_via_vm) - meta.rs: experimental metadata-aware hooks - tests.rs: bridge-specific unit tests - README.md: module documentation Benefits: - Clear separation of concerns per pattern - Easier navigation and maintenance - Each file has single responsibility - README documents module boundaries Co-authored-by: ChatGPT <noreply@openai.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
131 lines
4.8 KiB
Rust
131 lines
4.8 KiB
Rust
//! JoinIR Frontend — IfSelect A/B Test (Phase 34-2)
|
||
//!
|
||
//! Route A: 既存経路(AST→MIR→PHI→VM)
|
||
//! Route B: 新経路(AST→JoinIR→MIR'→VM)
|
||
|
||
use crate::mir::join_ir_ops::JoinValue;
|
||
use crate::tests::helpers::joinir_frontend::JoinIrFrontendTestRunner;
|
||
|
||
/// Phase 34-2: IfSelect simple pattern の A/B テスト
|
||
///
|
||
/// 入力: `fixtures/joinir_if_select_simple.program.json`
|
||
/// パターン: `if cond { return 10 } else { return 20 }`
|
||
/// 期待: Route A と Route B の結果が一致
|
||
#[test]
|
||
fn joinir_frontend_if_select_simple_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/joinir_if_select_simple.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(vec![JoinValue::Int(1)], JoinValue::Int(10)),
|
||
(vec![JoinValue::Int(0)], JoinValue::Int(20)),
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|
||
|
||
/// Phase 34-3: IfSelect local pattern の A/B テスト
|
||
///
|
||
/// 入力: `fixtures/joinir_if_select_local.program.json`
|
||
/// パターン: `if cond { x=10 } else { x=20 }; return x` (意味論的)
|
||
/// 期待: simple と同じ JoinIR 出力(Select ベース)
|
||
#[test]
|
||
fn joinir_frontend_if_select_local_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/joinir_if_select_local.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(vec![JoinValue::Int(1)], JoinValue::Int(10)),
|
||
(vec![JoinValue::Int(0)], JoinValue::Int(20)),
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|
||
|
||
/// Phase 34-6: JsonShapeToMap._read_value_from_pair/1 の完全実装テスト
|
||
///
|
||
/// 入力: `fixtures/json_shape_read_value.program.json`
|
||
/// パターン: `if at { return v.substring(0, at) } else { return v }`
|
||
/// 期待: 本物の substring 呼び出しが JoinIR MethodCall → MIR BoxCall で実行される
|
||
#[test]
|
||
fn joinir_frontend_json_shape_read_value_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/json_shape_read_value.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(
|
||
vec![JoinValue::Str("hello".to_string()), JoinValue::Int(3)],
|
||
JoinValue::Str("hel".to_string()),
|
||
),
|
||
(
|
||
vec![JoinValue::Str("world".to_string()), JoinValue::Int(0)],
|
||
JoinValue::Str("world".to_string()),
|
||
),
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|
||
|
||
/// Phase 34-7: tiny while loop の A/B テスト
|
||
///
|
||
/// 入力: `fixtures/loop_frontend_simple.program.json`
|
||
/// パターン: `local i = 0; local acc = 0; loop(i < n) { acc = acc + 1; i = i + 1; } return acc`
|
||
/// 期待: Case-A な JoinIR (entry → loop_step → return) が生成され、正しく実行される
|
||
#[test]
|
||
fn joinir_frontend_loop_simple_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/loop_frontend_simple.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(vec![JoinValue::Int(0)], JoinValue::Int(0)),
|
||
(vec![JoinValue::Int(3)], JoinValue::Int(3)),
|
||
(vec![JoinValue::Int(5)], JoinValue::Int(5)),
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|
||
|
||
/// Phase 34-8: Break pattern の A/B テスト
|
||
///
|
||
/// 入力: `fixtures/loop_frontend_break.program.json`
|
||
/// パターン: `loop { if i >= n { break }; acc = acc + i; i = i + 1 }`
|
||
/// 期待: n=5 → acc=10 (0+1+2+3+4)
|
||
#[test]
|
||
fn joinir_frontend_loop_break_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/loop_frontend_break.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(vec![JoinValue::Int(0)], JoinValue::Int(0)), // n=0 → 0
|
||
(vec![JoinValue::Int(5)], JoinValue::Int(10)), // n=5 → 10 (0+1+2+3+4)
|
||
(vec![JoinValue::Int(3)], JoinValue::Int(3)), // n=3 → 3 (0+1+2)
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|
||
|
||
/// Phase 34-8: Continue pattern の A/B テスト
|
||
///
|
||
/// 入力: `fixtures/loop_frontend_continue.program.json`
|
||
/// パターン: `loop { i = i + 1; if i == 3 { continue }; acc = acc + i }`
|
||
/// 期待: n=5 → acc=12 (1+2+4+5, i==3 スキップ)
|
||
#[test]
|
||
fn joinir_frontend_loop_continue_ab_test() {
|
||
JoinIrFrontendTestRunner::from_fixture(
|
||
"docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/loop_frontend_continue.program.json"
|
||
)
|
||
.lower()
|
||
.expect("Failed to lower fixture")
|
||
.run_cases(&[
|
||
(vec![JoinValue::Int(0)], JoinValue::Int(0)), // n=0 → 0
|
||
(vec![JoinValue::Int(5)], JoinValue::Int(12)), // n=5 → 12 (1+2+4+5)
|
||
(vec![JoinValue::Int(2)], JoinValue::Int(3)), // n=2 → 3 (1+2)
|
||
])
|
||
.expect("Test cases failed");
|
||
}
|