From 15026423dbe152e3cb1d992f18f29a140b5ed5f8 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Wed, 7 Nov 2018 18:24:44 -0600 Subject: [PATCH] REFACTOR: Rename our error::Error type to BuildError. --- Cargo.lock | 6 ++--- Cargo.toml | 2 +- src/build/ir.rs | 6 ++--- src/build/mod.rs | 56 ++++++++++++++++++++++----------------------- src/convert/exec.rs | 24 +++++++++---------- src/error.rs | 18 +++++---------- src/format.rs | 4 ++-- src/parse/mod.rs | 18 ++++----------- 8 files changed, 59 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36a4e68..6e04f9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [[package]] name = "abortable_parser" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -228,7 +228,7 @@ dependencies = [ name = "ucg" version = "0.2.2" dependencies = [ - "abortable_parser 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "abortable_parser 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bencher 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "cpuprofiler 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -285,7 +285,7 @@ dependencies = [ ] [metadata] -"checksum abortable_parser 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09cdf5378b5e4a079fa886e621519fcb2502d9cb008d3f76b92f61f3890d5906" +"checksum abortable_parser 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "685d99bbca3566d6b7f34b09d68039089ce4a36226f6f99f61ed8495850e3213" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "346d7644f0b5f9bc73082d3b2236b69a05fd35cce0cfa3724e184e6a5c9e2a2f" diff --git a/Cargo.toml b/Cargo.toml index da5b87e..210642e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["compiler", "config"] license = "Apache-2.0" [dependencies] -abortable_parser = "0.2.1" +abortable_parser = "~0.2.2" clap = "~2.26.0" serde_json = "~1.0.9" simple-error = "0.1" diff --git a/src/build/ir.rs b/src/build/ir.rs index 9d34748..84157c7 100644 --- a/src/build/ir.rs +++ b/src/build/ir.rs @@ -58,7 +58,7 @@ impl Val { target: &Self, file_name: &str, pos: Position, - ) -> Result { + ) -> Result { // first we do a type equality comparison match (self, target) { // Empty values are always equal. @@ -100,12 +100,12 @@ impl Val { Ok(true) } } - (&Val::Macro(_), &Val::Macro(_)) => Err(error::Error::new( + (&Val::Macro(_), &Val::Macro(_)) => Err(error::BuildError::new( format!("Macros are not comparable in file: {}", file_name), error::ErrorType::TypeFail, pos, )), - (me, tgt) => Err(error::Error::new( + (me, tgt) => Err(error::BuildError::new( format!("Types differ for {}, {} in file: {}", me, tgt, file_name), error::ErrorType::TypeFail, pos, diff --git a/src/build/mod.rs b/src/build/mod.rs index f2303f2..f0a647c 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -50,7 +50,7 @@ impl MacroDef { // Error conditions. If the args don't match the length and types of the argdefs then this is // macro call error. if args.len() > self.argdefs.len() { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Macro called with too many args in file: {}", root.to_string_lossy() @@ -125,7 +125,7 @@ macro_rules! eval_binary_expr { return Ok(Rc::new($result)); } val => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("Expected {} but got {}", $msg, val), error::ErrorType::TypeFail, $pos.clone(), @@ -163,7 +163,7 @@ impl<'a> Builder<'a> { &Value::Str(ref s) => Ok(Rc::new(Val::Str(s.val.to_string()))), &Value::Symbol(ref s) => { self.lookup_sym(&(s.into())) - .ok_or(Box::new(error::Error::new( + .ok_or(Box::new(error::BuildError::new( format!( "Unable to find {} in file: {}", s.val, @@ -263,7 +263,7 @@ impl<'a> Builder<'a> { Some(val) => Ok(val), } } - Err(err) => Err(Box::new(error::Error::new( + Err(err) => Err(Box::new(error::BuildError::new( format!("{}", err,), error::ErrorType::ParseError, (&input).into(), @@ -317,7 +317,7 @@ impl<'a> Builder<'a> { }; let key = sym.into(); if self.build_output.contains_key(&key) { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("Binding for import name {} already exists", sym.fragment), error::ErrorType::DuplicateBinding, def.path.pos.clone(), @@ -333,7 +333,7 @@ impl<'a> Builder<'a> { let name = &def.name; match self.build_output.entry(name.into()) { Entry::Occupied(e) => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Binding \ for {:?} already \ @@ -366,7 +366,7 @@ impl<'a> Builder<'a> { self.out_lock = Some((typ.fragment.to_string(), val.clone())); Ok(val) } else { - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!("You can only have one output per file."), error::ErrorType::DuplicateBinding, typ.pos.clone(), @@ -408,7 +408,7 @@ impl<'a> Builder<'a> { if let Some(vv) = Self::find_in_fieldlist(next.1, fs) { stack.push_back(vv.clone()); } else { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Unable to \ match element {} in selector \ @@ -435,7 +435,7 @@ impl<'a> Builder<'a> { if idx < elems.len() { stack.push_back(elems[idx].clone()); } else { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Unable to \ match element {} in selector \ @@ -495,7 +495,7 @@ impl<'a> Builder<'a> { continue; } _ => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("{} is not a Tuple or List", vref), error::ErrorType::TypeFail, next.pos.clone(), @@ -526,7 +526,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::Str([s.to_string(), ss.clone()].concat()))) } val => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Expected \ String \ @@ -547,7 +547,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::List(new_vec))); } val => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Expected \ List \ @@ -561,7 +561,7 @@ impl<'a> Builder<'a> { } }, ref expr => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("{} does not support the '+' operation", expr.type_name()), error::ErrorType::Unsupported, pos.clone(), @@ -584,7 +584,7 @@ impl<'a> Builder<'a> { eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f - ff), "Float") } ref expr => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("{} does not support the '-' operation", expr.type_name()), error::ErrorType::Unsupported, pos.clone(), @@ -607,7 +607,7 @@ impl<'a> Builder<'a> { eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f * ff), "Float") } ref expr => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("{} does not support the '*' operation", expr.type_name()), error::ErrorType::Unsupported, pos.clone(), @@ -630,7 +630,7 @@ impl<'a> Builder<'a> { eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f / ff), "Float") } ref expr => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("{} does not support the '*' operation", expr.type_name()), error::ErrorType::Unsupported, pos.clone(), @@ -677,7 +677,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::Boolean(l > r))); } } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!( "Incompatible types for numeric comparison {} with {}", left.type_name(), @@ -700,7 +700,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::Boolean(l < r))); } } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!( "Incompatible types for numeric comparison {} with {}", left.type_name(), @@ -727,7 +727,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::Boolean(l <= r))); } } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!( "Incompatible types for numeric comparison {} with {}", left.type_name(), @@ -754,7 +754,7 @@ impl<'a> Builder<'a> { return Ok(Rc::new(Val::Boolean(l >= r))); } } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!( "Incompatible types for numeric comparison {} with {}", left.type_name(), @@ -802,7 +802,7 @@ impl<'a> Builder<'a> { v.insert((count, val.clone())); count += 1; } else { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Duplicate \ field: {} in \ @@ -829,7 +829,7 @@ impl<'a> Builder<'a> { if src_val.1.type_equal(&expr_result) { v.insert((src_val.0, expr_result)); } else { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Expected type {} for field {} but got {}", src_val.1.type_name(), @@ -861,7 +861,7 @@ impl<'a> Builder<'a> { }).collect(), ))); } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( format!("Expected Tuple got {}", v), error::ErrorType::TypeFail, def.selector.pos.clone(), @@ -898,7 +898,7 @@ impl<'a> Builder<'a> { )); return Ok(Rc::new(Val::Tuple(fields))); } - Err(Box::new(error::Error::new( + Err(Box::new(error::BuildError::new( // We should pretty print the selectors here. format!("{} is not a Macro", v), error::ErrorType::TypeFail, @@ -909,7 +909,7 @@ impl<'a> Builder<'a> { fn eval_macro_def(&self, def: &MacroDef) -> Result, Box> { match def.validate_symbols() { Ok(()) => Ok(Rc::new(Val::Macro(def.clone()))), - Err(set) => Err(Box::new(error::Error::new( + Err(set) => Err(Box::new(error::BuildError::new( format!( "Macro has the following \ undefined symbols: {:?}", @@ -939,7 +939,7 @@ impl<'a> Builder<'a> { // Otherwise return the default. return self.eval_expr(def_expr); } else { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!( "Expected String but got \ {} in Select expression", @@ -956,7 +956,7 @@ impl<'a> Builder<'a> { let l = match maybe_list.as_ref() { &Val::List(ref elems) => elems, other => { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("Expected List as target but got {:?}", other.type_name()), error::ErrorType::TypeFail, def.target.pos().clone(), @@ -994,7 +994,7 @@ impl<'a> Builder<'a> { } return Ok(Rc::new(Val::List(out))); } - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( format!("Expected macro but got {:?}", mac), error::ErrorType::TypeFail, def.pos.clone(), diff --git a/src/convert/exec.rs b/src/convert/exec.rs index 9c7efbc..d3ef71a 100644 --- a/src/convert/exec.rs +++ b/src/convert/exec.rs @@ -22,7 +22,7 @@ use build::Val; use build::Val::Tuple; use convert; use convert::traits::{Converter, Result}; -use error::Error; +use error::BuildError; use error::ErrorType; pub struct ExecConverter {} @@ -43,7 +43,7 @@ impl ExecConverter { if let &Tuple(ref fields) = v { // We expect no more than three fields in our exec tuple. if fields.len() > 3 { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "Exec tuples must have no more than 3 fields", ErrorType::TypeFail, Position::new(0, 0, 0), @@ -56,7 +56,7 @@ impl ExecConverter { // We require a command field in our exec tuple. if name.val == "command" { if command.is_some() { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "There can only be one command field in an exec tuple", ErrorType::TypeFail, name.pos.clone(), @@ -66,7 +66,7 @@ impl ExecConverter { command = Some(s); continue; } - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "The command field of an exec tuple must be a string", ErrorType::TypeFail, name.pos.clone(), @@ -76,7 +76,7 @@ impl ExecConverter { if name.val == "env" { if let &Val::Tuple(ref l) = val.as_ref() { if env.is_some() { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "There can only be one env field in an exec tuple", ErrorType::TypeFail, name.pos.clone(), @@ -85,7 +85,7 @@ impl ExecConverter { env = Some(l); continue; } - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "The env field of an exec tuple must be a list", ErrorType::TypeFail, name.pos.clone(), @@ -95,7 +95,7 @@ impl ExecConverter { if name.val == "args" { if let &Val::List(ref l) = val.as_ref() { if args.is_some() { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "There can only be one args field of an exec tuple", ErrorType::TypeFail, name.pos.clone(), @@ -104,7 +104,7 @@ impl ExecConverter { args = Some(l); continue; } - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "The args field of an exec tuple must be a list", ErrorType::TypeFail, name.pos.clone(), @@ -112,7 +112,7 @@ impl ExecConverter { } } if command.is_none() { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "An exec tuple must have a command field", ErrorType::TypeFail, Position::new(0, 0, 0), @@ -133,7 +133,7 @@ impl ExecConverter { try!(write!(script, "{}=\"{}\"\n", name.val, s)); continue; } - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "The env fields of an exec tuple must contain only string values", ErrorType::TypeFail, name.pos.clone(), @@ -154,7 +154,7 @@ impl ExecConverter { } &Val::Tuple(_) => try!(flag_converter.convert(v.clone(), &mut script)), _ => { - return Err(Box::new(Error::new( + return Err(Box::new(BuildError::new( "Exec args must be a list of strings or tuples of strings.", ErrorType::TypeFail, Position::new(0, 0, 0), @@ -170,7 +170,7 @@ impl ExecConverter { return Ok(()); } - Err(Box::new(Error::new( + Err(Box::new(BuildError::new( "Exec outputs must be of type Tuple", ErrorType::TypeFail, Position::new(0, 0, 0), diff --git a/src/error.rs b/src/error.rs index e50e012..8e06d7e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -27,14 +27,11 @@ pub enum ErrorType { // Build Errors TypeFail, DuplicateBinding, - IncompleteParsing, Unsupported, NoSuchSymbol, BadArgLen, FormatError, // Parsing Errors - UnexpectedToken, - EmptyExpression, ParseError, AssertError, } @@ -44,13 +41,10 @@ impl fmt::Display for ErrorType { let name = match self { &ErrorType::TypeFail => "TypeFail", &ErrorType::DuplicateBinding => "DuplicateBinding", - &ErrorType::IncompleteParsing => "IncompleteParsing", &ErrorType::Unsupported => "Unsupported", &ErrorType::NoSuchSymbol => "NoSuchSymbol", &ErrorType::BadArgLen => "BadArgLen", &ErrorType::FormatError => "FormatError", - &ErrorType::UnexpectedToken => "UnexpectedToken", - &ErrorType::EmptyExpression => "EmptyExpression", &ErrorType::ParseError => "ParseError", &ErrorType::AssertError => "AssertError", }; @@ -59,16 +53,16 @@ impl fmt::Display for ErrorType { } /// Error defines an Error type for parsing and building UCG code. -pub struct Error { +pub struct BuildError { pub err_type: ErrorType, pub pos: Position, pub msg: String, _pkgonly: (), } -impl Error { +impl BuildError { pub fn new>(msg: S, t: ErrorType, pos: Position) -> Self { - Error { + BuildError { err_type: t, pos: pos, msg: msg.into(), @@ -86,19 +80,19 @@ impl Error { } } -impl Debug for Error { +impl Debug for BuildError { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.render(w) } } -impl fmt::Display for Error { +impl fmt::Display for BuildError { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.render(w) } } -impl error::Error for Error { +impl error::Error for BuildError { fn description(&self) -> &str { &self.msg } diff --git a/src/format.rs b/src/format.rs index edda478..6723669 100644 --- a/src/format.rs +++ b/src/format.rs @@ -45,7 +45,7 @@ impl + Clone> Formatter { for c in self.tmpl.chars() { if c == '@' && !should_escape { if count == self.args.len() { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( "Too few arguments to string \ formatter.", error::ErrorType::FormatError, @@ -63,7 +63,7 @@ impl + Clone> Formatter { } } if self.args.len() != count { - return Err(Box::new(error::Error::new( + return Err(Box::new(error::BuildError::new( "Too many arguments to string \ formatter.", error::ErrorType::FormatError, diff --git a/src/parse/mod.rs b/src/parse/mod.rs index fc0c000..261083c 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -846,7 +846,7 @@ make_fn!( name => wrap_err!(match_type!(BAREWORD), "Expected name for binding"), _ => punct!("="), // TODO(jwall): Wrap this error with an appropriate abortable_parser::Error - val => wrap_err!(trace_nom!(expression), "Expected Expression"), + val => with_err!(trace_nom!(expression), "Expected Expression"), _ => punct!(";"), (tuple_to_let(name, val)) ) @@ -904,7 +904,7 @@ make_fn!( do_each!( _ => word!("out"), typ => wrap_err!(must!(match_type!(BAREWORD)), "Expected converter name"), - expr => wrap_err!(must!(expression), "Expected Expression to export"), + expr => with_err!(must!(expression), "Expected Expression to export"), _ => must!(punct!(";")), (Statement::Output(typ.clone(), expr.clone())) ) @@ -937,21 +937,11 @@ pub fn parse<'a>(input: OffsetStrIter<'a>) -> std::result::Result } match statement(i.clone()) { Result::Abort(e) => { - let err = abortable_parser::Error::caused_by( - "Statement Parse Error", - Box::new(e), - Box::new(i.clone()), - ); - let ctx_err = StackPrinter { err: err }; + let ctx_err = StackPrinter { err: e }; return Err(format!("{}", ctx_err)); } Result::Fail(e) => { - let err = abortable_parser::Error::caused_by( - "Statement Parse Error", - Box::new(e), - Box::new(i.clone()), - ); - let ctx_err = StackPrinter { err: err }; + let ctx_err = StackPrinter { err: e }; return Err(format!("{}", ctx_err)); } Result::Incomplete(_ei) => {