Add pretty errors to commands

This commit is contained in:
Jonathan Turner
2019-06-08 10:35:07 +12:00
parent 2d13069ca3
commit e94d1d2758
26 changed files with 318 additions and 166 deletions

View File

@ -1,5 +1,6 @@
use crate::object::Primitive;
use crate::parser::ast;
use crate::parser::lexer::Spanned;
use crate::prelude::*;
use derive_new::new;
use indexmap::IndexMap;
@ -20,17 +21,25 @@ impl Scope {
}
}
crate fn evaluate_expr(expr: &ast::Expression, scope: &Scope) -> Result<Value, ShellError> {
crate fn evaluate_expr(
expr: &ast::Expression,
scope: &Scope,
) -> Result<Spanned<Value>, ShellError> {
use ast::*;
match &expr.expr {
RawExpression::Call(_) => Err(ShellError::unimplemented("Evaluating call expression")),
RawExpression::Leaf(l) => Ok(evaluate_leaf(l)),
RawExpression::Leaf(l) => Ok(Spanned::from_item(evaluate_leaf(l), expr.span.clone())),
RawExpression::Parenthesized(p) => evaluate_expr(&p.expr, scope),
RawExpression::Flag(f) => Ok(Value::Primitive(Primitive::String(f.print()))),
RawExpression::Flag(f) => Ok(Spanned::from_item(
Value::Primitive(Primitive::String(f.print())),
expr.span.clone(),
)),
RawExpression::Block(b) => evaluate_block(&b, scope),
RawExpression::Path(p) => evaluate_path(&p, scope),
RawExpression::Binary(b) => evaluate_binary(b, scope),
RawExpression::VariableReference(r) => evaluate_reference(r, scope),
RawExpression::VariableReference(r) => {
evaluate_reference(r, scope).map(|x| Spanned::from_item(x, expr.span.clone()))
}
}
}
@ -59,12 +68,15 @@ fn evaluate_reference(r: &ast::Variable, scope: &Scope) -> Result<Value, ShellEr
}
}
fn evaluate_binary(binary: &ast::Binary, scope: &Scope) -> Result<Value, ShellError> {
fn evaluate_binary(binary: &ast::Binary, scope: &Scope) -> Result<Spanned<Value>, ShellError> {
let left = evaluate_expr(&binary.left, scope)?;
let right = evaluate_expr(&binary.right, scope)?;
match left.compare(&binary.operator, &right) {
Some(v) => Ok(Value::boolean(v)),
Some(v) => Ok(Spanned::from_item(
Value::boolean(v),
binary.operator.span.clone(),
)),
None => Err(ShellError::TypeError(format!(
"Can't compare {} and {}",
left.type_name(),
@ -73,13 +85,16 @@ fn evaluate_binary(binary: &ast::Binary, scope: &Scope) -> Result<Value, ShellEr
}
}
fn evaluate_block(block: &ast::Block, _scope: &Scope) -> Result<Value, ShellError> {
Ok(Value::block(block.expr.clone()))
fn evaluate_block(block: &ast::Block, _scope: &Scope) -> Result<Spanned<Value>, ShellError> {
Ok(Spanned::from_item(
Value::block(block.expr.clone()),
block.expr.span.clone(),
))
}
fn evaluate_path(path: &ast::Path, scope: &Scope) -> Result<Value, ShellError> {
fn evaluate_path(path: &ast::Path, scope: &Scope) -> Result<Spanned<Value>, ShellError> {
let head = path.head();
let mut value = &evaluate_expr(head, scope)?;
let mut value = evaluate_expr(head, scope)?;
let mut seen = vec![];
for name in path.tail() {
@ -93,9 +108,9 @@ fn evaluate_path(path: &ast::Path, scope: &Scope) -> Result<Value, ShellError> {
subpath: itertools::join(seen, "."),
});
}
Some(v) => value = v,
Some(v) => value = Spanned::from_item(v.copy(), name.span.clone()),
}
}
Ok(value.copy())
Ok(value)
}