Phase 5: Complete destination pattern unification (28 sites, 53 lines)
Unified remaining destination write patterns with new helpers: - write_string() for VMValue::String writes - write_from_box() for VMValue::from_nyash_box() patterns Files updated: - boxes.rs: 8 sites unified (-14 lines) - boxes_plugin.rs: 9 sites unified (-17 lines) - boxes_object_fields.rs: 7 sites unified (-14 lines) - boxes_instance.rs: 2 sites unified (-4 lines) - calls.rs: 2 sites unified (-4 lines) - destination_helpers.rs: +28 lines (new helpers) Impact: 28 sites unified, net -25 lines, improved maintainability Tests: Phase 21.0 PASS (2/2, 100%) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -62,14 +62,10 @@ impl MirInterpreter {
|
||||
}
|
||||
match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) {
|
||||
Ok(Some(ret)) => {
|
||||
if let Some(d) = dst {
|
||||
self.regs.insert(d, VMValue::from_nyash_box(ret));
|
||||
}
|
||||
self.write_from_box(dst, ret);
|
||||
}
|
||||
Ok(None) => {
|
||||
if let Some(d) = dst {
|
||||
self.regs.insert(d, VMValue::Void);
|
||||
}
|
||||
self.write_void(dst);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(self.err_with_context(
|
||||
@ -80,10 +76,7 @@ impl MirInterpreter {
|
||||
}
|
||||
Ok(())
|
||||
} else if method == "toString" {
|
||||
if let Some(d) = dst {
|
||||
self.regs
|
||||
.insert(d, VMValue::String(recv_box.to_string_box().value));
|
||||
}
|
||||
self.write_string(dst, recv_box.to_string_box().value);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(self.err_method_not_found(&recv_box.type_name(), method))
|
||||
@ -100,12 +93,12 @@ impl MirInterpreter {
|
||||
// Dev-safe: stringify(Void) → "null" (最小安全弁)
|
||||
if method == "stringify" {
|
||||
if let VMValue::Void = self.reg_load(box_val)? {
|
||||
if let Some(d) = dst { self.regs.insert(d, VMValue::String("null".to_string())); }
|
||||
self.write_string(dst, "null".to_string());
|
||||
return Ok(());
|
||||
}
|
||||
if let VMValue::BoxRef(b) = self.reg_load(box_val)? {
|
||||
if b.as_any().downcast_ref::<crate::box_trait::VoidBox>().is_some() {
|
||||
if let Some(d) = dst { self.regs.insert(d, VMValue::String("null".to_string())); }
|
||||
self.write_string(dst, "null".to_string());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -151,14 +144,14 @@ impl MirInterpreter {
|
||||
match self.reg_load(box_val)? {
|
||||
VMValue::Void => {
|
||||
if let Some(val) = super::boxes_void_guards::handle_void_method(method) {
|
||||
if let Some(d) = dst { self.regs.insert(d, val); }
|
||||
self.write_result(dst, val);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
VMValue::BoxRef(ref b) => {
|
||||
if b.as_any().downcast_ref::<crate::box_trait::VoidBox>().is_some() {
|
||||
if let Some(val) = super::boxes_void_guards::handle_void_method(method) {
|
||||
if let Some(d) = dst { self.regs.insert(d, val); }
|
||||
self.write_result(dst, val);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -259,7 +252,7 @@ impl MirInterpreter {
|
||||
argv.push(recv_vm);
|
||||
for a in args { argv.push(self.reg_load(*a)?); }
|
||||
let ret = self.exec_function_inner(&func, Some(&argv))?;
|
||||
if let Some(d) = dst { self.regs.insert(d, ret); }
|
||||
self.write_result(dst, ret);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ pub(super) fn try_handle_instance_box(
|
||||
argv.push(recv_vm.clone());
|
||||
for a in args { argv.push(this.reg_load(*a)?); }
|
||||
let ret = this.exec_function_inner(&func, Some(&argv))?;
|
||||
if let Some(d) = dst { this.regs.insert(d, ret); }
|
||||
this.write_result(dst, ret);
|
||||
return Ok(true);
|
||||
} else {
|
||||
// Conservative fallback: search unique function by name tail ".method/arity"
|
||||
|
||||
@ -52,7 +52,7 @@ pub(super) fn try_handle_object_fields(
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::String("[map/bad-key] field name must be string".to_string())); }
|
||||
this.write_string(dst, "[map/bad-key] field name must be string".to_string());
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@ -113,19 +113,17 @@ pub(super) fn try_handle_object_fields(
|
||||
if std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
||||
eprintln!("[vm-trace] getField internal {}.{} -> {:?}", inst.class_name, fname, nv);
|
||||
}
|
||||
if let Some(d) = dst {
|
||||
// Special-case: NV::Box should surface as VMValue::BoxRef
|
||||
if let crate::value::NyashValue::Box(ref arc_m) = nv {
|
||||
if let Ok(guard) = arc_m.lock() {
|
||||
let cloned: Box<dyn crate::box_trait::NyashBox> = guard.clone_box();
|
||||
let arc: std::sync::Arc<dyn crate::box_trait::NyashBox> = std::sync::Arc::from(cloned);
|
||||
this.regs.insert(d, VMValue::BoxRef(arc));
|
||||
this.write_result(dst, VMValue::BoxRef(arc));
|
||||
} else {
|
||||
this.regs.insert(d, VMValue::Void);
|
||||
this.write_void(dst);
|
||||
}
|
||||
} else {
|
||||
this.regs.insert(d, nv_to_vm(&nv));
|
||||
}
|
||||
this.write_result(dst, nv_to_vm(&nv));
|
||||
}
|
||||
// Trace get
|
||||
if MirInterpreter::box_trace_enabled() {
|
||||
@ -157,7 +155,7 @@ pub(super) fn try_handle_object_fields(
|
||||
if std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
||||
eprintln!("[vm-trace] getField default JsonScanner.{} -> {:?}", fname, v);
|
||||
}
|
||||
if let Some(d) = dst { this.regs.insert(d, v); }
|
||||
this.write_result(dst, v);
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
@ -175,7 +173,7 @@ pub(super) fn try_handle_object_fields(
|
||||
if std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
|
||||
eprintln!("[vm-trace] getField default(JsonScanner missing) {} -> {:?}", fname, v);
|
||||
}
|
||||
if let Some(d) = dst { this.regs.insert(d, v.clone()); }
|
||||
this.write_result(dst, v.clone());
|
||||
if MirInterpreter::box_trace_enabled() {
|
||||
let kind = match &v {
|
||||
VMValue::Integer(_) => "Integer",
|
||||
@ -194,7 +192,7 @@ pub(super) fn try_handle_object_fields(
|
||||
}
|
||||
// Finally: legacy fields (SharedNyashBox) for complex values
|
||||
if let Some(shared) = inst.get_field(&fname) {
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::BoxRef(shared.clone())); }
|
||||
this.write_result(dst, VMValue::BoxRef(shared.clone()));
|
||||
if MirInterpreter::box_trace_enabled() {
|
||||
this.box_trace_emit_get(&inst.class_name, &fname, "BoxRef");
|
||||
}
|
||||
@ -269,7 +267,7 @@ pub(super) fn try_handle_object_fields(
|
||||
eprintln!("[vm-trace] getField legacy {} -> {:?}", fname, v);
|
||||
}
|
||||
}
|
||||
if let Some(d) = dst { this.regs.insert(d, v.clone()); }
|
||||
this.write_result(dst, v.clone());
|
||||
if MirInterpreter::box_trace_enabled() {
|
||||
let kind = match &v {
|
||||
VMValue::Integer(_) => "Integer",
|
||||
@ -309,7 +307,7 @@ pub(super) fn try_handle_object_fields(
|
||||
return Ok(true);
|
||||
}
|
||||
} else {
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::String("[map/bad-key] field name must be string".to_string())); }
|
||||
this.write_string(dst, "[map/bad-key] field name must be string".to_string());
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,9 +36,7 @@ pub(super) fn invoke_plugin_box(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(d) = dst {
|
||||
this.regs.insert(d, VMValue::String(s));
|
||||
}
|
||||
this.write_string(dst, s);
|
||||
return Ok(());
|
||||
}
|
||||
let host = crate::runtime::plugin_loader_unified::get_global_plugin_host();
|
||||
@ -49,15 +47,11 @@ pub(super) fn invoke_plugin_box(
|
||||
}
|
||||
match host.invoke_instance_method(&p.box_type, method, p.inner.instance_id, &argv) {
|
||||
Ok(Some(ret)) => {
|
||||
if let Some(d) = dst {
|
||||
this.regs.insert(d, VMValue::from_nyash_box(ret));
|
||||
}
|
||||
this.write_from_box(dst, ret);
|
||||
Ok(())
|
||||
}
|
||||
Ok(None) => {
|
||||
if let Some(d) = dst {
|
||||
this.regs.insert(d, VMValue::Void);
|
||||
}
|
||||
this.write_void(dst);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(this.err_with_context(
|
||||
@ -75,9 +69,7 @@ pub(super) fn invoke_plugin_box(
|
||||
if let Some(arg_id) = args.get(0) {
|
||||
let needle = this.reg_load(*arg_id)?.to_string();
|
||||
let result_box = string_box.lastIndexOf(&needle);
|
||||
if let Some(d) = dst {
|
||||
this.regs.insert(d, VMValue::from_nyash_box(result_box));
|
||||
}
|
||||
this.write_from_box(dst, result_box);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(this.err_invalid("lastIndexOf requires 1 argument"))
|
||||
@ -87,9 +79,7 @@ pub(super) fn invoke_plugin_box(
|
||||
if let Some(arg_id) = args.get(0) {
|
||||
let needle = this.reg_load(*arg_id)?.to_string();
|
||||
let result_box = string_box.find(&needle);
|
||||
if let Some(d) = dst {
|
||||
this.regs.insert(d, VMValue::from_nyash_box(result_box));
|
||||
}
|
||||
this.write_from_box(dst, result_box);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(this.err_invalid("indexOf/find requires 1 argument"))
|
||||
@ -122,15 +112,13 @@ pub(super) fn invoke_plugin_box(
|
||||
}
|
||||
// Generic toString fallback for any non-plugin box
|
||||
if method == "toString" {
|
||||
if let Some(d) = dst {
|
||||
// Map VoidBox.toString → "null" for JSON-friendly semantics
|
||||
let s = if recv_box.as_any().downcast_ref::<crate::box_trait::VoidBox>().is_some() {
|
||||
"null".to_string()
|
||||
} else {
|
||||
recv_box.to_string_box().value
|
||||
};
|
||||
this.regs.insert(d, VMValue::String(s));
|
||||
}
|
||||
this.write_string(dst, s);
|
||||
return Ok(());
|
||||
}
|
||||
// Minimal runtime fallback for common InstanceBox.is_eof when lowered function is not present.
|
||||
@ -167,7 +155,7 @@ pub(super) fn invoke_plugin_box(
|
||||
argv.push(this.reg_load(*a)?);
|
||||
}
|
||||
let ret = this.exec_function_inner(&func, Some(&argv))?;
|
||||
if let Some(d) = dst { this.regs.insert(d, ret); }
|
||||
this.write_result(dst, ret);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -175,7 +163,7 @@ pub(super) fn invoke_plugin_box(
|
||||
// when no class-specific handler is available. This avoids hard stops in JSON lint smokes
|
||||
// while builder rewrite and instance dispatch stabilize.
|
||||
if method == "current" && args.is_empty() {
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::String(String::new())); }
|
||||
this.write_string(dst, String::new());
|
||||
return Ok(());
|
||||
}
|
||||
// VoidBox graceful handling for common container-like methods
|
||||
@ -187,7 +175,7 @@ pub(super) fn invoke_plugin_box(
|
||||
return Ok(());
|
||||
}
|
||||
"stringify" => {
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::String("null".to_string())); }
|
||||
this.write_string(dst, "null".to_string());
|
||||
return Ok(());
|
||||
}
|
||||
"array_size" | "length" | "size" => {
|
||||
|
||||
@ -24,7 +24,7 @@ impl MirInterpreter {
|
||||
if let Some(Callee::Global(func_name)) = callee {
|
||||
if func_name == "hostbridge.extern_invoke" || func_name.starts_with("hostbridge.extern_invoke/") {
|
||||
let v = self.execute_extern_function("hostbridge.extern_invoke", args)?;
|
||||
if let Some(d) = dst { self.regs.insert(d, v); }
|
||||
self.write_result(dst, v);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -33,9 +33,7 @@ impl MirInterpreter {
|
||||
} else {
|
||||
self.execute_legacy_call(func, args)?
|
||||
};
|
||||
if let Some(d) = dst {
|
||||
self.regs.insert(d, call_result);
|
||||
}
|
||||
self.write_result(dst, call_result);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -45,4 +45,32 @@ impl MirInterpreter {
|
||||
self.regs.insert(d, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// String値をdestinationに書き込む
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dst` - 書き込み先のValueId (Noneの場合は何もしない)
|
||||
/// * `value` - 書き込むString
|
||||
#[inline]
|
||||
pub(crate) fn write_string(&mut self, dst: Option<ValueId>, value: String) {
|
||||
if let Some(d) = dst {
|
||||
self.regs.insert(d, VMValue::String(value));
|
||||
}
|
||||
}
|
||||
|
||||
/// Box<dyn NyashBox>をVMValueに変換してdestinationに書き込む
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `dst` - 書き込み先のValueId (Noneの場合は何もしない)
|
||||
/// * `nyash_box` - 書き込むBox (NullBox→Void, IntegerBox→Integer等に自動変換)
|
||||
#[inline]
|
||||
pub(crate) fn write_from_box(
|
||||
&mut self,
|
||||
dst: Option<ValueId>,
|
||||
nyash_box: Box<dyn crate::box_trait::NyashBox>,
|
||||
) {
|
||||
if let Some(d) = dst {
|
||||
self.regs.insert(d, VMValue::from_nyash_box(nyash_box));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user