|
|
@@ -1,548 +0,0 @@
|
|
|
-# 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.
|