deimos-lang/src/vm/value.rs
2025-04-12 21:20:08 -05:00

197 lines
5.0 KiB
Rust

use crate::vm::array::DvmArray;
use crate::vm::object::DvmObject;
use crate::vm::pointer::DvmPointer;
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
#[derive(Debug, PartialEq, Clone)]
pub enum DvmValue {
// Primitives
Byte(u8),
Int(i32),
Long(i64),
Double(f64),
USize(usize),
Boolean(bool),
// Object
Object(Rc<RefCell<DvmObject>>),
// Array
Array(Rc<RefCell<DvmArray>>),
// Pointer to constant u8
ConstantPointer(DvmPointer),
// Null
Empty,
}
impl Default for DvmValue {
fn default() -> Self {
DvmValue::Empty
}
}
impl Display for DvmValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
DvmValue::Byte(b) => write!(f, "Byte({:x})", b),
DvmValue::Int(i) => write!(f, "Int({})", i),
DvmValue::Long(i) => write!(f, "Long({})", i),
DvmValue::Double(i) => write!(f, "Double({})", i),
DvmValue::USize(u) => write!(f, "USize({})", u),
DvmValue::Boolean(b) => write!(f, "Boolean({})", b),
DvmValue::Object(o) => write!(f, "Object({:p})", &o),
DvmValue::Array(a) => write!(f, "Array({:p})", &a),
DvmValue::ConstantPointer(p) => write!(f, "ConstantPointer({})", p),
DvmValue::Empty => write!(f, "Empty"),
}
}
}
impl DvmValue {
pub fn from_object(object: DvmObject) -> Self {
DvmValue::Object(Rc::new(RefCell::new(object)))
}
pub fn expect_byte(&self) -> u8 {
if let DvmValue::Byte(b) = self {
*b
} else {
panic!("Expected DvmValue::Byte, but found DvmValue::{:?}", self);
}
}
pub fn expect_int(&self) -> i32 {
if let DvmValue::Int(i) = self {
*i
} else {
panic!("Expected DvmValue::Int, but found DvmValue::{:?}", self);
}
}
pub fn expect_long(&self) -> i64 {
if let DvmValue::Long(l) = self {
*l
} else {
panic!("Expected DvmValue::Long, but found DvmValue::{:?}", self);
}
}
pub fn is_long(&self) -> bool {
match self {
DvmValue::Long(_) => true,
_ => false,
}
}
pub fn expect_double(&self) -> f64 {
if let DvmValue::Double(d) = self {
*d
} else {
panic!("Expected DvmValue::Double, but found DvmValue::{:?}", self);
}
}
pub fn expect_object(&self) -> Rc<RefCell<DvmObject>> {
if let DvmValue::Object(o) = self {
o.clone()
} else {
panic!("Expected DvmValue::Object, but found DvmValue::{:?}", self);
}
}
pub fn map_object<T>(
&self,
mapper: impl FnOnce(Rc<RefCell<DvmObject>>) -> T,
on_non_object: impl FnOnce(&Self) -> T,
) -> T {
if let DvmValue::Object(o) = self {
mapper(o.clone())
} else {
on_non_object(self)
}
}
pub fn is_object(&self) -> bool {
match self {
DvmValue::Object(_) => true,
_ => false,
}
}
pub fn expect_array(&self) -> Rc<RefCell<DvmArray>> {
if let DvmValue::Array(a) = self {
a.clone()
} else {
panic!("Expected DvmValue::Array, but found DvmValue::{:?}", self);
}
}
pub fn is_array(&self) -> bool {
match self {
DvmValue::Array(_) => true,
_ => false,
}
}
pub fn map_array<T>(
&self,
mapper: impl FnOnce(Rc<RefCell<DvmArray>>) -> T,
on_non_array: impl FnOnce(&Self) -> T,
) -> T {
if let DvmValue::Array(a) = self {
mapper(a.clone())
} else {
on_non_array(self)
}
}
pub fn expect_usize(&self) -> usize {
if let DvmValue::USize(u) = self {
*u
} else {
panic!("Expected DvmValue::USize, but found DvmValue::{:?}", self);
}
}
pub fn is_usize(&self) -> bool {
match self {
DvmValue::USize(_) => true,
_ => false,
}
}
pub fn as_usize(&self) -> Option<usize> {
match self {
DvmValue::Byte(b) => Some(*b as usize),
DvmValue::Int(i) => Some(*i as usize),
DvmValue::Long(l) => Some(*l as usize),
DvmValue::Double(d) => Some(*d as usize),
DvmValue::USize(u) => Some(*u),
_ => None,
}
}
pub fn expect_boolean(&self) -> bool {
if let DvmValue::Boolean(b) = self {
*b
} else {
panic!("Expected DvmValue::Boolean, but found DvmValue::{:?}", self);
}
}
pub fn expect_constant_pointer(&self) -> DvmPointer {
if let DvmValue::ConstantPointer(ptr) = self {
ptr.clone()
} else {
panic!(
"Expected DvmValue::ConstantPointer, but found DvmValue::{:?}",
self
);
}
}
}