Error Messaging Redesign
This commit contains the following: * New data types to support full tracebacks * New traceback data type used across stl and ast * Updates to tests * fixes for error messaging in sym and some stl functions
This commit is contained in:
parent
91ad4eed12
commit
789349df48
24 changed files with 837 additions and 374 deletions
|
|
@ -81,7 +81,8 @@ mod eval_tests {
|
|||
let doc_tree = lex(&test_doc).unwrap();
|
||||
match eval(&doc_tree, &mut syms) {
|
||||
Err(e) => {
|
||||
assert_eq!(e, "error in call to undefined: undefined symbol: undefined")
|
||||
assert_eq!(e.0.first().unwrap().message,
|
||||
"(is an undefined symbol)")
|
||||
}
|
||||
|
||||
Ok(reduced) => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mod func_tests {
|
||||
use relish::ast::lex;
|
||||
use relish::ast::{Args, Ctr, Seg, Symbol, ValueType};
|
||||
use relish::ast::{SymTable, Type, UserFn};
|
||||
use relish::ast::{Args, Ctr, Seg, Symbol, ValueType, Traceback};
|
||||
use relish::ast::{SymTable, Type, UserFn, start_trace};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[test]
|
||||
|
|
@ -13,7 +13,7 @@ mod func_tests {
|
|||
docs: String::new(),
|
||||
args: Args::Strict(vec![Type::Bool]),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, String> {
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
|
|
@ -104,7 +104,7 @@ mod func_tests {
|
|||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, String> {
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
if let Ctr::Bool(b) = *inner.car {
|
||||
if b {
|
||||
|
|
@ -113,7 +113,7 @@ mod func_tests {
|
|||
Ok(Ctr::None)
|
||||
}
|
||||
} else {
|
||||
Err("not a bool".to_string())
|
||||
Err(start_trace(("", "not a bool".to_string()).into()))
|
||||
}
|
||||
},
|
||||
)),
|
||||
|
|
@ -153,7 +153,7 @@ mod func_tests {
|
|||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, String> {
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
|
|
@ -170,7 +170,11 @@ mod func_tests {
|
|||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"arg 1 expected to be bool".to_string(),
|
||||
);
|
||||
}
|
||||
|
|
@ -200,7 +204,11 @@ mod func_tests {
|
|||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"expected 1 args. Got 2.".to_string(),
|
||||
);
|
||||
}
|
||||
|
|
@ -226,7 +234,11 @@ mod func_tests {
|
|||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"expected 1 args. Got 0.".to_string(),
|
||||
);
|
||||
}
|
||||
|
|
@ -240,7 +252,7 @@ mod func_tests {
|
|||
args: Args::Strict(vec![Type::Bool]),
|
||||
docs: String::new(),
|
||||
value: ValueType::Internal(Rc::new(
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, String> {
|
||||
|a: &Seg, _: &mut SymTable| -> Result<Ctr, Traceback> {
|
||||
let inner = a;
|
||||
let mut is_bool = false;
|
||||
if let Ctr::Bool(_) = *inner.car {
|
||||
|
|
@ -260,8 +272,12 @@ mod func_tests {
|
|||
assert_eq!(
|
||||
syms.call_symbol(&"test_func_in".to_string(), &args, true)
|
||||
.err()
|
||||
.unwrap(),
|
||||
"error evaluating args: undefined symbol: undefined-symbol".to_string(),
|
||||
.unwrap()
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"(is an undefined symbol)".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ mod lex_tests {
|
|||
fn test_bad_symbol() {
|
||||
let document = String::from("(as@dd)");
|
||||
let output: &str = "Problem lexing document: \"Unparsable token: as@dd\"";
|
||||
assert_eq!(lex(&document).err().unwrap(), output.to_string(),);
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -42,14 +42,14 @@ mod lex_tests {
|
|||
fn test_unmatched_list_delim_flat() {
|
||||
let document = String::from("(one two");
|
||||
let output: &str = "Problem lexing document: \"Unmatched list delimiter in input\"";
|
||||
assert_eq!(lex(&document).err().unwrap(), output.to_string(),);
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unmatched_list_delim_complex() {
|
||||
let document = String::from("(one two (three)");
|
||||
let output: &str = "Problem lexing document: \"Unmatched list delimiter in input\"";
|
||||
assert_eq!(lex(&document).err().unwrap(), output.to_string(),);
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -100,6 +100,6 @@ mod lex_tests {
|
|||
fn test_bad_token_list() {
|
||||
let document = String::from("(one t(wo)");
|
||||
let output: &str = "Problem lexing document: \"list started in middle of another token\"";
|
||||
assert_eq!(lex(&document).err().unwrap(), output.to_string(),);
|
||||
assert_eq!(lex(&document).err().unwrap().0.first().unwrap().message, output.to_string(),);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,8 +132,11 @@ mod append_lib_tests {
|
|||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"error in call to car: argument is empty".to_string(),
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"input is empty".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -166,8 +169,11 @@ mod append_lib_tests {
|
|||
*eval(&lex(&document.to_string()).unwrap(), &mut syms)
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"error in call to cdr: argument is empty".to_string(),
|
||||
.0
|
||||
.first()
|
||||
.unwrap()
|
||||
.message,
|
||||
"input is empty".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,8 +163,8 @@ mod bool_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to toggle: can only toggle a boolean".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"can only toggle a boolean".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
|
|
@ -196,8 +196,8 @@ mod bool_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to toggle: cannot toggle a function".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"cannot toggle a function".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
|
|
|
|||
|
|
@ -233,8 +233,8 @@ mod control_lib_tests {
|
|||
|
||||
eval(&doc_tree, &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
eval(&test_tree, &mut syms).err().unwrap(),
|
||||
"error in call to result: undefined symbol: result".to_string()
|
||||
eval(&test_tree, &mut syms).err().unwrap().0.first().unwrap().message,
|
||||
"(is an undefined symbol)".to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ mod decl_lib_tests {
|
|||
let eval_result = eval(&lex(&doc3.to_string()).unwrap(), &mut syms);
|
||||
if let Err(s) = eval_result {
|
||||
assert_eq!(
|
||||
s.to_string(),
|
||||
"error in call to test: undefined symbol: test".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"(is an undefined symbol)".to_string()
|
||||
);
|
||||
} else {
|
||||
assert!(false);
|
||||
|
|
|
|||
|
|
@ -665,8 +665,8 @@ mod math_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to inc: can only increment an integer".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
|
|
@ -698,8 +698,8 @@ mod math_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to inc: cannot increment a function".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
|
|
@ -768,8 +768,8 @@ mod math_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to dec: can only decrement an integer".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
let intermediate = *eval(&check_tree, &mut syms).unwrap();
|
||||
if let Ctr::Seg(ref s) = intermediate {
|
||||
|
|
@ -801,8 +801,8 @@ mod math_lib_tests {
|
|||
eval(&doc_tree, &mut syms).unwrap();
|
||||
if let Err(s) = eval(&change_tree, &mut syms) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"error in call to dec: cannot decrement a function".to_string()
|
||||
s.0.first().unwrap().message,
|
||||
"expected tester to be an integer".to_string()
|
||||
);
|
||||
if let Ctr::String(ref s) = *eval(&check_tree, &mut syms).unwrap() {
|
||||
assert_eq!(*s, "1".to_string());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue