Add call stack error chain

This allows us to write out errors that follow the call stack and give
locations to where errors originated.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-01-16 15:25:58 -08:00
parent 2752bdf6d3
commit 9704e07c45
7 changed files with 90 additions and 24 deletions

View File

@@ -1,3 +1,4 @@
use crate::syn::span::Span;
use thiserror::Error;
#[derive(Error, Debug, Clone)]
@@ -15,7 +16,44 @@ pub enum RuntimeError {
CannotCall(String),
}
pub type Result<T, E = RuntimeError> = std::result::Result<T, E>;
pub type Result<T, E = RuntimeSpanError> = std::result::Result<T, E>;
pub enum RuntimeSpanError {
Span(Span, Box<RuntimeSpanError>),
Error(RuntimeError),
}
/// Add a location to the implemented value.
pub trait WithLocation {
type Out;
fn with_location(self, span: Span) -> Self::Out;
}
impl<T> WithLocation for Result<T, RuntimeSpanError> {
type Out = Result<T, RuntimeSpanError>;
fn with_location(self, span: Span) -> Self::Out {
if let Err(e) = self {
Err(RuntimeSpanError::Span(span, Box::new(e)))
} else {
self
}
}
}
impl WithLocation for RuntimeError {
type Out = RuntimeSpanError;
fn with_location(self, span: Span) -> Self::Out {
RuntimeSpanError::Span(span, Box::new(self.into()))
}
}
impl From<RuntimeError> for RuntimeSpanError {
fn from(other: RuntimeError) -> Self {
RuntimeSpanError::Error(other)
}
}
// TODO
// Error building idea:

View File

@@ -16,9 +16,6 @@ pub enum Inst {
//Dup,
/// Applies the top stack value, which should be a macro.
Call,
/// Pops and prints the top stack value.
Print,
}
// TODO - do we want separate function definition syntax? We would be able to

View File

@@ -93,7 +93,7 @@ impl Machine {
pub fn stack_push(&mut self, value: Value) -> Result<()> {
if let Some(max) = self.max_stack_size() {
if self.stack().len() >= max {
return Err(RuntimeError::StackOverflow);
return Err(RuntimeError::StackOverflow.into());
}
}
self.stack_mut().push(value);
@@ -103,7 +103,7 @@ impl Machine {
pub fn stack_pop(&mut self) -> Result<Value> {
self.stack_mut()
.pop()
.ok_or_else(|| RuntimeError::StackUnderflow)
.ok_or_else(|| RuntimeError::StackUnderflow.into())
}
pub fn lookup_word(&self, word: &Word) -> Option<&Value> {
@@ -267,12 +267,8 @@ impl Machine {
Value::BuiltinFn(builtin) => {
self.call_native(builtin);
}
value => return Err(RuntimeError::CannotCall(value.name().to_string())),
value => return Err(RuntimeError::CannotCall(value.name().to_string()).into()),
},
Inst::Print => {
let value = self.stack_pop()?;
println!("{}", value);
}
};
// Update this frame's PC
@@ -333,9 +329,22 @@ impl MachineBuilder {
} else {
return Err(RuntimeError::CannotCall(
"if statement requires quote value".to_string(),
));
)
.into());
}
});
self.register_builtin_fun("print", |machine, _| {
let value = machine.stack_pop()?;
print!("{}", value);
Ok(BuiltinExit::Return)
});
self.register_builtin_fun("println", |machine, _| {
let value = machine.stack_pop()?;
println!("{}", value);
Ok(BuiltinExit::Return)
});
}
fn register_builtin_fun(