🚀 Break/Continue/Try-Catch構文のサポート追加とMIRループ制御強化
## 主な変更点 ### 🎯 MIRループ制御の実装(根治対応) - src/mir/loop_builder.rs: Break/Continue対応のループコンテキスト管理 - ループのbreak/continueターゲットブロック追跡 - ネストループの適切な処理 - src/mir/builder.rs: Break/Continue文のMIR生成実装 - src/tokenizer.rs: Break/Continue/Tryトークン認識追加 ### 📝 セルフホストパーサーの拡張 - apps/selfhost-compiler/boxes/parser_box.nyash: - Stage-3: break/continue構文受理(no-op実装) - Stage-3: try-catch-finally構文受理(構文解析のみ) - エラー処理構文の将来対応準備 ### 📚 ドキュメント更新 - 論文K(爆速事件簿): 45事例に更新(4件追加) - PyVM迂回路の混乱事件 - Break/Continue無限ループ事件 - EXE-first戦略の再発見 - 論文I(開発秘話): Day 38の重要決定追加 ### 🧪 テストケース追加 - apps/tests/: ループ制御とPHIのテストケース - nested_loop_inner_break_isolated.nyash - nested_loop_inner_continue_isolated.nyash - loop_phi_one_sided.nyash - shortcircuit関連テスト ## 技術的詳細 - Break/ContinueをMIRレベルで適切に処理 - 無限ループ問題(CPU 99.9%暴走)の根本解決 - 将来の例外処理機能への準備 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
78
src/tests/mir_controlflow_extras.rs
Normal file
78
src/tests/mir_controlflow_extras.rs
Normal file
@ -0,0 +1,78 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parser::NyashParser;
|
||||
use crate::backend::VM;
|
||||
|
||||
fn run(code: &str) -> String {
|
||||
let ast = NyashParser::parse_from_string(code).expect("parse");
|
||||
let mut compiler = crate::mir::MirCompiler::new();
|
||||
let result = compiler.compile(ast).expect("compile");
|
||||
let mut vm = VM::new();
|
||||
let out = vm.execute_module(&result.module).expect("vm exec");
|
||||
out.to_string_box().value
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phi_merge_then_only_assignment() {
|
||||
let code = r#"
|
||||
local x = 5
|
||||
if 1 < 2 { x = 7 } else { }
|
||||
return x
|
||||
"#;
|
||||
assert_eq!(run(code), "7");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phi_merge_else_only_assignment() {
|
||||
let code = r#"
|
||||
local y = 5
|
||||
if 2 < 1 { y = 7 } else { }
|
||||
return y
|
||||
"#;
|
||||
assert_eq!(run(code), "5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shortcircuit_and_skips_rhs_side_effect() {
|
||||
let code = r#"
|
||||
local x = 0
|
||||
((x = x + 1) < 0) && ((x = x + 1) < 0)
|
||||
return x
|
||||
"#;
|
||||
// LHS false ⇒ RHS not evaluated ⇒ x == 1
|
||||
assert_eq!(run(code), "1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shortcircuit_or_skips_rhs_side_effect() {
|
||||
let code = r#"
|
||||
local x = 0
|
||||
((x = x + 1) >= 0) || ((x = x + 1) < 0)
|
||||
return x
|
||||
"#;
|
||||
// LHS true ⇒ RHS not evaluated ⇒ x == 1
|
||||
assert_eq!(run(code), "1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_loops_break_continue_mixed() {
|
||||
let code = r#"
|
||||
local i = 0
|
||||
local s = 0
|
||||
loop(i < 3) {
|
||||
local j = 0
|
||||
loop(j < 4) {
|
||||
j = j + 1
|
||||
if j == 1 { continue }
|
||||
if j == 3 { break }
|
||||
s = s + 1
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
return s
|
||||
"#;
|
||||
// For each i: j=1 continue (skip s), j=2 => s++, then j=3 break ⇒ s increments once per outer iter ⇒ 3
|
||||
assert_eq!(run(code), "3");
|
||||
}
|
||||
}
|
||||
|
||||
60
src/tests/mir_ctrlflow_break_continue.rs
Normal file
60
src/tests/mir_ctrlflow_break_continue.rs
Normal file
@ -0,0 +1,60 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parser::NyashParser;
|
||||
use crate::backend::VM;
|
||||
|
||||
#[test]
|
||||
fn vm_exec_simple_break() {
|
||||
let code = r#"
|
||||
loop(1) {
|
||||
break
|
||||
}
|
||||
return 1
|
||||
"#;
|
||||
let ast = NyashParser::parse_from_string(code).expect("parse");
|
||||
let mut compiler = crate::mir::MirCompiler::new();
|
||||
let result = compiler.compile(ast).expect("compile");
|
||||
let mut vm = VM::new();
|
||||
let out = vm.execute_module(&result.module).expect("vm exec");
|
||||
assert_eq!(out.to_string_box().value, "1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vm_exec_continue_skips_body() {
|
||||
let code = r#"
|
||||
local i = 0
|
||||
local s = 0
|
||||
loop(i < 5) {
|
||||
i = i + 1
|
||||
if i == 3 { continue }
|
||||
s = s + 1
|
||||
}
|
||||
return s
|
||||
"#;
|
||||
let ast = NyashParser::parse_from_string(code).expect("parse");
|
||||
let mut compiler = crate::mir::MirCompiler::new();
|
||||
let result = compiler.compile(ast).expect("compile");
|
||||
let mut vm = VM::new();
|
||||
let out = vm.execute_module(&result.module).expect("vm exec");
|
||||
assert_eq!(out.to_string_box().value, "4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vm_exec_break_inside_if() {
|
||||
let code = r#"
|
||||
local i = 0
|
||||
loop(i < 10) {
|
||||
if i == 3 { break }
|
||||
i = i + 1
|
||||
}
|
||||
return i
|
||||
"#;
|
||||
let ast = NyashParser::parse_from_string(code).expect("parse");
|
||||
let mut compiler = crate::mir::MirCompiler::new();
|
||||
let result = compiler.compile(ast).expect("compile");
|
||||
let mut vm = VM::new();
|
||||
let out = vm.execute_module(&result.module).expect("vm exec");
|
||||
assert_eq!(out.to_string_box().value, "3");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user