Skip to main content

runmat_ignition/
lib.rs

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}