summary.md 4.4 KB

SimpleMod2 project — summary

Subset of Modula-2 (no procedures/functions) with a Coco/R-generated compiler featuring a symbol table, static type checking and a Modula-2-generating backend. All work lives in Test1/, built with ../CR -m -C and GNU Modula-2 (gm2 -fiso).

1. Starting point

Analysed Sample grammars/ (21 Coco/R .atg files across the C / Pascal / Modula-2 / Oberon / Ada / calculator families, plus Other Formats/ with 6 ANTLR Modula-2 grammars) as reference material.

2. Simplified grammar — Test1/SimpleMod2.atg

Modula-2 subset without procedures/functions: program module only, CONST / TYPE / VAR, full expression hierarchy, assignment and IF CASE WHILE REPEAT LOOP/EXIT FOR WITH statements. Removed: procedure declarations and calls, formal parameters, RETURN, DEFINITION / IMPLEMENTATION modules, local modules, EXPORT, PRIORITY. LL(1)-clean (subrange rule factored for Coco/R).

3. Test infrastructure — Test1/

  • Parser / scanner / driver generated with CR -m -C SimpleMod2.atg (-C = emit compiler main module, -m = FORWARD declarations commented out), CRFRAMES pointing at Test1/ for the frame files.
  • Built with gm2 -fiso (FileIO SymTab CodeGen SimpleMS SimpleMP SimpleM, linked via generated module list) → Test1/SimpleM.
  • Test1/tests/: 30+ .mod sources with .LST listings — valid programs (t_ok_*, ok), syntax rejects (t_bad_*, bad), symbol-table rejects, type rejects, backend demos (t_be_demo, t_be_full).
  • Test1/gen/: backend output (<Module>.mod per successful parse).

4. Symbol table — Test1/SymTab.def/.mod

Scopes with levels (globals at level 0) and kinds (CONST / TYPE / VAR / IMPORT / MODULE / PREDEF / FIELD): duplicate declarations (200), undeclared identifiers (201), MODULE / END name match (202).

5. Type checking (error codes 210–224)

  • Type descriptors: one alias per TYPE declaration (so self-references such as POINTER TO Person resolve; A = A is caught as cyclical), subranges, enumerations (literals typed), arrays, records with field lists, sets, pointers, predefined types, string literals.
  • Synthesized types through all expressions and designators; checks for assignment compatibility (incl. assignment to a constant), arithmetic vs boolean operators, comparisons, BOOLEAN conditions, array indexing, pointer dereference, .field selection, FOR integer-ness, CASE label matching, IN / set elements, ordinal index and bound types, type-position names.
  • WITH pushes the record's fields as an inner scope, so unqualified field access works in its body.
  • Rules: declare-before-use (single pass); INTEGER, CARDINAL and subranges form one integer family; no mixed INTEGER/REAL arithmetic; INTEGER assigns to REAL; 1-character literal is CHAR; unknown types (InvalidType) suppress follow-on errors to avoid cascades.
  • 15 t_bad_* type tests, each producing exactly its intended code (e.g. x := 3.14 → 210, b + 1 → 211, x AND y → 212, x = r → 213, WHILE x → 214, x.y → 215, p.b → 216, x[1] → 217, v[r] → 218, x^ → 219, FOR r := → 220, v : x → 221, {1, 'a'} → 222, A = A → 223).

6. Backend — Test1/CodeGen.def/.mod

Syntax-directed pretty-printer: grammar actions re-emit every token with regenerated layout (Emit / Brk / Ind / Ded) into gen/<Module>.mod. Output is complete, ready-to-compile Modula-2 (comments dropped). Proven end to end: BeDemo / BeFull outputs compile (gm2 -fiso -c), link and run (exit 0); all other valid-test outputs compile too, except two whose original sources fail identically under gm2 (strict set typing, missing MathLib library) — i.e. the backend is faithful to its input.

7. Current state

  • Full suite: 32/32 correct verdicts with exact error codes and no cascades.
  • Rebuild from Test1/: CRFRAMES=$(pwd) ../CR -m -C SimpleMod2.atg, then gm2 -fiso -c on FileIO SymTab CodeGen SimpleMS SimpleMP SimpleM and link with -fgen-module-list / -fuse-list.
  • Run: ./SimpleM tests/<file>.mod (listing next to the source, generated code in gen/, symbol table dumped on stdout).
  • Known limits: no constant folding, no NIL literal in the language, multi-dimensional arrays check every index but track a single element type, backend output is only meaningful when the verdict is Parsed correctly.