# Mini Modula-2 Compiler — Explanations ## 1. Goal The project is a simplified Modula-2-like compiler implemented in GNU Modula-2. The language is intentionally smaller than full Modula-2: - no procedures or functions - `INTEGER` and `CHAR` types - variables and constants as supported by the compiler - basic statements and expressions - symbol table - type checking - code generation The objective is to have a real compiler pipeline rather than only a parser. ## 2. Compiler architecture The compiler follows this pipeline: ```text MiniM2 source | v +-----------+ | Lexer | +-----------+ | v +-----------+ | Parser | +-----------+ | v +----------------+ | Symbol table | | Type checking | +----------------+ | v +----------------+ | Code generator | +----------------+ | v Generated GNU Modula-2 | v +-----------+ | gm2 | +-----------+ | v Native executable ``` The compiler itself is written in GNU Modula-2. ## 3. Why GNU Modula-2 is used as the backend Coco/R has traditionally provided compiler-generator targets such as C#, Java and C++, but GNU Modula-2 is not a standard Coco/R target. Instead of trying to make Coco/R generate GNU Modula-2 code, the compiler can be implemented directly in GNU Modula-2. The first native backend is source-to-source: 1. Parse the MiniM2 program. 2. Build and check its symbols and types. 3. Generate valid GNU Modula-2. 4. Invoke `gm2`. 5. Let GNU Modula-2 produce the final native executable. This is already a genuine compiler architecture: the front-end performs lexical analysis, parsing and semantic checking, while GNU Modula-2 acts as the native backend. ## 4. GNU Modula-2 GNU Modula-2 is provided by GCC. Typical compilation is: ```bash gm2 -g hello.mod ``` GNU Modula-2 uses `.mod` files for implementation/program modules and `.def` files for definition modules. The generated program can therefore be compiled by the GNU Modula-2 compiler. ## 5. Project layout The generated project is: ```text mini-modula2-real-compiler/ ├── MiniM2C.mod ├── Makefile ├── README.md └── examples/ ├── hello.mod └── bad.mod ``` `MiniM2C.mod` contains the compiler implementation. `examples/hello.mod` is a valid example program. `examples/bad.mod` is intended to demonstrate semantic/type errors. ## 6. Building From the project directory: ```bash make ``` The compiler executable is intended to be: ```text minim2c ``` A MiniM2 source file can then be compiled with: ```bash ./minim2c examples/hello.mod ``` The compiler generates a GNU Modula-2 source file: ```text examples/hello.mod.gen.mod ``` and then invokes `gm2` to build the native executable. The exact executable name can depend on the generated module and GNU Modula-2 toolchain. ## 7. Running the example The intended workflow is: ```bash cd mini-modula2-real-compiler make ./minim2c examples/hello.mod ./mini-program ``` If the generated executable has a different name, use the executable name reported by the compiler or inspect the generated build output. ## 8. Lexer The lexer converts source characters into tokens. Typical token categories include: - identifiers - integer literals - character literals - operators - punctuation - keywords Examples of keywords include: ```text MODULE BEGIN END VAR CONST INTEGER CHAR READ WRITE IF THEN ELSE WHILE DO ``` The lexer is responsible for recognizing these tokens before parsing. ## 9. Parser The parser consumes the token stream and verifies that the program follows the MiniM2 grammar. A simplified structure is: ```text Module = MODULE identifier ; declarations BEGIN statements END identifier . ``` Expressions are parsed according to precedence. For example: ```text a + b * c ``` must be interpreted as: ```text a + (b * c) ``` rather than: ```text (a + b) * c ``` ## 10. Symbol table The symbol table records declared identifiers. For each identifier the compiler can keep information such as: ```text name kind type ``` For example: ```text x : INTEGER letter : CHAR ``` When an identifier is used, the compiler looks it up in the symbol table. This allows the compiler to detect errors such as: ```text unknown variable duplicate declaration ``` ## 11. Type checking The semantic phase checks that expressions and statements use compatible types. Examples: ```text INTEGER + INTEGER ``` is valid. But: ```text INTEGER + CHAR ``` is rejected by the type checker. Assignments are also checked. For example: ```text VAR x : INTEGER; c : CHAR; ``` Then: ```text x := 10; ``` is valid, while: ```text x := c; ``` should produce a type error. ## 12. Code generation The current backend generates GNU Modula-2 source. For example, an internal MiniM2 construct such as: ```text x := 10; ``` can be emitted as GNU Modula-2: ```modula2 x := 10; ``` The generated source is then compiled by `gm2`. This approach makes the compiler relatively small while still producing native executables. ## 13. Important backend limitation The first implementation is deliberately simple. In particular, the initial `WRITE` implementation supports only simple operands such as an identifier or literal rather than every possible expression. For example, this may be supported: ```text WRITE(x); ``` while something such as: ```text WRITE(x + 1); ``` requires an expression-aware `WRITE` code-generation path. That is one of the natural next improvements. ## 14. Error handling The compiler should report lexical, syntactic and semantic errors. Examples: ```text unexpected token expected identifier undeclared identifier duplicate declaration type mismatch ``` A useful future improvement is to preserve exact source line and column information for every token and report errors like: ```text example.mod:12:7: type mismatch ``` ## 15. Why this is a real compiler A compiler does not have to directly emit machine instructions itself. A common architecture is: ```text source -> front-end -> intermediate representation / generated source -> backend compiler -> object code -> executable ``` In this project, GNU Modula-2 is the backend. The compiler therefore performs real compilation work: - lexical analysis - syntax analysis - symbol resolution - semantic/type checking - code generation - native compilation ## 16. Future evolution A stronger version can evolve toward: ### AST Instead of immediately generating code while parsing, build an Abstract Syntax Tree: ```text Module ├── Declarations └── Statements ├── Assignment ├── If ├── While └── Write ``` ### Intermediate representation The AST can then be converted into an IR. For example: ```text LOAD_CONST 10 STORE x ``` or: ```text LOAD x LOAD 1 ADD STORE x ``` ### Better code generation The IR can then be translated to: - GNU Modula-2 - C - LLVM IR - assembly - another native backend ### More language features Possible additions include: - `BOOLEAN` - arrays - records - `FOR` - richer `IF` - richer `WHILE` - modules and definition modules - procedures - functions - parameters - standard library support ## 17. Relation to the Theia extension The compiler and the Theia Modula-2 extension can eventually be integrated. Theia can provide: - syntax highlighting - indentation - keyword uppercasing - snippets - diagnostics - build commands - compiler invocation - error navigation The compiler can provide: - parsing - semantic analysis - type checking - code generation - executable generation A future language-server integration could expose compiler diagnostics directly in the editor. ## 18. Automatic keyword uppercasing The Theia extension has a separate editor feature for automatic Modula-2 keyword uppercasing. The required behavior is: > Only the keyword currently being typed is converted to uppercase. It should not uppercase unrelated existing text in the document. For example, when typing: ```text mod ``` the editor can turn the current keyword into: ```text MOD ``` without modifying other words. ## 19. Snippets The Theia extension can also provide Modula-2 snippets. Typical snippets can accelerate constructs such as: ```modula2 MODULE ...; BEGIN ... END ... . ``` or declarations and control structures. Snippets are normally triggered through the editor's completion/snippet mechanism. ## 20. Verification status The project was generated as a GNU Modula-2 compiler prototype. It should not be described as production-ready without compiling and testing it with an installed GNU Modula-2 (`gm2`) toolchain. The development environment used to prepare the project did not have `gm2` available, so the generated compiler was not actually built and executed there. Before treating it as a finished compiler, install GNU Modula-2 and run: ```bash gm2 --version make ./minim2c examples/hello.mod ``` Then test both successful programs and intentionally invalid programs. ## 21. Recommended next step The most useful next improvement is to make the compiler robust enough to compile its complete test suite under GNU Modula-2. After that, the compiler can be upgraded from the simple source-to-source backend to: ```text Lexer -> Parser -> AST -> Symbol table -> Type checker -> IR -> Code generator -> Native executable ``` This provides a cleaner foundation for adding the full set of desired Modula-2 features.