Skip to main content

How to Add a Diagnostic Error Code

Morph uses a multi-locale diagnostic system. Error codes are defined in TOML files under morphs/<Package>/diagnostics/<locale>/ and referenced by package-prefixed IDs from C++.


Step 1 — Claim a Code Number

Open the target package manifest and package diagnostics catalog. Pick the package prefix and the next free <PREFIX><4-digit> code:

RangeCategory
CORE1xxxCore parser / lexer errors
CORE2xxxCore semantic errors
CORE3xxxCore ownership / lifetime errors
CORE4xxxCore module / type integration errors
BUILD5xxxBuild / code generation errors
SHADER2xxx / GRPHCS2xxxPlugin-owned semantic families
CORE6xxx / BUILD6xxxWarning families
VCON7xxxvcon container / sandbox VM errors
CORE9xxxInternal compiler errors

Pick the next available code in the range and add an entry to morphs/<Package>/diagnostics/catalog.toml:

[messages.CORE2042]
summary = "Type mismatch in assignment"
category = "semantic"
severity = "error"

Step 2 — Add the Diagnostic to Each Locale

For every locale required by morphs/<Package>/diagnostics/catalog.toml, add or update a file under morphs/<Package>/diagnostics/<locale>/ with:

[messages.CORE2042]
message = "cannot assign value of type '{got}' to variable of type '{expected}'"
note = "consider an explicit cast or check the declared type"

Use the package diagnostics helper to automate this across all locales:

python scripts/diagnostics/plugger.py --package Core add
python scripts/diagnostics/plugger.py --package Core update CORE2042
python scripts/diagnostics/plugger.py apply scripts/diagnostics/pending/Core/ADD_CORE2042.toml

Each package now owns its own diagnostics catalog and locale files; no central registry is used.


Step 3 — Reference the Code from C++

In the appropriate semantic/parser source file, emit the diagnostic:

// In src/sema/ExpressionAnalyzer.cpp (for example)
ctx.emitter.emit("CORE2042", expr.location(), {
{"got", got_type.name()},
{"expected", expected_type.name()}
});

The ctx.emitter is a DiagnosticEmitter (src/sema/DiagnosticEmitter.h). The DiagnosticLocalizer (src/diagnostics/DiagnosticLocalizer.cpp) resolves the locale at runtime using plugin-owned morphs/<Package>/diagnostics/<locale>/ TOML files.


Step 4 — Write a Test

Add a test that compiles a .mx snippet and asserts the diagnostic fires:

// In tests/sema/<something>.cpp
TEST("CORE2042 fires on type mismatch") {
auto result = compile("let x: i32 = \"hello\"");
EXPECT_DIAGNOSTIC(result, "CORE2042");
}

Step 5 — Verify

morphc.bat build
morph_unit_tests --filter Diagnostic