Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Throw error on macro name clash #293

Merged
merged 8 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions huff_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl Parser {
TokenKind::Macro | TokenKind::Fn | TokenKind::Test => {
let m = self.parse_macro()?;
tracing::info!(target: "parser", "SUCCESSFULLY PARSED MACRO {}", m.name);
self.check_duplicate_macro(&contract, m.clone())?;
contract.macros.push(m);
}
TokenKind::JumpTable | TokenKind::JumpTablePacked | TokenKind::CodeTable => {
Expand Down Expand Up @@ -185,6 +186,23 @@ impl Parser {
std::mem::discriminant(&self.current_token.kind) == std::mem::discriminant(&kind)
}

/// Checks if there is a duplicate macro name
pub fn check_duplicate_macro(
&self,
contract: &Contract,
m: MacroDefinition,
) -> Result<(), ParserError> {
if contract.macros.binary_search_by(|_macro| _macro.name.cmp(&m.name)).is_ok() {
Err(ParserError {
kind: ParserErrorKind::DuplicateMacro(m.name),
hint: Some("MACRO names should be unique".to_string()),
spans: AstSpan(vec![self.spans[2].clone()]),
Maddiaa0 marked this conversation as resolved.
Show resolved Hide resolved
})
} else {
Ok(())
}
}

/// Consumes the next token.
pub fn consume(&mut self) {
self.spans.push(self.current_token.span.clone());
Expand Down
66 changes: 66 additions & 0 deletions huff_parser/tests/macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1232,3 +1232,69 @@ fn empty_test_with_multi_flag_decorator() {
assert_eq!(macro_definition, expected);
assert_eq!(parser.current_token.kind, TokenKind::Eof);
}

#[test]
fn test_duplicate_macro_error() {
let source = r#"
#define macro CONSTRUCTOR() = takes(0) returns (0) {}

#define macro MINT() = takes(0) returns (0) {
0x04 calldataload // [to]
0x00 // [from (0x00), to]
0x24 calldataload // [value, from, to]
}

#define macro MINT() = takes(0) returns (0) {
0x04 calldataload // [to]
0x00 // [from (0x00), to]
0x24 calldataload // [value, from, to]
}

#define macro MAIN() = takes(0) returns (0) {
0x00 calldataload 0xE0 shr
dup1 0x40c10f19 eq mints jumpi

mints:
MINT()
}
"#;

//let const_start = source.find("MINT()").unwrap_or(0);
Maddiaa0 marked this conversation as resolved.
Show resolved Hide resolved
//let const_end = const_start + "MINT()".len() - 1;
let mut start = 0;
let target = "MINT";
let target_len = target.len();
let mut occurrences = Vec::new();

while let Some(pos) = source[start..].find(target) {
let adjusted_start = start + pos;
let adjusted_end = adjusted_start + target_len - 1;

occurrences.push((adjusted_start, adjusted_end));
start = adjusted_end + 1;
}

let full_source = FullFileSource { source, file: None, spans: vec![] };
let lexer = Lexer::new(full_source.source);
let tokens = lexer.into_iter().map(|x| x.unwrap()).collect::<Vec<Token>>();
let mut parser = Parser::new(tokens, Some("".to_string()));

// This should be caught before codegen invalid macro statement
match parser.parse() {
Ok(_) => panic!("moose"),
Err(e) => {
assert_eq!(
e,
ParserError {
kind: ParserErrorKind::DuplicateMacro("MINT".to_string()),
hint: Some("MACRO names should be unique".to_string()),
spans: AstSpan(vec![Span {
start: occurrences[1].0,
end: occurrences[1].1,
file: None
}]),
}
)
}
}
}
10 changes: 10 additions & 0 deletions huff_utils/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub enum ParserErrorKind {
InvalidDecoratorFlag(String),
/// Invalid decorator flag argument
InvalidDecoratorFlagArg(TokenKind),
/// Duplicate MACRO
DuplicateMacro(String),
}

/// A Lexing Error
Expand Down Expand Up @@ -488,6 +490,14 @@ impl fmt::Display for CompilerError {
pe.spans.error(pe.hint.as_ref())
)
}
ParserErrorKind::DuplicateMacro(mn) => {
write!(
f,
"\nError: Duplicate MACRO name found: \"{}\" \n{}\n",
mn,
pe.spans.error(pe.hint.as_ref())
)
}
},
CompilerError::PathBufRead(os_str) => {
write!(
Expand Down