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, } impl Vm { pub fn new() -> Result { 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 { self.objects.allocate(payload) } pub fn new_object(&mut self) -> Result { 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 { self.objects.ref_count(reference) } pub fn is_same(&self, left: ObjectRef, right: ObjectRef) -> Result { self.objects.is_same(left, right) } pub fn repr(&self, reference: ObjectRef) -> Result { self.objects.repr(reference) } pub fn str(&self, reference: ObjectRef) -> Result { self.objects.str(reference) } pub fn is_true(&self, reference: ObjectRef) -> Result { self.objects.is_true(reference) } pub fn hash(&self, reference: ObjectRef) -> Result { self.objects.hash(reference) } pub fn compare( &self, left: ObjectRef, right: ObjectRef, operation: CompareOp, ) -> Result { 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 { 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, 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( &self, reference: ObjectRef, expected: &'static str, ) -> Result<&T, VmError> { self.objects.payload::(reference, expected) } pub fn new_string(&mut self, text: impl Into) -> Result { self.objects.new_string(text) } pub fn new_code(&mut self, code: EndorCode) -> Result { self.objects.new_code(code) } pub fn new_function( &mut self, name: impl Into, code: ObjectRef, globals: ObjectRef, defaults: Vec, closure: Vec, ) -> Result { self.objects .new_function(name, code, globals, defaults, closure) } pub fn new_number(&mut self, number: EndorNumber) -> Result { self.objects.new_number(number) } pub fn new_dict(&mut self) -> Result { 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, 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 { 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) -> Result { self.objects.new_cell(value) } /// Reads a borrowed value; an empty cell is not Value::Nil. pub fn cell_get(&self, cell: ObjectRef) -> Result { 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) } }