|
|
hai 3 horas | |
|---|---|---|
| MC4 | hai 3 semanas | |
| docs | hai 3 horas | |
| src | hai 3 semanas | |
| tests | hai 3 semanas | |
| M2c-git instructions.txt | hai 3 semanas | |
| M2comp | hai 3 semanas | |
| README.md | hai 3 horas | |
| build.sh | hai 3 semanas | |
| gnu-m2-grammar.txt | hai 3 semanas | |
| run_tests.sh | hai 3 semanas | |
| tutorial.md | hai 3 horas |
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; a tree-walking back end emits a runnable MC64 bytecode image
(.MC4) that runs on the mcint interpreter.
This is the "V2" of a family of experimental compilers (V1 → V2 → V3). Unlike
V1, which emits code in a single pass while parsing, V2 follows the Blaise
front/back split: the front end builds a complete checked abstract syntax
tree (per Mössenböck's Coco/R recipe), and the back end (MGen) walks that
tree to produce the image. V2 was developed in numbered, test-guarded steps;
as of step 7 the suite is 65/65 green.
src/M2comp.atg --Coco/R (CR)--> src/M2compS.mod + M2compP.mod + M2comp.mod
| |
(scanner) (parser + semantic actions,
SymTab checks, AST build)
|
AST
|
MGen.EmitModule
(tree walk)
v
<Module>.MC4 --> mcint
src/M2comp.atg — the whole language: tokens, productions, and the
semantic actions that drive the symbol table and build the AST.src/M2compS.mod / src/M2compP.mod / src/M2comp.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, static type checking
(errors 200–224, 230–233), procedure signatures, exports, loop depth.src/AST — heap-allocated tree of declarations/statements/expressions
per the Mössenböck "How to Build Abstract Syntax Trees with Coco/R" recipe;
error-tolerant so dumps exist for rejected sources too.src/MGen — the MC64 backend: walks the checked AST, writes
<Module>.MC4, and prints the step-7 disassembly listing (DumpImage).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 (program last). The
symbol table and the emit buffer live for the whole session; each
implementation is merged into its definition unit, and the program module
names the image. SymTab.Init/MGen run once; up to 15 library units per
session.
gm2 -fiso), developed with GCC 16.0.1 experimental.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.sh, grep, sed, tr, timeout).From the project root:
./build.sh
This runs Coco/R on src/M2comp.atg (which reports "Compilation completed.
No errors detected."), recompiles FileIO, SymTab, AST, MGen and the
generated modules with gm2 -fiso, and links ./M2comp. Object files (.o)
and the generated sources stay in src/.
./M2comp tests/r_flow.mod # parse + type-check + AST + codegen
../m-code-64/mcint RFlow.MC4 # run the image
For every unit the driver prints Parsing <file>, the symbol table and the
--- AST --- tree on stdout. After a successful session it prints the
step-7 backend listing --- Code <Module> --- (global layout per scope, the
procedure table, then the disassembled image) followed by the verdict
Parsed correctly — or Incorrect source on any error. A .LST listing
(with ***** ^ message markers) is written next to each source file.
./M2comp tests/d_lib.def tests/d_lib.mod tests/d_basic.mod
../m-code-64/mcint DBasic.MC4
<Module>.MC4 in the current directory. A session without a program unit
is rejected (Incorrect source).The V2 language subset has no text I/O statements (no WriteString /
WriteInt as in V1), 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.
After building, and with mcint available:
./run_tests.sh
The runner compiles each test with ./M2comp, runs the resulting .MC4 under
mcint, and compares the printed ExitCode; it also asserts AST-dump node
names and backend-listing opcodes for representative sources. Helpers:
expect_ok / expect_run / expect_run_none /
expect_run_files (multi-file sessions)expect_dumpexpect_fail / expect_fail_files /
expect_fail_multi (program-last gate)expect_code (e.g. realCmp, jpfalse,
storeIndir0, the proc-table entry)Emitted images are collected into MC4/. 65/65 green at step 7
(61 inherited + 4 listing checks).
src/ M2comp.atg (grammar), *.frm (frames), FileIO/SymTab/AST/MGen,
generated M2compS/M2compP/M2comp and *.o
tests/ *.mod test cases + expected .LST listings
MC4/ collected .MC4 images (test outputs)
docs/ per-step summaries (summary_m2comp_stepN.md), goal_step8.md
roadmap, session notes, AST.pdf, oberon-master/, skills.*
build.sh regenerate + compile + link -> ./M2comp
run_tests.sh compile -> mcint -> compare
gnu-m2-grammar.txt GNU Modula-2 EBNF reference
src/*.o, the generated .mod sources and ./M2comp are build artifacts
(regenerated by ./build.sh).
Lowered today (steps 1–7):
CONST/TYPE/VAR with the predefined INTEGER
family (CARDINAL, SHORTINT, LONGINT), subranges ([lo .. hi],
INTEGER[lo .. N]), REAL/LONGREAL, CHAR, BOOLEAN.ARRAYs (multi-dimensional, whole-array copy),
RECORDs (whole-record copy, WITH), SET OF <ordinal> (assignment,
IN, =, #), POINTER TO (assignment, NIL, ^), and strings
(ARRAY OF CHAR literal assignment, indexing, CHAR literals).+ - * / DIV MOD AND OR NOT, all six relations plus
<>= aliases (# = <>), IN; INTEGER widens to REAL; REAL is
binary64 with E-notation literals.IF/ELSIF/ELSE, CASE
(label lists, ranges, ELSE, CHAR selectors), WHILE, REPEAT,
LOOP/EXIT, FOR (runtime bounds, BY, downward), WITH (nested),
RETURN (proper check of value/variable procedures).VAR parameters, functions, recursion.MODULEs (Wirth form, optional priority [n], EXPORT
[QUALIFIED], optional module init bodies that run at startup).DEFINITION MODULE, IMPLEMENTATION
MODULE, IMPORT / FROM ... IMPORT, qualified M.x, compiled into a
single image; an implementation's BEGIN init body runs first.Parsed and type-checked, but rejected with error 230 (deferred): value
composite parameters/returns, open arrays outside VAR formals, non-literal
CONST expressions and subrange bounds, real/string CONST in definitions,
EXIT outside LOOP, non-foldable CASE labels, imported names used as
values, plus — not in the grammar yet — enumeration types, set literals
{..}, NEW/DISPOSE, procedure types/variables, and standard procedures
(HIGH, INC, DEC, …). Opaque types are the next milestone
(docs/goal_step8.md).
INTEGER DIV/MOD truncate toward zero; AND/OR are eager.REAL is binary64; INTEGER widens to REAL.NIL dereference reads 0 (no static
check, no VM trap yet).CHAR/BOOLEAN elements still take one slot."h", 'b') is a CHAR, not a string.DEFINITION units, formal parameter names live in the definition
scope: reusing a parameter name in a second heading is a duplicate
identifier (error 200).<> is accepted as an alias of #.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 |
docs/ contains a summary per development step (summary_m2comp_step1.md …
summary_m2comp_step7.md), the forward-looking goal_step8.md roadmap
(opaque types, procedure types, quad-driven backend), session_steps1-4.md
(a day-wrap note with hard-won facts), and reference material (AST.pdf,
oberon-master/, skills.*, BenjaminKowarsh.txt, blaise-process.md).
Read src/M2comp.atg's header comment for the most current
feature/limits list.
Siblings in MyWork/:
m-code-64 — the MC64 virtual machine (mcint, loader, assembler) and
its specification (docs/mc64-spec.md); the execution target of M2comp.CocoGm2 — the GNU-Modula-2 port of Coco/R (CR) and its frames,
used to generate this compiler's scanner/parser/driver.m2compiler-V1, m2compiler-V3 — the earlier and later
generations of the same experiment (V1 emits in one pass; V3 is the
larger successor).src/M2comp.atg, kept LL(1)-clean and
confirmable by Coco/R ("No errors detected.").docs/summary_m2comp_stepN.md, tagged (m2comp-step1 … m2comp-step7,
plus m2comp-day1, m2comp-docs, m2comp-goal8).*.mod generated by Coco/R are never edited by hand: fix the .frm/.atg
sources and rebuild.