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;