M2compiler Version 1

Eric Streit ab2a0f1d14 step11.2: add project README and usage tutorial 13 godzin temu
MC4 ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
docs ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
src ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
tests ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
FileIO.o 1793b83e43 step1: Phase-0 scaffolding — M2c module-skeleton compiler, 4/4 tests green 3 tygodni temu
M2c ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
M2c-git instructions.txt e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
M2c.o 480e5149c4 step11: separate compilation units DEFINITION/IMPLEMENTATION/IMPORT; 157/157 tests green 3 tygodni temu
M2cP.o 480e5149c4 step11: separate compilation units DEFINITION/IMPLEMENTATION/IMPORT; 157/157 tests green 3 tygodni temu
M2cS.o 480e5149c4 step11: separate compilation units DEFINITION/IMPLEMENTATION/IMPORT; 157/157 tests green 3 tygodni temu
MGen.o ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
README.md ab2a0f1d14 step11.2: add project README and usage tutorial 13 godzin temu
SymTab.o 480e5149c4 step11: separate compilation units DEFINITION/IMPLEMENTATION/IMPORT; 157/157 tests green 3 tygodni temu
build.sh ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
gnu-m2-grammar.txt e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
img1.png e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
run_tests.sh ea1a294593 v1 sources to src/ (build with gm2 -I src, objects stay at root) plus real-comparison codegen fix (emit D5 before stack juggling, 158/158 tests green) 3 tygodni temu
skills.html e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
skills.jpeg e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
skills.md e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
skills.pdf e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
skills.png e0244f04a9 chore: add shared reference files (skills, grammar, instructions) 3 tygodni temu
tutorial.md ab2a0f1d14 step11.2: add project README and usage tutorial 13 godzin temu

README.md

M2c — a Modula-2 compiler for the MC64 virtual machine

A small, self-contained Modula-2 compiler written in Modula-2 (built with GNU Modula-2, gm2 -fiso). The front end is generated by Coco/R from an attributed grammar; the back end emits a runnable MC64 bytecode image (.MC4) that runs on the mcint interpreter.

This is the "V1" of a family of experimental compilers (V1 → V2 → V3). It was developed in numbered, test-guarded steps, each recorded in docs/. As of step 11 the suite is 158/158 green (99 accept/run, 65 rejection).

How it works

src/M2c.atg  --Coco/R (CR)-->  src/M2cS.mod + M2cP.mod + M2c.mod
                                     |            |
                              (scanner)      (parser + semantic actions)
                                     \           /
                                      \  gm2 -fiso
                                       v
                              ./M2c (native compiler)
                                       |
                          parse + type-check + codegen (MGen)
                                       v
                                 <Module>.MC4   -->  mcint
  • src/M2c.atg — the whole language: tokens, productions, and the semantic actions that drive the symbol table and the code generator.
  • src/M2cS.mod / src/M2cP.mod / src/M2c.mod — generated by Coco/R on every build. Do not edit them: edit their sources (src/compiler.frm, src/scanner.frm, src/parser.frm) and the grammar.
  • src/SymTab — scopes, type descriptors, and all static type checking.
  • src/MGen — the MC64 emitter (buffers an image in memory and writes it).
  • src/FileIO — the FileIO/Storage I/O library reused from Coco/R.

The driver runs one session over several files: definition files, then implementation files, then exactly one program module; SymTab.Init and MGen.OpenModule run once, and the program unit names the image.

Prerequisites

  • GNU Modula-2 (gm2 -fiso), developed with GCC 16.0.1 experimental.
  • Coco/R CR (the generator). Path is taken from CRBIN; defaults to the sibling CocoGm2/CR.
  • mcint, the MC64 interpreter, for running the produced images. Taken from MCINT; defaults to the sibling ../m-code-64/mcint.
  • Standard shell tools (sh, grep, sed, tr).

Build

From the project root:

./build.sh

This regenerates the scanner/parser/driver from src/M2c.atg, recompiles the hand-written modules, and links ./M2c. Object files (.o) stay in the project root; the generated sources live in src/.

Compiling a program

./M2c tests/t_arith.mod        # parse/type-check + codegen
mcint TArith.MC4               # run the image
  • A .LST listing (with error messages) is written next to each source, and the driver prints Parsed correctly or Incorrect source on stdout.
  • Multi-file (separate compilation) sessions pass the units in dependency order; the last file must be the program module:
  ./M2c tests/d_lib.def tests/d_libimpl.mod tests/d_basic.mod
  mcint DBasic.MC4
  • The image name comes from the program module, so the output is <Module>.MC4 in the current directory.

Test convention (no I/O in the language)

There is no text I/O in the language subset, so programs signal their result through a global variable. If the source declares

VAR ExitCode : INTEGER;

the epilogue prints its value as decimal + CRLF through an embedded print helper; without it the program simply ends.

