Adesh Compiler Diagnostics & Error Tables
The Adesh compiler diagnostics system is built to the highest modern standard of clarity, actionability, and elegance. Inspired by the usability of the Rust compiler, it replaces ad-hoc print statements with a structured, multi-error diagnostic architecture featuring:
- Rust Error-Code Equivalence: Canonical Rust error codes (
E0106,E0277,E0308,E0381,E0382,E0384,E0416,E0425,E0428,E0499,E0502,E0505,E0506,E0515,E0597,E0631,E0733) are assigned to matching semantic conditions with verified rationale. - Distinct Adesh Namespace (
AD0001–AD0007): Custom Adesh semantics (lexer tokens, parser recovery, async context, embedded heap prohibitions, ADOB binaries, and runtime traps) reside in a dedicated namespace. - Rust-Style Terminal Error Tables: Clear line-number gutters, precise carets (
^and~), primary/secondary labels, notes, actionable remediation hints, and automatic explain referrals. - Interactive Explanation Tooling:
adesh --explain <CODE>andadesh --explain listCLI commands for developer documentation lookup. - Machine-Readable JSON Diagnostics (
schema_version: "1.0.0"): Fully serializable reports for IDEs, language servers, and CI pipelines. - Elimination of Leaked Internal Traces: Adesh compiler panics or unexpected crashes are intercepted by an internal panic hook, presenting an Adesh-branded internal compiler error (ICE) directed to
ADESH_BACKTRACE=1oradesh --debug-backtrace.
Visual Presentation & Error Tables
Adesh errors are rendered as clean, legible tables matching the Rust diagnostic standard:
error[E0308]: mismatched types
--> examples/types.adesh:4:18
|
4 | let count: i32 = "seven";
| ^^^^^^^ expected `i32`, found string
|
= note: this declaration requires an integer value
= help: provide an integer or change the declared type
= help: run `adesh --explain E0308` for more information
Terminal Styling & Environment Controls
- Colors: Enabled by default in interactive TTYs using ANSI escape codes (red for errors, yellow for warnings, cyan for line markers and helps, green for suggestions).
NO_COLOR: When theNO_COLORenvironment variable is set (orCLICOLOR=0), the renderer strips all ANSI styling and outputs clean plain text.- Visual Gutter Width: Dynamically calculated based on the maximum line number being displayed, ensuring aligned vertical separator bars (
|). - Carets & Tildes: Primary error spans are underlined with
^and~for the exact visual column width of the token.
Core Diagnostic Data Model
The shared diagnostics subsystem resides in src/diagnostics/ and is exposed via adeshlang::diagnostics:
-
Diagnostic: Core structured diagnostic containing:code: Option<String>: Canonical error code (e.g."E0308","AD0001").severity: DiagnosticSeverity:Error,Warning, orInfo.phase: DiagnosticPhase: Compiler stage (Lexer,Parser,Semantic,TypeCheck,Ownership,Lowering,Codegen,Linker,Runtime,Cli).message: String: Concise diagnostic title.file: Option<String>: Source file path.primary_span: Option<Span>: Primary source location and line text.labels: Vec<Label>: Primary and secondary annotations pointing to declarations or related sites.notes: Vec<String>: Background context or invariant descriptions.helps: Vec<String>: Actionable remediation suggestions.suggestions: Vec<Suggestion>: Machine-applicable source replacements.
-
Span: Represents a contiguous range in source code:start_line: usize,start_col: usize(1-based)end_line: usize,end_col: usize(1-based)start_offset: Option<usize>,end_offset: Option<usize>(byte offsets)line_text: String
-
SourceMap: Efficient line index structure:- Stores line start byte-offsets in a monotonic table.
- Computes visual columns accounting for tab stops (default 4 columns) and multi-byte Unicode characters.
- Gracefully handles LF and CRLF line breaks, empty files, and unexpected EOF spans.
Diagnostic Phases & Lifecycle
The compiler pipeline passes diagnostics through well-defined stages:
[Source Code]
│
▼
1. Lexer ──────────────► (AD0001: Malformed token / invalid escape)
│
▼
2. Parser ─────────────► (AD0002: Syntax error / unexpected token)
│
▼
3. Semantic Indexing ──► (E0425: Undefined variable / E0428: Duplicate name)
│
▼
4. Type Checking ──────► (E0308: Type mismatch / AD0003: Await outside async)
│
▼
5. Memory Safety ──────► (E0382: Use after move / E0502: Borrow conflict / AD0004: Embedded heap)
│
▼
6. Lowering / Codegen ─► (E0515: Return local reference)
│
▼
7. Linker ─────────────► (AD0005: Corrupt object / AD0006: Relocation overflow / LNK001-LNK016)
│
▼
8. Runtime / VM ───────► (AD0007: Unhandled runtime trap / panic)
Cascading Error Suppression
When multiple syntax or semantic errors occur, compiler passes attempt recovery:
- The lexer skips corrupt byte sequences and resumes at the next valid token boundary.
- The parser synchronizes on statement boundaries (semicolons, closing braces
}, or statement keywordslet,fn,struct). - Type inference substitutes an
Unknownsentinel type for failed expressions, preventing a cascade of secondary mismatch errors downstream. - A configurable diagnostic cap (default 30) prevents log flooding on truncated inputs.
Command-Line Interface
Explaining Error Codes
Developers can view detailed explanations, common causes, erroneous code examples, and suggested resolutions using --explain:
# Explain a specific Rust-compatible error code
adesh --explain E0308
# Explain an Adesh-specific diagnostic code
adesh --explain AD0001
# List all registered diagnostic codes in a formatted table
adesh --explain list
Structured JSON Output
For IDE language servers (LSP), automated linters, and CI checks, diagnostics can be emitted as JSON:
adesh build main.adesh --diagnostic-format=json
Output Schema (schema_version: "1.0.0"):
{
"schema_version": "1.0.0",
"has_errors": true,
"error_count": 1,
"warning_count": 0,
"diagnostics": [
{
"code": "E0308",
"severity": "error",
"phase": "typecheck",
"message": "mismatched types",
"file": "examples/types.adesh",
"primary_span": {
"start_line": 4,
"start_col": 18,
"end_line": 4,
"end_col": 24,
"line_text": "let count: i32 = \"seven\";"
},
"labels": [
{
"file": null,
"span": {
"start_line": 4,
"start_col": 18,
"end_line": 4,
"end_col": 24,
"line_text": "let count: i32 = \"seven\";"
},
"message": "expected `i32`, found string",
"is_primary": true
}
],
"notes": [
"this declaration requires an integer value"
],
"helps": [
"provide an integer or change the declared type"
],
"suggestions": []
}
]
}
Compiler Panic & Backtrace Control
In the event of an internal compiler defect:
- By default, Adesh suppresses internal implementation stack traces and displays a clean message:
error: internal compiler error: Adesh encountered an unexpected failure= note: this is a compiler bug, not an error in your code= note: to inspect the full compiler backtrace, set ADESH_BACKTRACE=1 or run with --debug-backtrace= help: please report this issue at https://github.com/adeshlang/adeshlang/issues
- Setting
ADESH_BACKTRACE=1or runningadesh <COMMAND> --debug-backtraceprints the full internal stack frame trace for compiler developers.