diff --git a/CHANGELOG.md b/CHANGELOG.md index b1cdb77..7cf4656 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ## [Unreleased] +## [1.0.3] - 2025-01-12 +- Remove huff-examples submodule +- Fix invalid error mapping for import wih unmatched jump label +- Print unmatched jump labels + ## [1.0.2] - 2025-01-11 - Use latest stable Rust version 1.84 - Report error for invalid hex literals `0x0x` diff --git a/Cargo.lock b/Cargo.lock index ec84a83..626a4b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,9 +520,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.8" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0cf6e91fde44c773c6ee7ec6bba798504641a8bc2eb7e37a04ffbf4dfaa55a" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -949,7 +949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1141,7 +1141,7 @@ dependencies = [ [[package]] name = "hnc" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-primitives", "clap", @@ -1158,7 +1158,7 @@ dependencies = [ [[package]] name = "huff-neo-codegen" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -1171,7 +1171,7 @@ dependencies = [ [[package]] name = "huff-neo-core" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -1192,7 +1192,7 @@ dependencies = [ [[package]] name = "huff-neo-js" -version = "1.0.2" +version = "1.0.3" dependencies = [ "huff-neo-core", "huff-neo-utils", @@ -1203,7 +1203,7 @@ dependencies = [ [[package]] name = "huff-neo-lexer" -version = "1.0.2" +version = "1.0.3" dependencies = [ "huff-neo-utils", "lazy_static", @@ -1213,7 +1213,7 @@ dependencies = [ [[package]] name = "huff-neo-parser" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-primitives", "hex", @@ -1225,7 +1225,7 @@ dependencies = [ [[package]] name = "huff-neo-test-runner" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-primitives", "comfy-table", @@ -1241,7 +1241,7 @@ dependencies = [ [[package]] name = "huff-neo-utils" -version = "1.0.2" +version = "1.0.3" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -1621,9 +1621,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.24" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "matchers" @@ -2300,7 +2300,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2667,7 +2667,7 @@ dependencies = [ "getrandom", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3095,7 +3095,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index edfb4d5..d513887 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/cakevm/huff-neo" rust-version = "1.84" -version = "1.0.2" +version = "1.0.3" [workspace.dependencies] huff-neo-codegen = { path = "crates/codegen" } diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 07fd1b4..9f12921 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -121,13 +121,15 @@ impl Codegen { /// Fills table JUMPDEST placeholders. pub fn gen_table_bytecode(res: BytecodeRes) -> Result<String, CodegenError> { if !res.unmatched_jumps.is_empty() { + let labels = res.unmatched_jumps.iter().map(|uj| uj.label.to_string()).collect::<Vec<String>>(); tracing::error!( target: "codegen", "Source contains unmatched jump labels \"{}\"", - res.unmatched_jumps.iter().map(|uj| uj.label.to_string()).collect::<Vec<String>>().join(", ") + labels.join(", ") ); + return Err(CodegenError { - kind: CodegenErrorKind::UnmatchedJumpLabel, + kind: CodegenErrorKind::UnmatchedJumpLabels(labels), span: AstSpan(res.unmatched_jumps.iter().flat_map(|uj| uj.span.0.clone()).collect::<Vec<Span>>()), token: None, }); @@ -168,7 +170,11 @@ impl Codegen { "Definition not found for Jump Table Label: \"{}\"", label ); - return Err(CodegenError { kind: CodegenErrorKind::UnmatchedJumpLabel, span: s.span.clone(), token: None }); + return Err(CodegenError { + kind: CodegenErrorKind::UnmatchedJumpLabels(vec![label.clone()]), + span: s.span.clone(), + token: None, + }); } }; let hex = format_even_bytes(format!("{offset:02x}")); @@ -363,7 +369,7 @@ impl Codegen { let bytes = bytes.into_iter().fold(Vec::default(), |mut acc, (code_index, mut formatted_bytes)| { // Check if a jump table exists at `code_index` (starting offset of `b`) if let Some(jt) = jump_table.get(&code_index) { - // Loop through jumps inside of the found JumpTable + // Loop through jumps inside the found JumpTable for jump in jt { // Check if the jump label has been defined. If not, add `jump` to the // unmatched jumps and define its `bytecode_index` diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index abbc9fa..44ee163 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -221,15 +221,14 @@ impl<'a, 'l> Compiler<'a, 'l> { .map(|v| Self::recurse_deps(v, &Remapper::new("./"), self.file_provider.clone(), HashSet::new())) .collect(); - // Collect Recurse Deps errors and try to resolve to the first one - let mut errors = recursed_file_sources.iter().filter_map(|rfs| rfs.as_ref().err()).collect::<Vec<&Arc<CompilerError>>>(); - if !errors.is_empty() { - let error = errors.remove(0); - return Err(Arc::clone(error)); - } - // Unpack recursed dependencies into FileSources - let files = recursed_file_sources.into_iter().filter_map(|fs| fs.ok()).collect::<Vec<Arc<FileSource>>>(); + let mut files = vec![]; + for fs in recursed_file_sources { + match fs { + Ok(f) => files.push(f), + Err(e) => return Err(e), + } + } tracing::info!(target: "core", "COMPILER RECURSED {} FILE DEPENDENCIES", files.len()); // Parallel Compilation @@ -290,15 +289,14 @@ impl<'a, 'l> Compiler<'a, 'l> { .map(|f| Self::recurse_deps(f, &Remapper::new("./"), self.file_provider.clone(), HashSet::new())) .collect(); - // Collect Recurse Deps errors and try to resolve to the first one - let mut errors = recursed_file_sources.iter().filter_map(|rfs| rfs.as_ref().err()).collect::<Vec<&Arc<CompilerError>>>(); - if !errors.is_empty() { - let error = errors.remove(0); - return Err(Arc::clone(error)); - } - // Unpack recursed dependencies into FileSources - let files = recursed_file_sources.into_iter().filter_map(|fs| fs.ok()).collect::<Vec<Arc<FileSource>>>(); + let mut files = vec![]; + for fs in recursed_file_sources { + match fs { + Ok(f) => files.push(f), + Err(e) => return Err(e), + } + } tracing::info!(target: "core", "COMPILER RECURSED {} FILE DEPENDENCIES", files.len()); // Parse file sources and collect ASTs in parallel @@ -386,7 +384,9 @@ impl<'a, 'l> Compiler<'a, 'l> { .0 .into_iter() .map(|mut s| { - s.file = Some(Arc::clone(&file)); + if s.file.is_none() { + s.file = Some(Arc::clone(&file)); + } s }) .collect::<Vec<Span>>(), @@ -412,7 +412,9 @@ impl<'a, 'l> Compiler<'a, 'l> { .0 .into_iter() .map(|mut s| { - s.file = Some(Arc::clone(&file)); + if s.file.is_none() { + s.file = Some(Arc::clone(&file)); + } s }) .collect::<Vec<Span>>(); diff --git a/crates/core/tests/codegen_errors.rs b/crates/core/tests/codegen_errors.rs index 737353d..9a59f7b 100644 --- a/crates/core/tests/codegen_errors.rs +++ b/crates/core/tests/codegen_errors.rs @@ -303,7 +303,7 @@ fn test_unmatched_jump_label() { assert_eq!( e, CodegenError { - kind: CodegenErrorKind::UnmatchedJumpLabel, + kind: CodegenErrorKind::UnmatchedJumpLabels(vec!["err".to_string()]), span: AstSpan(vec![ Span { start: 372, end: 375, file: None }, Span { start: 376, end: 376, file: None }, diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 16badb1..72ada95 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -580,7 +580,7 @@ impl Parser { // If the opcode is a push that takes a literal value, we need to parse the next // literal if o.is_value_push() { - match self.current_token.kind.clone() { + match self.current_token.kind { TokenKind::Literal(val) => { let curr_spans = vec![self.current_token.span.clone()]; tracing::info!(target: "parser", "PARSING MACRO BODY: [LITERAL: {}]", hex::encode(val)); @@ -616,10 +616,10 @@ impl Parser { tracing::info!(target: "parser", "PARSING MACRO BODY: [IDENT: {}]", ident_str); self.match_kind(TokenKind::Ident("MACRO_NAME".to_string()))?; // Can be a macro call or label call - match self.current_token.kind.clone() { + match self.current_token.kind { TokenKind::OpenParen => { // Parse Macro Call - let lit_args = self.parse_macro_call()?; + let lit_args = self.parse_macro_call_args()?; // Grab all spans following our macro invocation spam if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) { curr_spans.append(&mut self.spans[(i + 1)..].to_vec()); @@ -728,7 +728,7 @@ impl Parser { match self.current_token.kind.clone() { TokenKind::OpenParen => { // Parse Macro Call - let lit_args = self.parse_macro_call()?; + let lit_args = self.parse_macro_call_args()?; // Grab all spans following our macro invocation spam if let Some(i) = self.spans.iter().position(|s| s.eq(&curr_spans[0])) { curr_spans.append(&mut self.spans[(i + 1)..].to_vec()); @@ -971,11 +971,6 @@ impl Parser { Ok(value) } - /// Parse call to a macro. - pub fn parse_macro_call(&mut self) -> Result<Vec<MacroArg>, ParserError> { - self.parse_macro_call_args() - } - /// Parse the arguments of a macro call. pub fn parse_macro_call_args(&mut self) -> Result<Vec<MacroArg>, ParserError> { let mut args = vec![]; diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index 9724327..bc65fb7 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -172,7 +172,7 @@ pub enum CodegenErrorKind { /// Abi Generation Failure AbiGenerationFailure, /// Unmatched Jump - UnmatchedJumpLabel, + UnmatchedJumpLabels(Vec<String>), /// An IO Error IOError(String), /// ArgCall has an unknown type @@ -232,7 +232,7 @@ impl<W: Write> Report<W> for CodegenError { write!(f.out, "Missing Error Definition for \"{ed}\"!") } CodegenErrorKind::AbiGenerationFailure => write!(f.out, "Abi generation failure!"), - CodegenErrorKind::UnmatchedJumpLabel => write!(f.out, "Unmatched jump label!"), + CodegenErrorKind::UnmatchedJumpLabels(labels) => write!(f.out, "Unmatched jump labels: \"{}\"!", labels.join(", ")), CodegenErrorKind::IOError(ioe) => write!(f.out, "IO ERROR: {ioe:?}"), CodegenErrorKind::UnkownArgcallType => write!(f.out, "Unknown Argcall Type!"), CodegenErrorKind::MissingMacroInvocation(str) => { @@ -483,8 +483,8 @@ impl fmt::Display for CompilerError { CodegenErrorKind::MissingMacroInvocation(mmi) => { write!(f, "\nError: Missing Macro Invocation: \"{}\"\n{}\n", mmi, ce.span.error(None)) } - CodegenErrorKind::UnmatchedJumpLabel => { - write!(f, "\nError: Unmatched Jump Label\n{}\n", ce.span.error(None)) + CodegenErrorKind::UnmatchedJumpLabels(labels) => { + write!(f, "\nError: Unmatched Jump Labels: \"{}\"\n{}\n", labels.join(", "), ce.span.error(None)) } CodegenErrorKind::UsizeConversion(_) => { write!(f, "\nError: Usize Conversion\n{}\n", ce.span.error(None)) diff --git a/crates/utils/src/file/span.rs b/crates/utils/src/file/span.rs index 8506cee..5512e2f 100644 --- a/crates/utils/src/file/span.rs +++ b/crates/utils/src/file/span.rs @@ -43,7 +43,13 @@ impl Span { .map(|s| { if self.start >= s.len() { // This should never happen, but currently does when the mapping from the flattened source is incorrect. - return format!("\nInternal compiler error: Start index out of range start={} len={}.", self.start, s.len()); + return format!( + "\nInternal compiler error: Start index out of range file={}, start={}, end={}, len={}.", + self.file.clone().unwrap_or_default().path, + self.start, + self.end, + s.len() + ); } let line_num = &s[0..self.start].as_bytes().iter().filter(|&&c| c == b'\n').count() + 1; let line_start = &s[0..self.start].rfind('\n').unwrap_or(0);