Skip to main content

yulang_runtime/vm/
mod.rs

1use std::collections::{BTreeMap, HashMap};
2use std::fmt;
3use std::path::PathBuf;
4use std::rc::Rc;
5
6use yulang_typed_ir as typed_ir;
7
8use crate::diagnostic::RuntimeError;
9use crate::invariant::{RuntimeStage, check_runtime_invariants};
10use crate::ir::{
11    Binding, EffectIdRef, EffectIdVar, Expr, ExprKind, HandleArm, MatchArm, Module, Pattern,
12    RecordExprField, RecordSpreadExpr, Stmt, Type,
13};
14use crate::runtime::bytes_tree::BytesTree;
15use crate::runtime::list_tree::{ListTree, ListView};
16use crate::runtime::string_tree::StringTree;
17use crate::types::effect_is_empty;
18
19pub struct VmModule {
20    module: Module,
21}
22
23impl VmModule {
24    pub fn module(&self) -> &Module {
25        &self.module
26    }
27
28    pub fn eval_root_expr(&self, index: usize) -> Result<VmResult, VmError> {
29        VmInterpreter::new(&self.module).eval_root_expr(index)
30    }
31
32    pub fn eval_root_expr_profiled(&self, index: usize) -> Result<(VmResult, VmProfile), VmError> {
33        let mut interpreter = VmInterpreter::new(&self.module);
34        let result = interpreter.eval_root_expr(index)?;
35        Ok((result, interpreter.profile()))
36    }
37
38    pub fn eval_roots(&self) -> Result<Vec<VmResult>, VmError> {
39        Ok(self.eval_roots_profiled()?.0)
40    }
41
42    pub fn eval_roots_profiled(&self) -> Result<(Vec<VmResult>, VmProfile), VmError> {
43        let mut interpreter = VmInterpreter::new(&self.module);
44        let results = (0..self.module.root_exprs.len())
45            .map(|index| interpreter.eval_root_expr(index))
46            .collect::<Result<Vec<_>, _>>()?;
47        Ok((results, interpreter.profile()))
48    }
49
50    pub fn resume_request(&self, request: VmRequest, value: VmValue) -> Result<VmResult, VmError> {
51        VmInterpreter::new(&self.module).resume(request.continuation, value)
52    }
53
54    pub fn force_value_profiled(&self, value: VmValue) -> Result<(VmResult, VmProfile), VmError> {
55        let mut interpreter = VmInterpreter::new(&self.module);
56        let result = interpreter.bind_here(value)?;
57        Ok((result, interpreter.profile()))
58    }
59
60    pub fn resume_request_profiled(
61        &self,
62        request: VmRequest,
63        value: VmValue,
64    ) -> Result<(VmResult, VmProfile), VmError> {
65        let mut interpreter = VmInterpreter::new(&self.module);
66        let result = interpreter.resume(request.continuation, value)?;
67        Ok((result, interpreter.profile()))
68    }
69}
70
71pub fn compile_vm_module(module: Module) -> Result<VmModule, VmError> {
72    check_runtime_invariants(&module, RuntimeStage::BeforeVm).map_err(VmError::Runtime)?;
73    let effects = EffectPathResolver::collect(&module);
74    Ok(VmModule {
75        module: erase_module(module, &effects)?,
76    })
77}
78
79#[derive(Debug, Clone, PartialEq)]
80pub enum VmError {
81    Runtime(RuntimeError),
82    ResidualPolymorphicBinding {
83        path: typed_ir::Path,
84        vars: Vec<typed_ir::TypeVar>,
85    },
86    MissingRootExpr(usize),
87    UnboundVariable(typed_ir::Path),
88    PatternMismatch,
89    ExpectedBool(VmValue),
90    ExpectedInt(VmValue),
91    ExpectedFloat(VmValue),
92    ExpectedString(VmValue),
93    ExpectedBytes(VmValue),
94    ExpectedPath(VmValue),
95    ExpectedList(VmValue),
96    ExpectedRecord(VmValue),
97    ExpectedVariant(VmValue),
98    ExpectedClosure(VmValue),
99    ExpectedThunk(VmValue),
100    ExpectedEffectId(VmValue),
101    InvalidPrimitiveArity {
102        expected: usize,
103        actual: usize,
104    },
105    UnsupportedPrimitive(typed_ir::PrimitiveOp),
106    UnsupportedEffectIdVar(usize),
107    UnsupportedFindId,
108    UnexpectedRequest(typed_ir::Path),
109}
110
111impl fmt::Display for VmError {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        write!(f, "{self:?}")
114    }
115}
116
117impl std::error::Error for VmError {}
118
119mod continuation;
120mod erase;
121mod guard;
122mod interpreter;
123mod model;
124pub mod primitive;
125mod value;
126
127use erase::*;
128use guard::*;
129use interpreter::*;
130use model::*;
131pub use model::{VmContinuation, VmPrimitive, VmProfile, VmRequest, VmResult, VmValue};
132use primitive::*;
133use value::*;
134
135#[cfg(test)]
136mod tests;