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:
@ -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()
|
||||
|
||||
Reference in New Issue
Block a user