Skip to content

Commit

Permalink
Merge pull request #1062 from saxenism/descriptive-error-missing-param
Browse files Browse the repository at this point in the history
missing params descriptive error message
  • Loading branch information
bobbinth authored Sep 8, 2023
2 parents 557b572 + ce2af47 commit c3369ed
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 24 deletions.
2 changes: 1 addition & 1 deletion assembly/src/ast/parsers/adv_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::{
pub fn parse_adv_inject(op: &Token) -> Result<Node, ParsingError> {
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.<injector>.<injector_param?>"));
}

let injector = match op.parts()[1] {
Expand Down
14 changes: 7 additions & 7 deletions assembly/src/ast/parsers/io_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn parse_push(op: &Token, constants: &LocalConstMap) -> Result<Node, Parsing
debug_assert_eq!(op.parts()[0], "push");
match op.num_parts() {
0 => unreachable!("missing token"),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "push.<a?>")),
2 => {
let param_str = op.parts()[1];
match param_str.strip_prefix("0x") {
Expand Down Expand Up @@ -65,7 +65,7 @@ pub fn parse_locaddr(op: &Token, constants: &LocalConstMap) -> Result<Node, Pars
debug_assert_eq!(op.parts()[0], "locaddr");
match op.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "locaddr.<index>")),
2 => {
let index = parse_param_with_constant_lookup::<u16>(op, 1, constants)?;
Ok(Instruction(Locaddr(index)))
Expand All @@ -83,7 +83,7 @@ pub fn parse_adv_push(op: &Token) -> Result<Node, ParsingError> {
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.<num_vals>")),
2 => {
let num_vals = parse_checked_param(op, 1, 1..=ADVICE_READ_LIMIT)?;
Ok(Instruction(AdvPush(num_vals)))
Expand Down Expand Up @@ -120,7 +120,7 @@ pub fn parse_loc_load(op: &Token, constants: &LocalConstMap) -> Result<Node, Par
debug_assert_eq!(op.parts()[0], "loc_load");
match op.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "loc_load.<index>")),
2 => {
let index = parse_param_with_constant_lookup::<u16>(op, 1, constants)?;
Ok(Instruction(LocLoad(index)))
Expand Down Expand Up @@ -157,7 +157,7 @@ pub fn parse_loc_loadw(op: &Token, constants: &LocalConstMap) -> Result<Node, Pa
debug_assert_eq!(op.parts()[0], "loc_loadw");
match op.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "loc_loadw.<index>")),
2 => {
let index = parse_param_with_constant_lookup::<u16>(op, 1, constants)?;
Ok(Instruction(LocLoadW(index)))
Expand Down Expand Up @@ -194,7 +194,7 @@ pub fn parse_loc_store(op: &Token, constants: &LocalConstMap) -> Result<Node, Pa
debug_assert_eq!(op.parts()[0], "loc_store");
match op.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "loc_store.<index>")),
2 => {
let index = parse_param_with_constant_lookup::<u16>(op, 1, constants)?;
Ok(Instruction(LocStore(index)))
Expand Down Expand Up @@ -231,7 +231,7 @@ pub fn parse_loc_storew(op: &Token, constants: &LocalConstMap) -> Result<Node, P
debug_assert_eq!(op.parts()[0], "loc_storew");
match op.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(op)),
1 => Err(ParsingError::missing_param(op, "loc_storew.<index>")),
2 => {
let index = parse_param_with_constant_lookup::<u16>(op, 1, constants)?;
Ok(Instruction(LocStoreW(index)))
Expand Down
4 changes: 2 additions & 2 deletions assembly/src/ast/parsers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ pub fn parse_constants(tokens: &mut TokenStream) -> Result<LocalConstMap, Parsin
fn parse_constant(token: &Token, constants: &LocalConstMap) -> Result<(String, u64), ParsingError> {
match token.num_parts() {
0 => unreachable!(),
1 => Err(ParsingError::missing_param(token)),
1 => Err(ParsingError::missing_param(token, "const.<name>=<value>")),
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.<name>=<value>")),
2 => {
let name = CONSTANT_LABEL_PARSER
.parse_label(const_declaration[0])
Expand Down
8 changes: 4 additions & 4 deletions assembly/src/ast/parsers/stack_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub fn parse_movup(op: &Token) -> Result<Node, ParsingError> {
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.<index>")),
2 => match op.parts()[1] {
"2" => Ok(Instruction(MovUp2)),
"3" => Ok(Instruction(MovUp3)),
Expand Down Expand Up @@ -157,7 +157,7 @@ pub fn parse_movdn(op: &Token) -> Result<Node, ParsingError> {
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.<index>")),
2 => match op.parts()[1] {
"2" => Ok(Instruction(MovDn2)),
"3" => Ok(Instruction(MovDn3)),
Expand Down Expand Up @@ -188,7 +188,7 @@ pub fn parse_movupw(op: &Token) -> Result<Node, ParsingError> {
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.<index>")),
2 => match op.parts()[1] {
"2" => Ok(Instruction(MovUpW2)),
"3" => Ok(Instruction(MovUpW3)),
Expand All @@ -207,7 +207,7 @@ pub fn parse_movdnw(op: &Token) -> Result<Node, ParsingError> {
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.<index>")),
2 => match op.parts()[1] {
"2" => Ok(Instruction(MovDnW2)),
"3" => Ok(Instruction(MovDnW3)),
Expand Down
7 changes: 5 additions & 2 deletions assembly/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
Expand Down
5 changes: 4 additions & 1 deletion assembly/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
17 changes: 10 additions & 7 deletions assembly/src/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<absolute_module_path>")),
2 => {
if let Some((module_path, module_name)) =
self.parts[1].split_once(Self::ALIAS_DELIM)
Expand Down Expand Up @@ -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].<procedure_name>")),
2 => (self.parts[1], 0),
3 => {
let num_locals = validate_proc_locals(self.parts[2], self)?;
Expand All @@ -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.<procedure_path>")),
2 => {
if self.parts[1].matches(LibraryPath::PATH_DELIM).count() != 1 {
return Err(ParsingError::invalid_reexported_procedure(self, self.parts[1]));
Expand Down Expand Up @@ -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))
Expand All @@ -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))
Expand All @@ -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.<num_repetitions>")),
2 => self.parts[1].parse::<u32>().map_err(|_| ParsingError::invalid_param(self, 1)),
_ => Err(ParsingError::extra_param(self)),
}
Expand All @@ -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}.<procedure_name>").to_string(),
)),
2 => InvocationTarget::parse(self.parts[1], self),
_ => Err(ParsingError::extra_param(self)),
}
Expand Down

0 comments on commit c3369ed

Please sign in to comment.