Files
hakorune/lang/src/vm/hakorune-vm/terminator_handler.hako

196 lines
6.7 KiB
Plaintext

// terminator_handler.hako — Phase 1 Day 3: Terminator処理
// Strategy: 箱化モジュール化 - Ret/Jump/Branch を分離
using selfhost.shared.common.string_helpers as StringHelpers
using selfhost.shared.common.string_ops as StringOps
using selfhost.vm.boxes.result_box as Result
using selfhost.vm.hakorune-vm.instrs_locator as InstrsLocatorBox
using selfhost.vm.hakorune-vm.backward_object_scanner as BackwardObjectScannerBox
using selfhost.vm.hakorune-vm.core_bridge_ops as CoreBridgeOps
static box TerminatorHandlerBox {
// Execute terminator instruction and return next action
// Returns: Result.Ok(MapBox with "type" and other fields) or Result.Err(message)
//
// Return types:
// - "ret": {"type": "ret", "value": <return_value>}
// - "jump": {"type": "jump", "next_bb": <target_block_id>}
// - "branch": {"type": "branch", "next_bb": <selected_block_id>}
handle_terminator(block_json, regs) {
// Find terminator field
local key_term = "\"terminator\":{"
local term_start = block_json.indexOf(key_term)
if term_start < 0 {
// No terminator (should not happen in valid MIR)
return Result.Err("terminator not found")
}
local term_json_start = term_start + key_term.length() - 1
local term_end = me._find_terminator_end(block_json, term_json_start)
if term_end < 0 {
return Result.Err("terminator end not found")
}
local term_json = block_json.substring(term_json_start, term_end + 1)
// Extract op field (tolerant: ':' + optional spaces)
local key_opk = "\"op\""
local pos = term_json.indexOf(key_opk)
if pos < 0 {
// fallback
local fb = me._fallback_handle(block_json, regs)
if fb.is_Ok() { return fb }
return Result.Err("terminator op not found")
}
pos = pos + key_opk.length()
// find ':' then skip whitespace
loop(pos < term_json.length()) {
local ch = term_json.substring(pos, pos+1)
if ch == ":" { pos = pos + 1 break }
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue }
local fb = me._fallback_handle(block_json, regs)
if fb.is_Ok() { return fb }
return Result.Err("terminator op colon not found")
}
loop(pos < term_json.length()) {
local ch = term_json.substring(pos, pos+1)
if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { pos = pos + 1 continue }
break
}
if term_json.substring(pos, pos+1) != "\"" {
local fb = me._fallback_handle(block_json, regs)
if fb.is_Ok() { return fb }
return Result.Err("terminator op quote not found")
}
local op_end = StringOps.index_of_from(term_json, "\"", pos+1)
if op_end < 0 {
local fb = me._fallback_handle(block_json, regs)
if fb.is_Ok() { return fb }
return Result.Err("terminator op end not found")
}
local op = term_json.substring(pos+1, op_end)
// Dispatch terminator type
if op == "ret" {
return me._handle_ret(term_json, regs)
}
if op == "jump" {
return me._handle_jump(term_json)
}
if op == "branch" {
return me._handle_branch(term_json, regs)
}
return Result.Err("unknown terminator op: " + op)
}
// Fallback helper
_fallback_handle(block_json, regs) {
local loc = InstrsLocatorBox.locate(block_json)
if loc.is_Err() { return loc }
local meta = loc.as_Ok()
local insts = meta.get("content")
if insts == "" { return Result.Err("terminator not found") }
local single = meta.get("single")
local term_json = null
if single != null && single == 1 { term_json = insts } else {
local last = BackwardObjectScannerBox.scan_last_object(insts, 200000)
if last.is_Err() { return Result.Err("terminator scan failed: " + last.as_Err()) }
term_json = last.as_Ok()
}
local k = "\"op\""
local p = term_json.indexOf(k)
if p < 0 { return Result.Err("terminator op not found") }
p = p + k.length()
loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == ":" { p = p + 1 break } if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } return Result.Err("terminator op colon not found") }
loop(p < term_json.length()) { local ch = term_json.substring(p,p+1) if ch == " " || ch == "\n" || ch == "\r" || ch == "\t" { p = p + 1 continue } break }
if term_json.substring(p,p+1) != "\"" { return Result.Err("terminator op quote not found") }
local e = StringOps.index_of_from(term_json, "\"", p+1)
if e < 0 { return Result.Err("terminator op end not found") }
local op = term_json.substring(p+1, e)
if op == "ret" { return me._handle_ret(term_json, regs) }
if op == "jump" { return me._handle_jump(term_json) }
if op == "branch" { return me._handle_branch(term_json, regs) }
return Result.Err("unknown terminator op")
}
// Ret terminator
_handle_ret(term_json, regs) {
local result_map = new MapBox()
result_map.set("type", "ret")
// Extract value field (optional)
local key_val = "\"value\":"
local val_start = term_json.indexOf(key_val)
if val_start < 0 {
// No value → return 0
result_map.set("value", 0)
return Result.Ok(result_map)
}
val_start = val_start + key_val.length()
local val_digits = StringHelpers.read_digits(term_json, val_start)
if val_digits == "" {
return Result.Err("ret: invalid value")
}
local val_id = StringHelpers.to_i64(val_digits)
local reg_key = StringHelpers.int_to_str(val_id)
// Unified behavior: get() -> null if missing
local val = regs.get(reg_key)
if val == null {
val = 0
}
result_map.set("value", val)
return Result.Ok(result_map)
}
// Jump terminator
_handle_jump(term_json) {
local r = CoreBridgeOps.select_jump_next_from_terminator(term_json)
if r.is_Err() { return r }
local next_bb = r.as_Ok()
local result_map = new MapBox(); result_map.set("type","jump"); result_map.set("next_bb", next_bb)
return Result.Ok(result_map)
}
// Branch terminator
_handle_branch(term_json, regs) {
local r = CoreBridgeOps.select_branch_next_from_terminator(term_json, regs)
if r.is_Err() { return r }
local next_bb = r.as_Ok()
local result_map = new MapBox(); result_map.set("type","branch"); result_map.set("next_bb", next_bb)
return Result.Ok(result_map)
}
// Helper: find terminator object end
_find_terminator_end(json, start) {
local depth = 0
local pos = start
local len = json.length()
loop(pos < len) {
local ch = json.substring(pos, pos + 1)
if ch == "{" {
depth = depth + 1
}
if ch == "}" {
depth = depth - 1
if depth == 0 {
return pos
}
}
pos = pos + 1
}
return -1
}
}