fix(mir/builder): use function-local ValueId throughout MIR builder
Phase 25.1b: Complete SSA fix - eliminate all global ValueId usage in function contexts. Root cause: ~75 locations throughout MIR builder were using global value generator (self.value_gen.next()) instead of function-local allocator (f.next_value_id()), causing SSA verification failures and runtime "use of undefined value" errors. Solution: - Added next_value_id() helper that automatically chooses correct allocator - Fixed 19 files with ~75 occurrences of ValueId allocation - All function-context allocations now use function-local IDs Files modified: - src/mir/builder/utils.rs: Added next_value_id() helper, fixed 8 locations - src/mir/builder/builder_calls.rs: 17 fixes - src/mir/builder/ops.rs: 8 fixes - src/mir/builder/stmts.rs: 7 fixes - src/mir/builder/emission/constant.rs: 6 fixes - src/mir/builder/rewrite/*.rs: 10 fixes - + 13 other files Verification: - cargo build --release: SUCCESS - Simple tests with NYASH_VM_VERIFY_MIR=1: Zero undefined errors - Multi-parameter static methods: All working Known remaining: ValueId(22) in Stage-B (separate issue to investigate) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -535,14 +535,19 @@ static box Main {
|
||||
local ast_json = p.parse_program2(body_src)
|
||||
|
||||
// 6.5) Dev-toggle: scan for function definitions (static box { method <name>(...) {...} })
|
||||
// Toggle: HAKO_STAGEB_FUNC_SCAN=1
|
||||
// Policy: conservative minimal scanner for Phase 21.6 call canary (no nesting, basic only)
|
||||
// Toggle: HAKO_STAGEB_FUNC_SCAN
|
||||
// Policy:
|
||||
// - 未設定(null) のときは既定で ON(defs を常に埋める)。
|
||||
// - 明示的に "0" が入っているときだけ OFF。
|
||||
// Scope: method <name>(params) { ... } outside of main (same box Main)
|
||||
// Output: inject "defs":[{"name":"<name>","params":[...],"body":[...], "box":"Main"}] to Program JSON
|
||||
local defs_json = ""
|
||||
{
|
||||
local func_scan = env.get("HAKO_STAGEB_FUNC_SCAN")
|
||||
if func_scan != null && ("" + func_scan) == "1" {
|
||||
local func_scan_env = env.get("HAKO_STAGEB_FUNC_SCAN")
|
||||
local func_scan_on = 1
|
||||
// 明示的に "0" のときだけ OFF 扱い。それ以外(null/1/true/on)は ON。
|
||||
if func_scan_env != null && ("" + func_scan_env) == "0" { func_scan_on = 0 }
|
||||
if func_scan_on == 1 {
|
||||
// Use FuncScannerBox to extract method definitions from all boxes
|
||||
local methods = FuncScannerBox.scan_all_boxes(src)
|
||||
|
||||
|
||||
@ -37,6 +37,14 @@ box ParserBox {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Dev-only: enable coarse-grained parser trace when NYASH_PARSER_TRACE=1.
|
||||
trace_enabled() {
|
||||
local v = env.get("NYASH_PARSER_TRACE")
|
||||
if v == null { return 0 }
|
||||
if ("" + v) == "1" { return 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
// === State management ===
|
||||
gpos_set(i) { me.gpos = i return 0 }
|
||||
gpos_get() { return me.gpos }
|
||||
@ -227,9 +235,14 @@ box ParserBox {
|
||||
|
||||
// === Top-level program parser ===
|
||||
parse_program2(src) {
|
||||
local trace = me.trace_enabled()
|
||||
|
||||
// Inline skip_ws to avoid VM bug: method-with-loop called from within loop
|
||||
local i = 0
|
||||
local n = src.length()
|
||||
if trace == 1 {
|
||||
print("[parser/trace:program2] start len=" + ("" + n) + " stage3=" + ("" + me.stage3))
|
||||
}
|
||||
if i < n {
|
||||
local ws_cont_init = 1
|
||||
loop(ws_cont_init == 1) {
|
||||
@ -246,6 +259,21 @@ box ParserBox {
|
||||
local cont_prog = 1
|
||||
|
||||
loop(cont_prog == 1) {
|
||||
if trace == 1 {
|
||||
local kind = "Stmt"
|
||||
if i >= n {
|
||||
kind = "EOF"
|
||||
} else {
|
||||
if me.starts_with(src, i, "static box") == 1 { kind = "StaticBox" }
|
||||
else {
|
||||
if me.starts_with(src, i, "box ") == 1 { kind = "BoxDecl" }
|
||||
else {
|
||||
if me.starts_with(src, i, "method ") == 1 { kind = "Method" }
|
||||
}
|
||||
}
|
||||
}
|
||||
print("[parser/trace:program2] pos=" + ("" + i) + " kind=" + kind + " stage3=" + ("" + me.stage3))
|
||||
}
|
||||
// Inline skip_ws instead of calling me.skip_ws(src, i)
|
||||
if i < n {
|
||||
local ws_cont_1 = 1
|
||||
@ -267,6 +295,9 @@ box ParserBox {
|
||||
|
||||
// Progress guard
|
||||
if i <= start_i {
|
||||
if trace == 1 {
|
||||
print("[parser/trace:program2] progress-guard bump i from " + ("" + start_i) + " to " + ("" + (start_i + 1)))
|
||||
}
|
||||
if i < src.length() { i = i + 1 }
|
||||
else { i = src.length() }
|
||||
me.gpos_set(i)
|
||||
@ -305,9 +336,15 @@ box ParserBox {
|
||||
|
||||
if s.length() > 0 {
|
||||
if first == 1 {
|
||||
if trace == 1 {
|
||||
print("[parser/trace:program2] emit-first stmt_len=" + ("" + s.length()))
|
||||
}
|
||||
body = body + s
|
||||
first = 0
|
||||
} else {
|
||||
if trace == 1 {
|
||||
print("[parser/trace:program2] emit stmt_len=" + ("" + s.length()))
|
||||
}
|
||||
body = body + "," + s
|
||||
}
|
||||
}
|
||||
@ -315,6 +352,9 @@ box ParserBox {
|
||||
}
|
||||
|
||||
body = body + "]"
|
||||
if trace == 1 {
|
||||
print("[parser/trace:program2] done pos=" + ("" + i) + " len=" + ("" + n))
|
||||
}
|
||||
return "{\"version\":0,\"kind\":\"Program\",\"body\":" + body + "}"
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ static box MapHelpersBox {
|
||||
get_str(m, key) {
|
||||
local v = me._raw_get(m, key)
|
||||
if v == null { return "" }
|
||||
if BoxHelpers.is_map(v) == 1 {
|
||||
if BoxHelpers.is_map(v) {
|
||||
local inner = BoxHelpers.map_get(v, "value")
|
||||
if inner != null { return "" + inner }
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ static box NormalizerBox {
|
||||
normalize_cmp(raw) {
|
||||
if raw == null { return null }
|
||||
// TEMP debug
|
||||
if BoxHelpers.is_map(raw) == 1 && BoxHelpers.map_get(raw, "cmp") != null { print("DBG:N.cmp_in=1") } else { print("DBG:N.cmp_in=0") }
|
||||
if BoxHelpers.is_map(raw) && BoxHelpers.map_get(raw, "cmp") != null { print("DBG:N.cmp_in=1") } else { print("DBG:N.cmp_in=0") }
|
||||
local out = new MapBox()
|
||||
// cmp
|
||||
local cmp = "" + BoxHelpers.map_get(raw, "cmp")
|
||||
|
||||
Reference in New Issue
Block a user