197 lines
5.0 KiB
Rust
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
|
|
);
|
|
}
|
|
}
|
|
}
|