FEATURE: better error reporting for out statements

This commit is contained in:
Jeremy Wall 2019-02-06 21:06:05 -06:00
parent dfae16ad41
commit 6de26820c8
5 changed files with 41 additions and 6 deletions

View File

@ -738,5 +738,5 @@ pub enum Statement {
Assert(Expression), Assert(Expression),
// Identify an Expression for output. // Identify an Expression for output.
Output(Token, Expression), Output(Position, Token, Expression),
} }

View File

@ -42,7 +42,7 @@ impl<'a> AstWalker<'a> {
Statement::Assert(ref mut expr) => { Statement::Assert(ref mut expr) => {
self.walk_expression(expr); self.walk_expression(expr);
} }
Statement::Output(_, ref mut expr) => { Statement::Output(_, _, ref mut expr) => {
self.walk_expression(expr); self.walk_expression(expr);
} }
} }

View File

@ -429,3 +429,37 @@ fn test_list_unclosed_bracket_compile_failure() {
], ],
) )
} }
#[test]
fn test_out_missing_type_compile_failure() {
assert_build_failure(
"out",
vec![
Regex::new(r"Expected converter name").unwrap(),
Regex::new(r"Not a Bareword").unwrap(),
Regex::new(r"at <eval> line: 1, column: 4").unwrap(),
],
)
}
#[test]
fn test_out_missing_out_expr_compile_failure() {
assert_build_failure(
"out json",
vec![
Regex::new(r"Expected Expression to export").unwrap(),
Regex::new(r"at <eval> line: 1, column: 9").unwrap(),
],
)
}
#[test]
fn test_out_multiple_times_compile_failure() {
assert_build_failure(
"out json {};\nout json {};",
vec![
Regex::new(r"You can only have one output per file").unwrap(),
Regex::new(r"at <eval> line: 2, column: 1").unwrap(),
],
)
}

View File

@ -491,7 +491,7 @@ impl<'a> FileBuilder<'a> {
&Statement::Expression(ref expr) => self.eval_expr(expr, &child_scope), &Statement::Expression(ref expr) => self.eval_expr(expr, &child_scope),
// Only one output can be used per file. Right now we enforce this by // Only one output can be used per file. Right now we enforce this by
// having a single builder per file. // having a single builder per file.
&Statement::Output(ref typ, ref expr) => { &Statement::Output(ref pos, ref typ, ref expr) => {
if let None = self.out_lock { if let None = self.out_lock {
let val = self.eval_expr(expr, &child_scope)?; let val = self.eval_expr(expr, &child_scope)?;
self.out_lock = Some((typ.fragment.to_string(), val.clone())); self.out_lock = Some((typ.fragment.to_string(), val.clone()));
@ -499,8 +499,8 @@ impl<'a> FileBuilder<'a> {
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new(
format!("You can only have one output per file."), format!("You can only have one output per file."),
error::ErrorType::DuplicateBinding, error::ErrorType::Unsupported,
typ.pos.clone(), pos.clone(),
))) )))
} }
} }

View File

@ -792,11 +792,12 @@ make_fn!(
make_fn!( make_fn!(
out_statement<SliceIter<Token>, Statement>, out_statement<SliceIter<Token>, Statement>,
do_each!( do_each!(
pos => pos,
_ => word!("out"), _ => word!("out"),
typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"), typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"),
expr => wrap_err!(must!(expression), "Expected Expression to export"), expr => wrap_err!(must!(expression), "Expected Expression to export"),
_ => must!(punct!(";")), _ => must!(punct!(";")),
(Statement::Output(typ.clone(), expr.clone())) (Statement::Output(pos, typ.clone(), expr.clone()))
) )
); );