Add call site discovery to call frames, and add call stack error messages

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-01-16 18:56:33 -08:00
parent dfac970cc7
commit b3cf1c5681

View File

@@ -1,7 +1,7 @@
use crate::compile::Compile; use crate::compile::Compile;
use crate::object::*; use crate::object::*;
use crate::scope::*; use crate::scope::*;
use crate::syn::ast::SpStmt; use crate::syn::{ast::SpStmt, span::Span};
use crate::vm::{error::*, inst::*}; use crate::vm::{error::*, inst::*};
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@@ -13,6 +13,22 @@ pub enum Frame {
Quote(QuoteFrame), 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<NativeFrame> for Frame { impl From<NativeFrame> for Frame {
fn from(other: NativeFrame) -> Self { fn from(other: NativeFrame) -> Self {
Frame::Native(other) Frame::Native(other)
@@ -27,6 +43,7 @@ impl From<QuoteFrame> for Frame {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct NativeFrame { pub struct NativeFrame {
call_site: Span,
fun: BuiltinFn, fun: BuiltinFn,
reentry: usize, reentry: usize,
} }
@@ -143,7 +160,7 @@ impl Machine {
self.call_stack.last() 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); let (_span, locals, _expr, code) = self.quote_table.get(quote);
// create a new stack frame // 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 { self.call_stack.push(Frame::Native(NativeFrame {
call_site,
fun: native, fun: native,
reentry: 0, reentry: 0,
})); }));
@@ -176,6 +194,20 @@ impl Machine {
// ///////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////
pub fn eval(&mut self, stmts: Vec<SpStmt>) -> Result<()> { pub fn eval(&mut self, stmts: Vec<SpStmt>) -> 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<SpStmt>) -> Result<()> {
// TODO - figure out the best way to figure out the call stack // TODO - figure out the best way to figure out the call stack
// locations, and build an error out of that // locations, and build an error out of that
self.scope_stack.push_scope(); self.scope_stack.push_scope();
@@ -202,8 +234,7 @@ impl Machine {
let inst = frame.inst(); let inst = frame.inst();
if let Some(inst) = inst { if let Some(inst) = inst {
let inst = inst.clone(); let inst = inst.clone();
let span = inst.span().clone(); self.eval_inst(inst)?;
self.eval_inst(inst).with_location(span)?;
} else { } else {
self.call_stack.pop(); self.call_stack.pop();
} }
@@ -268,7 +299,7 @@ impl Machine {
self.call_quote(quote); self.call_quote(quote);
} }
Value::BuiltinFn(builtin) => { Value::BuiltinFn(builtin) => {
self.call_native(builtin); self.call_native(inst.span().clone(), builtin);
} }
value => return Err(RuntimeError::CannotCall(value.name().to_string()).into()), value => return Err(RuntimeError::CannotCall(value.name().to_string()).into()),
}, },