OR-1 dataflow CPU sketch
at 00d336d2d4b197bbb9dbbf3641f5f112bf0cf3ec 94 lines 2.8 kB view raw
1"""Structured error types for OR1 assembler. 2 3Provides error categories, the AssemblyError dataclass, and utilities for 4formatting errors with source context in Rust style. 5""" 6 7from dataclasses import dataclass, field 8from enum import Enum 9 10from asm.ir import SourceLoc 11 12 13class ErrorCategory(Enum): 14 """Classification of assembly errors.""" 15 PARSE = "parse" 16 NAME = "name" 17 SCOPE = "scope" 18 PLACEMENT = "placement" 19 RESOURCE = "resource" 20 ARITY = "arity" 21 PORT = "port" 22 UNREACHABLE = "unreachable" 23 VALUE = "value" 24 25 26@dataclass(frozen=True) 27class AssemblyError: 28 """Structured error with source location and context. 29 30 Attributes: 31 loc: Source location where the error occurred 32 category: Error classification (see ErrorCategory) 33 message: Human-readable error message 34 suggestions: Optional list of suggestions for fixing the error 35 context_lines: Optional source lines for context 36 """ 37 loc: SourceLoc 38 category: ErrorCategory 39 message: str 40 suggestions: list[str] = field(default_factory=list) 41 context_lines: list[str] = field(default_factory=list) 42 43 44def format_error(error: AssemblyError, source: str) -> str: 45 """Format an error with source context in Rust style. 46 47 Produces output like: 48 error[SCOPE]: Duplicate label '&add' in function '$main' 49 --> line 5, column 3 50 | 51 5 | &add <| sub 52 | ^^^ 53 = help: First defined at line 2 54 55 Args: 56 error: The AssemblyError to format 57 source: The original source text 58 59 Returns: 60 Formatted error string with source context 61 """ 62 lines = source.split('\n') 63 64 # Build the header 65 result = f"error[{error.category.name}]: {error.message}\n" 66 result += f" --> line {error.loc.line}, column {error.loc.column}\n" 67 68 # Extract and display the source line 69 if 0 < error.loc.line <= len(lines): 70 source_line = lines[error.loc.line - 1] 71 72 # Compute gutter width based on line number 73 gutter_width = len(str(error.loc.line)) 74 75 result += " " * (gutter_width + 1) + "|\n" 76 result += f"{error.loc.line:>{gutter_width}} | {source_line}\n" 77 78 # Add carets pointing to the error column(s) 79 caret_col = error.loc.column 80 caret_end_col = error.loc.end_column if error.loc.end_column else caret_col + 1 81 caret_count = max(1, caret_end_col - caret_col) 82 carets = "^" * caret_count 83 84 result += " " * (gutter_width + 1) + "| " + " " * (caret_col - 1) + carets + "\n" 85 86 # Add suggestions 87 for suggestion in error.suggestions: 88 result += f" = help: {suggestion}\n" 89 90 # Add context lines if provided 91 for line in error.context_lines: 92 result += f" |\n | {line}\n" 93 94 return result