Skip to content

Commit a810fd2

Browse files
authored
Merge pull request #2 from Basigli/copilot/document-project-using-mkdocs
Add MkDocs documentation site with GitHub Pages deployment
2 parents 67120ab + 2f941ea commit a810fd2

File tree

12 files changed

+646
-0
lines changed

12 files changed

+646
-0
lines changed

.github/workflows/docs.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: false
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
25+
- name: Set up Python
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: '3.x'
29+
30+
- name: Install MkDocs and dependencies
31+
run: pip install mkdocs-material
32+
33+
- name: Build documentation
34+
run: mkdocs build --strict
35+
36+
- name: Upload Pages artifact
37+
uses: actions/upload-pages-artifact@v3
38+
with:
39+
path: site/
40+
41+
deploy:
42+
needs: build
43+
runs-on: ubuntu-latest
44+
environment:
45+
name: github-pages
46+
url: ${{ steps.deployment.outputs.page_url }}
47+
steps:
48+
- name: Deploy to GitHub Pages
49+
id: deployment
50+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

22
.idea/*
3+
site/

docs/architecture/ast.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# AST Generation
2+
3+
## Overview
4+
5+
After ANTLR parses the source file it produces a **Parse Tree** whose nodes are ANTLR `Context` objects. `ASTGenerationSTVisitor` traverses this Parse Tree and converts it into a typed **Abstract Syntax Tree (AST)** built from the static inner classes defined in `AST.java`.
6+
7+
## AST Node Hierarchy
8+
9+
All nodes extend the abstract `Node` interface. Each concrete node carries the children and data that are relevant for later phases:
10+
11+
| Node | Description |
12+
|---|---|
13+
| `ProgLetInNode` | Top-level `let … in` program |
14+
| `ProgNode` | Top-level expression-only program |
15+
| `ClassNode` | Class declaration (fields + methods) |
16+
| `FieldNode` | A class field (like a parameter) |
17+
| `MethodNode` | A class method (like a function) |
18+
| `FunNode` | Function declaration |
19+
| `ParNode` | Function parameter |
20+
| `VarNode` | Variable declaration |
21+
| `IdNode` | Identifier use |
22+
| `CallNode` | Function call |
23+
| `ClassCallNode` | Method call (`obj.method(...)`) |
24+
| `NewNode` | Object instantiation (`new C(...)`) |
25+
| `EmptyNode` | `null` literal |
26+
| `PlusNode` / `MinusNode` | Addition / subtraction |
27+
| `TimesNode` / `DivNode` | Multiplication / division |
28+
| `EqualNode` / `GreaterEqualNode` / `LessEqualNode` | Comparison |
29+
| `AndNode` / `OrNode` / `NotNode` | Logical operators |
30+
| `IfNode` | `if / then / else` |
31+
| `PrintNode` | `print(exp)` |
32+
| `IntNode` | Integer literal |
33+
| `BoolNode` | Boolean literal |
34+
35+
## Type Nodes
36+
37+
Type information is represented separately as `TypeNode` subtypes that appear in symbol-table entries:
38+
39+
| Type Node | Meaning |
40+
|---|---|
41+
| `IntTypeNode` | `int` |
42+
| `BoolTypeNode` | `bool` |
43+
| `RefTypeNode` | Reference to a class |
44+
| `EmptyTypeNode` | Type of `null` |
45+
| `ArrowTypeNode` | Function type (only in STentry) |
46+
| `MethodTypeNode` | Method type (only in STentry) |
47+
| `ClassTypeNode` | Class type (maps field/method indices to types) |
48+
49+
## Accept–Visit Cycle
50+
51+
The visitor pattern uses a two-step dispatch:
52+
53+
1. The visitor calls `visit(node)` → delegates to `node.accept(this)`.
54+
2. The node calls `visitor.visitNode(this)` passing its specific type.
55+
56+
This double dispatch allows the visitor to select the correct `visitNode` overload at runtime without explicit casts.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Code Generation
2+
3+
## Overview
4+
5+
`CodeGenerationASTVisitor` translates the type-checked Enriched AST into assembly instructions for the **Stack-based Virtual Machine (SVM)**. The generated code is written to a `.fool.asm` file.
6+
7+
## Target Architecture
8+
9+
The SVM is a simple stack machine with:
10+
11+
- A **stack** for operands and activation records.
12+
- A **heap** for dynamically allocated objects and dispatch tables.
13+
- A **frame pointer (fp)** and **stack pointer (sp)**.
14+
- A **heap pointer (hp)** that grows upward.
15+
16+
## Activation Record Layout
17+
18+
Each function/method call pushes an **activation record (AR)** onto the stack:
19+
20+
```
21+
high address
22+
┌──────────────────┐
23+
│ arguments │ (pushed by caller, right-to-left)
24+
├──────────────────┤
25+
│ return address │
26+
├──────────────────┤
27+
│ control link │ (saved fp of caller)
28+
├──────────────────┤
29+
│ access link │ (fp of statically enclosing scope)
30+
├──────────────────┤
31+
│ local variables │ (pushed by callee)
32+
└──────────────────┘
33+
low address
34+
```
35+
36+
## Object Layout (Heap)
37+
38+
Each object allocated with `new` is stored on the heap:
39+
40+
```
41+
[ dispatch-table pointer ][ field_0 ][ field_1 ] …
42+
```
43+
44+
The **dispatch table** is also stored on the heap and contains one entry per method (the code address of each method).
45+
46+
## Key Code Patterns
47+
48+
### Variable Access
49+
50+
A local variable at nesting level `nl` and offset `off` is reached by following `(current_level − nl)` access links and then loading from `fp + off`.
51+
52+
### Function Call
53+
54+
1. Push arguments.
55+
2. Push the access link (fp of the statically enclosing scope).
56+
3. Jump to the function label.
57+
4. On return, pop the AR.
58+
59+
### Method Dispatch
60+
61+
1. Load the object reference.
62+
2. Load the dispatch-table pointer from offset 0 of the object.
63+
3. Load the method address from the dispatch table at the method's index.
64+
4. Call the method address.
65+
66+
### Object Creation (`new`)
67+
68+
1. Push field values onto the heap.
69+
2. Store the dispatch-table pointer at the base of the new object.
70+
3. Return the object address.

docs/architecture/overview.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Architecture Overview
2+
3+
The FOOL compiler is structured as a classic multi-phase pipeline. Each phase transforms its input and passes the result to the next phase.
4+
5+
```
6+
Source text
7+
8+
9+
┌──────────────┐
10+
│ Lexer & │ ANTLR-generated from FOOL.g4
11+
│ Parser │
12+
└──────┬───────┘
13+
│ Parse Tree
14+
15+
┌──────────────┐
16+
│ AST │ ASTGenerationSTVisitor
17+
│ Generation │
18+
└──────┬───────┘
19+
│ AST (Node hierarchy)
20+
21+
┌──────────────┐
22+
│ Symbol │ SymbolTableASTVisitor
23+
│ Table │
24+
└──────┬───────┘
25+
│ Enriched AST (EAST) – nodes annotated with STentry
26+
27+
┌──────────────┐
28+
│ Type │ TypeCheckEASTVisitor
29+
│ Checking │
30+
└──────┬───────┘
31+
│ Type-checked EAST
32+
33+
┌──────────────┐
34+
│ Code │ CodeGenerationASTVisitor
35+
│ Generation │
36+
└──────┬───────┘
37+
│ SVM assembly
38+
39+
.fool.asm
40+
```
41+
42+
## Key Classes
43+
44+
| Class | Role |
45+
|---|---|
46+
| `FOOL.g4` | ANTLR grammar defining the language syntax |
47+
| `AST.java` | Defines all AST node types as static inner classes |
48+
| `ASTGenerationSTVisitor` | Visits the Parse Tree and builds the AST |
49+
| `SymbolTableASTVisitor` | Builds the symbol table and enriches the AST |
50+
| `TypeCheckEASTVisitor` | Performs type checking on the enriched AST |
51+
| `CodeGenerationASTVisitor` | Generates SVM assembly from the AST |
52+
| `PrintEASTVisitor` | Pretty-prints the enriched AST (debugging aid) |
53+
| `STentry` | Holds a symbol-table entry (type, nesting level, offset) |
54+
| `TypeRels` | Encodes subtype relationships between types |
55+
| `Test` | Entry point: orchestrates all compiler phases |
56+
57+
## Visitor Pattern
58+
59+
All tree-processing phases implement the **Visitor** pattern via `BaseASTVisitor<S, E>`.
60+
Each AST node has an `accept(BaseASTVisitor)` method that calls back the corresponding `visitNode` overload on the visitor, enabling double-dispatch without casts.
61+
62+
See the individual phase pages for deeper details:
63+
64+
- [AST Generation](ast.md)
65+
- [Symbol Table Analysis](symbol-table.md)
66+
- [Type Checking](type-checking.md)
67+
- [Code Generation](code-generation.md)

docs/architecture/symbol-table.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Symbol Table Analysis
2+
3+
## Overview
4+
5+
`SymbolTableASTVisitor` traverses the AST and builds a **symbol table** that maps every identifier to its declaration. It also *enriches* each `IdNode`, `CallNode`, and `ClassCallNode` with a reference to its `STentry`, producing the **Enriched AST (EAST)**.
6+
7+
## Symbol Table Structure
8+
9+
The symbol table is a stack of hash-maps (one map per nesting level):
10+
11+
```
12+
Level 0 (global) { Counter → STentry(ClassTypeNode, 0, 0), … }
13+
Level 1 (function) { x → STentry(IntTypeNode, 1, -1), … }
14+
```
15+
16+
Each `STentry` stores:
17+
18+
| Field | Description |
19+
|---|---|
20+
| `nl` | Nesting level of the declaration |
21+
| `type` | Declared type (`TypeNode`) |
22+
| `offset` | Memory offset in the activation record |
23+
24+
## Static Scoping
25+
26+
The visitor enforces two static-scoping rules:
27+
28+
1. A use of identifier `x` resolves to the declaration in the **most closely enclosing scope** that precedes the use.
29+
2. An inner-scope declaration of `x` **hides** any outer-scope declaration of the same name.
30+
31+
`stLookup(id)` searches from the innermost (current) scope outward, returning the first matching `STentry`.
32+
33+
## Class Table & Virtual Table
34+
35+
For object-oriented features the visitor maintains an additional **class table** (a map from class name to its `STentry`) and, for each class, a **virtual table** (a map from method name to its `STentry`). These are used to:
36+
37+
- Resolve field and method accesses in `ClassCallNode`.
38+
- Build the dispatch table layout used by the code generator.
39+
40+
## Error Handling
41+
42+
The visitor reports semantic errors without aborting, accumulating them in a counter. Detected errors include:
43+
44+
- Undeclared identifier
45+
- Identifier declared twice in the same scope
46+
- Calling a variable as a function
47+
- Using an undeclared class type

docs/architecture/type-checking.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Type Checking
2+
3+
## Overview
4+
5+
`TypeCheckEASTVisitor` traverses the Enriched AST and verifies that every expression has a well-formed type. It returns a `TypeNode` for each node, propagating types bottom-up through the tree.
6+
7+
## Subtype Relations
8+
9+
Type compatibility is determined by `TypeRels.isSubtype(a, b)`:
10+
11+
- `BoolTypeNode` is a subtype of `IntTypeNode` (booleans can be used as integers).
12+
- A class type `C` is a subtype of `D` if `C` extends `D` (directly or transitively).
13+
- `EmptyTypeNode` (`null`) is a subtype of any `RefTypeNode`.
14+
15+
## Key Rules
16+
17+
| Construct | Type Rule |
18+
|---|---|
19+
| `IntNode` | `IntTypeNode` |
20+
| `BoolNode` | `BoolTypeNode` |
21+
| `PlusNode`, `MinusNode`, `TimesNode`, `DivNode` | Both operands must be `int`; result is `IntTypeNode` |
22+
| `AndNode`, `OrNode` | Both operands must be `bool`; result is `BoolTypeNode` |
23+
| `NotNode` | Operand must be `bool`; result is `BoolTypeNode` |
24+
| `EqualNode` | Operands must share a common subtype |
25+
| `GreaterEqualNode`, `LessEqualNode` | Both operands must be `int`; result is `BoolTypeNode` |
26+
| `IfNode` | Condition must be `bool`; result is the **lowest common ancestor** of the two branch types |
27+
| `CallNode` | Argument types must be subtypes of the declared parameter types; result is the function's return type |
28+
| `NewNode` | Argument types must match class field types; result is `RefTypeNode(classID)` |
29+
| `ClassCallNode` | Like `CallNode` but resolves through the virtual table |
30+
| `VarNode` | Declared type must be a supertype of the initialiser type |
31+
| `FunNode` / `MethodNode` | Body type must be a subtype of the declared return type |
32+
33+
## Lowest Common Ancestor
34+
35+
For `if / then / else`, the result type is the lowest common ancestor (LCA) of the two branch types in the subtype hierarchy. For example, if one branch has type `C` and another has type `D` where both extend `Base`, the result type is `Base`.
36+
37+
## Error Reporting
38+
39+
Type errors are printed to standard error and counted. Compilation continues after a type error so that further errors can be reported in the same run.

docs/getting-started.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Getting Started
2+
3+
## Prerequisites
4+
5+
- **Java 8+** (JDK)
6+
- **ANTLR 4** runtime (included in `compiler/lib/`)
7+
- An IDE such as IntelliJ IDEA (optional but recommended)
8+
9+
## Building the Compiler
10+
11+
The project is structured as an IntelliJ IDEA project. Open the root directory in IntelliJ and build with the standard build action, or compile the sources manually:
12+
13+
```bash
14+
javac -cp compiler/lib/antlr-4.7.2-complete.jar compiler/*.java -d out/
15+
```
16+
17+
## Running the Compiler
18+
19+
To compile a `.fool` source file:
20+
21+
```bash
22+
java -cp out/:compiler/lib/antlr-4.7.2-complete.jar Test <source-file>.fool
23+
```
24+
25+
The compiler will:
26+
27+
1. Parse the source file using the ANTLR-generated lexer/parser.
28+
2. Build an AST and enrich it with symbol-table information.
29+
3. Perform type checking.
30+
4. Emit assembly code for the custom stack-based virtual machine (SVM).
31+
32+
The generated assembly is written to `<source-file>.fool.asm`.
33+
34+
## Running the Virtual Machine
35+
36+
Execute the generated assembly with the SVM interpreter:
37+
38+
```bash
39+
java -cp out/:compiler/lib/antlr-4.7.2-complete.jar ExecuteVM <source-file>.fool.asm
40+
```
41+
42+
## Example Programs
43+
44+
Several example `.fool` programs are included in the repository root:
45+
46+
| File | Description |
47+
|---|---|
48+
| `prova.fool` | Basic language features |
49+
| `prova2.fool` | Additional feature tests |
50+
| `quicksort.fool` | Quicksort algorithm |
51+
| `bankloan.fool` | Bank-loan class example |
52+
| `testClass.fool` | Class and method usage |

0 commit comments

Comments
 (0)