Files
endorphin-aster-vm/crates/core/src/vm.rs
T
codex-bot f77b8370ea
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m34s
refactor: extract core objects into a standalone package
2026-10-19 13:33:24 +08:00

193 lines
5.9 KiB
Rust

use objects::ObjectStore;
use crate::{
CompareOp, EndorCode, EndorNumber, EndorObject, ExecutionLocation, ObjectPayload, ObjectRef,
Value, VmError,
};
/// Owns the object store and execution state. Object representation, allocation,
/// reference accounting and builtin operations live in the objects crate.
#[derive(Debug)]
pub struct Vm {
objects: ObjectStore,
pub(crate) last_traceback: Vec<ExecutionLocation>,
}
impl Vm {
pub fn new() -> Result<Self, VmError> {
Ok(Self {
objects: ObjectStore::new()?,
last_traceback: Vec::new(),
})
}
pub fn object_count(&self) -> usize {
self.objects.object_count()
}
/// Returns one external strong reference. Copies of the returned handle
/// are borrowed; use retain/release to manage additional owned references.
pub fn allocate(&mut self, payload: impl ObjectPayload) -> Result<ObjectRef, VmError> {
self.objects.allocate(payload)
}
pub fn new_object(&mut self) -> Result<ObjectRef, VmError> {
self.objects.new_object()
}
pub fn object(&self, reference: ObjectRef) -> Result<&EndorObject, VmError> {
self.objects.object(reference)
}
pub fn retain(&mut self, reference: ObjectRef) -> Result<(), VmError> {
self.objects.retain(reference)
}
pub fn release(&mut self, reference: ObjectRef) -> Result<(), VmError> {
self.objects.release(reference)
}
pub fn ref_count(&self, reference: ObjectRef) -> Result<usize, VmError> {
self.objects.ref_count(reference)
}
pub fn is_same(&self, left: ObjectRef, right: ObjectRef) -> Result<bool, VmError> {
self.objects.is_same(left, right)
}
pub fn repr(&self, reference: ObjectRef) -> Result<String, VmError> {
self.objects.repr(reference)
}
pub fn str(&self, reference: ObjectRef) -> Result<String, VmError> {
self.objects.str(reference)
}
pub fn is_true(&self, reference: ObjectRef) -> Result<bool, VmError> {
self.objects.is_true(reference)
}
pub fn hash(&self, reference: ObjectRef) -> Result<u64, VmError> {
self.objects.hash(reference)
}
pub fn compare(
&self,
left: ObjectRef,
right: ObjectRef,
operation: CompareOp,
) -> Result<bool, VmError> {
self.objects.compare(left, right, operation)
}
/// Reads a borrowed value. An Object result needs retain() if the host
/// wants it to survive removal of the attribute that currently owns it.
pub fn get_attr(&self, reference: ObjectRef, name: &str) -> Result<Value, VmError> {
self.objects.get_attr(reference, name)
}
/// Object-valued attributes own internal strong references independently
/// of the caller's external references. Failure leaves the field unchanged.
pub fn set_attr(
&mut self,
reference: ObjectRef,
name: impl Into<String>,
value: Value,
) -> Result<(), VmError> {
self.objects.set_attr(reference, name, value)
}
pub fn del_attr(&mut self, reference: ObjectRef, name: &str) -> Result<(), VmError> {
self.objects.del_attr(reference, name)
}
pub(crate) fn validate_value(&self, value: &Value) -> Result<(), VmError> {
self.objects.validate_value(value)
}
/// Explicit full collection. Execution slots use owned roots, so values
/// on live execution stacks participate in the same root accounting.
pub fn collect_cycles(&mut self) -> usize {
self.objects.collect_cycles()
}
pub fn payload<T: ObjectPayload>(
&self,
reference: ObjectRef,
expected: &'static str,
) -> Result<&T, VmError> {
self.objects.payload::<T>(reference, expected)
}
pub fn new_string(&mut self, text: impl Into<String>) -> Result<ObjectRef, VmError> {
self.objects.new_string(text)
}
pub fn new_code(&mut self, code: EndorCode) -> Result<ObjectRef, VmError> {
self.objects.new_code(code)
}
pub fn new_function(
&mut self,
name: impl Into<String>,
code: ObjectRef,
globals: ObjectRef,
defaults: Vec<Value>,
closure: Vec<ObjectRef>,
) -> Result<ObjectRef, VmError> {
self.objects
.new_function(name, code, globals, defaults, closure)
}
pub fn new_number(&mut self, number: EndorNumber) -> Result<ObjectRef, VmError> {
self.objects.new_number(number)
}
pub fn new_dict(&mut self) -> Result<ObjectRef, VmError> {
self.objects.new_dict()
}
/// Returns borrowed keys and values in insertion order.
pub fn dict_items(&self, dictionary: ObjectRef) -> Result<&[(Value, Value)], VmError> {
self.objects.dict_items(dictionary)
}
pub fn dict_get(&self, dictionary: ObjectRef, key: &Value) -> Result<Option<Value>, VmError> {
self.objects.dict_get(dictionary, key)
}
pub fn dict_set(
&mut self,
dictionary: ObjectRef,
key: Value,
value: Value,
) -> Result<(), VmError> {
self.objects.dict_set(dictionary, key, value)
}
pub fn dict_delete(&mut self, dictionary: ObjectRef, key: &Value) -> Result<bool, VmError> {
self.objects.dict_delete(dictionary, key)
}
pub fn dict_clear(&mut self, dictionary: ObjectRef) -> Result<(), VmError> {
self.objects.dict_clear(dictionary)
}
pub fn new_cell(&mut self, value: Option<Value>) -> Result<ObjectRef, VmError> {
self.objects.new_cell(value)
}
/// Reads a borrowed value; an empty cell is not Value::Nil.
pub fn cell_get(&self, cell: ObjectRef) -> Result<Value, VmError> {
self.objects.cell_get(cell)
}
pub fn cell_set(&mut self, cell: ObjectRef, value: Value) -> Result<(), VmError> {
self.objects.cell_set(cell, value)
}
pub fn cell_clear(&mut self, cell: ObjectRef) -> Result<(), VmError> {
self.objects.cell_clear(cell)
}
}