diff --git a/src/backend/mir_interpreter/handlers/boxes.rs b/src/backend/mir_interpreter/handlers/boxes.rs index 500ff7d9..3aaf1896 100644 --- a/src/backend/mir_interpreter/handlers/boxes.rs +++ b/src/backend/mir_interpreter/handlers/boxes.rs @@ -11,7 +11,7 @@ impl MirInterpreter { ) -> Result<(), VMError> { // Provider Lock guard (受け口・既定は挙動不変) if let Err(e) = crate::runtime::provider_lock::guard_before_new_box(box_type) { - return Err(VMError::InvalidInstruction(e)); + return Err(self.err_invalid(e)); } let mut converted: Vec> = Vec::with_capacity(args.len()); for vid in args { @@ -22,9 +22,7 @@ impl MirInterpreter { .lock() .unwrap() .create_box(box_type, &converted) - .map_err(|e| { - VMError::InvalidInstruction(format!("NewBox {} failed: {}", box_type, e)) - })?; + .map_err(|e| self.err_with_context(&format!("NewBox {}", box_type), &e.to_string()))?; // Store created instance first so 'me' can be passed to birth let created_vm = VMValue::from_nyash_box(created); self.regs.insert(dst, created_vm.clone()); @@ -74,10 +72,10 @@ impl MirInterpreter { } } Err(e) => { - return Err(VMError::InvalidInstruction(format!( - "PluginInvoke {}.{} failed: {:?}", - p.box_type, method, e - ))) + return Err(self.err_with_context( + &format!("PluginInvoke {}.{}", p.box_type, method), + &format!("{:?}", e) + )) } } Ok(()) @@ -88,11 +86,7 @@ impl MirInterpreter { } Ok(()) } else { - Err(VMError::InvalidInstruction(format!( - "PluginInvoke unsupported on {} for method {}", - recv_box.type_name(), - method - ))) + Err(self.err_method_not_found(&recv_box.type_name(), method)) } } @@ -188,7 +182,7 @@ impl MirInterpreter { } if user_instance_class.is_some() && !crate::config::env::vm_allow_user_instance_boxcall() { let cls = user_instance_class.unwrap(); - return Err(VMError::InvalidInstruction(format!( + return Err(self.err_invalid(format!( "User Instance BoxCall disallowed in prod: {}.{} (enable builder rewrite)", cls, method ))); diff --git a/src/backend/mir_interpreter/handlers/boxes_array.rs b/src/backend/mir_interpreter/handlers/boxes_array.rs index 41dcee9b..3226d242 100644 --- a/src/backend/mir_interpreter/handlers/boxes_array.rs +++ b/src/backend/mir_interpreter/handlers/boxes_array.rs @@ -32,7 +32,7 @@ pub(super) fn try_handle_array_box( return Ok(true); } "pop" => { - if !args.is_empty() { return Err(VMError::InvalidInstruction("pop expects 0 args".into())); } + if !args.is_empty() { return Err(this.err_invalid("pop expects 0 args")); } let ret = ab.pop(); this.write_result(dst, VMValue::from_nyash_box(ret)); return Ok(true); diff --git a/src/backend/mir_interpreter/handlers/boxes_instance.rs b/src/backend/mir_interpreter/handlers/boxes_instance.rs index e8596ff1..57d1fa2c 100644 --- a/src/backend/mir_interpreter/handlers/boxes_instance.rs +++ b/src/backend/mir_interpreter/handlers/boxes_instance.rs @@ -92,7 +92,7 @@ pub(super) fn try_handle_instance_box( // Dev assert: forbid birth(me==Void) if method == "birth" && crate::config::env::using_is_dev() { if matches!(recv_vm, VMValue::Void) { - return Err(VMError::InvalidInstruction("Dev assert: birth(me==Void) is forbidden".into())); + return Err(this.err_invalid("Dev assert: birth(me==Void) is forbidden")); } } argv.push(recv_vm.clone()); @@ -127,7 +127,7 @@ pub(super) fn try_handle_instance_box( let mut argv: Vec = Vec::with_capacity(1 + args.len()); if method == "birth" && crate::config::env::using_is_dev() { if matches!(recv_vm, VMValue::Void) { - return Err(VMError::InvalidInstruction("Dev assert: birth(me==Void) is forbidden".into())); + return Err(this.err_invalid("Dev assert: birth(me==Void) is forbidden")); } } argv.push(recv_vm.clone()); diff --git a/src/backend/mir_interpreter/handlers/boxes_plugin.rs b/src/backend/mir_interpreter/handlers/boxes_plugin.rs index 5ac03147..e04a7392 100644 --- a/src/backend/mir_interpreter/handlers/boxes_plugin.rs +++ b/src/backend/mir_interpreter/handlers/boxes_plugin.rs @@ -60,10 +60,10 @@ pub(super) fn invoke_plugin_box( } Ok(()) } - Err(e) => Err(VMError::InvalidInstruction(format!( - "BoxCall {}.{} failed: {:?}", - p.box_type, method, e - ))), + Err(e) => Err(this.err_with_context( + &format!("BoxCall {}.{}", p.box_type, method), + &format!("{:?}", e) + )), } } else if let Some(string_box) = recv_box .as_any() @@ -80,9 +80,7 @@ pub(super) fn invoke_plugin_box( } Ok(()) } else { - Err(VMError::InvalidInstruction( - "lastIndexOf requires 1 argument".into(), - )) + Err(this.err_invalid("lastIndexOf requires 1 argument")) } } "indexOf" | "find" => { @@ -94,15 +92,10 @@ pub(super) fn invoke_plugin_box( } Ok(()) } else { - Err(VMError::InvalidInstruction( - "indexOf/find requires 1 argument".into(), - )) + Err(this.err_invalid("indexOf/find requires 1 argument")) } } - _ => Err(VMError::InvalidInstruction(format!( - "BoxCall method {} not supported on StringBox", - method - ))), + _ => Err(this.err_method_not_found("StringBox", method)), } } else { // Special-case: minimal runtime fallback for common InstanceBox methods when @@ -209,10 +202,6 @@ pub(super) fn invoke_plugin_box( _ => {} } } - Err(VMError::InvalidInstruction(format!( - "BoxCall unsupported on {}.{}", - recv_box.type_name(), - method - ))) + Err(this.err_method_not_found(&recv_box.type_name(), method)) } } diff --git a/src/backend/mir_interpreter/handlers/boxes_string.rs b/src/backend/mir_interpreter/handlers/boxes_string.rs index 67e7bd70..19d32d9a 100644 --- a/src/backend/mir_interpreter/handlers/boxes_string.rs +++ b/src/backend/mir_interpreter/handlers/boxes_string.rs @@ -72,8 +72,8 @@ pub(super) fn try_handle_string_box( (n, from.max(0) as usize) } _ => { - return Err(VMError::InvalidInstruction( - "indexOf expects 1 or 2 args (search [, fromIndex])".into(), + return Err(this.err_invalid( + "indexOf expects 1 or 2 args (search [, fromIndex])" )); } }; @@ -144,8 +144,8 @@ pub(super) fn try_handle_string_box( (s, e) } _ => { - return Err(VMError::InvalidInstruction( - "substring expects 1 or 2 args (start [, end])".into(), + return Err(this.err_invalid( + "substring expects 1 or 2 args (start [, end])" )); } }; @@ -172,7 +172,7 @@ pub(super) fn try_handle_string_box( let s = this.reg_load(args[0])?.to_string(); s.chars().next() } else { - return Err(VMError::InvalidInstruction("is_digit_char expects 0 or 1 arg".into())); + return Err(this.err_invalid("is_digit_char expects 0 or 1 arg")); }; let is_digit = ch_opt.map(|c| c.is_ascii_digit()).unwrap_or(false); this.write_result(dst, VMValue::Bool(is_digit)); @@ -185,7 +185,7 @@ pub(super) fn try_handle_string_box( let s = this.reg_load(args[0])?.to_string(); s.chars().next() } else { - return Err(VMError::InvalidInstruction("is_hex_digit_char expects 0 or 1 arg".into())); + return Err(this.err_invalid("is_hex_digit_char expects 0 or 1 arg")); }; let is_hex = ch_opt.map(|c| c.is_ascii_hexdigit()).unwrap_or(false); this.write_result(dst, VMValue::Bool(is_hex)); diff --git a/src/backend/mir_interpreter/handlers/calls.rs b/src/backend/mir_interpreter/handlers/calls.rs index c953eec5..057c3374 100644 --- a/src/backend/mir_interpreter/handlers/calls.rs +++ b/src/backend/mir_interpreter/handlers/calls.rs @@ -424,15 +424,10 @@ impl MirInterpreter { if let Some(s) = first_arg_str { match crate::host_providers::mir_builder::program_json_to_mir_json(&s) { Ok(out) => Ok(VMValue::String(out)), - Err(e) => Err(VMError::InvalidInstruction(format!( - "env.mirbuilder.emit: {}", - e - ))), + Err(e) => Err(self.err_with_context("env.mirbuilder.emit", &e.to_string())), } } else { - Err(VMError::InvalidInstruction( - "extern_invoke env.mirbuilder.emit expects 1 arg".into(), - )) + Err(self.err_invalid("extern_invoke env.mirbuilder.emit expects 1 arg")) } } ("env.codegen", "emit_object") => { @@ -445,15 +440,10 @@ impl MirInterpreter { }; match crate::host_providers::llvm_codegen::mir_json_to_object(&s, opts) { Ok(p) => Ok(VMValue::String(p.to_string_lossy().into_owned())), - Err(e) => Err(VMError::InvalidInstruction(format!( - "env.codegen.emit_object: {}", - e - ))), + Err(e) => Err(self.err_with_context("env.codegen.emit_object", &e.to_string())), } } else { - Err(VMError::InvalidInstruction( - "extern_invoke env.codegen.emit_object expects 1 arg".into(), - )) + Err(self.err_invalid("extern_invoke env.codegen.emit_object expects 1 arg")) } } ("env.codegen", "link_object") => { @@ -611,7 +601,7 @@ impl MirInterpreter { if std::env::var("HAKO_CABI_TRACE").ok().as_deref() == Some("1") { eprintln!("[hb:unsupported:calls] {}.{}", name, method); } - Err(VMError::InvalidInstruction(format!( + Err(self.err_invalid(format!( "hostbridge.extern_invoke unsupported for {}.{} [calls]", name, method ))) @@ -705,9 +695,7 @@ impl MirInterpreter { let new_str = format!("{}{}", s, arg_val.to_string()); Ok(VMValue::String(new_str)) } else { - Err(VMError::InvalidInstruction( - "concat requires 1 argument".into(), - )) + Err(self.err_invalid("concat requires 1 argument")) } } "replace" => { @@ -716,9 +704,7 @@ impl MirInterpreter { let new = self.reg_load(args[1])?.to_string(); Ok(VMValue::String(s.replace(&old, &new))) } else { - Err(VMError::InvalidInstruction( - "replace requires 2 arguments".into(), - )) + Err(self.err_invalid("replace requires 2 arguments")) } } "indexOf" => { @@ -727,9 +713,7 @@ impl MirInterpreter { let idx = s.find(&needle).map(|i| i as i64).unwrap_or(-1); Ok(VMValue::Integer(idx)) } else { - Err(VMError::InvalidInstruction( - "indexOf requires 1 argument".into(), - )) + Err(self.err_invalid("indexOf requires 1 argument")) } } "lastIndexOf" => { @@ -738,9 +722,7 @@ impl MirInterpreter { let idx = s.rfind(&needle).map(|i| i as i64).unwrap_or(-1); Ok(VMValue::Integer(idx)) } else { - Err(VMError::InvalidInstruction( - "lastIndexOf requires 1 argument".into(), - )) + Err(self.err_invalid("lastIndexOf requires 1 argument")) } } "substring" => { @@ -774,9 +756,7 @@ impl MirInterpreter { let result_box = string_box.lastIndexOf(&needle); Ok(VMValue::from_nyash_box(result_box)) } else { - Err(VMError::InvalidInstruction( - "lastIndexOf requires 1 argument".into(), - )) + Err(self.err_invalid("lastIndexOf requires 1 argument")) } } "indexOf" | "find" => { @@ -785,9 +765,7 @@ impl MirInterpreter { let result_box = string_box.find(&needle); Ok(VMValue::from_nyash_box(result_box)) } else { - Err(VMError::InvalidInstruction( - "indexOf/find requires 1 argument".into(), - )) + Err(self.err_invalid("indexOf/find requires 1 argument")) } } _ => Err(self.err_method_not_found("StringBox", method)), @@ -811,17 +789,13 @@ impl MirInterpreter { ) { Ok(Some(ret)) => Ok(VMValue::from_nyash_box(ret)), Ok(None) => Ok(VMValue::Void), - Err(e) => Err(VMError::InvalidInstruction(format!( - "Plugin method {}.{} failed: {:?}", - p.box_type, method, e - ))), + Err(e) => Err(self.err_with_context( + &format!("Plugin method {}.{}", p.box_type, method), + &format!("{:?}", e) + )), } } else { - Err(VMError::InvalidInstruction(format!( - "Method {} not supported on BoxRef({})", - method, - box_ref.type_name() - ))) + Err(self.err_method_not_found(&box_ref.type_name(), method)) } } _ => Err(self.err_with_context("method call", &format!("{} not supported on {:?}", method, receiver))), diff --git a/src/backend/mir_interpreter/handlers/extern_provider.rs b/src/backend/mir_interpreter/handlers/extern_provider.rs index 3d00413f..0cbf1f32 100644 --- a/src/backend/mir_interpreter/handlers/extern_provider.rs +++ b/src/backend/mir_interpreter/handlers/extern_provider.rs @@ -82,7 +82,7 @@ impl MirInterpreter { // Only supported on C-API route; expect 1 or 2 args: obj_path [, exe_out] let obj_path = match args.get(0) { Some(v) => match self.reg_load(*v) { Ok(v) => v.to_string(), Err(e) => return Some(Err(e)) }, - None => return Some(Err(VMError::InvalidInstruction("env.codegen.link_object expects 1+ args".into()))), + None => return Some(Err(self.err_invalid("env.codegen.link_object expects 1+ args"))), }; let exe_out = match args.get(1) { Some(v) => Some(match self.reg_load(*v) { Ok(v) => v.to_string(), Err(e) => return Some(Err(e)) }), @@ -114,9 +114,7 @@ impl MirInterpreter { eprintln!("[hb:entry:provider] hostbridge.extern_invoke"); } if args.len() < 2 { - return Some(Err(VMError::InvalidInstruction( - "extern_invoke expects at least 2 args".into(), - ))); + return Some(Err(self.err_invalid("extern_invoke expects at least 2 args"))); } let name = match self.reg_load(args[0]) { Ok(v) => v.to_string(), Err(e) => return Some(Err(e)) }; let method = match self.reg_load(args[1]) { Ok(v) => v.to_string(), Err(e) => return Some(Err(e)) }; @@ -186,7 +184,7 @@ impl MirInterpreter { _ => (v.to_string(), None), } } else { - return Some(Err(VMError::InvalidInstruction("extern_invoke env.codegen.link_object expects args array".into()))); + return Some(Err(self.err_invalid("extern_invoke env.codegen.link_object expects args array"))); }; if std::env::var("NYASH_LLVM_USE_CAPI").ok().as_deref() != Some("1") || std::env::var("HAKO_V1_EXTERN_PROVIDER_C_ABI").ok().as_deref() != Some("1") { @@ -204,15 +202,10 @@ impl MirInterpreter { if let Some(s) = first_arg_str { match crate::host_providers::mir_builder::program_json_to_mir_json(&s) { Ok(out) => Ok(VMValue::String(Self::patch_mir_json_version(&out))), - Err(e) => Err(VMError::InvalidInstruction(format!( - "env.mirbuilder.emit: {}", - e - ))), + Err(e) => Err(self.err_with_context("env.mirbuilder.emit", &e.to_string())), } } else { - Err(VMError::InvalidInstruction( - "extern_invoke env.mirbuilder.emit expects 1 arg".into(), - )) + Err(self.err_invalid("extern_invoke env.mirbuilder.emit expects 1 arg")) } } ("env.codegen", "emit_object") => { @@ -225,15 +218,10 @@ impl MirInterpreter { }; match crate::host_providers::llvm_codegen::mir_json_to_object(&s, opts) { Ok(p) => Ok(VMValue::String(p.to_string_lossy().into_owned())), - Err(e) => Err(VMError::InvalidInstruction(format!( - "env.codegen.emit_object: {}", - e - ))), + Err(e) => Err(self.err_with_context("env.codegen.emit_object", &e.to_string())), } } else { - Err(VMError::InvalidInstruction( - "extern_invoke env.codegen.emit_object expects 1 arg".into(), - )) + Err(self.err_invalid("extern_invoke env.codegen.emit_object expects 1 arg")) } } ("env.codegen", "link_object") => { @@ -267,7 +255,7 @@ impl MirInterpreter { } let objs = match obj_s { Some(s) => s, - None => return Some(Err(VMError::InvalidInstruction("extern_invoke env.codegen.link_object expects args".into()))), + None => return Some(Err(self.err_invalid("extern_invoke env.codegen.link_object expects args"))), }; if std::env::var("NYASH_LLVM_USE_CAPI").ok().as_deref() != Some("1") || std::env::var("HAKO_V1_EXTERN_PROVIDER_C_ABI").ok().as_deref() != Some("1") { @@ -285,7 +273,7 @@ impl MirInterpreter { if std::env::var("HAKO_CABI_TRACE").ok().as_deref() == Some("1") { eprintln!("[hb:unsupported:provider] {}.{}", name, method); } - Err(VMError::InvalidInstruction(format!( + Err(self.err_invalid(format!( "hostbridge.extern_invoke unsupported for {}.{} [provider]", name, method ))) diff --git a/src/backend/mir_interpreter/handlers/externals.rs b/src/backend/mir_interpreter/handlers/externals.rs index a80e340e..1ccd1185 100644 --- a/src/backend/mir_interpreter/handlers/externals.rs +++ b/src/backend/mir_interpreter/handlers/externals.rs @@ -155,7 +155,7 @@ impl MirInterpreter { // Note: This branch is used for ExternCall form; provider toggles must be ON. if std::env::var("NYASH_LLVM_USE_CAPI").ok().as_deref() != Some("1") || std::env::var("HAKO_V1_EXTERN_PROVIDER_C_ABI").ok().as_deref() != Some("1") { - return Err(VMError::InvalidInstruction("env.codegen.link_object: C-API route disabled".into())); + return Err(self.err_invalid("env.codegen.link_object: C-API route disabled")); } // Extract array payload let (obj_path, exe_out) = if let Some(a2) = args.get(2) { @@ -177,13 +177,13 @@ impl MirInterpreter { _ => (v.to_string(), None), } } else { - return Err(VMError::InvalidInstruction("extern_invoke env.codegen.link_object expects args array".into())); + return Err(self.err_invalid("extern_invoke env.codegen.link_object expects args array")); }; let extra = std::env::var("HAKO_AOT_LDFLAGS").ok(); let obj = std::path::PathBuf::from(obj_path); let exe = exe_out.map(std::path::PathBuf::from).unwrap_or_else(|| std::env::temp_dir().join("hako_link_out.exe")); crate::host_providers::llvm_codegen::link_object_capi(&obj, &exe, extra.as_deref()) - .map_err(|e| VMError::InvalidInstruction(format!("env.codegen.link_object: {}", e)))?; + .map_err(|e| self.err_with_context("env.codegen.link_object", &e.to_string()))?; self.write_result(dst, VMValue::String(exe.to_string_lossy().into_owned())); Ok(()) } @@ -195,9 +195,9 @@ impl MirInterpreter { } return Ok(()); } - return Err(VMError::InvalidInstruction("hostbridge.extern_invoke unsupported [externals]".into())); + return Err(self.err_invalid("hostbridge.extern_invoke unsupported [externals]")); } - _ => Err(VMError::InvalidInstruction(format!( + _ => Err(self.err_invalid(format!( "ExternCall {}.{} not supported", iface, method ))), diff --git a/src/backend/mir_interpreter/handlers/mod.rs b/src/backend/mir_interpreter/handlers/mod.rs index 1241d32d..5b30ad13 100644 --- a/src/backend/mir_interpreter/handlers/mod.rs +++ b/src/backend/mir_interpreter/handlers/mod.rs @@ -96,7 +96,7 @@ impl MirInterpreter { | MirInstruction::Safepoint | MirInstruction::Nop => {} other => { - return Err(VMError::InvalidInstruction(format!( + return Err(self.err_invalid(format!( "MIR interp: unimplemented instruction: {:?}", other )))