diff --git a/src/vm/machine.rs b/src/vm/machine.rs index 1826318..da1c89b 100644 --- a/src/vm/machine.rs +++ b/src/vm/machine.rs @@ -1,7 +1,7 @@ use crate::compile::Compile; use crate::object::*; use crate::scope::*; -use crate::syn::ast::SpStmt; +use crate::syn::{ast::SpStmt, span::Span}; use crate::vm::{error::*, inst::*}; use std::cell::RefCell; use std::collections::BTreeMap; @@ -13,6 +13,22 @@ pub enum Frame { Quote(QuoteFrame), } +impl Frame { + pub fn call_site(&self) -> Option<&Span> { + use Frame::*; + match self { + Native(frame) => Some(&frame.call_site), + Quote(frame) => { + if frame.pc >= frame.code.len() { + frame.code.last().map(|inst| inst.span()) + } else { + frame.inst().map(|inst| inst.span()) + } + } + } + } +} + impl From for Frame { fn from(other: NativeFrame) -> Self { Frame::Native(other) @@ -27,6 +43,7 @@ impl From for Frame { #[derive(Debug, Clone)] pub struct NativeFrame { + call_site: Span, fun: BuiltinFn, reentry: usize, } @@ -143,7 +160,7 @@ impl Machine { self.call_stack.last() } - pub fn call_quote(&mut self, quote: Quote) { + fn call_quote(&mut self, quote: Quote) { let (_span, locals, _expr, code) = self.quote_table.get(quote); // create a new stack frame @@ -157,8 +174,9 @@ impl Machine { ); } - pub fn call_native(&mut self, native: BuiltinFn) { + fn call_native(&mut self, call_site: Span, native: BuiltinFn) { self.call_stack.push(Frame::Native(NativeFrame { + call_site, fun: native, reentry: 0, })); @@ -176,6 +194,20 @@ impl Machine { // ///////////////////////////////////////////////////////////////////////// pub fn eval(&mut self, stmts: Vec) -> Result<()> { + if let Err(mut error) = self.eval_stmt_list(stmts) { + // go through the call stack and make the error + for frame in self.call_stack.iter() { + if let Some(call_site) = frame.call_site() { + error = error.with_location(call_site.clone()); + } + } + Err(error) + } else { + Ok(()) + } + } + + fn eval_stmt_list(&mut self, stmts: Vec) -> 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(); @@ -202,8 +234,7 @@ impl Machine { let inst = frame.inst(); if let Some(inst) = inst { let inst = inst.clone(); - let span = inst.span().clone(); - self.eval_inst(inst).with_location(span)?; + self.eval_inst(inst)?; } else { self.call_stack.pop(); } @@ -268,7 +299,7 @@ impl Machine { self.call_quote(quote); } Value::BuiltinFn(builtin) => { - self.call_native(builtin); + self.call_native(inst.span().clone(), builtin); } value => return Err(RuntimeError::CannotCall(value.name().to_string()).into()), },