builder/vm: stabilize json_lint_vm under unified calls
- Fix condition_fn resolution: Value call path + dev safety + stub injection - VM bridge: handle Method::birth via BoxCall; ArrayBox push/get/length/set direct bridge - Receiver safety: pin receiver in method_call_handlers to avoid undefined use across blocks - Local vars: materialize on declaration (use init ValueId; void for uninit) - Prefer legacy BoxCall for Array/Map/String/user boxes in emit_box_or_plugin_call (stability-first) - Test runner: update LLVM hint to llvmlite harness (remove LLVM_SYS_180_PREFIX guidance) - Docs/roadmap: update CURRENT_TASK with unified default-ON + guards Note: NYASH_DEV_BIRTH_INJECT_BUILTINS=1 can re-enable builtin birth() injection during migration.
This commit is contained in:
@ -26,15 +26,52 @@ impl MirInterpreter {
|
||||
) -> Result<VMValue, VMError> {
|
||||
match callee {
|
||||
Callee::Global(func_name) => self.execute_global_function(func_name, args),
|
||||
Callee::Method {
|
||||
box_name: _,
|
||||
method,
|
||||
receiver,
|
||||
certainty: _,
|
||||
} => {
|
||||
Callee::Method { box_name: _, method, receiver, certainty: _, } => {
|
||||
if let Some(recv_id) = receiver {
|
||||
let recv_val = self.reg_load(*recv_id)?;
|
||||
let dev_trace = std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1");
|
||||
// Fast bridge for builtin boxes (Array) and common methods.
|
||||
// Preserve legacy semantics when plugins are absent.
|
||||
if let VMValue::BoxRef(bx) = &recv_val {
|
||||
// ArrayBox bridge
|
||||
if let Some(arr) = bx.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
|
||||
match method.as_str() {
|
||||
"birth" => { return Ok(VMValue::Void); }
|
||||
"push" => {
|
||||
if let Some(a0) = args.get(0) {
|
||||
let v = self.reg_load(*a0)?.to_nyash_box();
|
||||
let _ = arr.push(v);
|
||||
return Ok(VMValue::Void);
|
||||
}
|
||||
}
|
||||
"len" | "length" | "size" => {
|
||||
let ret = arr.length();
|
||||
return Ok(VMValue::from_nyash_box(ret));
|
||||
}
|
||||
"get" => {
|
||||
if let Some(a0) = args.get(0) {
|
||||
let idx = self.reg_load(*a0)?.to_nyash_box();
|
||||
let ret = arr.get(idx);
|
||||
return Ok(VMValue::from_nyash_box(ret));
|
||||
}
|
||||
}
|
||||
"set" => {
|
||||
if args.len() >= 2 {
|
||||
let idx = self.reg_load(args[0])?.to_nyash_box();
|
||||
let val = self.reg_load(args[1])?.to_nyash_box();
|
||||
let _ = arr.set(idx, val);
|
||||
return Ok(VMValue::Void);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Minimal bridge for birth(): delegate to BoxCall handler and return Void
|
||||
if method == &"birth" {
|
||||
let _ = self.handle_box_call(None, *recv_id, method, args)?;
|
||||
return Ok(VMValue::Void);
|
||||
}
|
||||
let is_kw = method == &"keyword_to_token_type";
|
||||
if dev_trace && is_kw {
|
||||
let a0 = args.get(0).and_then(|id| self.reg_load(*id).ok());
|
||||
|
||||
@ -62,18 +62,20 @@ fn reroute_to_correct_method(
|
||||
}
|
||||
|
||||
/// Try mapping special methods to canonical targets (table-driven).
|
||||
/// Example: toString/0 → stringify/0 (prefer instance class, then base class without "Instance" suffix).
|
||||
/// Example: toString/0 → str/0(互換: stringify/0)(prefer instance class, then base class without "Instance" suffix).
|
||||
fn try_special_reroute(
|
||||
interp: &mut MirInterpreter,
|
||||
recv_cls: &str,
|
||||
parsed: &ParsedSig<'_>,
|
||||
arg_vals: Option<&[VMValue]>,
|
||||
) -> Option<Result<VMValue, VMError>> {
|
||||
// toString → stringify
|
||||
// toString → str(互換: stringify)
|
||||
if parsed.method == "toString" && parsed.arity_str == "0" {
|
||||
// Prefer instance class stringify first, then base (strip trailing "Instance")
|
||||
// Prefer instance class 'str' first, then base(strip trailing "Instance")。なければ 'stringify' を互換で探す
|
||||
let base = recv_cls.strip_suffix("Instance").unwrap_or(recv_cls);
|
||||
let candidates = [
|
||||
format!("{}.str/0", recv_cls),
|
||||
format!("{}.str/0", base),
|
||||
format!("{}.stringify/0", recv_cls),
|
||||
format!("{}.stringify/0", base),
|
||||
];
|
||||
@ -91,7 +93,7 @@ fn try_special_reroute(
|
||||
"method": parsed.method,
|
||||
"arity": parsed.arity_str,
|
||||
"target": name,
|
||||
"reason": "toString->stringify",
|
||||
"reason": if name.ends_with(".str/0") { "toString->str" } else { "toString->stringify" },
|
||||
}),
|
||||
);
|
||||
return Some(interp.exec_function_inner(&f, arg_vals));
|
||||
|
||||
Reference in New Issue
Block a user