# Modula-2 diagnostics — step 1 This first diagnostics layer is deliberately lightweight. It does **not** replace Coco/R. It provides immediate editor feedback for a small set of structural errors while the real parser/LSP is being prepared. It currently checks: - unterminated `(* ... *)` comments; - unterminated string literals; - presence of the module header; - `;` after the module header; - presence of the final `END .`; - module-name consistency between the header and final `END`; - the final period after `END `. The diagnostics are published through the VS Code-compatible `DiagnosticCollection`, which Theia displays directly in the editor. The next stage will replace the structural checks with diagnostics generated by the Coco/R parser, while keeping the same editor diagnostic mechanism. ## Server-side semantic layer (`src/m2/analyse.ts`, source `modula2`) In parallel, the language server runs its own checks on every open document — always on, merged with Coco/R output when a validator is configured: - duplicate declarations in one scope (error, with first-declared line); - unknown identifiers (error), with conservative skips: qualified names, import clauses, `WITH` regions, unverifiable FROM-imports, predefined identifiers, closing `END Name`; - enumeration literals `(A, B, ...)` are treated as declared constants, so they resolve, complete, and appear in the outline. Not covered (needs statement/expression parsing): assignment type compatibility, call arity, use-before-declaration order, FROM-list membership against the defining `.def`. ## Statement checker (`src/m2/checker.ts` + `src/m2/types.ts`, source `modula2`) Bodies (`BEGIN..END`, recorded by the parser) are walked with a recursive statement/expression analyser. Operator and compatibility rules were calibrated case-by-case against `gm2`: - assignment compatibility, including whole-number family, `REAL`↔`LONGREAL`, `CHAR`/string rules with `ARRAY OF CHAR` length checks, sets, pointers, enumerations, `NIL`; - call arity (GNU optional parameters supported) and argument types, including open-array formals; ignored function results and void procedures used as values; - `BOOLEAN` conditions (`IF`, `WHILE`, `ELSIF`, `UNTIL`), ordinal `CASE` selectors and `FOR` variables/bounds/`BY` steps; - illegal targets (`CONST`, procedure, type, module), illegal operands (`NOT`/`AND`/`OR`, mixed arithmetic, `DIV`/`MOD` on reals, indexing, dereferencing, comparisons of arrays/records, `CARDINAL` vs `INTEGER` comparisons); - `RETURN` without a value, value-returning `RETURN`s, `RETURN` outside procedures and values returned from void procedures. Still out of scope: use-before-declaration order, range checking, builtin-procedure signatures, record-field types, `WITH`-block internals.