Phase v2-B loopform.hako 完全実装: 【実装】 - loopform.hako (258行): 6-block LoopForm 完全実装 - Header PHI: incoming 配列 + computed フラグ - Dispatch PHI (tag/payload): break/continue 処理 - Condition: MIR/Payload/Guard 全モード対応 - Safepoint: GC 安全点統合 - builder.hako (392行): 9 LLVM instructions 統合 - instructions/*.hako (9ファイル): 全命令実装 【テスト】 - Unit test: test_basic.hako (4 tests, 159行) - Smoke tests (3本, 130行): - while_simple.hako: 基本 while ループ - for_counter.hako: payload mode カウンタ - if_loop_merge.hako: 複合制御フロー + guard 【進捗】 - Stage 1: スケルトン実装 ✅ - Stage 2: PHI incoming 配列化 ✅ - Stage 3: Safepoint & Condition ✅ (Stage 1に含む) - Stage 4: スモークテスト3本 ✅ 【成果】 - 実装: 258行 (Python 224行 + 機能拡張) - テスト: 289行 (unit 159行 + smoke 130行) - ビルド: 成功 (0 errors) 次: Phase v2-C MIR Call 統合 + C++ backend 実装 Ref: docs/private/roadmap/phases/phase-33/PHASE_V2_LOOPFORM_*.md
224 lines
6.2 KiB
Plaintext
224 lines
6.2 KiB
Plaintext
// LoopForm Instruction Box - Unit Test
|
||
// Stage 1: Basic LoopForm generation
|
||
// Stage 2: PHI incoming arrays + computed flags
|
||
|
||
using "lang/src/llvm_ir/instructions/loopform.hako" as LoopFormInst
|
||
|
||
static box Main {
|
||
main() {
|
||
print("=== LoopForm Instruction Unit Test (Stage 1 + 2) ===")
|
||
|
||
// Test 1: 基本的な LoopForm 命令生成
|
||
me.test_basic_loopform()
|
||
|
||
// Test 2: Blocks 検証
|
||
me.test_blocks_validation()
|
||
|
||
// Test 3: Condition モード
|
||
me.test_condition_modes()
|
||
|
||
// Test 4: PHI incoming 配列検証(Stage 2)
|
||
me.test_phi_incoming_arrays()
|
||
|
||
print("=== All Tests Passed! ===")
|
||
return 0
|
||
}
|
||
|
||
// Test 1: 基本的な LoopForm 命令生成
|
||
test_basic_loopform() {
|
||
print("\n[Test 1] Basic LoopForm generation")
|
||
|
||
// Blocks マップを作成
|
||
local blocks = new MapBox()
|
||
blocks.set("preheader", 10)
|
||
blocks.set("header", 11)
|
||
blocks.set("body", 12)
|
||
blocks.set("dispatch", 13)
|
||
blocks.set("latch", 14)
|
||
blocks.set("exit", 15)
|
||
|
||
// Options (null でデフォルト使用)
|
||
local options = null
|
||
|
||
local result = LoopFormInst.lower_loopform(1, blocks, 5, options)
|
||
|
||
// 期待値: {"op":"loopform","loop_id":1,"blocks":{...},...}
|
||
print("Generated: " + result)
|
||
|
||
// 簡易検証: "loopform" が含まれているか
|
||
local contains_op = result.indexOf("loopform")
|
||
if contains_op < 0 {
|
||
print("ERROR: loopform op not found")
|
||
return 1
|
||
}
|
||
|
||
// "loop_id":1 が含まれているか
|
||
local contains_id = result.indexOf("\"loop_id\":1")
|
||
if contains_id < 0 {
|
||
print("ERROR: loop_id not found")
|
||
return 1
|
||
}
|
||
|
||
// "blocks" が含まれているか
|
||
local contains_blocks = result.indexOf("\"blocks\"")
|
||
if contains_blocks < 0 {
|
||
print("ERROR: blocks not found")
|
||
return 1
|
||
}
|
||
|
||
// "header":11 が含まれているか
|
||
local contains_header = result.indexOf("\"header\":11")
|
||
if contains_header < 0 {
|
||
print("ERROR: header block not found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: Basic LoopForm generation")
|
||
return 0
|
||
}
|
||
|
||
// Test 2: Blocks 検証
|
||
test_blocks_validation() {
|
||
print("\n[Test 2] Blocks validation")
|
||
|
||
local blocks = new MapBox()
|
||
blocks.set("preheader", 20)
|
||
blocks.set("header", 21)
|
||
blocks.set("body", 22)
|
||
blocks.set("dispatch", 23)
|
||
blocks.set("latch", 24)
|
||
blocks.set("exit", 25)
|
||
|
||
local options = null
|
||
local result = LoopFormInst.lower_loopform(2, blocks, 10, options)
|
||
|
||
// 全ブロックIDが含まれているか確認
|
||
local has_preheader = result.indexOf("\"preheader\":20")
|
||
local has_header = result.indexOf("\"header\":21")
|
||
local has_body = result.indexOf("\"body\":22")
|
||
local has_dispatch = result.indexOf("\"dispatch\":23")
|
||
local has_latch = result.indexOf("\"latch\":24")
|
||
local has_exit = result.indexOf("\"exit\":25")
|
||
|
||
if has_preheader < 0 || has_header < 0 || has_body < 0 ||
|
||
has_dispatch < 0 || has_latch < 0 || has_exit < 0 {
|
||
print("ERROR: Not all blocks found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: Blocks validation")
|
||
return 0
|
||
}
|
||
|
||
// Test 3: Condition モード
|
||
test_condition_modes() {
|
||
print("\n[Test 3] Condition modes")
|
||
|
||
local blocks = new MapBox()
|
||
blocks.set("preheader", 30)
|
||
blocks.set("header", 31)
|
||
blocks.set("body", 32)
|
||
blocks.set("dispatch", 33)
|
||
blocks.set("latch", 34)
|
||
blocks.set("exit", 35)
|
||
|
||
// Test 3a: MIR モード(デフォルト)
|
||
local options_mir = new MapBox()
|
||
options_mir.set("mode", "mir")
|
||
|
||
local result_mir = LoopFormInst.lower_loopform(3, blocks, 15, options_mir)
|
||
|
||
local has_mir_mode = result_mir.indexOf("\"mode\":\"mir\"")
|
||
if has_mir_mode < 0 {
|
||
print("ERROR: MIR mode not found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: MIR mode")
|
||
|
||
// Test 3b: Payload モード(実験的)
|
||
local options_payload = new MapBox()
|
||
options_payload.set("mode", "payload")
|
||
options_payload.set("payload_max", 500000)
|
||
|
||
local result_payload = LoopFormInst.lower_loopform(4, blocks, 20, options_payload)
|
||
|
||
local has_payload_mode = result_payload.indexOf("\"mode\":\"payload\"")
|
||
if has_payload_mode < 0 {
|
||
print("ERROR: Payload mode not found")
|
||
return 1
|
||
}
|
||
|
||
local has_max = result_payload.indexOf("\"payload_max\":500000")
|
||
if has_max < 0 {
|
||
print("ERROR: payload_max not found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: Payload mode")
|
||
|
||
return 0
|
||
}
|
||
|
||
// Test 4: PHI incoming 配列検証(Stage 2)
|
||
test_phi_incoming_arrays() {
|
||
print("\n[Test 4] PHI incoming arrays (Stage 2)")
|
||
|
||
local blocks = new MapBox()
|
||
blocks.set("preheader", 40)
|
||
blocks.set("header", 41)
|
||
blocks.set("body", 42)
|
||
blocks.set("dispatch", 43)
|
||
blocks.set("latch", 44)
|
||
blocks.set("exit", 45)
|
||
|
||
local options = null
|
||
local result = LoopFormInst.lower_loopform(5, blocks, 25, options)
|
||
|
||
// Test 4a: Header PHI incoming 配列検証
|
||
// Expected: {"dst":0,"incoming":[{"value":0,"block":40},{"value":0,"block":44,"computed":true}]}
|
||
local has_header_phi_incoming = result.indexOf("\"header_phi\"")
|
||
if has_header_phi_incoming < 0 {
|
||
print("ERROR: header_phi not found")
|
||
return 1
|
||
}
|
||
|
||
local has_incoming_array = result.indexOf("\"incoming\":[")
|
||
if has_incoming_array < 0 {
|
||
print("ERROR: incoming array not found")
|
||
return 1
|
||
}
|
||
|
||
local has_preheader_incoming = result.indexOf("{\"value\":0,\"block\":40}")
|
||
if has_preheader_incoming < 0 {
|
||
print("ERROR: preheader incoming not found")
|
||
return 1
|
||
}
|
||
|
||
local has_latch_incoming = result.indexOf("{\"value\":0,\"block\":44,\"computed\":true}")
|
||
if has_latch_incoming < 0 {
|
||
print("ERROR: latch incoming with computed flag not found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: Header PHI incoming array")
|
||
|
||
// Test 4b: Dispatch PHI computed フラグ検証
|
||
local has_dispatch_phis = result.indexOf("\"dispatch_phis\"")
|
||
if has_dispatch_phis < 0 {
|
||
print("ERROR: dispatch_phis not found")
|
||
return 1
|
||
}
|
||
|
||
local has_payload_computed = result.indexOf("{\"value\":0,\"block\":42,\"computed\":true}")
|
||
if has_payload_computed < 0 {
|
||
print("ERROR: payload PHI computed flag not found")
|
||
return 1
|
||
}
|
||
|
||
print("✓ PASS: Dispatch PHI computed flags")
|
||
|
||
return 0
|
||
}
|
||
}
|