phase-20.39 step3 (partial): concat-safety in vm helpers – add StrCast, refactor MiniMap, ValueManager, MiniArray/MiniMap2, mir_call_v1_handler, extern provider/call; keep behavior; canaries PASS
This commit is contained in:
@ -5,7 +5,8 @@ box MiniArray {
|
|||||||
field data: String
|
field data: String
|
||||||
birth() { me.data = "" return 0 }
|
birth() { me.data = "" return 0 }
|
||||||
push(v) {
|
push(v) {
|
||||||
v = "" + v
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
v = StrCast.to_str(v)
|
||||||
if me.data == "" { me.data = v } else { me.data = me.data + "," + v }
|
if me.data == "" { me.data = v } else { me.data = me.data + "," + v }
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -26,14 +27,15 @@ box MiniArray {
|
|||||||
// Fail‑Fast accessor: returns element string; prints error and returns 0 on OOB
|
// Fail‑Fast accessor: returns element string; prints error and returns 0 on OOB
|
||||||
at(index) {
|
at(index) {
|
||||||
// normalize and validate index
|
// normalize and validate index
|
||||||
local si = "" + index
|
using selfhost.shared.common.string_helpers as StringHelpers
|
||||||
|
local si = StringHelpers.int_to_str(index)
|
||||||
local idx = 0
|
local idx = 0
|
||||||
if si != "" {
|
if si != "" {
|
||||||
local i = 0
|
local i = 0
|
||||||
loop(i < si.length()) { idx = idx * 10 + ("0123456789".indexOf(si.substring(i,i+1))) i = i + 1 }
|
loop(i < si.length()) { idx = idx * 10 + ("0123456789".indexOf(si.substring(i,i+1))) i = i + 1 }
|
||||||
}
|
}
|
||||||
local n = me.length()
|
local n = me.length()
|
||||||
if idx < 0 || idx >= n { print("[ERROR] MiniArray.at: index out of range: " + (""+idx) + "/" + (""+n)) return 0 }
|
if idx < 0 || idx >= n { print("[ERROR] MiniArray.at: index out of range: " + StringHelpers.int_to_str(idx) + "/" + StringHelpers.int_to_str(n)) return 0 }
|
||||||
// find start position of idx-th element
|
// find start position of idx-th element
|
||||||
local s = me.data
|
local s = me.data
|
||||||
local pos = 0
|
local pos = 0
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
// mini_map_box.hako — MiniMap
|
// mini_map_box.hako — MiniMap
|
||||||
// Responsibility: minimal string-backed map for Mini‑VM registers
|
// Responsibility: minimal string-backed map for Mini‑VM registers
|
||||||
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
|
||||||
box MiniMap {
|
box MiniMap {
|
||||||
store: StringBox
|
store: StringBox
|
||||||
@ -8,8 +9,8 @@ box MiniMap {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
set(key, value) {
|
set(key, value) {
|
||||||
key = "" + key
|
key = StrCast.to_str(key)
|
||||||
value = "" + value
|
value = StrCast.to_str(value)
|
||||||
// remove existing key
|
// remove existing key
|
||||||
local out = ""
|
local out = ""
|
||||||
local s = me.store
|
local s = me.store
|
||||||
@ -31,7 +32,7 @@ box MiniMap {
|
|||||||
// Compatibility: hv1 helpers expect getField/setField
|
// Compatibility: hv1 helpers expect getField/setField
|
||||||
setField(key, value) { return me.set(key, value) }
|
setField(key, value) { return me.set(key, value) }
|
||||||
get(key) {
|
get(key) {
|
||||||
key = "" + key
|
key = StrCast.to_str(key)
|
||||||
local s = me.store
|
local s = me.store
|
||||||
local pos = 0
|
local pos = 0
|
||||||
local last = null
|
local last = null
|
||||||
|
|||||||
@ -31,7 +31,7 @@ static box MirCallV1HandlerBox {
|
|||||||
// Per‑receiver or global length counter
|
// Per‑receiver or global length counter
|
||||||
local per_recv = env.get("HAKO_VM_MIRCALL_SIZESTATE_PER_RECV"); if per_recv == null { per_recv = "0" }
|
local per_recv = env.get("HAKO_VM_MIRCALL_SIZESTATE_PER_RECV"); if per_recv == null { per_recv = "0" }
|
||||||
local key = "__vm_len"
|
local key = "__vm_len"
|
||||||
if ("" + per_recv) == "1" {
|
if StringHelpers.int_to_str(per_recv) == "1" {
|
||||||
local rid = MiniMirV1Scan.receiver_id(seg)
|
local rid = MiniMirV1Scan.receiver_id(seg)
|
||||||
if rid != null { key = "__vm_len:" + (""+rid) }
|
if rid != null { key = "__vm_len:" + (""+rid) }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,8 @@ static box MirVmMin {
|
|||||||
_tprint(msg) {
|
_tprint(msg) {
|
||||||
// Only emit hard errors by default; avoid env dependencies in Mini‑VM
|
// Only emit hard errors by default; avoid env dependencies in Mini‑VM
|
||||||
// Coerce to string to avoid VoidBox receiver issues during early boot
|
// Coerce to string to avoid VoidBox receiver issues during early boot
|
||||||
msg = "" + msg
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
msg = StrCast.to_str(msg)
|
||||||
if msg.indexOf("[ERROR]") >= 0 { print(msg) }
|
if msg.indexOf("[ERROR]") >= 0 { print(msg) }
|
||||||
}
|
}
|
||||||
_d(msg, trace) { if trace == 1 { print(msg) } }
|
_d(msg, trace) { if trace == 1 { print(msg) } }
|
||||||
|
|||||||
@ -10,9 +10,11 @@ using selfhost.shared.json.core.json_cursor as JsonCursorBox
|
|||||||
static box RetResolveSimpleBox {
|
static box RetResolveSimpleBox {
|
||||||
_to_i64(s) { return StringHelpers.to_i64(s) }
|
_to_i64(s) { return StringHelpers.to_i64(s) }
|
||||||
_load_reg(regs, id) {
|
_load_reg(regs, id) {
|
||||||
local v = regs.get("" + id)
|
using selfhost.shared.common.string_helpers as StringHelpers
|
||||||
|
local v = regs.get(StringHelpers.int_to_str(id))
|
||||||
if v == null { return 0 }
|
if v == null { return 0 }
|
||||||
local s = "" + v
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
local s = StrCast.to_str(v)
|
||||||
if StringHelpers.is_numeric_str(s) == 1 { return me._to_i64(s) }
|
if StringHelpers.is_numeric_str(s) == 1 { return me._to_i64(s) }
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,8 @@ static box ExternCallHandlerBox {
|
|||||||
local p = env.get("HAKO_NYVM_EXTERN_POLICY")
|
local p = env.get("HAKO_NYVM_EXTERN_POLICY")
|
||||||
if p == null { p = env.get("NYASH_NYVM_EXTERN_POLICY") }
|
if p == null { p = env.get("NYASH_NYVM_EXTERN_POLICY") }
|
||||||
if p == null { return 0 }
|
if p == null { return 0 }
|
||||||
local s = "" + p
|
using selfhost.shared.common.string_helpers as StringHelpers
|
||||||
|
local s = StringHelpers.int_to_str(p)
|
||||||
s = s.to_lower()
|
s = s.to_lower()
|
||||||
if s == "allow" || s == "allowlist" || s == "on" || s == "1" { return 1 }
|
if s == "allow" || s == "allowlist" || s == "on" || s == "1" { return 1 }
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@ -8,13 +8,15 @@ static box HakoruneExternProviderBox {
|
|||||||
if name == "env.get" {
|
if name == "env.get" {
|
||||||
if args == null { return null }
|
if args == null { return null }
|
||||||
// args: single string key
|
// args: single string key
|
||||||
local key = "" + args
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
local key = StrCast.to_str(args)
|
||||||
return env.get(key)
|
return env.get(key)
|
||||||
}
|
}
|
||||||
if name == "env.console.log" || name == "nyash.console.log" || name == "print" {
|
if name == "env.console.log" || name == "nyash.console.log" || name == "print" {
|
||||||
// Accept single argument value → print as string
|
// Accept single argument value → print as string
|
||||||
if args == null { print(""); return 0 }
|
if args == null { print(""); return 0 }
|
||||||
print("" + args)
|
using selfhost.vm.hakorune-vm.str_cast as StrCast
|
||||||
|
print(StrCast.to_str(args))
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if name == "env.console.warn" || name == "nyash.console.warn" {
|
if name == "env.console.warn" || name == "nyash.console.warn" {
|
||||||
|
|||||||
14
lang/src/vm/hakorune-vm/str_cast.hako
Normal file
14
lang/src/vm/hakorune-vm/str_cast.hako
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// str_cast.hako — StrCast
|
||||||
|
// Responsibility: centralize to-string coercion used by hv1 helpers.
|
||||||
|
// Note: Uses minimal fallback concatenation internally to avoid scattered ""+x in codebase.
|
||||||
|
|
||||||
|
static box StrCast {
|
||||||
|
to_str(x) {
|
||||||
|
if x == null { return "" }
|
||||||
|
// Fallback coercion
|
||||||
|
return "" + x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static box StrCastMain { method main(args) { return 0 } }
|
||||||
|
|
||||||
@ -93,7 +93,8 @@ static box ValueManagerBox {
|
|||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
_map_key_str(value) {
|
_map_key_str(value) {
|
||||||
return "" + value
|
// Keys for map meta should be string; centralize conversion
|
||||||
|
return StringHelpers.int_to_str(value)
|
||||||
}
|
}
|
||||||
mark_map_entry(regs, reg_id, key_value) {
|
mark_map_entry(regs, reg_id, key_value) {
|
||||||
local meta = me._meta(regs)
|
local meta = me._meta(regs)
|
||||||
|
|||||||
Reference in New Issue
Block a user