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

@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/../../../../../.." && pwd)"
source "$ROOT_DIR/tools/smokes/v2/lib/test_runner.sh" || true
source "$ROOT_DIR/tools/smokes/v2/lib/result_checker.sh" || true
require_env || { echo "[SKIP] env not ready"; exit 0; }
test_vm_llvm_scope_assign() {
local code='static box Main { method main(args) { local x = 0 { if (1==1) { x = 42 } } return x } }'
# Stage-3 parse is required for `local`
NYASH_PARSER_STAGE3=1 check_parity -c "$code" "vm_llvm_scope_assign"
}
run_test "vm_llvm_scope_assign" test_vm_llvm_scope_assign

View File

@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/../../../../../../.." && pwd)"
source "$ROOT_DIR/tools/smokes/v2/lib/test_runner.sh" || true
source "$ROOT_DIR/tools/smokes/v2/lib/result_checker.sh" || true
require_env || { echo "[SKIP] env not ready"; exit 0; }
test_scope_assign_vm() {
local code='static box Main { method main(args) { local x = 0 { if (1==1) { x = 42 } } return x } }'
local tmp
tmp=$(mktemp --suffix .hako)
printf '%s' "$code" > "$tmp"
# Quick: VM should reflect nested assignment
local rc
NYASH_PARSER_STAGE3=1 "$NYASH_BIN" --backend vm "$tmp" >/dev/null 2>&1
rc=$?
if [[ "$rc" -ne 42 ]]; then
echo "[FAIL] scope_assign_vm: vm rc=$rc (expected 42)"
return 1
fi
echo "[PASS] scope_assign_vm"
rm -f "$tmp" 2>/dev/null || true
return 0
}
run_test "scope_assign_vm" test_scope_assign_vm

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../../../../../.." && pwd)"
BIN="$ROOT/target/release/hakorune"
if [[ ! -x "$BIN" ]]; then
echo "[SKIP] hakorune not built"; exit 0
fi
# Source with nested assignment; Stage-B should extract body or at least output Program JSON
SRC='static box Main { method main(args) { local x = 0 { if (1==1) { x = 42 } } return x } }'
out=$(NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 "$BIN" --backend vm "$ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --source "$SRC" 2>/dev/null || true)
echo "$out" | grep -q '"kind":"Program"' || { echo "[FAIL] stageb_scope_extract_canary: no Program JSON"; exit 1; }
# Heuristic check: JSON contains at least a numeric literal 42 somewhere
echo "$out" | grep -q '42' || { echo "[FAIL] stageb_scope_extract_canary: literal 42 not found"; exit 1; }
echo "[PASS] stageb_scope_extract_canary"