1#![allow(clippy::result_large_err)]
2
3#[cfg(feature = "native-accel")]
4pub mod accel_graph;
5pub mod bytecode;
6pub mod compiler;
7pub mod functions;
8#[cfg(feature = "native-accel")]
9mod fusion_stack_layout;
10pub mod gc_roots;
11pub mod instr;
12pub mod vm;
13
14pub use bytecode::compile;
15pub use functions::{Bytecode, ExecutionContext, UserFunction};
16pub use instr::Instr;
17pub use vm::{
18 interpret, interpret_with_vars, push_pending_workspace, set_call_stack_limit,
19 set_error_namespace, take_updated_workspace_state, InterpreterOutcome, InterpreterState,
20 PendingWorkspaceGuard, DEFAULT_CALLSTACK_LIMIT, DEFAULT_ERROR_NAMESPACE,
21};
22
23use miette::{SourceOffset, SourceSpan};
24use runmat_builtins::Value;
25use runmat_hir::{HirProgram, SemanticError, Span};
26use runmat_runtime::{build_runtime_error, RuntimeError};
27use std::collections::HashMap;
28
29#[derive(Debug, Clone)]
30pub struct CompileError {
31 pub message: String,
32 pub span: Option<Span>,
33 pub identifier: Option<String>,
34}
35
36impl CompileError {
37 pub fn new(message: impl Into<String>) -> Self {
38 Self {
39 message: message.into(),
40 span: None,
41 identifier: None,
42 }
43 }
44
45 pub fn with_span(mut self, span: Span) -> Self {
46 self.span = Some(span);
47 self
48 }
49
50 pub fn with_identifier(mut self, identifier: impl Into<String>) -> Self {
51 self.identifier = Some(identifier.into());
52 self
53 }
54}
55
56impl std::fmt::Display for CompileError {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(f, "{}", self.message)
59 }
60}
61
62impl std::error::Error for CompileError {}
63
64impl From<String> for CompileError {
65 fn from(value: String) -> Self {
66 CompileError::new(value)
67 }
68}
69
70impl From<&str> for CompileError {
71 fn from(value: &str) -> Self {
72 CompileError::new(value)
73 }
74}
75
76impl From<SemanticError> for CompileError {
77 fn from(value: SemanticError) -> Self {
78 let mut err = CompileError::new(value.message);
79 if let Some(span) = value.span {
80 err = err.with_span(span);
81 }
82 if let Some(identifier) = value.identifier {
83 err = err.with_identifier(identifier);
84 }
85 err
86 }
87}
88
89impl From<CompileError> for RuntimeError {
90 fn from(value: CompileError) -> Self {
91 let mut builder = build_runtime_error(value.message);
92 if let Some(identifier) = value.identifier {
93 builder = builder.with_identifier(identifier);
94 }
95 if let Some(span) = value.span {
96 let len = span.end.saturating_sub(span.start).max(1);
97 builder = builder.with_span(SourceSpan::new(SourceOffset::from(span.start), len));
98 }
99 builder.build()
100 }
101}
102
103pub async fn execute(program: &HirProgram) -> Result<Vec<Value>, RuntimeError> {
104 let bc = compile(program, &HashMap::new()).map_err(RuntimeError::from)?;
105 interpret(&bc).await
106}