use crate::bytecode::{Instruction, OpCode, Operand};
use shape_value::v2::string_obj::StringObj;
use shape_value::{NativeKind, VMError};
use super::super::VirtualMachine;
impl VirtualMachine {
pub(crate) fn exec_v2_string(
&mut self,
instruction: &Instruction,
) -> Result<(), VMError> {
match instruction.opcode {
OpCode::NewStringV2 => {
let str_id = match instruction.operand {
Some(Operand::Property(id)) => id as usize,
Some(Operand::Const(id)) => id as usize,
_ => {
return Err(VMError::NotImplemented(
"NewStringV2 requires a string operand".to_string(),
));
}
};
let s = self
.program
.strings
.get(str_id)
.cloned()
.unwrap_or_default();
let ptr = StringObj::new(&s);
self.push_kinded(ptr as usize as u64, NativeKind::UInt64)?;
Ok(())
}
OpCode::StringLenV2 => {
let (str_bits, _str_kind) = self.pop_kinded()?;
let str_ptr = str_bits as usize as *const StringObj;
let len = unsafe { StringObj::len(str_ptr) };
self.push_kinded(len as u64, NativeKind::Int64)?;
Ok(())
}
OpCode::StringConcatV2 => {
let (b_bits, _b_kind) = self.pop_kinded()?;
let (a_bits, _a_kind) = self.pop_kinded()?;
let a_ptr = a_bits as usize as *const StringObj;
let b_ptr = b_bits as usize as *const StringObj;
let result = unsafe { StringObj::concat(a_ptr, b_ptr) };
self.push_kinded(result as usize as u64, NativeKind::UInt64)?;
Ok(())
}
OpCode::StringEqV2 => {
let (b_bits, _b_kind) = self.pop_kinded()?;
let (a_bits, _a_kind) = self.pop_kinded()?;
let a_ptr = a_bits as usize as *const StringObj;
let b_ptr = b_bits as usize as *const StringObj;
let eq = unsafe { StringObj::eq(a_ptr, b_ptr) };
self.push_kinded(eq as u64, NativeKind::Bool)?;
Ok(())
}
_ => Err(VMError::NotImplemented(format!(
"v2 string opcode {:?} not implemented",
instruction.opcode
))),
}
}
}