From ce2af475b9152206704f70ae07b7640825ede6ad Mon Sep 17 00:00:00 2001 From: Rahul Saxena Date: Tue, 5 Sep 2023 03:43:28 +0530 Subject: [PATCH] missing params descriptive error message --- assembly/src/ast/parsers/adv_ops.rs | 2 +- assembly/src/ast/parsers/io_ops.rs | 14 +++++++------- assembly/src/ast/parsers/mod.rs | 4 ++-- assembly/src/ast/parsers/stack_ops.rs | 8 ++++---- assembly/src/errors.rs | 7 +++++-- assembly/src/tests.rs | 5 ++++- assembly/src/tokens/mod.rs | 17 ++++++++++------- 7 files changed, 33 insertions(+), 24 deletions(-) diff --git a/assembly/src/ast/parsers/adv_ops.rs b/assembly/src/ast/parsers/adv_ops.rs index 3813d929ed..f2d6a94e05 100644 --- a/assembly/src/ast/parsers/adv_ops.rs +++ b/assembly/src/ast/parsers/adv_ops.rs @@ -17,7 +17,7 @@ use super::{ pub fn parse_adv_inject(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "adv"); if op.num_parts() < 2 { - return Err(ParsingError::missing_param(op)); + return Err(ParsingError::missing_param(op, "adv..")); } let injector = match op.parts()[1] { diff --git a/assembly/src/ast/parsers/io_ops.rs b/assembly/src/ast/parsers/io_ops.rs index e54309c4c5..a0e49af899 100644 --- a/assembly/src/ast/parsers/io_ops.rs +++ b/assembly/src/ast/parsers/io_ops.rs @@ -27,7 +27,7 @@ pub fn parse_push(op: &Token, constants: &LocalConstMap) -> Result unreachable!("missing token"), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "push.")), 2 => { let param_str = op.parts()[1]; match param_str.strip_prefix("0x") { @@ -65,7 +65,7 @@ pub fn parse_locaddr(op: &Token, constants: &LocalConstMap) -> Result unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "locaddr.")), 2 => { let index = parse_param_with_constant_lookup::(op, 1, constants)?; Ok(Instruction(Locaddr(index))) @@ -83,7 +83,7 @@ pub fn parse_adv_push(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "adv_push"); match op.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "adv_push.")), 2 => { let num_vals = parse_checked_param(op, 1, 1..=ADVICE_READ_LIMIT)?; Ok(Instruction(AdvPush(num_vals))) @@ -120,7 +120,7 @@ pub fn parse_loc_load(op: &Token, constants: &LocalConstMap) -> Result unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "loc_load.")), 2 => { let index = parse_param_with_constant_lookup::(op, 1, constants)?; Ok(Instruction(LocLoad(index))) @@ -157,7 +157,7 @@ pub fn parse_loc_loadw(op: &Token, constants: &LocalConstMap) -> Result unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "loc_loadw.")), 2 => { let index = parse_param_with_constant_lookup::(op, 1, constants)?; Ok(Instruction(LocLoadW(index))) @@ -194,7 +194,7 @@ pub fn parse_loc_store(op: &Token, constants: &LocalConstMap) -> Result unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "loc_store.")), 2 => { let index = parse_param_with_constant_lookup::(op, 1, constants)?; Ok(Instruction(LocStore(index))) @@ -231,7 +231,7 @@ pub fn parse_loc_storew(op: &Token, constants: &LocalConstMap) -> Result unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "loc_storew.")), 2 => { let index = parse_param_with_constant_lookup::(op, 1, constants)?; Ok(Instruction(LocStoreW(index))) diff --git a/assembly/src/ast/parsers/mod.rs b/assembly/src/ast/parsers/mod.rs index 884e57a3b4..3f4a34f250 100644 --- a/assembly/src/ast/parsers/mod.rs +++ b/assembly/src/ast/parsers/mod.rs @@ -57,12 +57,12 @@ pub fn parse_constants(tokens: &mut TokenStream) -> Result Result<(String, u64), ParsingError> { match token.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(token)), + 1 => Err(ParsingError::missing_param(token, "const.=")), 2 => { let const_declaration: Vec<&str> = token.parts()[1].split('=').collect(); match const_declaration.len() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(token)), + 1 => Err(ParsingError::missing_param(token, "const.=")), 2 => { let name = CONSTANT_LABEL_PARSER .parse_label(const_declaration[0]) diff --git a/assembly/src/ast/parsers/stack_ops.rs b/assembly/src/ast/parsers/stack_ops.rs index 5d64525a1f..bc0b56eea4 100644 --- a/assembly/src/ast/parsers/stack_ops.rs +++ b/assembly/src/ast/parsers/stack_ops.rs @@ -126,7 +126,7 @@ pub fn parse_movup(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "movup"); match op.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "movup.")), 2 => match op.parts()[1] { "2" => Ok(Instruction(MovUp2)), "3" => Ok(Instruction(MovUp3)), @@ -157,7 +157,7 @@ pub fn parse_movdn(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "movdn"); match op.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "movdn.")), 2 => match op.parts()[1] { "2" => Ok(Instruction(MovDn2)), "3" => Ok(Instruction(MovDn3)), @@ -188,7 +188,7 @@ pub fn parse_movupw(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "movupw"); match op.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "movupw.")), 2 => match op.parts()[1] { "2" => Ok(Instruction(MovUpW2)), "3" => Ok(Instruction(MovUpW3)), @@ -207,7 +207,7 @@ pub fn parse_movdnw(op: &Token) -> Result { debug_assert_eq!(op.parts()[0], "movdnw"); match op.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(op)), + 1 => Err(ParsingError::missing_param(op, "movdnw.")), 2 => match op.parts()[1] { "2" => Ok(Instruction(MovDnW2)), "3" => Ok(Instruction(MovDnW3)), diff --git a/assembly/src/errors.rs b/assembly/src/errors.rs index 163f233a64..df1a10ee34 100644 --- a/assembly/src/errors.rs +++ b/assembly/src/errors.rs @@ -273,9 +273,12 @@ impl ParsingError { } } - pub fn missing_param(token: &Token) -> Self { + pub fn missing_param(token: &Token, expected_format: &str) -> Self { + let _actual_params: usize = token.num_parts(); ParsingError { - message: format!("malformed instruction '{token}': missing required parameter"), + message: format!( + "malformed instruction '{token}': expected format `{expected_format}`" + ), location: *token.location(), op: token.to_string(), } diff --git a/assembly/src/tests.rs b/assembly/src/tests.rs index 9bbb619d0f..05362ef32f 100644 --- a/assembly/src/tests.rs +++ b/assembly/src/tests.rs @@ -1302,7 +1302,10 @@ fn invalid_while() { let program = assembler.compile(source); assert!(program.is_err()); if let Err(error) = program { - assert_eq!(error.to_string(), "malformed instruction 'while': missing required parameter"); + assert_eq!( + error.to_string(), + "malformed instruction 'while': expected format `while.true`" + ); } let source = "begin push.1 add while.abc mul end end"; diff --git a/assembly/src/tokens/mod.rs b/assembly/src/tokens/mod.rs index 8eb9c213c9..c1105b37a7 100644 --- a/assembly/src/tokens/mod.rs +++ b/assembly/src/tokens/mod.rs @@ -116,7 +116,7 @@ impl<'a> Token<'a> { assert_eq!(Self::USE, self.parts[0], "not a use"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param(self, "use.")), 2 => { if let Some((module_path, module_name)) = self.parts[1].split_once(Self::ALIAS_DELIM) @@ -150,7 +150,7 @@ impl<'a> Token<'a> { let is_export = self.parts[0] == Self::EXPORT; let (name_str, num_locals) = match self.num_parts() { 0 => unreachable!(), - 1 => return Err(ParsingError::missing_param(self)), + 1 => return Err(ParsingError::missing_param(self, "[proc|export].")), 2 => (self.parts[1], 0), 3 => { let num_locals = validate_proc_locals(self.parts[2], self)?; @@ -170,7 +170,7 @@ impl<'a> Token<'a> { assert_eq!(Self::EXPORT, self.parts[0], "not an export"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param(self, "export.")), 2 => { if self.parts[1].matches(LibraryPath::PATH_DELIM).count() != 1 { return Err(ParsingError::invalid_reexported_procedure(self, self.parts[1])); @@ -201,7 +201,7 @@ impl<'a> Token<'a> { assert_eq!(Self::IF, self.parts[0], "not an if"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param(self, "if.true")), 2 => { if self.parts[1] != "true" { Err(ParsingError::invalid_param(self, 1)) @@ -226,7 +226,7 @@ impl<'a> Token<'a> { assert_eq!(Self::WHILE, self.parts[0], "not a while"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param(self, "while.true")), 2 => { if self.parts[1] != "true" { Err(ParsingError::invalid_param(self, 1)) @@ -242,7 +242,7 @@ impl<'a> Token<'a> { assert_eq!(Self::REPEAT, self.parts[0], "not a repeat"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param(self, "repeat.")), 2 => self.parts[1].parse::().map_err(|_| ParsingError::invalid_param(self, 1)), _ => Err(ParsingError::extra_param(self)), } @@ -255,7 +255,10 @@ impl<'a> Token<'a> { assert_eq!(invocation_token, self.parts[0], "not an {invocation_token}"); match self.num_parts() { 0 => unreachable!(), - 1 => Err(ParsingError::missing_param(self)), + 1 => Err(ParsingError::missing_param( + self, + &format!("{invocation_token}.").to_string(), + )), 2 => InvocationTarget::parse(self.parts[1], self), _ => Err(ParsingError::extra_param(self)), }