use oxilean_kernel::Name;
use super::functions::{TAG_ARRAY, TAG_EXTERNAL, TAG_IO_ACTION, TAG_STRING, TAG_TASK, TAG_THUNK};
use super::types::{
ArrayData, BoxedFloatData, ByteArrayData, ConstructorData, ExternalData, HeapObject,
IoActionData, IoActionKind, ObjectHeader, ObjectStore, StringData, TaskData, TaskState,
ThunkData, ThunkState, TypeTag,
};
#[derive(Clone)]
pub struct RtObject {
pub(super) bits: u64,
}
impl RtObject {
pub fn with_heap<R>(&self, f: impl FnOnce(&HeapObject) -> R) -> Option<R> {
if self.is_inline() {
return None;
}
let id = self.payload() as usize;
ObjectStore::global_store(|store| store.get(id).map(f))
}
pub fn with_heap_mut<R>(&self, f: impl FnOnce(&mut HeapObject) -> R) -> Option<R> {
if self.is_inline() {
return None;
}
let id = self.payload() as usize;
ObjectStore::global_store(|store| store.get_mut(id).map(f))
}
pub fn string(s: String) -> Self {
let heap = HeapObject::StringObj(StringData {
header: ObjectHeader::new(TypeTag::StringObj, ((s.len() + 7) / 8 + 1) as u16),
value: s,
cached_hash: None,
});
RtObject::from_heap_with_tag(heap, TAG_STRING)
}
pub fn array(elements: Vec<RtObject>) -> Self {
let cap = elements.capacity();
let heap = HeapObject::Array(ArrayData {
header: ObjectHeader::new(TypeTag::Array, (elements.len() + 1) as u16),
elements,
capacity: cap,
});
RtObject::from_heap_with_tag(heap, TAG_ARRAY)
}
pub fn constructor(ctor_index: u32, fields: Vec<RtObject>) -> Self {
let num_fields = fields.len() as u16;
let heap = HeapObject::Constructor(ConstructorData {
header: ObjectHeader::new(TypeTag::Constructor, (fields.len() + 2) as u16),
ctor_index,
num_fields,
scalar_fields: Vec::new(),
object_fields: fields,
name: None,
});
RtObject::from_heap(heap)
}
pub fn named_constructor(name: Name, ctor_index: u32, fields: Vec<RtObject>) -> Self {
let num_fields = fields.len() as u16;
let heap = HeapObject::Constructor(ConstructorData {
header: ObjectHeader::new(TypeTag::Constructor, (fields.len() + 2) as u16),
ctor_index,
num_fields,
scalar_fields: Vec::new(),
object_fields: fields,
name: Some(name),
});
RtObject::from_heap(heap)
}
pub fn thunk(closure: RtObject) -> Self {
let heap = HeapObject::Thunk(ThunkData {
header: ObjectHeader::new(TypeTag::Thunk, 2),
state: ThunkState::Unevaluated { closure },
});
RtObject::from_heap_with_tag(heap, TAG_THUNK)
}
pub fn io_pure(value: RtObject) -> Self {
let heap = HeapObject::IoAction(IoActionData {
header: ObjectHeader::new(TypeTag::IoAction, 2),
kind: IoActionKind::Pure(value),
});
RtObject::from_heap_with_tag(heap, TAG_IO_ACTION)
}
pub fn task(task_id: u64) -> Self {
let heap = HeapObject::Task(TaskData {
header: ObjectHeader::new(TypeTag::Task, 2),
state: TaskState::Pending,
task_id,
});
RtObject::from_heap_with_tag(heap, TAG_TASK)
}
pub fn external(type_name: String, payload: Vec<u8>) -> Self {
let heap = HeapObject::External(ExternalData {
header: ObjectHeader::new(TypeTag::External, 2),
type_name,
payload,
});
RtObject::from_heap_with_tag(heap, TAG_EXTERNAL)
}
pub fn boxed_float(value: f64) -> Self {
let heap = HeapObject::BoxedFloat(BoxedFloatData {
header: ObjectHeader::new(TypeTag::BoxedFloat, 2),
value,
});
RtObject::from_heap(heap)
}
pub fn byte_array(bytes: Vec<u8>) -> Self {
let heap = HeapObject::ByteArray(ByteArrayData {
header: ObjectHeader::new(TypeTag::ByteArray, ((bytes.len() + 7) / 8 + 1) as u16),
bytes,
});
RtObject::from_heap(heap)
}
}