Files
endorphin-aster-vm/crates/core/src/frame.rs
T

94 lines
2.5 KiB
Rust

use std::sync::Arc;
use crate::{EndorCode, ObjectRef, Value};
/// NULL is a call-protocol marker and can never escape as a language value.
/// Each Value::Object in a live frame owns one execution root.
#[derive(Debug, Clone)]
pub(crate) enum StackEntry {
Null,
Value(Value),
}
#[derive(Debug)]
pub(crate) struct NativeReturn {
pub name: String,
pub expected: crate::CallType,
}
impl NativeReturn {
pub fn check(&self, store: &objects::ObjectStore, value: &Value) -> Result<(), crate::VmError> {
self.expected
.check(store, &self.name, "return".into(), value)
}
}
/// Internal activation record, analogous to _PyInterpreterFrame. It has no
/// EndorObject header; introspection objects can be added independently later.
#[derive(Debug)]
pub struct EndorFrame {
pub(crate) function: ObjectRef,
pub(crate) return_type: Option<crate::AnnotationType>,
pub(crate) native_returns: Vec<NativeReturn>,
/// Index of the caller in the execution's frame vector, never a pointer.
pub(crate) previous: Option<usize>,
pub(crate) code: ObjectRef,
pub(crate) executable: Arc<EndorCode>,
pub(crate) globals: ObjectRef,
pub(crate) builtins: Option<ObjectRef>,
pub(crate) name: String,
pub(crate) instruction_offset: usize,
pub(crate) current_offset: usize,
pub(crate) localsplus: Vec<Option<Value>>,
pub(crate) stack: Vec<StackEntry>,
}
impl EndorFrame {
pub fn previous(&self) -> Option<usize> {
self.previous
}
pub fn function(&self) -> ObjectRef {
self.function
}
pub fn code(&self) -> ObjectRef {
self.code
}
pub fn globals(&self) -> ObjectRef {
self.globals
}
pub fn builtins(&self) -> Option<ObjectRef> {
self.builtins
}
pub fn instruction_offset(&self) -> usize {
self.instruction_offset
}
pub fn localsplus(&self) -> &[Option<Value>] {
&self.localsplus
}
pub fn stack_depth(&self) -> usize {
self.stack.len()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExecutionLocation {
pub function: String,
pub filename: String,
pub first_line: usize,
pub instruction_offset: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExecutionLimits {
pub max_frames: usize,
pub max_instructions: usize,
}
impl Default for ExecutionLimits {
fn default() -> Self {
Self {
max_frames: 1000,
max_instructions: usize::MAX,
}
}
}