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:
@@ -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()),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user