runmat_vm/interpreter/
errors.rs1use crate::bytecode::Bytecode;
2use crate::runtime::call_stack::error_namespace;
3use miette::{SourceOffset, SourceSpan};
4use runmat_runtime::{build_runtime_error, RuntimeError};
5use runmat_thread_local::runmat_thread_local;
6use std::cell::Cell;
7
8runmat_thread_local! {
9 static CURRENT_PC: Cell<usize> = const { Cell::new(0) };
10}
11
12#[inline]
13pub fn set_vm_pc(pc: usize) {
14 CURRENT_PC.with(|cell| cell.set(pc));
15}
16
17#[inline]
18pub fn current_vm_pc() -> usize {
19 CURRENT_PC.with(|cell| cell.get())
20}
21
22pub fn attach_span_at(bytecode: &Bytecode, pc: usize, mut err: RuntimeError) -> RuntimeError {
23 if err.span.is_none() {
24 if let Some(span) = bytecode.instr_spans.get(pc) {
25 let len = span.end.saturating_sub(span.start).max(1);
26 err.span = Some(SourceSpan::new(SourceOffset::from(span.start), len));
27 }
28 }
29 err
30}
31
32pub fn attach_span_from_pc(bytecode: &Bytecode, err: RuntimeError) -> RuntimeError {
33 let pc = current_vm_pc();
34 attach_span_at(bytecode, pc, err)
35}
36
37#[inline]
38pub fn mex(id: &str, msg: &str) -> RuntimeError {
39 let suffix = match id.find(':') {
40 Some(pos) => &id[pos + 1..],
41 None => id,
42 };
43 let ident = format!("{}:{suffix}", error_namespace());
44 build_runtime_error(msg.to_string())
45 .with_identifier(ident)
46 .build()
47}
48
49#[inline]
50pub fn ensure_runtime_error_identifier(mut err: RuntimeError) -> RuntimeError {
51 if err.identifier.is_none() {
52 err.identifier = Some(format!("{}:RuntimeError", error_namespace()));
53 }
54 err
55}