From c27f6466e8a319da01d2bee5f5f9c613032ff8be Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Mon, 17 Nov 2025 15:57:34 +0900 Subject: [PATCH] =?UTF-8?q?fix(builder):=20BoxCompilationContext=20clear()?= =?UTF-8?q?=E3=82=A2=E3=83=97=E3=83=AD=E3=83=BC=E3=83=81=E7=A2=BA=E7=AB=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 箱理論: swap累積バグを修正し、clear()で完全独立化を実現 ## 問題 - swap実装は ctx に変数が累積され、次のメソッドで汚染される - StageBArgsBox.resolve_src で ValueId(21) 未定義エラー ## 解決策 - swap → clear() に変更(開始時・終了時両方) - context_active mode: clear() のみ(完全独立) - legacy mode: saved_var_map で従来の挙動維持 ## 成果 ✅ StageBArgsBox.resolve_src - 成功! ❌ StageBBodyExtractorBox.build_body_src - 次の問題箇所(進展!) ## 実装 - src/mir/builder/builder_calls.rs: - 開始時: context_active なら clear()(swap削除) - 終了時: context_active なら clear()(swap back削除) - legacy mode: saved_var_map で復元 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/private | 2 +- src/mir/builder/builder_calls.rs | 57 +++++++++++-------- src/tests/mir_stage1_using_resolver_verify.rs | 9 +-- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/docs/private b/docs/private index e54d615e..118726f6 160000 --- a/docs/private +++ b/docs/private @@ -1 +1 @@ -Subproject commit e54d615e5fb615025d39ca4f7bec52ce6f8bcf6c +Subproject commit 118726f606f6d565c8923e7f58db82f8562985cd diff --git a/src/mir/builder/builder_calls.rs b/src/mir/builder/builder_calls.rs index a7e12bb0..36ade7d8 100644 --- a/src/mir/builder/builder_calls.rs +++ b/src/mir/builder/builder_calls.rs @@ -860,18 +860,6 @@ impl super::MirBuilder { params: Vec, body: Vec, ) -> Result<(), String> { - // 🎯 箱理論: コンテキスト分離(開始) - // compilation_contextがある場合、その内容を既存のフィールドとswap - // これにより、既存のコードを変更せずにコンテキスト分離を実現 - let context_active = self.compilation_context.is_some(); - if context_active { - if let Some(ref mut ctx) = self.compilation_context { - std::mem::swap(&mut self.variable_map, &mut ctx.variable_map); - std::mem::swap(&mut self.value_origin_newbox, &mut ctx.value_origin_newbox); - std::mem::swap(&mut self.value_types, &mut ctx.value_types); - } - } - // Derive static box context from function name prefix, e.g., "BoxName.method/N" let saved_static_ctx = self.current_static_box.clone(); if let Some(pos) = func_name.find('.') { @@ -880,6 +868,26 @@ impl super::MirBuilder { self.current_static_box = Some(box_name.to_string()); } } + + // 🎯 箱理論: BoxCompilationContext と saved_var_map をモード別に管理 + // context_active = true の場合(BoxCompilationContext mode): + // - clear() で完全独立化(各メソッドが汚染されない) + // - swap は不要(累積バグの原因) + // context_active = false の場合(Legacy mode): + // - saved_var_map に退避して空から開始し、終了時に復元 + let context_active = self.compilation_context.is_some(); + let saved_var_map = if !context_active { + Some(std::mem::take(&mut self.variable_map)) + } else { + None + }; + if context_active { + // 🎯 箱理論: 完全独立化(clear のみ、swap 不要) + self.variable_map.clear(); + self.value_origin_newbox.clear(); + self.value_types.clear(); + } + let signature = function_lowering::prepare_static_method_signature( func_name, ¶ms, @@ -890,7 +898,6 @@ impl super::MirBuilder { let function = super::MirFunction::new(signature, entry); let saved_function = self.current_function.take(); let saved_block = self.current_block.take(); - let saved_var_map = std::mem::take(&mut self.variable_map); self.current_function = Some(function); self.current_block = Some(entry); self.ensure_block_exists(entry)?; @@ -952,20 +959,22 @@ impl super::MirBuilder { } self.current_function = saved_function; self.current_block = saved_block; - self.variable_map = saved_var_map; + + // 🎯 箱理論: モード別に状態を復元 + if context_active { + // 🎯 BoxCompilationContext mode: clear のみ(次回も完全独立) + // swap は不要(累積バグを防ぐ) + self.variable_map.clear(); + self.value_origin_newbox.clear(); + self.value_types.clear(); + } else if let Some(saved) = saved_var_map { + // 従来モード: Main.main 側の variable_map を元に戻す + self.variable_map = saved; + } + // Restore static box context self.current_static_box = saved_static_ctx; - // 🎯 箱理論: コンテキスト分離(終了) - // swap backでコンテキストに変更を保存 - if context_active { - if let Some(ref mut ctx) = self.compilation_context { - std::mem::swap(&mut self.variable_map, &mut ctx.variable_map); - std::mem::swap(&mut self.value_origin_newbox, &mut ctx.value_origin_newbox); - std::mem::swap(&mut self.value_types, &mut ctx.value_types); - } - } - Ok(()) } } diff --git a/src/tests/mir_stage1_using_resolver_verify.rs b/src/tests/mir_stage1_using_resolver_verify.rs index 6e1e7334..ef026ba1 100644 --- a/src/tests/mir_stage1_using_resolver_verify.rs +++ b/src/tests/mir_stage1_using_resolver_verify.rs @@ -70,7 +70,7 @@ static box Stage1UsingResolverMini { /// Verify MIR/SSA for ParserBox.parse_program2 in isolation by compiling a small wrapper. #[test] -fn mir_parserbox_parse_program2_verifies() { +fn mir_parserbox_parse_program2_harness_parses_minimal_source() { // Minimal wrapper that brings ParserBox into scope and calls parse_program2. let src = r#" using lang.compiler.parser.parser_box as ParserBox @@ -84,15 +84,16 @@ static box ParserBoxHarness { } "#; - let ast: ASTNode = NyashParser::parse_from_string(src).expect("parse ok"); + // Stage‑3 構文キーワード `local` を含む最小ソースを ParserBoxHarness でパースする + let harness_ast: ASTNode = NyashParser::parse_from_string(src).expect("parse ok"); let mut mc = MirCompiler::with_options(false); - let cr = mc.compile(ast).expect("compile"); + let cr = mc.compile(harness_ast).expect("compile"); let mut verifier = MirVerifier::new(); if let Err(errors) = verifier.verify_module(&cr.module) { for e in &errors { eprintln!("[mir-verify] {}", e); } - panic!("MIR verification failed for ParserBoxHarness.parse_program2"); + panic!("MIR verification failed for ParserBoxHarness"); } }