# Nyash言語 マスターリファクタリング計画 **Version**: 1.0 **Date**: 2025-09-20 **Status**: 実行準備完了 **Duration**: 13-18週間(約3-4ヶ月) **Scope**: JIT Cranelift除外、根本品質重視の統一化 ## 🎯 戦略概要 ### 核心原則 - **Progressive Unification**: 段階的統一による安全な移行 - **Fundamentals First**: 80/20回避、根本からの品質構築 - **Reference Integrity**: PyVMを品質保証の参照点として維持 - **Non-Destructive**: 既存安定機能の破壊を避ける ### 現状の問題構造 ``` 現在の混在状態: ├── Rust VM (Legacy) - 部分的実装、不安定 ├── Python PyVM - 参照実装、安定稼働 ├── MIR Interpreter - 最小実装 ├── JIT Cranelift - 【除外対象】 └── Mini-VM (Nyash) - 開発中、将来の統一目標 ``` ### 目標アーキテクチャ ``` 統一後の構造: ├── Unified VM Interface │ ├── PyVM Backend (Reference) │ ├── Nyash VM Backend (Primary) │ └── MIR Interpreter Backend (Debug) ├── Common Entry Resolution ├── Unified Control Flow ├── Type Safety Layer └── Single Macro Expansion Path ``` --- ## 📋 Phase 1: VM Core統一 (4-6週間) ### 🎯 Phase 1 目標 **「3つのVM実装を統一インターフェースで管理し、段階的にNyash VMに移行する基盤を確立」** ### Step 1.1: PyVM機能完全化 (Week 1-2) #### **実装対象** ```python # src/llvm_py/pyvm/vm_enhanced.py class EnhancedPyVM: def __init__(self): self.nested_function_handler = NestedFunctionHandler() self.control_flow_manager = ControlFlowManager() self.scope_boundary_tracker = ScopeBoundaryTracker() def execute_with_nested_functions(self, mir_module): # ネスト関数の自動リフト処理 lifted_module = self.nested_function_handler.lift_nested_functions(mir_module) return self.execute_standard(lifted_module) def handle_break_continue(self, instruction, context): # Box境界を跨ぐbreak/continue の安全処理 if context.is_box_boundary(): return self.control_flow_manager.handle_box_boundary_control(instruction, context) return self.control_flow_manager.handle_standard_control(instruction, context) ``` #### **ネスト関数リフト機能** ```python class NestedFunctionHandler: def lift_nested_functions(self, mir_module): """ function outer() { function inner() { return 42; } // ← これを自動リフト return inner(); } ↓ 変換後 function _lifted_inner_123() { return 42; } function outer() { return _lifted_inner_123(); } """ lifted_functions = [] for func in mir_module.functions: nested_funcs, cleaned_func = self.extract_nested_functions(func) lifted_functions.extend(nested_funcs) lifted_functions.append(cleaned_func) return MirModule(functions=lifted_functions) def extract_nested_functions(self, function): # 関数内の function 宣言を検出・抽出 # gensym による名前生成(衝突回避) # 呼び出し箇所を生成された名前に置換 pass ``` #### **制御フロー強化** ```python class ControlFlowManager: def __init__(self): self.loop_stack = [] # ループコンテキストスタック self.function_stack = [] # 関数コンテキストスタック def enter_loop(self, loop_id, break_target, continue_target): self.loop_stack.append({ 'id': loop_id, 'break_target': break_target, 'continue_target': continue_target, 'in_box_method': self.is_in_box_method() }) def handle_break(self, instruction): if not self.loop_stack: raise RuntimeError("break outside of loop") current_loop = self.loop_stack[-1] if current_loop['in_box_method']: # Boxメソッド内のbreak特別処理 return self.handle_box_method_break(current_loop) return self.jump_to_target(current_loop['break_target']) def handle_continue(self, instruction): if not self.loop_stack: raise RuntimeError("continue outside of loop") current_loop = self.loop_stack[-1] if current_loop['in_box_method']: # Boxメソッド内のcontinue特別処理 return self.handle_box_method_continue(current_loop) return self.jump_to_target(current_loop['continue_target']) ``` #### **受け入れ基準** ```bash # テストスイート ./tools/test/phase1/pyvm_nested_functions.sh ./tools/test/phase1/pyvm_control_flow.sh ./tools/test/phase1/pyvm_box_boundaries.sh # 期待する成功例 echo 'function outer() { function inner() { return 42; } return inner(); }' | python pyvm_enhanced.py # → 出力: 42 echo 'loop(i < 10) { if (i == 5) break; i = i + 1; }' | python pyvm_enhanced.py # → 正常終了、i = 5 ``` ### Step 1.2: Unified VM Interface設計 (Week 2-3) #### **共通インターフェース実装** ```rust // src/backend/vm_unified.rs use std::collections::HashMap; #[derive(Debug, Clone)] pub struct VMResult { pub return_value: Option, pub stdout: String, pub stderr: String, pub execution_stats: VMStats, } #[derive(Debug, Clone)] pub struct VMStats { pub instructions_executed: u64, pub memory_used: usize, pub execution_time_ms: u64, pub function_calls: u64, } pub trait UnifiedVM { fn name(&self) -> &str; fn execute_mir(&mut self, module: &MirModule) -> Result; fn set_debug_mode(&mut self, enabled: bool); fn set_trace_mode(&mut self, enabled: bool); fn get_current_stats(&self) -> VMStats; fn reset_stats(&mut self); } // PyVM実装 pub struct PyVMBackend { python_path: PathBuf, debug_enabled: bool, trace_enabled: bool, stats: VMStats, } impl UnifiedVM for PyVMBackend { fn name(&self) -> &str { "PyVM" } fn execute_mir(&mut self, module: &MirModule) -> Result { // 1. MIRをJSON形式でシリアライズ let mir_json = serde_json::to_string(module)?; // 2. Python VMを呼び出し let mut cmd = Command::new("python"); cmd.arg(&self.python_path) .arg("--mode").arg("execute") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()); if self.debug_enabled { cmd.arg("--debug"); } if self.trace_enabled { cmd.arg("--trace"); } let mut child = cmd.spawn()?; child.stdin.as_mut().unwrap().write_all(mir_json.as_bytes())?; let output = child.wait_with_output()?; // 3. 結果をパース let result: VMResult = serde_json::from_slice(&output.stdout)?; self.stats = result.execution_stats.clone(); Ok(result) } fn set_debug_mode(&mut self, enabled: bool) { self.debug_enabled = enabled; } fn set_trace_mode(&mut self, enabled: bool) { self.trace_enabled = enabled; } fn get_current_stats(&self) -> VMStats { self.stats.clone() } fn reset_stats(&mut self) { self.stats = VMStats::default(); } } // Nyash VM実装(将来) pub struct NyashVMBackend { vm_script_path: PathBuf, debug_enabled: bool, interpreter: NyashInterpreter, } impl UnifiedVM for NyashVMBackend { fn name(&self) -> &str { "NyashVM" } fn execute_mir(&mut self, module: &MirModule) -> Result { // Nyashスクリプトで実装されたVMを実行 // 現在は開発中、将来的にはこれが主力 todo!("Nyash VM implementation in progress") } // ... 他のメソッド実装 } ``` #### **VM管理システム** ```rust // src/backend/vm_manager.rs pub struct VMManager { backends: HashMap>, default_backend: String, fallback_chain: Vec, } impl VMManager { pub fn new() -> Self { let mut manager = VMManager { backends: HashMap::new(), default_backend: "PyVM".to_string(), fallback_chain: vec!["PyVM".to_string(), "MIRInterpreter".to_string()], }; // 利用可能なバックエンドを登録 manager.register_backend("PyVM", Box::new(PyVMBackend::new())); manager.register_backend("MIRInterpreter", Box::new(MIRInterpreterBackend::new())); // NyashVMが利用可能な場合のみ登録 if NyashVMBackend::is_available() { manager.register_backend("NyashVM", Box::new(NyashVMBackend::new())); manager.default_backend = "NyashVM".to_string(); } manager } pub fn execute_with_fallback(&mut self, module: &MirModule) -> Result { // デフォルトバックエンドを試行 if let Some(backend) = self.backends.get_mut(&self.default_backend) { match backend.execute_mir(module) { Ok(result) => return Ok(result), Err(e) => { eprintln!("Warning: {} failed: {}", self.default_backend, e); } } } // フォールバックチェーンを順次試行 for backend_name in &self.fallback_chain { if backend_name == &self.default_backend { continue; // 既に試行済み } if let Some(backend) = self.backends.get_mut(backend_name) { match backend.execute_mir(module) { Ok(result) => { eprintln!("Fallback to {} succeeded", backend_name); return Ok(result); } Err(e) => { eprintln!("Warning: {} failed: {}", backend_name, e); } } } } Err(VMError::AllBackendsFailed) } pub fn register_backend(&mut self, name: &str, backend: Box) { self.backends.insert(name.to_string(), backend); } pub fn list_available_backends(&self) -> Vec { self.backends.keys().cloned().collect() } pub fn get_backend_stats(&self, name: &str) -> Option { self.backends.get(name).map(|b| b.get_current_stats()) } } ``` ### Step 1.3: Mini-VM段階的拡張 (Week 3-4) #### **JSON v0 完全ローダー** ```nyash // apps/selfhost/vm/json_loader.nyash static box JSONLoader { parse_mir_module(json_string: StringBox) -> MirModuleBox { local root = me.parse_json_object(json_string) local functions = new ArrayBox() local funcs_array = root.get("functions") local i = 0 loop(i < funcs_array.length()) { local func_data = funcs_array.get(i) local parsed_func = me.parse_function(func_data) functions.push(parsed_func) i = i + 1 } local module = new MirModuleBox() module.set_functions(functions) return module } parse_function(func_obj: MapBox) -> FunctionBox { local name = func_obj.get("name") local params = me.parse_parameters(func_obj.get("parameters")) local body = me.parse_basic_blocks(func_obj.get("body")) local function = new FunctionBox() function.set_name(name) function.set_parameters(params) function.set_body(body) return function } parse_basic_blocks(blocks_array: ArrayBox) -> ArrayBox { local blocks = new ArrayBox() local i = 0 loop(i < blocks_array.length()) { local block_data = blocks_array.get(i) local block = me.parse_basic_block(block_data) blocks.push(block) i = i + 1 } return blocks } parse_basic_block(block_obj: MapBox) -> BasicBlockBox { local id = block_obj.get("id") local instructions = me.parse_instructions(block_obj.get("instructions")) local block = new BasicBlockBox() block.set_id(id) block.set_instructions(instructions) return block } parse_instructions(instrs_array: ArrayBox) -> ArrayBox { local instructions = new ArrayBox() local i = 0 loop(i < instrs_array.length()) { local instr_data = instrs_array.get(i) local instruction = me.parse_instruction(instr_data) instructions.push(instruction) i = i + 1 } return instructions } parse_instruction(instr_obj: MapBox) -> InstructionBox { local opcode = instr_obj.get("opcode") local operands = instr_obj.get("operands") local instruction = new InstructionBox() instruction.set_opcode(opcode) instruction.set_operands(operands) return instruction } } ``` #### **MIR14命令完全実装** ```nyash // apps/selfhost/vm/mir_executor.nyash static box MirExecutor { stack: ArrayBox heap: MapBox call_stack: ArrayBox current_function: FunctionBox current_block: IntegerBox instruction_pointer: IntegerBox birth() { me.stack = new ArrayBox() me.heap = new MapBox() me.call_stack = new ArrayBox() me.current_block = 0 me.instruction_pointer = 0 } execute_module(module: MirModuleBox) -> VMResultBox { // エントリポイント解決 local entry_func = me.resolve_entry_point(module) // メイン実行ループ me.current_function = entry_func local result = me.execute_function(entry_func, new ArrayBox()) local vm_result = new VMResultBox() vm_result.set_return_value(result) vm_result.set_stdout(me.get_stdout()) vm_result.set_stderr(me.get_stderr()) return vm_result } execute_function(function: FunctionBox, args: ArrayBox) -> ValueBox { // 関数フレーム設定 me.push_call_frame(function, args) // 基本ブロック実行 local blocks = function.get_body() me.current_block = 0 loop(me.current_block < blocks.length()) { local block = blocks.get(me.current_block) local result = me.execute_basic_block(block) if (result.is_return()) { me.pop_call_frame() return result.get_value() } if (result.is_jump()) { me.current_block = result.get_target_block() } else { me.current_block = me.current_block + 1 } } // デフォルトリターン return new NullValueBox() } execute_basic_block(block: BasicBlockBox) -> ExecutionResultBox { local instructions = block.get_instructions() local i = 0 loop(i < instructions.length()) { local instruction = instructions.get(i) local result = me.execute_instruction(instruction) if (result.is_control_flow()) { return result } i = i + 1 } return new ContinueResultBox() } execute_instruction(instruction: InstructionBox) -> ExecutionResultBox { local opcode = instruction.get_opcode() local operands = instruction.get_operands() return peek opcode { "const" => me.execute_const(operands), "load" => me.execute_load(operands), "store" => me.execute_store(operands), "binop" => me.execute_binop(operands), "compare" => me.execute_compare(operands), "branch" => me.execute_branch(operands), "jump" => me.execute_jump(operands), "call" => me.execute_call(operands), "ret" => me.execute_ret(operands), "phi" => me.execute_phi(operands), "newbox" => me.execute_newbox(operands), "boxcall" => me.execute_boxcall(operands), "externcall" => me.execute_externcall(operands), "typeop" => me.execute_typeop(operands), else => panic("Unknown instruction: " + opcode) } } // 各命令の実装 execute_const(operands: ArrayBox) -> ExecutionResultBox { local value = operands.get(0) local target = operands.get(1) me.set_variable(target, value) return new ContinueResultBox() } execute_binop(operands: ArrayBox) -> ExecutionResultBox { local op = operands.get(0) local left = me.get_variable(operands.get(1)) local right = me.get_variable(operands.get(2)) local target = operands.get(3) local result = peek op { "add" => left + right, "sub" => left - right, "mul" => left * right, "div" => left / right, else => panic("Unknown binary operation: " + op) } me.set_variable(target, result) return new ContinueResultBox() } execute_call(operands: ArrayBox) -> ExecutionResultBox { local func_name = operands.get(0) local args = me.evaluate_arguments(operands.slice(1)) local target = operands.get_last() local function = me.resolve_function(func_name) local result = me.execute_function(function, args) me.set_variable(target, result) return new ContinueResultBox() } execute_ret(operands: ArrayBox) -> ExecutionResultBox { local value = if (operands.length() > 0) { me.get_variable(operands.get(0)) } else { new NullValueBox() } local result = new ReturnResultBox() result.set_value(value) return result } execute_branch(operands: ArrayBox) -> ExecutionResultBox { local condition = me.get_variable(operands.get(0)) local true_block = operands.get(1) local false_block = operands.get(2) local target_block = if (condition.to_boolean()) { true_block } else { false_block } local result = new JumpResultBox() result.set_target_block(target_block) return result } execute_jump(operands: ArrayBox) -> ExecutionResultBox { local target_block = operands.get(0) local result = new JumpResultBox() result.set_target_block(target_block) return result } } ``` #### **受け入れ基準** ```bash # Mini-VM基本機能テスト ./tools/test/phase1/mini_vm_basic.sh # PyVMとの出力比較テスト ./tools/test/phase1/mini_vm_vs_pyvm.sh # 期待する成功例 echo '{"functions": [{"name": "main", "body": [...]}]}' | ./mini_vm.nyash # → PyVMと同一の出力 ``` --- ## 📋 Phase 2: エントリ解決統一 (2-3週間) ### 🎯 Phase 2 目標 **「すべてのVM実装で一貫したエントリポイント解決を実現し、実行時の不整合を根絶」** ### Step 2.1: エントリ解決ライブラリ設計 (Week 1) #### **統一エントリ解決システム** ```rust // src/runtime/entry_resolver.rs use std::collections::HashMap; #[derive(Debug, Clone)] pub struct EntryResolverConfig { pub allow_toplevel_main: bool, pub strict_main_signature: bool, pub fallback_to_first_function: bool, pub require_main_box: bool, } impl Default for EntryResolverConfig { fn default() -> Self { Self { allow_toplevel_main: false, // デフォルトは strict strict_main_signature: true, fallback_to_first_function: false, require_main_box: true, } } } pub struct EntryResolver { config: EntryResolverConfig, } impl EntryResolver { pub fn new(config: EntryResolverConfig) -> Self { Self { config } } pub fn resolve_entry_point(&self, module: &MirModule) -> Result { // 1. Main.main() を最優先で検索 if let Some(func_id) = self.find_main_box_main(module) { return Ok(func_id); } // 2. 設定によってtoplevel main() を試行 if self.config.allow_toplevel_main { if let Some(func_id) = self.find_toplevel_main(module) { return Ok(func_id); } } // 3. フォールバック戦略 if self.config.fallback_to_first_function && !module.functions.is_empty() { return Ok(FunctionId(0)); } // 4. エラー Err(EntryResolutionError::NoValidEntryPoint { found_functions: self.list_available_functions(module), config: self.config.clone(), }) } fn find_main_box_main(&self, module: &MirModule) -> Option { for (i, function) in module.functions.iter().enumerate() { // "Main.main" または "main" (Boxメソッドとして) if function.name == "Main.main" || (function.is_box_method && function.name == "main" && function.box_name == Some("Main")) { if self.config.strict_main_signature { if self.validate_main_signature(function) { return Some(FunctionId(i)); } } else { return Some(FunctionId(i)); } } } None } fn find_toplevel_main(&self, module: &MirModule) -> Option { for (i, function) in module.functions.iter().enumerate() { if function.name == "main" && !function.is_box_method { if self.config.strict_main_signature { if self.validate_main_signature(function) { return Some(FunctionId(i)); } } else { return Some(FunctionId(i)); } } } None } fn validate_main_signature(&self, function: &MirFunction) -> bool { // main() または main(args: ArrayBox) を受け入れ match function.parameters.len() { 0 => true, // main() 1 => { // main(args: ArrayBox) を確認 function.parameters[0].type_hint.as_ref() .map(|t| t == "ArrayBox") .unwrap_or(true) // 型ヒントない場合は許可 } _ => false, // 2個以上の引数は不正 } } fn list_available_functions(&self, module: &MirModule) -> Vec { module.functions.iter() .map(|f| format!("{}({})", f.name, f.parameters.len())) .collect() } pub fn create_detailed_error_message(&self, error: &EntryResolutionError) -> String { match error { EntryResolutionError::NoValidEntryPoint { found_functions, config } => { let mut msg = String::new(); msg.push_str("No valid entry point found.\n\n"); msg.push_str("Expected entry points (in order of preference):\n"); if config.require_main_box { msg.push_str(" 1. static box Main { main() { ... } } (最推奨)\n"); msg.push_str(" 2. static box Main { main(args) { ... } }\n"); } if config.allow_toplevel_main { msg.push_str(" 3. function main() { ... } (非推奨)\n"); msg.push_str(" 4. function main(args) { ... }\n"); } msg.push_str("\nFound functions:\n"); for func in found_functions { msg.push_str(&format!(" - {}\n", func)); } msg.push_str("\nRecommendation:\n"); msg.push_str("Add this to your code:\n"); msg.push_str("static box Main {\n"); msg.push_str(" main() {\n"); msg.push_str(" // Your code here\n"); msg.push_str(" }\n"); msg.push_str("}\n"); msg } } } } #[derive(Debug, Clone)] pub enum EntryResolutionError { NoValidEntryPoint { found_functions: Vec, config: EntryResolverConfig, }, } impl std::fmt::Display for EntryResolutionError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { EntryResolutionError::NoValidEntryPoint { .. } => { write!(f, "No valid entry point found") } } } } impl std::error::Error for EntryResolutionError {} ``` #### **環境変数による設定** ```rust // src/runtime/entry_resolver.rs に追加 impl EntryResolverConfig { pub fn from_environment() -> Self { Self { allow_toplevel_main: std::env::var("NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN") .map(|v| v == "1" || v.to_lowercase() == "true") .unwrap_or(false), strict_main_signature: std::env::var("NYASH_ENTRY_STRICT_SIGNATURE") .map(|v| v == "1" || v.to_lowercase() == "true") .unwrap_or(true), fallback_to_first_function: std::env::var("NYASH_ENTRY_FALLBACK_FIRST") .map(|v| v == "1" || v.to_lowercase() == "true") .unwrap_or(false), require_main_box: std::env::var("NYASH_ENTRY_REQUIRE_MAIN_BOX") .map(|v| v != "0" && v.to_lowercase() != "false") .unwrap_or(true), } } } ``` ### Step 2.2: 全バックエンド統合 (Week 2-3) #### **Unified VM Interface に統合** ```rust // src/backend/vm_unified.rs に追加 impl UnifiedVM for PyVMBackend { fn execute_mir(&mut self, module: &MirModule) -> Result { // 1. エントリ解決 let resolver = EntryResolver::new(EntryResolverConfig::from_environment()); let entry_func_id = resolver.resolve_entry_point(module) .map_err(|e| VMError::EntryResolution(e))?; // 2. モジュールにエントリ情報を付加 let mut module_with_entry = module.clone(); module_with_entry.entry_point = Some(entry_func_id); // 3. PyVMに渡すJSONに含める let mir_json = serde_json::to_string(&module_with_entry)?; // ... 以下既存のPyVM実行ロジック } } ``` #### **PyVM側での対応** ```python # src/llvm_py/pyvm/vm_enhanced.py に追加 class EnhancedPyVM: def execute_mir_module(self, mir_json_str): mir_module = json.loads(mir_json_str) # エントリポイント解決(Rust側で解決済みを使用) if 'entry_point' in mir_module: entry_func_id = mir_module['entry_point'] entry_function = mir_module['functions'][entry_func_id] else: # フォールバック(古い形式互換性) entry_function = self.resolve_entry_legacy(mir_module) # メイン実行 result = self.execute_function(entry_function, []) return { 'return_value': result, 'stdout': self.get_stdout(), 'stderr': self.get_stderr(), 'execution_stats': self.get_stats(), } def resolve_entry_legacy(self, mir_module): """レガシー互換性のためのエントリ解決""" # "Main.main" を検索 for func in mir_module['functions']: if func['name'] == 'Main.main': return func # "main" を検索 for func in mir_module['functions']: if func['name'] == 'main': return func # 最初の関数を使用 if mir_module['functions']: return mir_module['functions'][0] raise RuntimeError("No executable function found") ``` #### **受け入れ基準** ```bash # エントリ解決統一テスト ./tools/test/phase2/entry_resolution_unified.sh # 設定による動作変更テスト NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 ./tools/test/phase2/toplevel_main_test.sh NYASH_ENTRY_STRICT_SIGNATURE=0 ./tools/test/phase2/relaxed_signature_test.sh # 期待する成功例 # Main.main() パターン echo 'static box Main { main() { print("Hello"); } }' | ./nyash --backend pyvm # → Hello # toplevel main() パターン(環境変数有効時) NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 echo 'function main() { print("World"); }' | ./nyash --backend pyvm # → World # エラーメッセージ品質確認 echo 'function foo() { print("test"); }' | ./nyash --backend pyvm # → 詳細なエラーメッセージと修正提案 ``` --- ## 📋 Phase 3: 制御フロー根本修正 (3-4週間) ### 🎯 Phase 3 目標 **「ネスト関数、break/continue、Box境界での制御フローを完全に統一し、言語機能の完全性を達成」** ### Step 3.1: 制御フロー統一設計 (Week 1) #### **制御フローコンテキスト管理** ```rust // src/mir/control_flow_unified.rs use std::collections::HashMap; #[derive(Debug, Clone)] pub struct ControlFlowContext { loop_stack: Vec, function_stack: Vec, break_targets: HashMap, continue_targets: HashMap, scope_stack: Vec, } #[derive(Debug, Clone)] pub struct LoopContext { id: LoopId, break_label: String, continue_label: String, is_in_box_method: bool, parent_function: FunctionId, } #[derive(Debug, Clone)] pub struct FunctionContext { id: FunctionId, name: String, is_box_method: bool, box_name: Option, return_type: Option, } #[derive(Debug, Clone)] pub struct ScopeContext { scope_type: ScopeType, depth: usize, parent_function: FunctionId, variables: HashMap, } #[derive(Debug, Clone)] pub enum ScopeType { Function, Loop, If, Block, BoxMethod, } impl ControlFlowContext { pub fn new() -> Self { Self { loop_stack: Vec::new(), function_stack: Vec::new(), break_targets: HashMap::new(), continue_targets: HashMap::new(), scope_stack: Vec::new(), } } pub fn enter_function(&mut self, func_id: FunctionId, name: String, is_box_method: bool) { let context = FunctionContext { id: func_id, name, is_box_method, box_name: None, // TODO: 実際のBox名を取得 return_type: None, }; self.function_stack.push(context); self.scope_stack.push(ScopeContext { scope_type: if is_box_method { ScopeType::BoxMethod } else { ScopeType::Function }, depth: self.scope_stack.len(), parent_function: func_id, variables: HashMap::new(), }); } pub fn exit_function(&mut self) { self.function_stack.pop(); // 関数スコープを削除 while let Some(scope) = self.scope_stack.last() { if matches!(scope.scope_type, ScopeType::Function | ScopeType::BoxMethod) { self.scope_stack.pop(); break; } self.scope_stack.pop(); } } pub fn enter_loop(&mut self, loop_id: LoopId, break_target: BasicBlockId, continue_target: BasicBlockId) { let current_function = self.current_function_id(); let is_in_box_method = self.is_in_box_method(); let context = LoopContext { id: loop_id, break_label: format!("break_{}", loop_id.0), continue_label: format!("continue_{}", loop_id.0), is_in_box_method, parent_function: current_function, }; self.loop_stack.push(context); self.break_targets.insert(loop_id, break_target); self.continue_targets.insert(loop_id, continue_target); self.scope_stack.push(ScopeContext { scope_type: ScopeType::Loop, depth: self.scope_stack.len(), parent_function: current_function, variables: HashMap::new(), }); } pub fn exit_loop(&mut self) { if let Some(loop_context) = self.loop_stack.pop() { self.break_targets.remove(&loop_context.id); self.continue_targets.remove(&loop_context.id); } // ループスコープを削除 while let Some(scope) = self.scope_stack.last() { if matches!(scope.scope_type, ScopeType::Loop) { self.scope_stack.pop(); break; } self.scope_stack.pop(); } } pub fn handle_break(&self) -> Result { let current_loop = self.loop_stack.last() .ok_or(ControlFlowError::BreakOutsideLoop)?; if current_loop.is_in_box_method { // Boxメソッド内のbreak特別処理 self.handle_box_method_break(current_loop) } else { // 通常のbreak処理 Ok(self.break_targets[¤t_loop.id]) } } pub fn handle_continue(&self) -> Result { let current_loop = self.loop_stack.last() .ok_or(ControlFlowError::ContinueOutsideLoop)?; if current_loop.is_in_box_method { // Boxメソッド内のcontinue特別処理 self.handle_box_method_continue(current_loop) } else { // 通常のcontinue処理 Ok(self.continue_targets[¤t_loop.id]) } } fn handle_box_method_break(&self, loop_context: &LoopContext) -> Result { // Boxメソッド境界を超えるbreak処理 // TODO: Boxメソッドの特別な制御フロー処理 Ok(self.break_targets[&loop_context.id]) } fn handle_box_method_continue(&self, loop_context: &LoopContext) -> Result { // Boxメソッド境界を超えるcontinue処理 // TODO: Boxメソッドの特別な制御フロー処理 Ok(self.continue_targets[&loop_context.id]) } pub fn current_function_id(&self) -> FunctionId { self.function_stack.last() .map(|ctx| ctx.id) .unwrap_or(FunctionId(0)) } pub fn is_in_box_method(&self) -> bool { self.function_stack.last() .map(|ctx| ctx.is_box_method) .unwrap_or(false) } pub fn validate_break(&self) -> Result<(), ControlFlowError> { if self.loop_stack.is_empty() { return Err(ControlFlowError::BreakOutsideLoop); } // Box境界チェック let current_loop = &self.loop_stack[self.loop_stack.len() - 1]; let current_function = self.current_function_id(); if current_loop.parent_function != current_function { return Err(ControlFlowError::BreakAcrossFunctionBoundary); } Ok(()) } pub fn validate_continue(&self) -> Result<(), ControlFlowError> { if self.loop_stack.is_empty() { return Err(ControlFlowError::ContinueOutsideLoop); } // Box境界チェック let current_loop = &self.loop_stack[self.loop_stack.len() - 1]; let current_function = self.current_function_id(); if current_loop.parent_function != current_function { return Err(ControlFlowError::ContinueAcrossFunctionBoundary); } Ok(()) } } #[derive(Debug, Clone)] pub enum ControlFlowError { BreakOutsideLoop, ContinueOutsideLoop, BreakAcrossFunctionBoundary, ContinueAcrossFunctionBoundary, InvalidLoopNesting, } impl std::fmt::Display for ControlFlowError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ControlFlowError::BreakOutsideLoop => write!(f, "break statement outside of loop"), ControlFlowError::ContinueOutsideLoop => write!(f, "continue statement outside of loop"), ControlFlowError::BreakAcrossFunctionBoundary => write!(f, "break statement cannot cross function boundary"), ControlFlowError::ContinueAcrossFunctionBoundary => write!(f, "continue statement cannot cross function boundary"), ControlFlowError::InvalidLoopNesting => write!(f, "invalid loop nesting structure"), } } } impl std::error::Error for ControlFlowError {} ``` ### Step 3.2: ネスト関数リフト標準化 (Week 2) #### **ネスト関数自動リフトシステム** ```rust // src/mir/nested_function_lifter.rs use std::collections::{HashMap, HashSet}; pub struct NestedFunctionLifter { symbol_generator: SymbolGenerator, captured_variables: HashMap>, } impl NestedFunctionLifter { pub fn new() -> Self { Self { symbol_generator: SymbolGenerator::new(), captured_variables: HashMap::new(), } } pub fn lift_nested_functions(&mut self, module: &mut MirModule) -> Result<(), LiftError> { let mut lifted_functions = Vec::new(); let mut modified_functions = Vec::new(); for (func_id, function) in module.functions.iter().enumerate() { let (nested_funcs, modified_func) = self.extract_and_lift_nested( FunctionId(func_id), function )?; lifted_functions.extend(nested_funcs); modified_functions.push(modified_func); } // 元の関数を置換 module.functions = modified_functions; // リフトされた関数を追加 module.functions.extend(lifted_functions); Ok(()) } fn extract_and_lift_nested(&mut self, parent_id: FunctionId, function: &MirFunction) -> Result<(Vec, MirFunction), LiftError> { let mut nested_functions = Vec::new(); let mut modified_body = function.body.clone(); let mut replacement_map = HashMap::new(); // 1. ネスト関数を検出・抽出 for (block_idx, block) in function.body.iter().enumerate() { for (instr_idx, instruction) in block.instructions.iter().enumerate() { if let Some(nested_func) = self.extract_function_declaration(instruction)? { // 新しい関数名を生成 let lifted_name = self.symbol_generator.generate_function_name( &function.name, &nested_func.name ); // キャプチャ変数を分析 let captured = self.analyze_captured_variables(&nested_func, function)?; if !captured.is_empty() { return Err(LiftError::CapturedVariablesNotSupported { function_name: nested_func.name.clone(), captured_variables: captured, }); } // リフトされた関数を作成 let mut lifted_func = nested_func.clone(); lifted_func.name = lifted_name.clone(); lifted_func.is_nested = false; nested_functions.push(lifted_func); // 置換マップに記録 replacement_map.insert(nested_func.name.clone(), lifted_name); // 元の命令を削除(no-op に置換) modified_body[block_idx].instructions[instr_idx] = MirInstruction::noop(); } } } // 2. 関数呼び出しを置換 self.replace_function_calls(&mut modified_body, &replacement_map)?; let mut modified_function = function.clone(); modified_function.body = modified_body; Ok((nested_functions, modified_function)) } fn extract_function_declaration(&self, instruction: &MirInstruction) -> Result, LiftError> { match instruction { MirInstruction::FunctionDeclaration { function } => { Ok(Some(function.clone())) } _ => Ok(None) } } fn analyze_captured_variables(&self, nested_func: &MirFunction, parent_func: &MirFunction) -> Result, LiftError> { let mut captured = HashSet::new(); let mut nested_locals = HashSet::new(); let parent_locals = self.collect_local_variables(parent_func); // ネスト関数のローカル変数を収集 for param in &nested_func.parameters { nested_locals.insert(param.name.clone()); } // ネスト関数内で使用される変数を分析 for block in &nested_func.body { for instruction in &block.instructions { for used_var in self.extract_used_variables(instruction) { if !nested_locals.contains(&used_var) && parent_locals.contains(&used_var) { captured.insert(used_var); } } } } Ok(captured) } fn collect_local_variables(&self, function: &MirFunction) -> HashSet { let mut locals = HashSet::new(); // パラメータを追加 for param in &function.parameters { locals.insert(param.name.clone()); } // ローカル変数宣言を検索 for block in &function.body { for instruction in &block.instructions { if let Some(var_name) = self.extract_local_declaration(instruction) { locals.insert(var_name); } } } locals } fn extract_used_variables(&self, instruction: &MirInstruction) -> Vec { match instruction { MirInstruction::Load { source, .. } => vec![source.clone()], MirInstruction::Store { target, source } => vec![target.clone(), source.clone()], MirInstruction::BinOp { left, right, .. } => vec![left.clone(), right.clone()], MirInstruction::Call { args, .. } => args.clone(), // ... 他の命令タイプ _ => Vec::new(), } } fn extract_local_declaration(&self, instruction: &MirInstruction) -> Option { match instruction { MirInstruction::LocalDeclaration { name } => Some(name.clone()), _ => None, } } fn replace_function_calls(&self, body: &mut Vec, replacement_map: &HashMap) -> Result<(), LiftError> { for block in body.iter_mut() { for instruction in block.instructions.iter_mut() { if let MirInstruction::Call { function_name, .. } = instruction { if let Some(new_name) = replacement_map.get(function_name) { *function_name = new_name.clone(); } } } } Ok(()) } } pub struct SymbolGenerator { counter: u32, } impl SymbolGenerator { pub fn new() -> Self { Self { counter: 0 } } pub fn generate_function_name(&mut self, parent_name: &str, nested_name: &str) -> String { self.counter += 1; format!("_lifted_{}_{}__{}", parent_name, nested_name, self.counter) } } #[derive(Debug, Clone)] pub enum LiftError { CapturedVariablesNotSupported { function_name: String, captured_variables: HashSet, }, InvalidNestedFunction { function_name: String, reason: String, }, } impl std::fmt::Display for LiftError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LiftError::CapturedVariablesNotSupported { function_name, captured_variables } => { write!(f, "Nested function '{}' captures variables from parent scope: {:?}. \ Closure capture is not yet supported. \ Please move the function to top level or box level.", function_name, captured_variables ) } LiftError::InvalidNestedFunction { function_name, reason } => { write!(f, "Invalid nested function '{}': {}", function_name, reason) } } } } impl std::error::Error for LiftError {} ``` ### Step 3.3: Box境界制御フロー (Week 3-4) #### **Box境界制御フロー処理** ```rust // src/mir/box_boundary_control_flow.rs use std::collections::HashMap; pub struct BoxBoundaryControlFlowHandler { box_method_contexts: HashMap, active_loops: HashMap, } #[derive(Debug, Clone)] pub struct BoxMethodContext { box_name: String, method_name: String, parent_scope: Option, boundary_type: BoxBoundaryType, } #[derive(Debug, Clone)] pub enum BoxBoundaryType { Isolated, // Box内で完結 Transparent, // 外部ループを継承 Controlled, // 特別な制御が必要 } #[derive(Debug, Clone)] pub struct LoopBoundaryInfo { loop_id: LoopId, parent_function: FunctionId, crossing_box_methods: Vec, break_handling: BreakHandlingStrategy, continue_handling: ContinueHandlingStrategy, } #[derive(Debug, Clone)] pub enum BreakHandlingStrategy { Standard, // 通常のbreak処理 BoxMethodExit, // Boxメソッド終了として処理 ParentLoopBreak, // 親ループのbreakに変換 Error, // エラーとして処理 } #[derive(Debug, Clone)] pub enum ContinueHandlingStrategy { Standard, // 通常のcontinue処理 BoxMethodReturn, // Boxメソッドreturnとして処理 ParentLoopContinue, // 親ループのcontinueに変換 Error, // エラーとして処理 } impl BoxBoundaryControlFlowHandler { pub fn new() -> Self { Self { box_method_contexts: HashMap::new(), active_loops: HashMap::new(), } } pub fn register_box_method(&mut self, func_id: FunctionId, box_name: String, method_name: String) { let context = BoxMethodContext { box_name, method_name, parent_scope: None, boundary_type: self.determine_boundary_type(&box_name), }; self.box_method_contexts.insert(func_id, context); } fn determine_boundary_type(&self, box_name: &str) -> BoxBoundaryType { // Boxの種類に応じて境界タイプを決定 match box_name { // システムBoxは透明 "ArrayBox" | "StringBox" | "MapBox" => BoxBoundaryType::Transparent, // ユーザー定義Boxは分離 _ => BoxBoundaryType::Isolated, } } pub fn handle_loop_entry(&mut self, loop_id: LoopId, current_function: FunctionId) { let boundary_info = LoopBoundaryInfo { loop_id, parent_function: current_function, crossing_box_methods: Vec::new(), break_handling: self.determine_break_strategy(current_function), continue_handling: self.determine_continue_strategy(current_function), }; self.active_loops.insert(loop_id, boundary_info); } pub fn handle_loop_exit(&mut self, loop_id: LoopId) { self.active_loops.remove(&loop_id); } fn determine_break_strategy(&self, function_id: FunctionId) -> BreakHandlingStrategy { if let Some(context) = self.box_method_contexts.get(&function_id) { match context.boundary_type { BoxBoundaryType::Isolated => BreakHandlingStrategy::BoxMethodExit, BoxBoundaryType::Transparent => BreakHandlingStrategy::Standard, BoxBoundaryType::Controlled => BreakHandlingStrategy::ParentLoopBreak, } } else { BreakHandlingStrategy::Standard } } fn determine_continue_strategy(&self, function_id: FunctionId) -> ContinueHandlingStrategy { if let Some(context) = self.box_method_contexts.get(&function_id) { match context.boundary_type { BoxBoundaryType::Isolated => ContinueHandlingStrategy::BoxMethodReturn, BoxBoundaryType::Transparent => ContinueHandlingStrategy::Standard, BoxBoundaryType::Controlled => ContinueHandlingStrategy::ParentLoopContinue, } } else { ContinueHandlingStrategy::Standard } } pub fn process_break(&self, loop_id: LoopId, current_function: FunctionId) -> Result { let loop_info = self.active_loops.get(&loop_id) .ok_or(BoxBoundaryError::LoopNotFound(loop_id))?; match loop_info.break_handling { BreakHandlingStrategy::Standard => { Ok(ControlFlowAction::Break(loop_info.loop_id)) } BreakHandlingStrategy::BoxMethodExit => { // Boxメソッド終了として処理 Ok(ControlFlowAction::Return(None)) } BreakHandlingStrategy::ParentLoopBreak => { // 親ループのbreakに変換 if loop_info.parent_function != current_function { self.find_parent_loop_break(current_function) } else { Ok(ControlFlowAction::Break(loop_info.loop_id)) } } BreakHandlingStrategy::Error => { Err(BoxBoundaryError::BreakAcrossBoundary { loop_id, function_id: current_function, }) } } } pub fn process_continue(&self, loop_id: LoopId, current_function: FunctionId) -> Result { let loop_info = self.active_loops.get(&loop_id) .ok_or(BoxBoundaryError::LoopNotFound(loop_id))?; match loop_info.continue_handling { ContinueHandlingStrategy::Standard => { Ok(ControlFlowAction::Continue(loop_info.loop_id)) } ContinueHandlingStrategy::BoxMethodReturn => { // Boxメソッドreturnとして処理(継続的な意味で) Ok(ControlFlowAction::Return(None)) } ContinueHandlingStrategy::ParentLoopContinue => { // 親ループのcontinueに変換 if loop_info.parent_function != current_function { self.find_parent_loop_continue(current_function) } else { Ok(ControlFlowAction::Continue(loop_info.loop_id)) } } ContinueHandlingStrategy::Error => { Err(BoxBoundaryError::ContinueAcrossBoundary { loop_id, function_id: current_function, }) } } } fn find_parent_loop_break(&self, current_function: FunctionId) -> Result { // 現在の関数の親スコープでアクティブなループを検索 for (loop_id, loop_info) in &self.active_loops { if loop_info.crossing_box_methods.contains(¤t_function) { return Ok(ControlFlowAction::Break(*loop_id)); } } Err(BoxBoundaryError::NoParentLoop(current_function)) } fn find_parent_loop_continue(&self, current_function: FunctionId) -> Result { // 現在の関数の親スコープでアクティブなループを検索 for (loop_id, loop_info) in &self.active_loops { if loop_info.crossing_box_methods.contains(¤t_function) { return Ok(ControlFlowAction::Continue(*loop_id)); } } Err(BoxBoundaryError::NoParentLoop(current_function)) } } #[derive(Debug, Clone)] pub enum ControlFlowAction { Break(LoopId), Continue(LoopId), Return(Option), Jump(BasicBlockId), } #[derive(Debug, Clone)] pub enum BoxBoundaryError { LoopNotFound(LoopId), BreakAcrossBoundary { loop_id: LoopId, function_id: FunctionId }, ContinueAcrossBoundary { loop_id: LoopId, function_id: FunctionId }, NoParentLoop(FunctionId), InvalidBoundaryType(String), } impl std::fmt::Display for BoxBoundaryError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BoxBoundaryError::LoopNotFound(loop_id) => write!(f, "Loop {} not found in active loop contexts", loop_id.0), BoxBoundaryError::BreakAcrossBoundary { loop_id, function_id } => write!(f, "break statement in function {} cannot reach loop {}", function_id.0, loop_id.0), BoxBoundaryError::ContinueAcrossBoundary { loop_id, function_id } => write!(f, "continue statement in function {} cannot reach loop {}", function_id.0, loop_id.0), BoxBoundaryError::NoParentLoop(function_id) => write!(f, "No parent loop found for function {}", function_id.0), BoxBoundaryError::InvalidBoundaryType(msg) => write!(f, "Invalid box boundary type: {}", msg), } } } impl std::error::Error for BoxBoundaryError {} ``` #### **受け入れ基準** ```bash # 制御フロー統合テスト ./tools/test/phase3/control_flow_unified.sh # ネスト関数リフトテスト ./tools/test/phase3/nested_function_lift.sh # Box境界制御フローテスト ./tools/test/phase3/box_boundary_control_flow.sh # 期待する成功例 # ネスト関数の自動リフト echo 'function outer() { function inner() { return 42; } return inner(); }' | ./nyash --backend pyvm # → 42 (正常実行) # Box境界でのbreak/continue echo 'local arr = new ArrayBox(); loop(i < 10) { arr.forEach(x => { if (x > 5) break; }); }' | ./nyash --backend pyvm # → 適切なエラーメッセージまたは正常実行 # 複雑な制御フロー echo 'loop(i < 10) { loop(j < 5) { if (condition) continue; if (other) break; } }' | ./nyash --backend pyvm # → 正常実行 ``` --- この詳細計画により、Nyashの根本的な品質問題を段階的に解決し、真の意味でのセルフホスティング成功への基盤を確立できます。