Skip to main content

huff_neo_utils/
error.rs

1use crate::ast::span::AstSpan;
2use crate::file::span::{Span, Spanned};
3use crate::file::unpack_files::UnpackError;
4use crate::lexer_context::Context;
5use crate::{
6    prelude::{Opcode, parse_extension},
7    report::{Report, Reporter},
8    token::TokenKind,
9};
10use std::{ffi::OsString, fmt, io::Write};
11
12/// A Parser Error
13#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
14pub struct ParserError {
15    /// The type of Parser Error
16    pub kind: ParserErrorKind,
17    /// Hints about the error
18    pub hint: Option<String>,
19    /// A collection of spans the Parser Error crosses
20    pub spans: AstSpan,
21    /// Line number where the error was seen
22    pub cursor: usize,
23}
24
25/// A Type of Parser Error
26#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
27pub enum ParserErrorKind {
28    /// An invalid literal was passed to a push opcode
29    InvalidPush(Opcode),
30    /// Missing or out-of-range stack operand for DUPN, SWAPN or EXCHANGE
31    InvalidStackImmediate(Opcode),
32    /// Unexpected type
33    UnexpectedType(TokenKind),
34    /// Argument name is a reserved evm primitive type keyword
35    InvalidTypeAsArgumentName(TokenKind),
36    /// Invalid definition
37    InvalidDefinition(TokenKind),
38    /// Invalid constant value
39    InvalidConstantValue(TokenKind),
40    /// Invalid constant name (reserved name)
41    InvalidConstantName,
42    /// Invalid macro name (reserved builtin function name)
43    InvalidMacroName,
44    /// Unexpected token in macro body
45    InvalidTokenInMacroBody(TokenKind),
46    /// Unexpected token in label definition
47    InvalidTokenInLabelDefinition(TokenKind),
48    /// Unexpected Single Arg
49    InvalidSingleArg(TokenKind),
50    /// Unexpected Table Body Token
51    InvalidTableBodyToken(TokenKind),
52    /// Invalid constant
53    InvalidConstant(TokenKind),
54    /// Unexpected Arg Call Token
55    InvalidArgCallIdent(TokenKind),
56    /// Invalid name (macro, event, function, constant)
57    InvalidName(TokenKind),
58    /// Invalid arguments
59    InvalidArgs(TokenKind),
60    /// Invalid Uint256 Size
61    InvalidUint256(usize),
62    /// Invalid Bytes
63    InvalidBytes(usize),
64    /// Invalid Int
65    InvalidInt(usize),
66    /// Invalid macro call arguments
67    InvalidMacroArgs(TokenKind),
68    /// Invalid return arguments
69    InvalidReturnArgs,
70    /// Invalid import path
71    InvalidImportPath(String),
72    /// Invalid decorator flag
73    InvalidDecoratorFlag(String),
74    /// Invalid decorator flag argument
75    InvalidDecoratorFlagArg(TokenKind),
76    /// A decorator placed over a macro that is not a test
77    DecoratorOnNonTest(String),
78    /// Duplicate label
79    DuplicateLabel(String),
80    /// Duplicate MACRO
81    DuplicateMacro(String),
82    /// Invalid code table statement
83    InvalidTableStatement(String),
84    /// Invalid expression syntax
85    InvalidExpression(TokenKind),
86}
87
88/// A Lexing Error
89#[derive(Debug, PartialEq, Eq, Clone)]
90pub struct LexicalError {
91    /// The kind of error
92    pub kind: LexicalErrorKind,
93    /// The span where the error occurred
94    pub span: Span,
95}
96
97impl LexicalError {
98    /// Public associated function to instantiate a new LexicalError.
99    pub fn new(kind: LexicalErrorKind, span: Span) -> Self {
100        Self { kind, span }
101    }
102}
103
104/// A Lexical Error Kind
105#[derive(Debug, PartialEq, Eq, Clone)]
106pub enum LexicalErrorKind {
107    /// Unexpected end of file
108    UnexpectedEof,
109    /// Invalid character
110    InvalidCharacter(char),
111    /// Invalid hex literal
112    HexLiteralTooLong(String),
113    /// Invalid Hex Literal
114    InvalidHexLiteral(String),
115    /// Invalid Array Size
116    /// String param expected to be usize parsable
117    InvalidArraySize(String),
118    /// Invalid Primitive EVM Type
119    InvalidPrimitiveType(String),
120    /// Stack Underflow
121    StackUnderflow,
122    /// Unexpected Context
123    UnexpectedContext(Context),
124}
125
126impl Spanned for LexicalError {
127    fn span(&self) -> Span {
128        self.span.clone()
129    }
130}
131
132impl<W: Write> Report<W> for LexicalError {
133    fn report(&self, f: &mut Reporter<'_, W>) -> std::io::Result<()> {
134        match &self.kind {
135            LexicalErrorKind::InvalidCharacter(ch) => write!(f.out, "Invalid character '{ch}'"),
136            LexicalErrorKind::UnexpectedEof => write!(f.out, "Found unexpected EOF"),
137            LexicalErrorKind::InvalidArraySize(str) => {
138                write!(f.out, "Invalid array size: '{str}'")
139            }
140            LexicalErrorKind::InvalidPrimitiveType(str) => {
141                write!(f.out, "Invalid Primitive EVM Type '{str}'")
142            }
143            LexicalErrorKind::HexLiteralTooLong(str) => {
144                write!(f.out, "Hex literal has more than 32 bytes '{str}'")
145            }
146            LexicalErrorKind::InvalidHexLiteral(str) => {
147                write!(f.out, "Invalid hex literal '{str}'")
148            }
149            LexicalErrorKind::StackUnderflow => write!(f.out, "Stack underflow"),
150            LexicalErrorKind::UnexpectedContext(context) => write!(f.out, "Unexpected context: {context:?}"),
151        }
152    }
153}
154
155/// A Code Generation Error
156#[derive(Debug, PartialEq, Eq, Clone)]
157pub struct CodegenError {
158    /// The kind of code generation error
159    pub kind: CodegenErrorKind,
160    /// An Optional Span where the error occured
161    pub span: Box<AstSpan>,
162    /// An Optional Token Kind
163    pub token: Option<TokenKind>,
164}
165
166impl CodegenError {
167    /// Public associated function to instatiate a new CodegenError.
168    pub fn new(kind: CodegenErrorKind, spans: AstSpan, token: Option<TokenKind>) -> Self {
169        Self { kind, span: Box::new(spans), token }
170    }
171}
172
173/// The Code Generation Error Kind
174#[derive(Debug, PartialEq, Eq, Clone)]
175pub enum CodegenErrorKind {
176    /// Locking Error
177    LockingError,
178    /// Storage Pointers Not Derived
179    StoragePointersNotDerived,
180    /// Invalid Macro Body Statement
181    InvalidMacroStatement,
182    /// The Argument Definition is Missing
183    MissingArgumentDefinition(String),
184    /// The Macro Definition is Missing
185    MissingMacroDefinition(String),
186    /// The Function Interface is Missing
187    MissingFunctionInterface(String),
188    /// The Event Interface is Missing
189    MissingEventInterface(String),
190    /// Missing Constant Definition
191    MissingConstantDefinition(String),
192    /// String constant used directly instead of with __BYTES builtin
193    StringConstantNotBytes(String),
194    /// Missing Error Definition
195    MissingErrorDefinition(String),
196    /// Abi Generation Failure
197    AbiGenerationFailure,
198    /// Unmatched Jump
199    UnmatchedJumpLabels(Vec<String>),
200    /// An IO Error
201    IOError(String),
202    /// ArgCall has an unknown type
203    UnkownArgcallType,
204    /// Missing Macro Invocation
205    MissingMacroInvocation(String),
206    /// Missing Macro Definition for Invocation
207    InvalidMacroInvocation(String),
208    /// Invalid Argument Count with macro name, expected and actual
209    InvalidArgumentCount(String, usize, usize),
210    /// Conversion Error for usize
211    UsizeConversion(String),
212    /// Invalid Arguments
213    InvalidArguments(String),
214    /// Invalid Macro Argument Type (e.g., cannot invoke __NOOP as a macro)
215    InvalidMacroArgumentType(String),
216    /// Invalid Hex String
217    InvalidHex(String),
218    /// Invalid Table Statement
219    InvalidTableStatement(String),
220    /// Invalid Code Length
221    InvalidCodeLength(usize),
222    /// Test Invocation
223    TestInvocation(String),
224    /// Constructor arguments that do not match the declared constructor or cannot be read
225    InvalidConstructorArgs(String),
226    /// `__argsstart()` outside the constructor, where constructor arguments do not exist
227    ArgsStartOutsideConstructor,
228    /// Missing Table Size
229    MissingTableSize(String),
230    /// Unsupported Builtin Function
231    UnsupportedBuiltinFunction(String),
232    /// `__codesize(RUNTIME)` referenced before the runtime size has been computed (e.g. when
233    /// the constructor is compiled in isolation without first generating MAIN).
234    RuntimeSizeNotComputed,
235    /// `__codesize(RUNTIME)` referenced inside a code table. Code tables contribute to the
236    /// runtime size, so embedding the runtime size inside one creates a circular dependency.
237    CodesizeRuntimeInCodeTable,
238    /// Codegen failed to converge on stable `__codesize` values within the iteration cap.
239    CodesizeNotConverged(usize),
240    /// Unsupported Statement Type
241    UnsupportedStatementType(String),
242    /// Duplicate Label in Same Scope
243    DuplicateLabelInScope(String),
244    /// Duplicate label defined in multiple sibling scopes
245    /// When a label is not found in current scope, fallback searches siblings - but will always find the first definition, making subsequent ones unreachable
246    DuplicateLabelAcrossSiblings(String),
247    /// Duplicate Table Embedding
248    DuplicateTableEmbedding(String),
249    /// Jump target is too large for the specified opcode
250    JumpTargetTooLarge {
251        /// The label name
252        label: String,
253        /// The target offset that was too large
254        target: usize,
255        /// The opcode that couldn't represent the target
256        opcode: String,
257    },
258    /// Circular macro invocation detected
259    CircularMacroInvocation(String),
260    /// Circular constant dependency detected
261    CircularConstantDependency(String),
262    /// Recursion depth limit exceeded
263    RecursionDepthExceeded(usize),
264    /// Undefined constant in expression
265    UndefinedConstant(String),
266    /// Invalid constant expression (contains runtime elements)
267    InvalidConstantExpression,
268    /// Arithmetic overflow in constant expression
269    ArithmeticOverflow,
270    /// Arithmetic underflow in constant expression
271    ArithmeticUnderflow,
272    /// Division by zero in constant expression
273    DivisionByZero,
274    /// ArgCall in constant expression (requires macro invocation context)
275    ArgCallInConstantExpression(String),
276    /// Invalid opcode for EVM version (opcode, required_version, current_version)
277    InvalidOpcodeForEVMVersion(String, String, String),
278    /// Invalid loop step value (step cannot be zero)
279    InvalidLoopStep,
280    /// Loop iteration limit exceeded (contains max limit)
281    LoopIterationLimitExceeded(usize),
282    /// PC (program counter) assertion failed (expected, actual)
283    AssertPcFailed(usize, usize),
284    /// Exceeded maximum iterations when resolving argument references through the scope chain
285    /// First parameter is the argument name, second is the maximum allowed iterations
286    ArgResolutionLimitExceeded(String, usize),
287    /// Exceeded maximum iterations in bubble_arg_call when bubbling up through nested macro calls
288    /// First parameter is the argument name, second is the maximum allowed iterations
289    BubbleArgLimitExceeded(String, usize),
290    /// Runtime bytecode exceeds the contract size limit of the target EVM version (size, limit)
291    ContractSizeLimitExceeded(usize, usize),
292    /// Deployment bytecode exceeds the initcode size limit of the target EVM version (size, limit)
293    InitcodeSizeLimitExceeded(usize, usize),
294    /// An opcode operand resolved to a value the opcode cannot encode (description)
295    InvalidOpcodeOperand(String),
296    /// A bytecode offset that is stored in a fixed 2-byte field exceeds 0xffff (what, offset)
297    OffsetExceedsTwoBytes(String, usize),
298}
299
300impl Spanned for CodegenError {
301    fn span(&self) -> Span {
302        self.span[0].clone()
303    }
304}
305
306impl<W: Write> Report<W> for CodegenError {
307    fn report(&self, f: &mut Reporter<'_, W>) -> std::io::Result<()> {
308        match &self.kind {
309            CodegenErrorKind::LockingError => {
310                write!(f.out, "Synchronisation Error - Please execute again!")
311            }
312            CodegenErrorKind::StoragePointersNotDerived => {
313                write!(f.out, "Storage pointers not derived for AST!")
314            }
315            CodegenErrorKind::InvalidMacroStatement => write!(f.out, "Invalid Macro Statement!"),
316            CodegenErrorKind::InvalidMacroInvocation(str) => {
317                write!(f.out, "Missing Macro Definition for Invocation: \"{str}\"!")
318            }
319            CodegenErrorKind::InvalidArgumentCount(str, expected, actual) => {
320                write!(f.out, "Invalid Argument Count for \"{str}\", expected {expected}, got {actual}!")
321            }
322            CodegenErrorKind::MissingArgumentDefinition(str) => {
323                write!(f.out, "Missing Argument \"{str}\" Definition!")
324            }
325            CodegenErrorKind::MissingMacroDefinition(str) => {
326                write!(f.out, "Missing Macro \"{str}\" Definition!")
327            }
328            CodegenErrorKind::MissingFunctionInterface(str) => {
329                write!(f.out, "Missing Function Interface for \"{str}\"!")
330            }
331            CodegenErrorKind::MissingEventInterface(str) => {
332                write!(f.out, "Missing Event Interface for \"{str}\"!")
333            }
334            CodegenErrorKind::MissingConstantDefinition(cd) => {
335                write!(f.out, "Missing Constant Definition for \"{cd}\"!")
336            }
337            CodegenErrorKind::StringConstantNotBytes(msg) => {
338                write!(f.out, "String constant cannot be used directly: \"{msg}\"")
339            }
340            CodegenErrorKind::MissingErrorDefinition(ed) => {
341                write!(f.out, "Missing Error Definition for \"{ed}\"!")
342            }
343            CodegenErrorKind::AbiGenerationFailure => write!(f.out, "Abi generation failure!"),
344            CodegenErrorKind::UnmatchedJumpLabels(labels) => write!(f.out, "Unmatched jump labels: \"{}\"!", labels.join(", ")),
345            CodegenErrorKind::IOError(ioe) => write!(f.out, "IO ERROR: {ioe:?}"),
346            CodegenErrorKind::UnkownArgcallType => write!(f.out, "Unknown Argcall Type!"),
347            CodegenErrorKind::MissingMacroInvocation(str) => {
348                write!(f.out, "Missing Macro \"{str}\" Invocation!")
349            }
350            CodegenErrorKind::UsizeConversion(input) => {
351                write!(f.out, "Usize Conversion Failed for \"{input}\"")
352            }
353            CodegenErrorKind::InvalidArguments(msg) => {
354                write!(f.out, "Invalid arguments: \"{msg}\"")
355            }
356            CodegenErrorKind::InvalidMacroArgumentType(msg) => {
357                write!(f.out, "Invalid macro argument type: {msg}")
358            }
359            CodegenErrorKind::InvalidHex(msg) => {
360                write!(f.out, "Invalid hex string: \"{msg}\"")
361            }
362            CodegenErrorKind::InvalidTableStatement(msg) => {
363                write!(f.out, "Invalid table statement: \"{msg}\"")
364            }
365            CodegenErrorKind::InvalidCodeLength(len) => {
366                write!(f.out, "Invalid code length: {len}")
367            }
368            CodegenErrorKind::TestInvocation(msg) => {
369                write!(f.out, "Test cannot be invoked: \"{msg}\"")
370            }
371            CodegenErrorKind::InvalidConstructorArgs(msg) => {
372                write!(f.out, "Invalid constructor arguments: {msg}")
373            }
374            CodegenErrorKind::ArgsStartOutsideConstructor => {
375                write!(f.out, "__argsstart() can only be used in the constructor")
376            }
377            CodegenErrorKind::MissingTableSize(table_name) => {
378                write!(f.out, "Missing Table Size for table: \"{table_name}\"")
379            }
380            CodegenErrorKind::UnsupportedBuiltinFunction(bf) => {
381                write!(f.out, "Unsupported Builtin Function: \"{bf}\"")
382            }
383            CodegenErrorKind::RuntimeSizeNotComputed => {
384                write!(f.out, "__codesize(RUNTIME) cannot be resolved here: MAIN bytecode has not been generated yet")
385            }
386            CodegenErrorKind::CodesizeRuntimeInCodeTable => {
387                write!(f.out, "__codesize(RUNTIME) is not allowed inside a code table")
388            }
389            CodegenErrorKind::CodesizeNotConverged(iterations) => {
390                write!(f.out, "__codesize did not converge after {iterations} codegen passes")
391            }
392            CodegenErrorKind::UnsupportedStatementType(st) => {
393                write!(f.out, "Unsupported Statement Type: \"{st}\"")
394            }
395            CodegenErrorKind::DuplicateLabelInScope(label) => {
396                write!(f.out, "Duplicate label '{}' defined in the same scope", label)
397            }
398            CodegenErrorKind::DuplicateLabelAcrossSiblings(label) => {
399                write!(f.out, "Duplicate label '{}' defined across siblings in same scope", label)
400            }
401            CodegenErrorKind::DuplicateTableEmbedding(table) => {
402                write!(f.out, "Table \"{}\" has already been embedded. Each table can only be embedded once with __EMBED_TABLE.", table)
403            }
404            CodegenErrorKind::JumpTargetTooLarge { label, target, opcode } => {
405                write!(f.out, "Jump target {:#x} too large for {} in label \"{}\"", target, opcode, label)
406            }
407            CodegenErrorKind::CircularMacroInvocation(macro_name) => {
408                write!(f.out, "Circular macro invocation detected: '{}' is already in the call stack", macro_name)
409            }
410            CodegenErrorKind::CircularConstantDependency(constant_name) => {
411                write!(f.out, "Circular constant dependency detected: '{}' is already being evaluated", constant_name)
412            }
413            CodegenErrorKind::RecursionDepthExceeded(depth) => {
414                write!(f.out, "Recursion depth limit exceeded: maximum depth of {} reached", depth)
415            }
416            CodegenErrorKind::UndefinedConstant(name) => {
417                write!(f.out, "Undefined constant '{}' used in expression", name)
418            }
419            CodegenErrorKind::InvalidConstantExpression => {
420                write!(f.out, "Invalid constant expression - expression contains runtime elements")
421            }
422            CodegenErrorKind::ArithmeticOverflow => {
423                write!(f.out, "Arithmetic overflow in constant expression")
424            }
425            CodegenErrorKind::ArithmeticUnderflow => {
426                write!(f.out, "Arithmetic underflow in constant expression")
427            }
428            CodegenErrorKind::DivisionByZero => {
429                write!(f.out, "Division by zero in constant expression")
430            }
431            CodegenErrorKind::ArgCallInConstantExpression(name) => {
432                write!(f.out, "Macro argument <{}> cannot be used in global constant expression - requires macro invocation context", name)
433            }
434            CodegenErrorKind::InvalidOpcodeForEVMVersion(opcode, required_version, current_version) => {
435                write!(
436                    f.out,
437                    "Opcode '{}' requires EVM version '{}' or later (current version: '{}')",
438                    opcode, required_version, current_version
439                )
440            }
441            CodegenErrorKind::InvalidLoopStep => {
442                write!(f.out, "Invalid loop step: step value cannot be zero")
443            }
444            CodegenErrorKind::LoopIterationLimitExceeded(max) => {
445                write!(f.out, "Loop iteration limit exceeded: maximum {} iterations allowed at compile-time", max)
446            }
447            CodegenErrorKind::AssertPcFailed(expected, actual) => {
448                write!(f.out, "PC assertion failed: expected position 0x{:x}, but current position is 0x{:x}", expected, actual)
449            }
450            CodegenErrorKind::ArgResolutionLimitExceeded(arg_name, max_iterations) => {
451                write!(
452                    f.out,
453                    "Exceeded maximum iterations ({}) while resolving argument reference '<{}>' through the scope chain - possible circular argument reference",
454                    max_iterations, arg_name
455                )
456            }
457            CodegenErrorKind::BubbleArgLimitExceeded(arg_name, max_iterations) => {
458                write!(
459                    f.out,
460                    "Exceeded maximum iterations ({}) while bubbling argument '<{}>' up through nested macro calls",
461                    max_iterations, arg_name
462                )
463            }
464            CodegenErrorKind::ContractSizeLimitExceeded(size, limit) => {
465                write!(f.out, "Contract bytecode size ({} bytes) exceeds the contract size limit ({} bytes)", size, limit)
466            }
467            CodegenErrorKind::InitcodeSizeLimitExceeded(size, limit) => {
468                write!(f.out, "Deployment bytecode size ({} bytes) exceeds the initcode size limit ({} bytes)", size, limit)
469            }
470            CodegenErrorKind::InvalidOpcodeOperand(msg) => {
471                write!(f.out, "Invalid opcode operand: {msg}")
472            }
473            CodegenErrorKind::OffsetExceedsTwoBytes(what, offset) => {
474                write!(f.out, "Offset {offset:#x} of {what} does not fit into 2 bytes")
475            }
476        }
477    }
478}
479
480/// CompilerError
481#[derive(Debug, Clone, PartialEq, Eq)]
482pub enum CompilerError {
483    /// Failed to Lex Source
484    LexicalError(LexicalError),
485    /// File unpacking error
486    FileUnpackError(UnpackError),
487    /// Parsing Error
488    ParserError(ParserError),
489    /// Reading PathBuf Failed
490    PathBufRead(OsString),
491    /// Empty Import Path
492    EmptyImportPath(OsString),
493    /// Bytecode Generation Error
494    CodegenError(CodegenError),
495    /// Multiple Failed Compiles
496    FailedCompiles(Vec<CompilerError>),
497    /// A constant override names a constant that does not appear in the source
498    UnknownConstantOverride(String),
499}
500
501impl fmt::Display for CompilerError {
502    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
503        match self {
504            CompilerError::LexicalError(le) => match &le.kind {
505                LexicalErrorKind::UnexpectedEof => {
506                    write!(f, "\nError: Unexpected End Of File {}{}\n", le.span.identifier(), le.span.source_seg())
507                }
508                LexicalErrorKind::InvalidCharacter(c) => {
509                    write!(f, "\nError: Invalid Character: \"{}\" {}{}\n", c, le.span.identifier(), le.span.source_seg())
510                }
511                LexicalErrorKind::InvalidArraySize(a) => {
512                    write!(f, "\nError: Invalid Array Size: \"{}\" {}{}\n", a, le.span.identifier(), le.span.source_seg())
513                }
514                LexicalErrorKind::InvalidPrimitiveType(ty) => {
515                    write!(f, "\nError: Invalid Primitive Type: \"{}\" {}{}\n", ty, le.span.identifier(), le.span.source_seg())
516                }
517                LexicalErrorKind::HexLiteralTooLong(h) => {
518                    write!(f, "\nError: Hex literal has more than 32 bytes: \"{}\" {}{}\n", h, le.span.identifier(), le.span.source_seg())
519                }
520                LexicalErrorKind::InvalidHexLiteral(h) => {
521                    write!(f, "\nError: Invalid Hex literal: \"{}\" {}{}\n", h, le.span.identifier(), le.span.source_seg())
522                }
523                LexicalErrorKind::StackUnderflow => {
524                    write!(f, "\nError: Stack Underflow {}{}\n", le.span.identifier(), le.span.source_seg())
525                }
526                LexicalErrorKind::UnexpectedContext(context) => {
527                    write!(f, "\nError: Unexpected Context: {:?} {}{}\n", context, le.span.identifier(), le.span.source_seg())
528                }
529            },
530            CompilerError::FileUnpackError(ue) => match ue {
531                UnpackError::InvalidDirectory(id) => {
532                    write!(f, "\nError: Invalid File Directory {id}\n")
533                }
534                UnpackError::UnsupportedExtension(unsupported) => {
535                    write!(
536                        f,
537                        "\nError: Unsupported File Extension \"{}\"\n--> {}\n",
538                        parse_extension(unsupported).unwrap_or(""),
539                        unsupported
540                    )
541                }
542                UnpackError::MissingFile(file) => {
543                    write!(f, "\nError: File Not Found \"{file}\"\n")
544                }
545            },
546            CompilerError::ParserError(pe) => match &pe.kind {
547                ParserErrorKind::InvalidPush(op) => {
548                    write!(f, "\nError at token {}: Invalid use of \"{:?}\" \n{}\n", pe.cursor, op, pe.spans.error(pe.hint.as_ref()))
549                }
550                ParserErrorKind::InvalidStackImmediate(op) => {
551                    write!(
552                        f,
553                        "\nError at token {}: Invalid stack operand for \"{:?}\" \n{}\n",
554                        pe.cursor,
555                        op,
556                        pe.spans.error(pe.hint.as_ref())
557                    )
558                }
559                ParserErrorKind::UnexpectedType(ut) => {
560                    write!(f, "\nError at token {}: Unexpected Type: \"{}\" \n{}\n", pe.cursor, ut, pe.spans.error(pe.hint.as_ref()))
561                }
562                ParserErrorKind::InvalidTypeAsArgumentName(ut) => {
563                    write!(
564                        f,
565                        "\nError at token {}: Unexpected Argument Name is an EVM Type: \"{}\" \n{}\n",
566                        pe.cursor,
567                        ut,
568                        pe.spans.error(pe.hint.as_ref())
569                    )
570                }
571                ParserErrorKind::InvalidDefinition(k) => {
572                    write!(f, "\nError at token {}: Invalid Defintion \"{}\"\n{}\n", pe.cursor, k, pe.spans.error(pe.hint.as_ref()))
573                }
574                ParserErrorKind::InvalidConstantValue(cv) => {
575                    write!(f, "\nError at token {}: Invalid Constant Value: \"{}\" \n{}\n", pe.cursor, cv, pe.spans.error(pe.hint.as_ref()))
576                }
577                ParserErrorKind::InvalidConstantName => {
578                    write!(f, "\nError at token {}: Invalid Constant Name \n{}\n", pe.cursor, pe.spans.error(pe.hint.as_ref()))
579                }
580                ParserErrorKind::InvalidMacroName => {
581                    write!(f, "\nError at token {}: Invalid Macro Name \n{}\n", pe.cursor, pe.spans.error(pe.hint.as_ref()))
582                }
583                ParserErrorKind::InvalidTokenInMacroBody(tmb) => {
584                    write!(
585                        f,
586                        "\nError at token {}: Invalid Token In Macro Body: \"{}\" \n{}\n",
587                        pe.cursor,
588                        tmb,
589                        pe.spans.error(pe.hint.as_ref())
590                    )
591                }
592                ParserErrorKind::InvalidTokenInLabelDefinition(tlb) => {
593                    write!(
594                        f,
595                        "\nError at token {}: Invalid Token In Label Definition: \"{}\" \n{}\n",
596                        pe.cursor,
597                        tlb,
598                        pe.spans.error(pe.hint.as_ref())
599                    )
600                }
601                ParserErrorKind::InvalidSingleArg(sa) => {
602                    write!(f, "\nError at token {}: Invalid Argument: \"{}\" \n{}\n", pe.cursor, sa, pe.spans.error(pe.hint.as_ref()))
603                }
604                ParserErrorKind::InvalidTableBodyToken(tbt) => {
605                    write!(
606                        f,
607                        "\nError at token {}: Invalid Token In Table Body: \"{}\" \n{}\n",
608                        pe.cursor,
609                        tbt,
610                        pe.spans.error(pe.hint.as_ref())
611                    )
612                }
613                ParserErrorKind::InvalidConstant(constant) => {
614                    write!(f, "\nError at token {}: Invalid Constant: \"{}\" \n{}\n", pe.cursor, constant, pe.spans.error(pe.hint.as_ref()))
615                }
616                ParserErrorKind::InvalidArgCallIdent(aci) => {
617                    write!(
618                        f,
619                        "\nError at token {}: Invalid Argument Call Identifier: \"{}\" \n{}\n",
620                        pe.cursor,
621                        aci,
622                        pe.spans.error(pe.hint.as_ref())
623                    )
624                }
625                ParserErrorKind::InvalidName(name) => {
626                    write!(f, "\nError at token {}: Invalid Name: \"{}\" \n{}\n", pe.cursor, name, pe.spans.error(pe.hint.as_ref()))
627                }
628                ParserErrorKind::InvalidArgs(args) => {
629                    write!(
630                        f,
631                        "\nError at token {}: Invalid Argument Type: \"{}\" \n{}\n",
632                        pe.cursor,
633                        args,
634                        pe.spans.error(pe.hint.as_ref())
635                    )
636                }
637                ParserErrorKind::InvalidUint256(v) => {
638                    write!(f, "\nError at token {}: Invalid Uint256 Value: \"{}\" \n{}\n", pe.cursor, v, pe.spans.error(pe.hint.as_ref()))
639                }
640                ParserErrorKind::InvalidBytes(b) => {
641                    write!(f, "\nError at token {}: Invalid Bytes Value: \"{}\" \n{}\n", pe.cursor, b, pe.spans.error(pe.hint.as_ref()))
642                }
643                ParserErrorKind::InvalidInt(i) => {
644                    write!(f, "\nError at token {}: Invalid Int Value: \"{}\" \n{}\n", pe.cursor, i, pe.spans.error(pe.hint.as_ref()))
645                }
646                ParserErrorKind::InvalidMacroArgs(ma) => {
647                    write!(
648                        f,
649                        "\nError at token {}: Invalid Macro Arguments: \"{}\" \n{}\n",
650                        pe.cursor,
651                        ma,
652                        pe.spans.error(pe.hint.as_ref())
653                    )
654                }
655                ParserErrorKind::InvalidReturnArgs => {
656                    write!(f, "\nError at token {}: Invalid Return Arguments\n{}\n", pe.cursor, pe.spans.error(pe.hint.as_ref()))
657                }
658                ParserErrorKind::InvalidImportPath(ip) => {
659                    write!(f, "\nError at token {}: Invalid Import Path: \"{}\" \n{}\n", pe.cursor, ip, pe.spans.error(pe.hint.as_ref()))
660                }
661                ParserErrorKind::InvalidDecoratorFlag(df) => {
662                    write!(f, "\nError at token {}: Invalid Decorator Flag: \"{}\" \n{}\n", pe.cursor, df, pe.spans.error(pe.hint.as_ref()))
663                }
664                ParserErrorKind::InvalidDecoratorFlagArg(dfa) => {
665                    write!(
666                        f,
667                        "\nError at token {}: Invalid Decorator Flag Argument: \"{}\" \n{}\n",
668                        pe.cursor,
669                        dfa,
670                        pe.spans.error(pe.hint.as_ref())
671                    )
672                }
673                ParserErrorKind::DecoratorOnNonTest(name) => {
674                    write!(
675                        f,
676                        "\nError at token {}: Decorator on non-test macro: \"{}\" \n{}\n",
677                        pe.cursor,
678                        name,
679                        pe.spans.error(pe.hint.as_ref())
680                    )
681                }
682                ParserErrorKind::DuplicateLabel(label) => {
683                    write!(f, "\nError: Duplicate label: \"{}\" \n{}\n", label, pe.spans.error(pe.hint.as_ref()))
684                }
685                ParserErrorKind::DuplicateMacro(mn) => {
686                    write!(f, "\nError: Duplicate MACRO name found: \"{}\" \n{}\n", mn, pe.spans.error(pe.hint.as_ref()))
687                }
688                ParserErrorKind::InvalidTableStatement(statement_type) => {
689                    write!(f, "\nError: Invalid Table Statement: \"{}\" \n{}\n", statement_type, pe.spans.error(pe.hint.as_ref()))
690                }
691                ParserErrorKind::InvalidExpression(token) => {
692                    write!(
693                        f,
694                        "\nError at token {}: Invalid expression syntax: \"{}\" \n{}\n",
695                        pe.cursor,
696                        token,
697                        pe.spans.error(pe.hint.as_ref())
698                    )
699                }
700            },
701            CompilerError::PathBufRead(os_str) => {
702                write!(f, "\nError: Invalid Import Path: \"{}\"", os_str.as_os_str().to_str().unwrap_or("<unknown import>"))
703            }
704            CompilerError::CodegenError(ce) => match &ce.kind {
705                CodegenErrorKind::LockingError => {
706                    write!(f, "\nError: Synchronisation Failure\n")
707                }
708                CodegenErrorKind::StoragePointersNotDerived => {
709                    write!(f, "\nError: Storage Pointers Not Derived\n{}\n", ce.span.error(None))
710                }
711                CodegenErrorKind::InvalidMacroStatement => {
712                    write!(f, "\nError: Invalid Macro Statement\n{}\n", ce.span.error(None))
713                }
714                CodegenErrorKind::InvalidArgumentCount(mn, expected, actual) => {
715                    write!(
716                        f,
717                        "\nError: Invalid Argument Count for \"{}\", expected {}, got {}!\n{}",
718                        mn,
719                        expected,
720                        actual,
721                        ce.span.error(None)
722                    )
723                }
724                CodegenErrorKind::MissingArgumentDefinition(ad) => {
725                    write!(f, "\nError: Missing Argument Definition For \"{}\"\n{}", ad, ce.span.error(None))
726                }
727                CodegenErrorKind::MissingMacroDefinition(md) => {
728                    write!(f, "\nError: Missing Macro Definition For \"{}\"\n{}", md, ce.span.file())
729                }
730                CodegenErrorKind::InvalidMacroInvocation(mmi) => {
731                    write!(f, "\nError: Missing Macro Definition For Invocation: \"{}\"\n{}\n", mmi, ce.span.error(None))
732                }
733                CodegenErrorKind::MissingFunctionInterface(func) => {
734                    write!(f, "\nError: Missing Function Interface: \"{}\"\n{}\n", func, ce.span.error(None))
735                }
736                CodegenErrorKind::MissingEventInterface(event) => {
737                    write!(f, "\nError: Missing Event Interface: \"{}\"\n{}\n", event, ce.span.error(None))
738                }
739                CodegenErrorKind::MissingConstantDefinition(_) => {
740                    write!(f, "\nError: Missing Constant Definition\n{}\n", ce.span.error(None))
741                }
742                CodegenErrorKind::StringConstantNotBytes(msg) => {
743                    write!(f, "\nError: String constant cannot be used directly: {}\n{}\n", msg, ce.span.error(None))
744                }
745                CodegenErrorKind::MissingErrorDefinition(_) => {
746                    write!(f, "\nError: Missing Error Definition\n{}\n", ce.span.error(None))
747                }
748                CodegenErrorKind::AbiGenerationFailure => {
749                    write!(f, "\nError: ABI Generation Failed\n{}\n", ce.span.error(None))
750                }
751                CodegenErrorKind::IOError(ioe) => {
752                    write!(f, "\nError: IO Error: {ioe}\n{}", ce.span.file())
753                }
754                CodegenErrorKind::UnkownArgcallType => {
755                    write!(f, "\nError: Unknown Arg Call Type\n{}\n", ce.span.error(None))
756                }
757                CodegenErrorKind::MissingMacroInvocation(mmi) => {
758                    write!(f, "\nError: Missing Macro Invocation: \"{}\"\n{}\n", mmi, ce.span.error(None))
759                }
760                CodegenErrorKind::UnmatchedJumpLabels(labels) => {
761                    write!(f, "\nError: Unmatched Jump Labels: \"{}\"\n{}\n", labels.join(", "), ce.span.error(None))
762                }
763                CodegenErrorKind::UsizeConversion(_) => {
764                    write!(f, "\nError: Usize Conversion\n{}\n", ce.span.error(None))
765                }
766                CodegenErrorKind::InvalidArguments(_) => {
767                    write!(f, "\nError: Invalid Arguments\n{}\n", ce.span.error(None))
768                }
769                CodegenErrorKind::InvalidMacroArgumentType(msg) => {
770                    write!(f, "\nError: Invalid Macro Argument Type\n{}\n{}\n", msg, ce.span.error(None))
771                }
772                CodegenErrorKind::InvalidHex(_) => {
773                    write!(f, "\nError: Invalid Hex\n{}\n", ce.span.error(None))
774                }
775                CodegenErrorKind::InvalidTableStatement(_) => {
776                    write!(f, "\nError: Invalid Table Statement\n{}\n", ce.span.error(None))
777                }
778                CodegenErrorKind::InvalidCodeLength(_) => {
779                    write!(f, "\nError: Invalid Code Length\n{}\n", ce.span.error(None))
780                }
781                CodegenErrorKind::TestInvocation(_) => {
782                    write!(f, "\nError: Test Invocation\n{}\n", ce.span.error(None))
783                }
784                CodegenErrorKind::InvalidConstructorArgs(msg) => {
785                    write!(f, "\nError: Invalid constructor arguments: {msg}\n{}\n", ce.span.error(None))
786                }
787                CodegenErrorKind::ArgsStartOutsideConstructor => {
788                    write!(
789                        f,
790                        "\nError: __argsstart() can only be used in the constructor, as constructor arguments are not part of the deployed code\n{}\n",
791                        ce.span.error(None)
792                    )
793                }
794                CodegenErrorKind::MissingTableSize(table_name) => {
795                    write!(f, "\nError: Missing Table Size for table: \"{table_name}\"\n{}\n", ce.span.error(None))
796                }
797                CodegenErrorKind::UnsupportedBuiltinFunction(bf) => {
798                    write!(f, "\nError: Unsupported Builtin Function: \"{bf}\"\n{}\n", ce.span.error(None))
799                }
800                CodegenErrorKind::RuntimeSizeNotComputed => {
801                    write!(
802                        f,
803                        "\nError: __codesize(RUNTIME) cannot be resolved here: MAIN bytecode has not been generated yet\n{}\n",
804                        ce.span.error(None)
805                    )
806                }
807                CodegenErrorKind::CodesizeRuntimeInCodeTable => {
808                    write!(f, "\nError: __codesize(RUNTIME) is not allowed inside a code table\n{}\n", ce.span.error(None))
809                }
810                CodegenErrorKind::CodesizeNotConverged(iterations) => {
811                    write!(f, "\nError: __codesize did not converge after {iterations} codegen passes\n{}\n", ce.span.error(None))
812                }
813                CodegenErrorKind::UnsupportedStatementType(st) => {
814                    write!(f, "\nError: Unsupported Statement Type: \"{st}\"\n{}\n", ce.span.error(None))
815                }
816                CodegenErrorKind::DuplicateLabelInScope(label) => {
817                    write!(f, "\nError: Duplicate label '{}' defined in the same scope\n{}\n", label, ce.span.error(None))
818                }
819                CodegenErrorKind::DuplicateLabelAcrossSiblings(label) => {
820                    write!(f, "\nError: Duplicate label '{}' defined across siblings in same scope\n{}\n", label, ce.span.error(None))
821                }
822                CodegenErrorKind::DuplicateTableEmbedding(table) => {
823                    write!(f, "\nError: Table \"{}\" has already been embedded\n{}\n", table, ce.span.error(None))
824                }
825                CodegenErrorKind::JumpTargetTooLarge { label, target, opcode } => {
826                    write!(
827                        f,
828                        "\nError: Jump target {:#x} too large for {} in label \"{}\"\n{}\n",
829                        target,
830                        opcode,
831                        label,
832                        ce.span.error(None)
833                    )
834                }
835                CodegenErrorKind::CircularMacroInvocation(macro_name) => {
836                    write!(
837                        f,
838                        "\nError: Circular macro invocation detected: '{}' is already in the call stack\n{}\n",
839                        macro_name,
840                        ce.span.error(None)
841                    )
842                }
843                CodegenErrorKind::CircularConstantDependency(constant_name) => {
844                    write!(
845                        f,
846                        "\nError: Circular constant dependency detected: '{}' is already being evaluated\n{}\n",
847                        constant_name,
848                        ce.span.error(None)
849                    )
850                }
851                CodegenErrorKind::RecursionDepthExceeded(depth) => {
852                    write!(f, "\nError: Recursion depth limit exceeded: maximum depth of {} reached\n{}\n", depth, ce.span.error(None))
853                }
854                CodegenErrorKind::UndefinedConstant(name) => {
855                    write!(f, "\nError: Undefined constant '{}' used in expression\n{}\n", name, ce.span.error(None))
856                }
857                CodegenErrorKind::InvalidConstantExpression => {
858                    write!(f, "\nError: Invalid constant expression - contains runtime elements\n{}\n", ce.span.error(None))
859                }
860                CodegenErrorKind::ArithmeticOverflow => {
861                    write!(f, "\nError: Arithmetic overflow in constant expression\n{}\n", ce.span.error(None))
862                }
863                CodegenErrorKind::ArithmeticUnderflow => {
864                    write!(f, "\nError: Arithmetic underflow in constant expression\n{}\n", ce.span.error(None))
865                }
866                CodegenErrorKind::DivisionByZero => {
867                    write!(f, "\nError: Division by zero in constant expression\n{}\n", ce.span.error(None))
868                }
869                CodegenErrorKind::ArgCallInConstantExpression(name) => {
870                    write!(
871                        f,
872                        "\nError: Macro argument <{}> cannot be used in global constant expression\nRequires macro invocation context\n{}\n",
873                        name,
874                        ce.span.error(None)
875                    )
876                }
877                CodegenErrorKind::InvalidOpcodeForEVMVersion(opcode, required_version, current_version) => {
878                    write!(
879                        f,
880                        "\nError: Opcode '{}' requires EVM version '{}' or later (current version: '{}')\n{}\n",
881                        opcode,
882                        required_version,
883                        current_version,
884                        ce.span.error(None)
885                    )
886                }
887                CodegenErrorKind::InvalidLoopStep => {
888                    write!(f, "\nError: Invalid loop step: step value cannot be zero\n{}\n", ce.span.error(None))
889                }
890                CodegenErrorKind::LoopIterationLimitExceeded(max) => {
891                    write!(
892                        f,
893                        "\nError: Loop iteration limit exceeded\nMaximum {} iterations allowed at compile-time\n{}\n",
894                        max,
895                        ce.span.error(None)
896                    )
897                }
898                CodegenErrorKind::AssertPcFailed(expected, actual) => {
899                    write!(
900                        f,
901                        "\nError: PC assertion failed\nExpected position: 0x{:x}\nActual position: 0x{:x}\n{}\n",
902                        expected,
903                        actual,
904                        ce.span.error(None)
905                    )
906                }
907                CodegenErrorKind::ArgResolutionLimitExceeded(arg_name, max_iterations) => {
908                    write!(
909                        f,
910                        "\nError: Exceeded maximum iterations ({}) while resolving argument reference '<{}>'\nPossible circular argument reference\n{}\n",
911                        max_iterations,
912                        arg_name,
913                        ce.span.error(None)
914                    )
915                }
916                CodegenErrorKind::BubbleArgLimitExceeded(arg_name, max_iterations) => {
917                    write!(
918                        f,
919                        "\nError: Exceeded maximum iterations ({}) while bubbling argument '<{}>' up through nested macro calls\n{}\n",
920                        max_iterations,
921                        arg_name,
922                        ce.span.error(None)
923                    )
924                }
925                CodegenErrorKind::ContractSizeLimitExceeded(size, limit) => {
926                    write!(
927                        f,
928                        "\nError: Contract bytecode size ({} bytes) exceeds the contract size limit ({} bytes)\nUse --no-size-limit to skip this check\n{}\n",
929                        size,
930                        limit,
931                        ce.span.error(None)
932                    )
933                }
934                CodegenErrorKind::InvalidOpcodeOperand(msg) => {
935                    write!(f, "\nError: Invalid Opcode Operand\n{}\n{}\n", msg, ce.span.error(None))
936                }
937                CodegenErrorKind::OffsetExceedsTwoBytes(what, offset) => {
938                    write!(f, "\nError: Offset {:#x} of {} does not fit into 2 bytes\n{}\n", offset, what, ce.span.error(None))
939                }
940                CodegenErrorKind::InitcodeSizeLimitExceeded(size, limit) => {
941                    write!(
942                        f,
943                        "\nError: Deployment bytecode size ({} bytes) exceeds the initcode size limit ({} bytes)\nUse --no-size-limit to skip this check\n{}\n",
944                        size,
945                        limit,
946                        ce.span.error(None)
947                    )
948                }
949            },
950            CompilerError::FailedCompiles(v) => {
951                v.iter().for_each(|ce| {
952                    let _ = write!(f, "{ce}");
953                });
954                Ok(())
955            }
956            CompilerError::EmptyImportPath(os_str) => {
957                write!(f, "\nError: Import path with empty string: \"{}\"", os_str.as_os_str().to_str().unwrap_or("<unknown import>"))
958            }
959            CompilerError::UnknownConstantOverride(name) => {
960                write!(f, "\nError: Constant override \"{name}\" does not match any constant in the source\n")
961            }
962        }
963    }
964}