Remove RuntimeSpanError and just incorporate it into RuntimeError; add Span information to compiled instructions
* RuntimeSpanError was an extraneous solution to adding spans to the errors; so instead this behavior has been delegated to the RuntimeError itself. * Usage of Inst has mostly been replaced with SpInst so if an error is encountered, we can spit out where it happened in the source code (hopefully with a stack trace). Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -14,14 +14,12 @@ pub enum RuntimeError {
|
||||
|
||||
#[error("cannot call non-quote value '{0}'")]
|
||||
CannotCall(String),
|
||||
|
||||
#[error("at {0}")]
|
||||
Span(Span, Box<RuntimeError>),
|
||||
}
|
||||
|
||||
pub type Result<T, E = RuntimeSpanError> = std::result::Result<T, E>;
|
||||
|
||||
pub enum RuntimeSpanError {
|
||||
Span(Span, Box<RuntimeSpanError>),
|
||||
Error(RuntimeError),
|
||||
}
|
||||
pub type Result<T, E = RuntimeError> = std::result::Result<T, E>;
|
||||
|
||||
/// Add a location to the implemented value.
|
||||
pub trait WithLocation {
|
||||
@@ -29,12 +27,12 @@ pub trait WithLocation {
|
||||
fn with_location(self, span: Span) -> Self::Out;
|
||||
}
|
||||
|
||||
impl<T> WithLocation for Result<T, RuntimeSpanError> {
|
||||
type Out = Result<T, RuntimeSpanError>;
|
||||
impl<T> WithLocation for Result<T, RuntimeError> {
|
||||
type Out = Result<T, RuntimeError>;
|
||||
|
||||
fn with_location(self, span: Span) -> Self::Out {
|
||||
if let Err(e) = self {
|
||||
Err(RuntimeSpanError::Span(span, Box::new(e)))
|
||||
Err(e.with_location(span))
|
||||
} else {
|
||||
self
|
||||
}
|
||||
@@ -42,36 +40,9 @@ impl<T> WithLocation for Result<T, RuntimeSpanError> {
|
||||
}
|
||||
|
||||
impl WithLocation for RuntimeError {
|
||||
type Out = RuntimeSpanError;
|
||||
type Out = RuntimeError;
|
||||
|
||||
fn with_location(self, span: Span) -> Self::Out {
|
||||
RuntimeSpanError::Span(span, Box::new(self.into()))
|
||||
RuntimeError::Span(span, Box::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeError> for RuntimeSpanError {
|
||||
fn from(other: RuntimeError) -> Self {
|
||||
RuntimeSpanError::Error(other)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// Error building idea:
|
||||
// pass RuntimeError values upward, but also keep a list of spans/locations
|
||||
// added by functions adding errors upward.
|
||||
|
||||
// e.g.
|
||||
|
||||
/*
|
||||
|
||||
fn do_thing() -> Result<()> {
|
||||
...
|
||||
let result = do_fallible_thing();
|
||||
if let Err(e) = result {
|
||||
e.add_location(context.file, context.span);
|
||||
return Err(e);
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::object::Value;
|
||||
use crate::scope::Word;
|
||||
use crate::syn::span::Spanned;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Inst {
|
||||
@@ -18,12 +19,4 @@ pub enum Inst {
|
||||
Call,
|
||||
}
|
||||
|
||||
// TODO - do we want separate function definition syntax? We would be able to
|
||||
// know ahead of time which words are functions with this.
|
||||
// : sq dup * ;
|
||||
// vs.
|
||||
// [ dup * ] =sq
|
||||
// - do we want to have separate function call syntax?
|
||||
// 5 sq call
|
||||
// 5 sq !
|
||||
// and then store macros in the function variables. the ! means "apply"
|
||||
pub type SpInst = Spanned<Inst>;
|
||||
|
||||
@@ -34,12 +34,12 @@ pub struct NativeFrame {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QuoteFrame {
|
||||
locals: BTreeMap<Word, Option<Value>>,
|
||||
code: Rc<Vec<Inst>>,
|
||||
code: Rc<Vec<SpInst>>,
|
||||
pc: usize,
|
||||
}
|
||||
|
||||
impl QuoteFrame {
|
||||
pub fn inst(&self) -> Option<&Inst> {
|
||||
pub fn inst(&self) -> Option<&SpInst> {
|
||||
self.code.get(self.pc)
|
||||
}
|
||||
}
|
||||
@@ -176,6 +176,8 @@ impl Machine {
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub fn eval(&mut self, stmts: Vec<SpStmt>) -> Result<()> {
|
||||
// TODO - figure out the best way to figure out the call stack
|
||||
// locations, and build an error out of that
|
||||
self.scope_stack.push_scope();
|
||||
let mut compile = Compile::new(&mut self.scope_stack, &mut self.quote_table);
|
||||
let code = Rc::new(compile.compile(stmts));
|
||||
@@ -200,7 +202,8 @@ impl Machine {
|
||||
let inst = frame.inst();
|
||||
if let Some(inst) = inst {
|
||||
let inst = inst.clone();
|
||||
self.eval_inst(inst)?;
|
||||
let span = inst.span().clone();
|
||||
self.eval_inst(inst).with_location(span)?;
|
||||
} else {
|
||||
self.call_stack.pop();
|
||||
}
|
||||
@@ -242,11 +245,11 @@ impl Machine {
|
||||
native.call(self, reentry)
|
||||
}
|
||||
|
||||
fn eval_inst(&mut self, inst: Inst) -> Result<()> {
|
||||
fn eval_inst(&mut self, inst: SpInst) -> Result<()> {
|
||||
let current_frame = self.call_stack.len() - 1;
|
||||
let next_pc = self.pc().unwrap() + 1;
|
||||
match inst {
|
||||
Inst::PushValue(value) => self.stack_push(value)?,
|
||||
match inst.inner() {
|
||||
Inst::PushValue(value) => self.stack_push(value.clone())?,
|
||||
Inst::Load(word) => {
|
||||
let value = self
|
||||
.lookup_word(&word)
|
||||
@@ -258,7 +261,7 @@ impl Machine {
|
||||
}
|
||||
Inst::Store(word) => {
|
||||
let value = self.stack_pop()?;
|
||||
self.store_local(word, value);
|
||||
self.store_local(word.clone(), value);
|
||||
}
|
||||
Inst::Call => match self.stack_pop()? {
|
||||
Value::Quote(quote) => {
|
||||
@@ -352,7 +355,10 @@ impl MachineBuilder {
|
||||
name: &str,
|
||||
fun: fn(&mut Machine, usize) -> Result<BuiltinExit>,
|
||||
) {
|
||||
self.register_global(name, Value::BuiltinFn(BuiltinFn::new(Rc::new(fun))));
|
||||
self.register_global(
|
||||
name,
|
||||
Value::BuiltinFn(BuiltinFn::new(name.to_string(), Rc::new(fun))),
|
||||
);
|
||||
}
|
||||
|
||||
fn register_global(&mut self, name: &str, value: Value) {
|
||||
|
||||
Reference in New Issue
Block a user