fix(env): improve Environment::set scope resolution (partial)

Fixed:
- Environment::set now properly searches ancestor chain before creating new binding
- Added exists_in_chain_locked() helper for explicit existence checking
- Simple {} blocks now correctly update outer scope variables

Verified Working:
- local x = 10; { x = 42 }; print(x) → prints 42 

Still Broken:
- else blocks don't update outer scope variables
- local x = 10; if flag { x = 99 } else { x = 42 }; print(x) → prints 10 

Root Cause Identified:
- Issue is in MIR Builder (compile-time), not Environment (runtime)
- src/mir/builder/if_form.rs:108 resets variable_map before else block
- PHI generation at merge doesn't use else_var_map_end correctly
- MIR shows: phi [%32, bb1], [%1, bb2] where %1 is original value, not else value

Next: Fix else block variable merging in if_form.rs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-13 18:55:14 +09:00
parent 1ac0c6b880
commit 801833df8d
5 changed files with 187 additions and 11 deletions

View File

@ -109,20 +109,32 @@ impl Environment {
return Ok(());
}
// 親スコープで再帰的に検索・設定
// 祖先いずれかに既存があれば「既存を更新」、無ければ「現在スコープに新規定義」
if let Some(parent) = &self.parent {
match parent.lock().unwrap().set(&name, value.clone_or_share()) {
Ok(()) => return Ok(()),
Err(EnvironmentError::UndefinedVariable { .. }) => {
// 親にもない場合は現在のスコープに新規定義
}
Err(e) => return Err(e),
if Self::exists_in_chain_locked(&parent.lock().unwrap(), &name) {
// 祖先のどこかに存在 → そこで更新
parent.lock().unwrap().set(&name, value)
} else {
// どこにも存在しない → 現在のスコープで定義
self.bindings.lock().unwrap().insert(name, value);
Ok(())
}
} else {
// 親がない(グローバル)→ 現在で定義
self.bindings.lock().unwrap().insert(name, value);
Ok(())
}
}
// 新規定義として現在のスコープに追加
self.bindings.lock().unwrap().insert(name, value);
Ok(())
/// 祖先(自分含む)に名前が存在するか(ロック下で使用)
fn exists_in_chain_locked(&self, name: &str) -> bool {
if self.bindings.lock().unwrap().contains_key(name) {
return true;
}
if let Some(parent) = &self.parent {
return parent.lock().unwrap().exists_in_chain_locked(name);
}
false
}
/// 変数が存在するかチェック