FEATURE: BuildError no longer requires a position.

This commit is contained in:
Jeremy Wall 2019-02-19 17:16:36 -06:00
parent ceaed5c543
commit 8639912567
9 changed files with 128 additions and 124 deletions

View File

@ -71,6 +71,11 @@ impl Position {
offset: offset, offset: offset,
} }
} }
pub fn with_file<P: Into<PathBuf>>(mut self, file: P) -> Self {
self.file = Some(file.into());
self
}
} }
impl<'a> From<&'a Position> for Position { impl<'a> From<&'a Position> for Position {

View File

@ -54,7 +54,7 @@ impl<V: Into<String> + Clone> FormatRenderer for SimpleFormatter<V> {
for c in self.tmpl.chars() { for c in self.tmpl.chars() {
if c == '@' && !should_escape { if c == '@' && !should_escape {
if count == self.args.len() { if count == self.args.len() {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Too few arguments to string \ "Too few arguments to string \
formatter.", formatter.",
error::ErrorType::FormatError, error::ErrorType::FormatError,
@ -72,7 +72,7 @@ impl<V: Into<String> + Clone> FormatRenderer for SimpleFormatter<V> {
} }
} }
if self.args.len() != count { if self.args.len() != count {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Too many arguments to string \ "Too many arguments to string \
formatter.", formatter.",
error::ErrorType::FormatError, error::ErrorType::FormatError,
@ -111,7 +111,7 @@ impl<'a> ExpressionFormatter<'a> {
if c == '{' { if c == '{' {
brace_count += 1; brace_count += 1;
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Invalid syntax for format string expected '{{' but got {}", "Invalid syntax for format string expected '{{' but got {}",
c c
@ -122,7 +122,7 @@ impl<'a> ExpressionFormatter<'a> {
} }
} }
None => { None => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Invalid syntax for format string expected '{' but string ended", "Invalid syntax for format string expected '{' but string ended",
error::ErrorType::FormatError, error::ErrorType::FormatError,
pos.clone(), pos.clone(),
@ -148,7 +148,7 @@ impl<'a> ExpressionFormatter<'a> {
} }
// empty expressions are an error // empty expressions are an error
if expr_string.is_empty() { if expr_string.is_empty() {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Got an empty expression in format string", "Got an empty expression in format string",
error::ErrorType::FormatError, error::ErrorType::FormatError,
pos.clone(), pos.clone(),
@ -163,7 +163,7 @@ impl<'a> ExpressionFormatter<'a> {
expr_string.push(c); expr_string.push(c);
} }
} }
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Expected '}' but got end of string", "Expected '}' but got end of string",
error::ErrorType::FormatError, error::ErrorType::FormatError,
pos.clone(), pos.clone(),

View File

@ -60,7 +60,7 @@ impl Val {
) )
} }
pub fn equal(&self, target: &Self, pos: Position) -> Result<bool, error::BuildError> { pub fn equal(&self, target: &Self) -> Result<bool, error::BuildError> {
// first we do a type equality comparison // first we do a type equality comparison
match (self, target) { match (self, target) {
// Empty values are always equal. // Empty values are always equal.
@ -74,7 +74,7 @@ impl Val {
Ok(false) Ok(false)
} else { } else {
for (i, lv) in ldef.iter().enumerate() { for (i, lv) in ldef.iter().enumerate() {
if !lv.equal(rdef[i].as_ref(), pos.clone())? { if !lv.equal(rdef[i].as_ref())? {
return Ok(false); return Ok(false);
} }
} }
@ -92,7 +92,7 @@ impl Val {
return Ok(false); return Ok(false);
} else { } else {
// field value equality. // field value equality.
if !lv.1.equal(field_target.1.as_ref(), pos.clone())? { if !lv.1.equal(field_target.1.as_ref())? {
return Ok(false); return Ok(false);
} }
} }
@ -100,16 +100,13 @@ impl Val {
Ok(true) Ok(true)
} }
} }
// FIXME(jwall): Maybe we don't require positions here?
(&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new( (&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new(
"Func are not comparable", "Func are not comparable",
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos,
)), )),
(&Val::Module(_), &Val::Module(_)) => Err(error::BuildError::new( (&Val::Module(_), &Val::Module(_)) => Err(error::BuildError::new(
"Module are not comparable", "Module are not comparable",
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos,
)), )),
// EMPTY is always comparable for equality. // EMPTY is always comparable for equality.
(&Val::Empty, _) => Ok(false), (&Val::Empty, _) => Ok(false),
@ -117,7 +114,6 @@ impl Val {
(me, tgt) => Err(error::BuildError::new( (me, tgt) => Err(error::BuildError::new(
format!("Expected {} but got ({})", me.type_name(), tgt), format!("Expected {} but got ({})", me.type_name(), tgt),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos,
)), )),
} }
} }

View File

@ -61,7 +61,7 @@ impl FuncDef {
// Error conditions. If the args don't match the length and types of the argdefs then this is // Error conditions. If the args don't match the length and types of the argdefs then this is
// func call error. // func call error.
if args.len() > self.argdefs.len() { if args.len() > self.argdefs.len() {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
"Func called with too many args", "Func called with too many args",
error::ErrorType::BadArgLen, error::ErrorType::BadArgLen,
self.pos.clone(), self.pos.clone(),
@ -129,7 +129,7 @@ macro_rules! eval_binary_expr {
return Ok(Rc::new($result)); return Ok(Rc::new($result));
} }
val => { val => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected {} but got ({})", $msg, val), format!("Expected {} but got ({})", $msg, val),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
$pos.clone(), $pos.clone(),
@ -277,15 +277,13 @@ impl<'a> FileBuilder<'a> {
&Value::Int(ref i) => Ok(Rc::new(Val::Int(i.val))), &Value::Int(ref i) => Ok(Rc::new(Val::Int(i.val))),
&Value::Float(ref f) => Ok(Rc::new(Val::Float(f.val))), &Value::Float(ref f) => Ok(Rc::new(Val::Float(f.val))),
&Value::Str(ref s) => Ok(Rc::new(Val::Str(s.val.to_string()))), &Value::Str(ref s) => Ok(Rc::new(Val::Str(s.val.to_string()))),
&Value::Symbol(ref s) => { &Value::Symbol(ref s) => scope.lookup_sym(&(s.into()), true).ok_or(Box::new(
scope error::BuildError::new_with_pos(
.lookup_sym(&(s.into()), true) format!("Unable to find binding {}", s.val,),
.ok_or(Box::new(error::BuildError::new( error::ErrorType::NoSuchSymbol,
format!("Unable to find binding {}", s.val,), v.pos().clone(),
error::ErrorType::NoSuchSymbol, ),
v.pos().clone(), )),
)))
}
&Value::List(ref def) => self.eval_list(def, scope), &Value::List(ref def) => self.eval_list(def, scope),
&Value::Tuple(ref tuple) => self.eval_tuple(&tuple.val, scope), &Value::Tuple(ref tuple) => self.eval_tuple(&tuple.val, scope),
} }
@ -329,7 +327,7 @@ impl<'a> FileBuilder<'a> {
Some(val) => Ok(val), Some(val) => Ok(val),
} }
} }
Err(err) => Err(Box::new(error::BuildError::new( Err(err) => Err(Box::new(error::BuildError::new_with_pos(
format!("{}", err,), format!("{}", err,),
error::ErrorType::ParseError, error::ErrorType::ParseError,
(&input).into(), (&input).into(),
@ -410,7 +408,7 @@ impl<'a> FileBuilder<'a> {
mut_assets_cache.stash(path, result.clone())?; mut_assets_cache.stash(path, result.clone())?;
return Ok(result); return Ok(result);
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("No such import {} in the std library.", def.path.fragment), format!("No such import {} in the std library.", def.path.fragment),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
def.pos.clone(), def.pos.clone(),
@ -420,7 +418,7 @@ impl<'a> FileBuilder<'a> {
// Try a relative path first. // Try a relative path first.
let normalized = self.find_file(&def.path.fragment, true)?; let normalized = self.find_file(&def.path.fragment, true)?;
if self.detect_import_cycle(normalized.to_string_lossy().as_ref()) { if self.detect_import_cycle(normalized.to_string_lossy().as_ref()) {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Import Cycle Detected!!!! {} is already in import stack: {:?}", "Import Cycle Detected!!!! {} is already in import stack: {:?}",
normalized.to_string_lossy(), normalized.to_string_lossy(),
@ -452,7 +450,7 @@ impl<'a> FileBuilder<'a> {
let val = self.eval_expr(&def.value, &child_scope)?; let val = self.eval_expr(&def.value, &child_scope)?;
let name = &def.name; let name = &def.name;
if Self::check_reserved_word(&name.fragment) { if Self::check_reserved_word(&name.fragment) {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Let {} binding collides with reserved word", name.fragment), format!("Let {} binding collides with reserved word", name.fragment),
error::ErrorType::ReservedWordError, error::ErrorType::ReservedWordError,
name.pos.clone(), name.pos.clone(),
@ -460,7 +458,7 @@ impl<'a> FileBuilder<'a> {
} }
match self.scope.build_output.entry(name.into()) { match self.scope.build_output.entry(name.into()) {
Entry::Occupied(e) => { Entry::Occupied(e) => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Binding \ "Binding \
for {:?} already \ for {:?} already \
@ -492,7 +490,7 @@ impl<'a> FileBuilder<'a> {
self.out_lock = Some((typ.fragment.to_string(), val.clone())); self.out_lock = Some((typ.fragment.to_string(), val.clone()));
Ok(val) Ok(val)
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("You can only have one output per file."), format!("You can only have one output per file."),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
pos.clone(), pos.clone(),
@ -521,7 +519,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::Str([s.to_string(), ss.clone()].concat()))); return Ok(Rc::new(Val::Str([s.to_string(), ss.clone()].concat())));
} }
val => { val => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected \ "Expected \
String \ String \
@ -542,7 +540,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::List(new_vec))); return Ok(Rc::new(Val::List(new_vec)));
} }
val => { val => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected \ "Expected \
List \ List \
@ -556,7 +554,7 @@ impl<'a> FileBuilder<'a> {
} }
}, },
ref expr => { ref expr => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("{} does not support the '+' operation", expr.type_name()), format!("{} does not support the '+' operation", expr.type_name()),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
lpos.clone(), lpos.clone(),
@ -580,7 +578,7 @@ impl<'a> FileBuilder<'a> {
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f - ff), "Float") eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f - ff), "Float")
} }
ref expr => { ref expr => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("{} does not support the '-' operation", expr.type_name()), format!("{} does not support the '-' operation", expr.type_name()),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
lpos.clone(), lpos.clone(),
@ -604,7 +602,7 @@ impl<'a> FileBuilder<'a> {
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f * ff), "Float") eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f * ff), "Float")
} }
ref expr => { ref expr => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("{} does not support the '*' operation", expr.type_name()), format!("{} does not support the '*' operation", expr.type_name()),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
lpos.clone(), lpos.clone(),
@ -628,7 +626,7 @@ impl<'a> FileBuilder<'a> {
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f % ff), "Float") eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f % ff), "Float")
} }
ref expr => { ref expr => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"{} does not support the 'modulus' operation", "{} does not support the 'modulus' operation",
expr.type_name() expr.type_name()
@ -655,7 +653,7 @@ impl<'a> FileBuilder<'a> {
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f / ff), "Float") eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f / ff), "Float")
} }
ref expr => { ref expr => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("{} does not support the '*' operation", expr.type_name()), format!("{} does not support the '*' operation", expr.type_name()),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
lpos.clone(), lpos.clone(),
@ -670,9 +668,14 @@ impl<'a> FileBuilder<'a> {
left: Rc<Val>, left: Rc<Val>,
right: Rc<Val>, right: Rc<Val>,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
Ok(Rc::new(Val::Boolean( match left.equal(right.as_ref()) {
left.equal(right.as_ref(), pos.clone())?, Ok(b) => Ok(Rc::new(Val::Boolean(b))),
))) Err(e) => Err(Box::new(error::BuildError::new_with_pos(
e.msg,
e.err_type,
pos.clone(),
))),
}
} }
fn do_not_deep_equal( fn do_not_deep_equal(
@ -681,9 +684,14 @@ impl<'a> FileBuilder<'a> {
left: Rc<Val>, left: Rc<Val>,
right: Rc<Val>, right: Rc<Val>,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
Ok(Rc::new(Val::Boolean( match left.equal(right.as_ref()) {
!left.equal(right.as_ref(), pos.clone())?, Ok(b) => Ok(Rc::new(Val::Boolean(!b))),
))) Err(e) => Err(Box::new(error::BuildError::new_with_pos(
e.msg,
e.err_type,
pos.clone(),
))),
}
} }
fn do_gt( fn do_gt(
@ -703,7 +711,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::Boolean(l > r))); return Ok(Rc::new(Val::Boolean(l > r)));
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Expected {} but got ({})", left.type_name(), right,), format!("Expected {} but got ({})", left.type_name(), right,),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -727,7 +735,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::Boolean(l < r))); return Ok(Rc::new(Val::Boolean(l < r)));
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Expected {} but got ({})", left.type_name(), right,), format!("Expected {} but got ({})", left.type_name(), right,),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -750,7 +758,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::Boolean(l <= r))); return Ok(Rc::new(Val::Boolean(l <= r)));
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Expected {} but got ({})", left.type_name(), right), format!("Expected {} but got ({})", left.type_name(), right),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -773,7 +781,7 @@ impl<'a> FileBuilder<'a> {
return Ok(Rc::new(Val::Boolean(l >= r))); return Ok(Rc::new(Val::Boolean(l >= r)));
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Expected {} but got ({})", left.type_name(), right,), format!("Expected {} but got ({})", left.type_name(), right,),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -789,7 +797,7 @@ impl<'a> FileBuilder<'a> {
Expression::Simple(Value::Symbol(ref s)) => { Expression::Simple(Value::Symbol(ref s)) => {
scope scope
.lookup_sym(s, true) .lookup_sym(s, true)
.ok_or(Box::new(error::BuildError::new( .ok_or(Box::new(error::BuildError::new_with_pos(
format!("Unable to find binding {}", s.val,), format!("Unable to find binding {}", s.val,),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos, pos,
@ -798,7 +806,7 @@ impl<'a> FileBuilder<'a> {
Expression::Simple(Value::Str(ref s)) => { Expression::Simple(Value::Str(ref s)) => {
scope scope
.lookup_sym(s, false) .lookup_sym(s, false)
.ok_or(Box::new(error::BuildError::new( .ok_or(Box::new(error::BuildError::new_with_pos(
format!("Unable to find binding {}", s.val,), format!("Unable to find binding {}", s.val,),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos, pos,
@ -813,12 +821,12 @@ impl<'a> FileBuilder<'a> {
Val::Int(i) => scope.lookup_idx(right.pos(), &Val::Int(*i)), Val::Int(i) => scope.lookup_idx(right.pos(), &Val::Int(*i)),
Val::Str(ref s) => scope Val::Str(ref s) => scope
.lookup_sym(&PositionedItem::new(s.clone(), pos.clone()), false) .lookup_sym(&PositionedItem::new(s.clone(), pos.clone()), false)
.ok_or(Box::new(error::BuildError::new( .ok_or(Box::new(error::BuildError::new_with_pos(
format!("Unable to find binding {}", s,), format!("Unable to find binding {}", s,),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos, pos,
))), ))),
_ => Err(Box::new(error::BuildError::new( _ => Err(Box::new(error::BuildError::new_with_pos(
format!("Invalid selector lookup {}", val.type_name(),), format!("Invalid selector lookup {}", val.type_name(),),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos, pos,
@ -859,7 +867,7 @@ impl<'a> FileBuilder<'a> {
return Ok(right); return Ok(right);
} }
} }
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected boolean value for operator but got ({})", "Expected boolean value for operator but got ({})",
left.type_name() left.type_name()
@ -868,7 +876,7 @@ impl<'a> FileBuilder<'a> {
right_pos.clone(), right_pos.clone(),
))); )));
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected boolean value for operator but got ({})", "Expected boolean value for operator but got ({})",
left.type_name() left.type_name()
@ -891,7 +899,7 @@ impl<'a> FileBuilder<'a> {
let right = self.eval_expr(right, scope)?; let right = self.eval_expr(right, scope)?;
// presence checks are only valid for tuples and lists. // presence checks are only valid for tuples and lists.
if !(right.is_tuple() || right.is_list()) { if !(right.is_tuple() || right.is_list()) {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Invalid righthand type for in operator {}", "Invalid righthand type for in operator {}",
right.type_name() right.type_name()
@ -935,7 +943,7 @@ impl<'a> FileBuilder<'a> {
let re = if let Val::Str(ref s) = right.as_ref() { let re = if let Val::Str(ref s) = right.as_ref() {
regex::Regex::new(s.as_ref())? regex::Regex::new(s.as_ref())?
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected string for regex but got ({})", right.type_name()), format!("Expected string for regex but got ({})", right.type_name()),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
right_pos.clone(), right_pos.clone(),
@ -944,7 +952,7 @@ impl<'a> FileBuilder<'a> {
let tgt = if let Val::Str(ref s) = left.as_ref() { let tgt = if let Val::Str(ref s) = left.as_ref() {
s.as_ref() s.as_ref()
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected string but got ({})", left.type_name()), format!("Expected string but got ({})", left.type_name()),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
left_pos.clone(), left_pos.clone(),
@ -993,7 +1001,7 @@ impl<'a> FileBuilder<'a> {
&BinaryExprType::Div => self.divide_vals(&def.pos, def.right.pos(), left, right), &BinaryExprType::Div => self.divide_vals(&def.pos, def.right.pos(), left, right),
&BinaryExprType::Mod => self.mod_vals(&def.pos, def.right.pos(), left, right), &BinaryExprType::Mod => self.mod_vals(&def.pos, def.right.pos(), left, right),
// Handle Comparison operators here // Handle Comparison operators here
&BinaryExprType::Equal => self.do_deep_equal(def.right.pos(), left, right), &BinaryExprType::Equal => self.do_deep_equal(&def.right.pos(), left, right),
&BinaryExprType::GT => self.do_gt(&def.right.pos(), left, right), &BinaryExprType::GT => self.do_gt(&def.right.pos(), left, right),
&BinaryExprType::LT => self.do_lt(&def.right.pos(), left, right), &BinaryExprType::LT => self.do_lt(&def.right.pos(), left, right),
&BinaryExprType::GTEqual => self.do_gtequal(&def.right.pos(), left, right), &BinaryExprType::GTEqual => self.do_gtequal(&def.right.pos(), left, right),
@ -1045,7 +1053,6 @@ impl<'a> FileBuilder<'a> {
key key
), ),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
} }
@ -1067,7 +1074,7 @@ impl<'a> FileBuilder<'a> {
{ {
v.insert((src_val.0, expr_result)); v.insert((src_val.0, expr_result));
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected type {} for field {} but got ({})", "Expected type {} for field {} but got ({})",
src_val.1.type_name(), src_val.1.type_name(),
@ -1125,7 +1132,7 @@ impl<'a> FileBuilder<'a> {
PositionedItem::new_with_pos(String::from("mod"), Position::new(0, 0, 0)); PositionedItem::new_with_pos(String::from("mod"), Position::new(0, 0, 0));
match b.scope.build_output.entry(mod_key) { match b.scope.build_output.entry(mod_key) {
Entry::Occupied(e) => { Entry::Occupied(e) => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Binding \ "Binding \
for {:?} already \ for {:?} already \
@ -1146,7 +1153,7 @@ impl<'a> FileBuilder<'a> {
// tuple using them. // tuple using them.
return Ok(b.get_outputs_as_val()); return Ok(b.get_outputs_as_val());
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Weird value stored in our module parameters slot {:?}", "Weird value stored in our module parameters slot {:?}",
mod_def.arg_tuple mod_def.arg_tuple
@ -1156,7 +1163,7 @@ impl<'a> FileBuilder<'a> {
))); )));
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Expected Tuple or Module but got ({})", v), format!("Expected Tuple or Module but got ({})", v),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.selector.pos().clone(), def.selector.pos().clone(),
@ -1200,14 +1207,14 @@ impl<'a> FileBuilder<'a> {
} }
return match def.eval(self, argvals) { return match def.eval(self, argvals) {
Ok(v) => Ok(v), Ok(v) => Ok(v),
Err(e) => Err(Box::new(error::BuildError::new( Err(e) => Err(Box::new(error::BuildError::new_with_pos(
format!("Func evaluation failed\nCaused by:\n\t{}", e), format!("Func evaluation failed\nCaused by:\n\t{}", e),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
call_pos, call_pos,
))), ))),
}; };
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
// We should pretty print the selectors here. // We should pretty print the selectors here.
format!("{} is not a Function", v), format!("{} is not a Function", v),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
@ -1273,7 +1280,7 @@ impl<'a> FileBuilder<'a> {
// Otherwise return the default. // Otherwise return the default.
return self.eval_expr(def_expr, scope); return self.eval_expr(def_expr, scope);
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected String but got \ "Expected String but got \
{} in Select expression", {} in Select expression",
@ -1333,7 +1340,7 @@ impl<'a> FileBuilder<'a> {
let new_name = if let &Val::Str(ref s) = fs[0].as_ref() { let new_name = if let &Val::Str(ref s) = fs[0].as_ref() {
s.clone() s.clone()
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"map on tuple expects the first item out list to be a string but got size {}", "map on tuple expects the first item out list to be a string but got size {}",
fs[0].type_name() fs[0].type_name()
@ -1344,7 +1351,7 @@ impl<'a> FileBuilder<'a> {
}; };
out.push((new_name, fs[1].clone())); out.push((new_name, fs[1].clone()));
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"map on a tuple field expects a list of size 2 as output but got size {}", "map on a tuple field expects a list of size 2 as output but got size {}",
fs.len() fs.len()
@ -1354,7 +1361,7 @@ impl<'a> FileBuilder<'a> {
))); )));
} }
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"map on a tuple field expects a list as output but got ({})", "map on a tuple field expects a list as output but got ({})",
result.type_name() result.type_name()
@ -1386,7 +1393,7 @@ impl<'a> FileBuilder<'a> {
let funcdef = match maybe_mac.as_ref() { let funcdef = match maybe_mac.as_ref() {
&Val::Func(ref funcdef) => funcdef, &Val::Func(ref funcdef) => funcdef,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected func but got {:?}", def.func), format!("Expected func but got {:?}", def.func),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.pos.clone(), def.pos.clone(),
@ -1416,7 +1423,7 @@ impl<'a> FileBuilder<'a> {
} }
} }
other => { other => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected List Str, or Tuple as target but got {:?}", "Expected List Str, or Tuple as target but got {:?}",
other.type_name() other.type_name()
@ -1451,7 +1458,7 @@ impl<'a> FileBuilder<'a> {
// noop // noop
} }
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected boolean or NULL for filter return but got ({})", "Expected boolean or NULL for filter return but got ({})",
out.type_name() out.type_name()
@ -1467,7 +1474,7 @@ impl<'a> FileBuilder<'a> {
result.push_str(&s); result.push_str(&s);
} }
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected string map return but got ({})", out.type_name()), format!("Expected string map return but got ({})", out.type_name()),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.pos.clone(), def.pos.clone(),
@ -1490,7 +1497,7 @@ impl<'a> FileBuilder<'a> {
let macdef = match maybe_mac.as_ref() { let macdef = match maybe_mac.as_ref() {
&Val::Func(ref macdef) => macdef, &Val::Func(ref macdef) => macdef,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected func but got {:?}", def.func), format!("Expected func but got {:?}", def.func),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.pos.clone(), def.pos.clone(),
@ -1502,7 +1509,7 @@ impl<'a> FileBuilder<'a> {
&Val::Tuple(ref fs) => self.eval_functional_tuple_processing(fs, macdef, typ), &Val::Tuple(ref fs) => self.eval_functional_tuple_processing(fs, macdef, typ),
// TODO(jwall): Strings? // TODO(jwall): Strings?
&Val::Str(ref s) => self.eval_functional_string_processing(s, macdef, typ), &Val::Str(ref s) => self.eval_functional_string_processing(s, macdef, typ),
other => Err(Box::new(error::BuildError::new( other => Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected List or Tuple as target but got {:?}", "Expected List or Tuple as target but got {:?}",
other.type_name() other.type_name()
@ -1612,7 +1619,7 @@ impl<'a> FileBuilder<'a> {
let normalized = match self.find_file(path, false) { let normalized = match self.find_file(path, false) {
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(e) => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Error finding file {} {}", path, e), format!("Error finding file {} {}", path, e),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -1622,7 +1629,7 @@ impl<'a> FileBuilder<'a> {
let mut f = match File::open(&normalized) { let mut f = match File::open(&normalized) {
Ok(f) => f, Ok(f) => f,
Err(e) => { Err(e) => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Error opening file {} {}", normalized.to_string_lossy(), e), format!("Error opening file {} {}", normalized.to_string_lossy(), e),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -1653,7 +1660,7 @@ impl<'a> FileBuilder<'a> {
}; };
Ok(val) Ok(val)
} }
None => Err(Box::new(error::BuildError::new( None => Err(Box::new(error::BuildError::new_with_pos(
format!("Unknown include conversion type {}", def.typ.fragment), format!("Unknown include conversion type {}", def.typ.fragment),
error::ErrorType::Unsupported, error::ErrorType::Unsupported,
def.typ.pos.clone(), def.typ.pos.clone(),
@ -1679,7 +1686,7 @@ impl<'a> FileBuilder<'a> {
let start = match start.as_ref() { let start = match start.as_ref() {
&Val::Int(i) => i, &Val::Int(i) => i,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected an integer for range start but got ({})", "Expected an integer for range start but got ({})",
start.type_name() start.type_name()
@ -1696,7 +1703,7 @@ impl<'a> FileBuilder<'a> {
match step.as_ref() { match step.as_ref() {
&Val::Int(i) => i, &Val::Int(i) => i,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected an integer for range step but got ({})", "Expected an integer for range step but got ({})",
step.type_name() step.type_name()
@ -1715,7 +1722,7 @@ impl<'a> FileBuilder<'a> {
let end = match end.as_ref() { let end = match end.as_ref() {
&Val::Int(i) => i, &Val::Int(i) => i,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected an integer for range start but got ({})", "Expected an integer for range start but got ({})",
end.type_name() end.type_name()
@ -1742,7 +1749,7 @@ impl<'a> FileBuilder<'a> {
let typ = match tval.as_ref() { let typ = match tval.as_ref() {
Val::Str(ref s) => s.clone(), Val::Str(ref s) => s.clone(),
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected string expression but got ({})", tval), format!("Expected string expression but got ({})", tval),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.right.pos().clone(), def.right.pos().clone(),
@ -1761,7 +1768,7 @@ impl<'a> FileBuilder<'a> {
"func" => val.is_func(), "func" => val.is_func(),
"module" => val.is_module(), "module" => val.is_module(),
other => { other => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Expected valid type name but got ({})", other), format!("Expected valid type name but got ({})", other),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
def.right.pos().clone(), def.right.pos().clone(),
@ -1797,13 +1804,13 @@ impl<'a> FileBuilder<'a> {
&Expression::Fail(ref def) => { &Expression::Fail(ref def) => {
let err = self.eval_expr(&def.message, scope)?; let err = self.eval_expr(&def.message, scope)?;
return if let Val::Str(ref s) = err.as_ref() { return if let Val::Str(ref s) = err.as_ref() {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
s.clone(), s.clone(),
error::ErrorType::UserDefined, error::ErrorType::UserDefined,
def.pos.clone(), def.pos.clone(),
))) )))
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected string for message but got ({})", "Expected string for message but got ({})",
def.message.as_ref() def.message.as_ref()
@ -1818,7 +1825,7 @@ impl<'a> FileBuilder<'a> {
return if let Val::Boolean(b) = val.as_ref() { return if let Val::Boolean(b) = val.as_ref() {
Ok(Rc::new(Val::Boolean(!b))) Ok(Rc::new(Val::Boolean(!b)))
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!( format!(
"Expected boolean for expression but got ({})", "Expected boolean for expression but got ({})",
def.expr.as_ref() def.expr.as_ref()

View File

@ -115,7 +115,7 @@ impl Scope {
return Self::lookup_in_list(pos, idx, fs); return Self::lookup_in_list(pos, idx, fs);
} }
} }
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
"Not a list in index lookup.", "Not a list in index lookup.",
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -189,7 +189,7 @@ impl Scope {
if let Some(vv) = find_in_fieldlist(&field, fs) { if let Some(vv) = find_in_fieldlist(&field, fs) {
Ok(vv) Ok(vv)
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("Unable to {} match element in tuple.", field,), format!("Unable to {} match element in tuple.", field,),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos.clone(), pos.clone(),
@ -206,7 +206,7 @@ impl Scope {
&Val::Int(i) => i as usize, &Val::Int(i) => i as usize,
&Val::Str(ref s) => s.parse::<usize>()?, &Val::Str(ref s) => s.parse::<usize>()?,
_ => { _ => {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new_with_pos(
format!("Invalid idx type {} for list lookup", field), format!("Invalid idx type {} for list lookup", field),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
pos.clone(), pos.clone(),
@ -216,7 +216,7 @@ impl Scope {
if idx < elems.len() { if idx < elems.len() {
Ok(elems[idx].clone()) Ok(elems[idx].clone())
} else { } else {
Err(Box::new(error::BuildError::new( Err(Box::new(error::BuildError::new_with_pos(
format!("idx {} out of bounds in list", idx), format!("idx {} out of bounds in list", idx),
error::ErrorType::NoSuchSymbol, error::ErrorType::NoSuchSymbol,
pos.clone(), pos.clone(),

View File

@ -17,7 +17,6 @@ use std;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use std::rc::Rc; use std::rc::Rc;
use crate::ast::Position;
use crate::build::Val; use crate::build::Val;
use crate::build::Val::Tuple; use crate::build::Val::Tuple;
use crate::convert; use crate::convert;
@ -46,21 +45,18 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"Exec tuples must have no more than 3 fields", "Exec tuples must have no more than 3 fields",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
let mut env: Option<&Vec<(String, Rc<Val>)>> = None; let mut env: Option<&Vec<(String, Rc<Val>)>> = None;
let mut command: Option<&str> = None; let mut command: Option<&str> = None;
let mut args: Option<&Vec<Rc<Val>>> = None; let mut args: Option<&Vec<Rc<Val>>> = None;
for &(ref name, ref val) in fields.iter() { for &(ref name, ref val) in fields.iter() {
// FIXME(jwall): BuildError should not require a Position.
// We require a command field in our exec tuple. // We require a command field in our exec tuple.
if name == "command" { if name == "command" {
if command.is_some() { if command.is_some() {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one command field in an exec tuple", "There can only be one command field in an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
if let &Val::Str(ref s) = val.as_ref() { if let &Val::Str(ref s) = val.as_ref() {
@ -70,7 +66,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The command field of an exec tuple must be a string", "The command field of an exec tuple must be a string",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
// We optionally allow an env field in our exec tuple. // We optionally allow an env field in our exec tuple.
@ -80,7 +75,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one env field in an exec tuple", "There can only be one env field in an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
env = Some(l); env = Some(l);
@ -89,7 +83,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The env field of an exec tuple must be a list", "The env field of an exec tuple must be a list",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
// We optionally allow an args field in our exec tuple. // We optionally allow an args field in our exec tuple.
@ -99,7 +92,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one args field of an exec tuple", "There can only be one args field of an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
args = Some(l); args = Some(l);
@ -108,7 +100,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The args field of an exec tuple must be a list", "The args field of an exec tuple must be a list",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
} }
@ -116,7 +107,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"An exec tuple must have a command field", "An exec tuple must have a command field",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
// Okay if we have made it this far then we are ready to start creating our script. // Okay if we have made it this far then we are ready to start creating our script.
@ -137,7 +127,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The env fields of an exec tuple must contain only string values", "The env fields of an exec tuple must contain only string values",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
} }
@ -158,7 +147,6 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"Exec args must be a list of strings or tuples of strings.", "Exec args must be a list of strings or tuples of strings.",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
} }
@ -174,7 +162,6 @@ impl ExecConverter {
Err(Box::new(BuildError::new( Err(Box::new(BuildError::new(
"Exec outputs must be of type Tuple", "Exec outputs must be of type Tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))) )))
} }
} }

View File

@ -18,7 +18,6 @@ use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
use super::traits::{ConvertResult, Converter}; use super::traits::{ConvertResult, Converter};
use crate::ast::Position;
use crate::build::Val; use crate::build::Val;
use crate::error::BuildError; use crate::error::BuildError;
use crate::error::ErrorType; use crate::error::ErrorType;
@ -38,7 +37,6 @@ impl XmlConverter {
Err(Box::new(BuildError::new( Err(Box::new(BuildError::new(
"Not a String value", "Not a String value",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))) )))
} }
} }
@ -50,7 +48,6 @@ impl XmlConverter {
Err(Box::new(BuildError::new( Err(Box::new(BuildError::new(
"Not a tuple value", "Not a tuple value",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))) )))
} }
} }
@ -62,7 +59,6 @@ impl XmlConverter {
Err(Box::new(BuildError::new( Err(Box::new(BuildError::new(
"Not a List value", "Not a List value",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))) )))
} }
} }
@ -123,7 +119,6 @@ impl XmlConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"XML nodes can not have both text and name fields", "XML nodes can not have both text and name fields",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
if name.is_some() { if name.is_some() {
@ -160,7 +155,6 @@ impl XmlConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"XML nodes must be a Tuple or a string", "XML nodes must be a Tuple or a string",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
Ok(()) Ok(())
@ -209,7 +203,6 @@ impl XmlConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"XML version must be either 1.0 or 1.1", "XML version must be either 1.0 or 1.1",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))); )));
} }
} }
@ -226,14 +219,12 @@ impl XmlConverter {
None => Err(Box::new(BuildError::new( None => Err(Box::new(BuildError::new(
"XML doc tuples must have a root field", "XML doc tuples must have a root field",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))), ))),
} }
} else { } else {
Err(Box::new(BuildError::new( Err(Box::new(BuildError::new(
"XML outputs must be a Tuple", "XML outputs must be a Tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
Position::new(0, 0, 0),
))) )))
} }
} }

View File

@ -59,31 +59,44 @@ impl fmt::Display for ErrorType {
/// Error defines an Error type for parsing and building UCG code. /// Error defines an Error type for parsing and building UCG code.
pub struct BuildError { pub struct BuildError {
pub err_type: ErrorType, pub err_type: ErrorType,
pub pos: Position, pub pos: Option<Position>,
pub msg: String, pub msg: String,
_pkgonly: (), _pkgonly: (),
} }
impl BuildError { impl BuildError {
pub fn new<S: Into<String>>(msg: S, t: ErrorType, pos: Position) -> Self { pub fn new_with_pos<S: Into<String>>(msg: S, t: ErrorType, pos: Position) -> Self {
BuildError { BuildError {
err_type: t, err_type: t,
pos: pos, pos: Some(pos),
msg: msg.into(),
_pkgonly: (),
}
}
pub fn new<S: Into<String>>(msg: S, t: ErrorType) -> Self {
BuildError {
err_type: t,
pos: None,
msg: msg.into(), msg: msg.into(),
_pkgonly: (), _pkgonly: (),
} }
} }
fn render(&self, w: &mut fmt::Formatter) -> fmt::Result { fn render(&self, w: &mut fmt::Formatter) -> fmt::Result {
let file = match self.pos.file { if let Some(ref pos) = self.pos {
Some(ref pb) => pb.to_string_lossy().to_string(), let file = match pos.file {
None => "<eval>".to_string(), Some(ref pb) => pb.to_string_lossy().to_string(),
}; None => "<eval>".to_string(),
write!( };
w, write!(
"{} at {} line: {}, column: {}\nCaused By:\n\t{} ", w,
self.err_type, file, self.pos.line, self.pos.column, self.msg "{} at {} line: {}, column: {}\nCaused By:\n\t{} ",
)?; self.err_type, file, pos.line, pos.column, self.msg
)?;
} else {
write!(w, "{} \nCaused By:\n\t{} ", self.err_type, self.msg)?;
}
Ok(()) Ok(())
} }
} }

View File

@ -664,7 +664,12 @@ pub fn pos<'a>(i: SliceIter<'a, Token>) -> Result<SliceIter<'a, Token>, Position
let tok = _i.next().unwrap(); let tok = _i.next().unwrap();
let line = tok.pos.line; let line = tok.pos.line;
let column = tok.pos.column; let column = tok.pos.column;
Result::Complete(i.clone(), Position::new(line, column, i.get_offset())) let pos = Position::new(line, column, i.get_offset());
let pos = match tok.pos.file {
Some(ref f) => pos.with_file(f),
None => pos,
};
Result::Complete(i.clone(), pos)
} }
#[cfg(test)] #[cfg(test)]