Testing

After building, and with mcint available:

./run_tests.sh

The runner compiles each test with ./M2c, runs the resulting .MC4 under mcint, and compares the printed ExitCode; rejection tests assert the exact message text in the .LST. Run tests:

  • accept/parse — expect_ok
  • compile + run — expect_run / expect_run_none
  • multi-file run — expect_run_files
  • rejections — expect_fail / expect_fail_files

158/158 green at step 11.

Layout

src/            M2c.atg (grammar), *.frm (frames), hand modules, generated
tests/          *.mod test cases + expected .LST listings
MC4/            compiled .MC4 images (test outputs)
docs/           per-step summaries (summary_stepN.md) and goal notes
build.sh        regenerate + compile + link -> ./M2c
run_tests.sh    compile -> mcint -> compare

Root-level *.o and ./M2c are build artifacts. Shared reference material lives at the root as well: skills.md (a Modula-2 language reference), gnu-m2-grammar.txt, and the Showcase*.mod tours in src/.

Language status

Lowered today (steps 1–11):

  • Program modules; CONST/TYPE/VAR including INTEGER, CARDINAL, subranges, REAL, CHAR, BOOLEAN, enumerations.
  • Composites: fixed and open ARRAYs, RECORDs, SETs (union +, difference -, intersection *, inclusive .. ranges, IN), POINTERs (NEW/DISPOSE, ^, NIL), and strings (ARRAY OF CHAR literal assignment and comparison).
  • Full scalar and composite expressions; whole array/record copy.
  • Statements: assignment, procedure call, IF, CASE, WHILE, REPEAT, LOOP/EXIT, FOR, WITH (nested), RETURN, NEW, DISPOSE.
  • Procedures: nested, value and VAR parameters, functions, recursion, FORWARD headings, HIGH on open arrays.
  • Local MODULEs (EXPORTed constants, types, variables and procedures; optional BEGIN init bodies run at startup in declaration order).
  • Separate compilation units: DEFINITION MODULE, IMPLEMENTATION MODULE, IMPORT/FROM ... IMPORT, qualified M.x, compiled into a single image.

Parsed and type-checked, but rejected with error 230 (deferred): open arrays beyond the supported shapes, whole array/record copy except string literals, value composite params/returns, non-literal CONST expressions and BY steps, EXIT outside LOOP, imported names used as values, procedure types/variables, LONGINT/LONGCARD, LONGREAL, and opaque types.

Known semantic edges

  • INTEGER DIV/MOD truncate toward zero; CARDINAL past MAXINT compares as signed; AND/OR are eager.
  • REAL is binary64; INTEGER widens to REAL.
  • Array indexing is unchecked (no DA/DB); NIL dereference reads 0 (no static check, no VM trap yet).
  • CHAR/BOOLEAN arrays are byte-packed (1 byte/element, slots over-allocated 8×).
  • Phased caps: 64 procedures, 64 actuals per call, 16 names per FP-section, 8-deep nested calls, 8-deep WITH, 1024 slots max per type; 8 definitions, 32 interface names each, 64 FROM-aliases; one image (depCount 0).

Error codes

Static semantic errors use the following codes (the listing prints the message, not the number):

code message
200 duplicate identifier
201 undeclared identifier
202 module/procedure name mismatch
210 incompatible assignment
211 arithmetic operand must be numeric
212 boolean operand required
213 incompatible comparison
214 BOOLEAN condition required
215 not a RECORD type
216 unknown field
217 not an ARRAY type
218 array index must be integer
219 not a POINTER type
220 FOR needs integer variable and bounds
221 not a type name
222 set operand mismatch
223 cyclical type definition
224 ordinal type required
230 not supported in this phase
231 procedure forward mismatch or missing body
232 bad RETURN
233 invalid procedure call

Documentation

docs/ contains a summary per development step (summary_step1.md … summary_step11.md, plus summary_step11.1.md for the real-comparison codegen fix) and the forward-looking goal_step4.md / goal_step5.md. Read src/M2c.atg's header comment for the most current feature/limits list.

Related projects

Siblings in MyWork/:

  • m-code-64 — the MC64 virtual machine (mcint, loader, assembler) and its specification (docs/mc64-spec.md); the execution target of M2c.
  • CocoGm2 — the GNU-Modula-2 port of Coco/R (CR) and its frames, used to generate this compiler's scanner/parser/driver.
  • m2compiler-V2, m2compiler-V3 — later, more ambitious generations of the same experiment.

Working conventions

  • Grammar grows section by section in src/M2c.atg, kept LL(1)-clean.
  • Every step keeps the full suite green; each step is recorded in docs/summary_stepN.md and tagged (step1 … step11).
  • *.mod generated by Coco/R are never edited by hand: fix the .frm/.atg sources and rebuild.