Diagnostics & Warnings
Compiler warnings, error output formats, and typo suggestions.
Achronyme reports errors and warnings with source snippets, underline carets, and actionable suggestions — similar to rustc. The diagnostic system works across all commands (run, compile, circuit, disassemble).
Error Output
By default, errors render with source context:
error: undefined variable: `conuter`
--> 3:9
|
3 | let y = conuter + 1
| ^^^^^^^
|
= help: did you mean `counter`?
The output includes:
- Severity —
errororwarning, with an optional code like[W001] - Location —
file:line:col(orline:colfor stdin) - Source snippet — the offending line with underline carets (
^^^) - Labels — secondary spans pointing to related locations
- Notes — additional context (
= note: ...) - Suggestions — actionable fixes (
= help: ...)
Compiler Warnings
The compiler emits warnings for code that is valid but likely incorrect. Warnings never prevent compilation.
W001: Unused Variable
Triggers when a local variable or function parameter is never read:
let count = 42
// warning[W001]: unused variable: `count`
Prefix with _ to silence the warning:
let _count = 42 // no warning
W002: Unused Mutable
Triggers when a variable is declared with mut but never reassigned:
let mut total = 0
print(total)
// warning[W002]: variable `total` declared as mutable but never mutated
Remove the mut keyword if the variable doesn’t need to change.
W003: Unreachable Code
Triggers when statements follow a return in the same block:
fn foo() {
return 1
let x = 2 // warning[W003]: unreachable code
}
W004: Variable Shadowing
Triggers when a new binding shadows an existing variable in the same scope:
let x = 1
let x = 2 // warning[W004]: variable `x` shadows a previous binding in the same scope
W005: Unused Selective Import
Triggers when a name brought in by a selective import is never used:
import { add, PI } from "./math.ach"
print(add(1, 2))
// warning[W005]: imported name `PI` is never used
Prefix with _ to silence the warning:
import { add, _PI } from "./math.ach"
print(add(1, 2)) // no warning for _PI
This warning only applies to selective imports (import { ... } from). Namespace imports (import "..." as alias) are not checked because the alias is a single binding.
”Did You Mean?” Suggestions
When the compiler encounters an undefined variable, it searches all in-scope names (locals, globals, upvalues) for similar identifiers using Levenshtein distance. If a close match is found, it suggests the correction:
error: undefined variable: `prnt`
--> 2:1
|
2 | prnt("hello")
| ^^^^
|
= help: did you mean `print`?
The suggestion threshold scales with name length — short names (3 characters or fewer) require a closer match to avoid false suggestions.
Output Formats
The --error-format flag controls how diagnostics are rendered. It applies globally to all subcommands.
human (default)
Rich output with source snippets, underline carets, and ANSI colors (when stderr is a terminal):
ach run program.ach --error-format human
json
One JSON object per diagnostic (JSON Lines format), suitable for editor integrations and CI pipelines:
ach run program.ach --error-format json
{"code":"W001","level":"warning","message":"unused variable: `x`","notes":["if this is intentional, prefix with underscore: `_x`"],"spans":[{"byte_end":5,"byte_start":4,"column_end":6,"column_start":5,"file_name":null,"label":"primary","line_end":1,"line_start":1}],"suggestions":[]}
Each JSON object contains:
| Field | Type | Description |
|---|---|---|
message | string | The diagnostic message |
code | string|null | Warning/error code (e.g., "W001") |
level | string | "error", "warning", "note", or "help" |
spans | array | Source locations with byte offsets, line/col, and labels |
notes | array | Additional context strings |
suggestions | array | Suggested code replacements with spans |
short
Compact one-line format, grep-friendly:
ach run program.ach --error-format short
<stdin>:3:9: error: undefined variable: `x`
Format: file:line:col: severity: message
Error Recovery
The parser collects multiple errors per compilation instead of stopping at the first one. Failed regions appear as Error nodes in the AST, allowing the parser to continue and report additional issues:
$ ach compile broken.ach
error: expected expression
--> 1:9
|
1 | let x =
| ^
|
error: unexpected token `}`
--> 3:1
|
3 | }
| ^
|
This means a single compilation run can surface multiple problems at once, reducing the edit-compile-fix cycle.