String unification bridge: VM string-like normalization (compare/add/method fallbacks) and Interpreter normalization for compare/add; fix lifetime issues; update CURRENT_TASK status

This commit is contained in:
Moe Charm
2025-08-30 23:58:58 +09:00
parent 4ae92cfb56
commit 8d7888f6f1
4 changed files with 122 additions and 27 deletions

View File

@ -11,6 +11,30 @@ use crate::mir::{BinaryOp, CompareOp, UnaryOp};
use super::vm::{VM, VMError, VMValue};
impl VM {
/// Try to view a BoxRef as a UTF-8 string (internal StringBox, Result.Ok(String-like), or plugin StringBox via toUtf8)
fn try_boxref_to_string(&self, b: &dyn crate::box_trait::NyashBox) -> Option<String> {
// Internal StringBox
if let Some(sb) = b.as_any().downcast_ref::<crate::box_trait::StringBox>() {
return Some(sb.value.clone());
}
// Result.Ok(inner) → recurse
if let Some(res) = b.as_any().downcast_ref::<crate::boxes::result::NyashResultBox>() {
if let crate::boxes::result::NyashResultBox::Ok(inner) = res { return self.try_boxref_to_string(inner.as_ref()); }
}
// Plugin StringBox → call toUtf8
if let Some(pb) = b.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
if pb.box_type == "StringBox" {
let host = crate::runtime::get_global_plugin_host();
let tmp: Option<String> = if let Ok(ro) = host.read() {
if let Ok(val_opt) = ro.invoke_instance_method("StringBox", "toUtf8", pb.inner.instance_id, &[]) {
if let Some(vb) = val_opt { if let Some(sb2) = vb.as_any().downcast_ref::<crate::box_trait::StringBox>() { Some(sb2.value.clone()) } else { None } } else { None }
} else { None }
} else { None };
if tmp.is_some() { return tmp; }
}
}
None
}
/// Execute binary operation
pub(super) fn execute_binary_op(&self, op: &BinaryOp, left: &VMValue, right: &VMValue) -> Result<VMValue, VMError> {
let debug_bin = std::env::var("NYASH_VM_DEBUG_BIN").ok().as_deref() == Some("1");
@ -57,12 +81,14 @@ impl VM {
// String + BoxRef concatenation
(VMValue::String(l), VMValue::BoxRef(r)) => {
match op { BinaryOp::Add => Ok(VMValue::String(format!("{}{}", l, r.to_string_box().value))), _ => Err(VMError::TypeError("String-BoxRef operations only support addition".to_string())) }
let rs = self.try_boxref_to_string(r.as_ref()).unwrap_or_else(|| r.to_string_box().value);
match op { BinaryOp::Add => Ok(VMValue::String(format!("{}{}", l, rs))), _ => Err(VMError::TypeError("String-BoxRef operations only support addition".to_string())) }
},
// BoxRef + String concatenation
(VMValue::BoxRef(l), VMValue::String(r)) => {
match op { BinaryOp::Add => Ok(VMValue::String(format!("{}{}", l.to_string_box().value, r))), _ => Err(VMError::TypeError("BoxRef-String operations only support addition".to_string())) }
let ls = self.try_boxref_to_string(l.as_ref()).unwrap_or_else(|| l.to_string_box().value);
match op { BinaryOp::Add => Ok(VMValue::String(format!("{}{}", ls, r))), _ => Err(VMError::TypeError("BoxRef-String operations only support addition".to_string())) }
},
// Arithmetic with BoxRef(IntegerBox) — support both legacy and new IntegerBox
@ -90,6 +116,15 @@ impl VM {
};
Ok(VMValue::Integer(res))
}
// BoxRef + BoxRef string-like concatenation
(VMValue::BoxRef(li), VMValue::BoxRef(ri)) => {
if matches!(*op, BinaryOp::Add) {
let ls = self.try_boxref_to_string(li.as_ref()).unwrap_or_else(|| li.to_string_box().value);
let rs = self.try_boxref_to_string(ri.as_ref()).unwrap_or_else(|| ri.to_string_box().value);
return Ok(VMValue::String(format!("{}{}", ls, rs)));
}
Err(VMError::TypeError("Unsupported BoxRef+BoxRef operation".to_string()))
}
// Mixed Integer forms
(VMValue::BoxRef(li), VMValue::Integer(r)) if li.as_any().downcast_ref::<crate::box_trait::IntegerBox>().is_some()