Skip to content

Commit

Permalink
Fail on duplicate labels in parser
Browse files Browse the repository at this point in the history
Co-authored-by: sword-smith <thor@neptune.cash>
  • Loading branch information
sshine and Sword-Smith committed Nov 25, 2022
1 parent 471b56f commit 42c41ac
Showing 1 changed file with 38 additions and 1 deletion.
39 changes: 38 additions & 1 deletion triton-vm/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::fmt::Display;
use std::ops::Neg;
use std::str::SplitWhitespace;
use std::vec;

use anyhow::{bail, Result};
use itertools::Itertools;
use num_traits::One;
use strum::{EnumCount, IntoEnumIterator};
use strum_macros::{Display as DisplayMacro, EnumCount as EnumCountMacro, EnumIter};
Expand Down Expand Up @@ -401,6 +402,25 @@ pub fn parse(code: &str) -> Result<Vec<LabelledInstruction>> {
instructions.append(&mut instruction);
}

let all_labels: Vec<String> = instructions
.iter()
.flat_map(|instr| match instr {
LabelledInstruction::Instruction(_) => vec![],
LabelledInstruction::Label(label) => vec![label.clone()],
})
.collect();
let mut seen_labels: HashSet<String> = HashSet::default();
let mut duplicate_labels: HashSet<String> = HashSet::default();
for label in all_labels {
if !seen_labels.insert(label.clone()) {
duplicate_labels.insert(label);
}
}

if !duplicate_labels.is_empty() {
bail!("Duplicate labels: {}", duplicate_labels.iter().join(", "));
}

Ok(instructions)
}

Expand Down Expand Up @@ -1352,6 +1372,23 @@ mod instruction_tests {
}
}

#[test]
fn fail_on_duplicate_labels_test() {
let code = "
push 2
call foo
bar: push 2
foo: push 3
foo: push 4
halt
";
let program = Program::from_code(code);
assert!(
program.is_err(),
"Duplicate labels should result in a parse error"
);
}

#[test]
fn ib_registers_are_binary_test() {
use Ord7::*;
Expand Down

0 comments on commit 42c41ac

Please sign in to comment.