90 lines
1.8 KiB
Rust
90 lines
1.8 KiB
Rust
use std::ops::ControlFlow;
|
|
use std::path::PathBuf;
|
|
|
|
use fix_error::Error;
|
|
use fix_lang::StringId;
|
|
use gc_arena::{Collect, Gc};
|
|
use hashbrown::HashSet;
|
|
|
|
use crate::{GcEnv, Thunk};
|
|
|
|
#[allow(dead_code)]
|
|
pub enum VmError {
|
|
Catchable(String),
|
|
Uncatchable(Box<Error>),
|
|
}
|
|
|
|
impl From<Box<Error>> for VmError {
|
|
fn from(e: Box<Error>) -> Self {
|
|
VmError::Uncatchable(e)
|
|
}
|
|
}
|
|
|
|
impl VmError {
|
|
pub fn into_error(self) -> Box<Error> {
|
|
match self {
|
|
VmError::Catchable(_) => todo!("Check for tryEval catch frames"),
|
|
VmError::Uncatchable(e) => e,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn vm_err(msg: impl Into<String>) -> VmError {
|
|
VmError::Uncatchable(Error::eval_error(msg.into()))
|
|
}
|
|
|
|
#[derive(Collect, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
#[collect(require_static)]
|
|
pub enum ForceMode {
|
|
#[default]
|
|
AsIs,
|
|
Shallow,
|
|
Deep,
|
|
}
|
|
|
|
#[repr(u8)]
|
|
pub enum Break {
|
|
Force,
|
|
Done,
|
|
LoadFile,
|
|
}
|
|
|
|
pub type Step = ControlFlow<Break>;
|
|
|
|
#[allow(dead_code)]
|
|
pub struct ErrorFrame {
|
|
pub span_id: u32,
|
|
pub message: Option<String>,
|
|
}
|
|
|
|
#[derive(Collect, Debug)]
|
|
#[collect(no_drop)]
|
|
pub struct CallFrame<'gc> {
|
|
pub pc: usize,
|
|
pub thunk: Option<Gc<'gc, Thunk<'gc>>>,
|
|
pub env: GcEnv<'gc>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct PendingLoad {
|
|
pub path: PathBuf,
|
|
pub scope: Option<PendingScope>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct PendingScope {
|
|
pub keys: HashSet<StringId>,
|
|
pub slot_id: u32,
|
|
}
|
|
|
|
/// Extra scope passed to a re-entrant compile from inside a running VM.
|
|
///
|
|
/// Currently only `ScopedImport` is produced (by the `scopedImport` builtin),
|
|
/// but the variant is kept open so REPL bindings could later land here too.
|
|
pub enum ExtraScope {
|
|
ScopedImport {
|
|
keys: HashSet<StringId>,
|
|
slot_id: u32,
|
|
},
|
|
}
|