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