Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COOL Compiler #69

Open
wants to merge 178 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
284b700
Added lexer and related errors
Apr 28, 2021
e988421
Defined compiler main entry point
Apr 28, 2021
5722e34
Lexer passed all tests
Apr 29, 2021
9a2e6db
Reestructured project and parsing tests passed
Apr 30, 2021
52819a0
Added missing files in previous commit
Apr 30, 2021
f214396
Fixed test error file for class1.cl
svex99 Feb 17, 2022
42bf096
Passed semantic tests
svex99 Feb 17, 2022
0f68946
Added SPIM manual
svex99 Feb 17, 2022
b931e14
build: Add ply to
samueldsr99 Feb 18, 2022
51c3532
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
svex99 Feb 18, 2022
b958447
Project refactoring & CIL working
svex99 Feb 20, 2022
4b1e953
Added more nodes to CIL
svex99 Feb 22, 2022
67312d7
Added more nodes to CIL formatter
svex99 Feb 22, 2022
626f9aa
Fixed bug with empty string in CIL
svex99 Feb 22, 2022
2da7c85
fix: Initilize void
svex99 Feb 22, 2022
69360c6
feat: Add mips ast
samueldsr99 Feb 22, 2022
d1e3371
feat: Add registers utils
samueldsr99 Feb 22, 2022
ca53d0f
feat: Add mips visitor & formatter
samueldsr99 Feb 22, 2022
a002d5d
expose `build_mips` method
samueldsr99 Feb 22, 2022
febce30
fix: repeated in locals
svex99 Feb 23, 2022
c63fa4b
feat: Add some shitty code
samueldsr99 Feb 23, 2022
6191a97
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
samueldsr99 Feb 23, 2022
a53a475
feat: Append `mips` to `coolc.py`
samueldsr99 Feb 23, 2022
24f98ad
Added mips instructions pdf
svex99 Feb 23, 2022
ec432de
refactor: Add type annotations
samueldsr99 Feb 23, 2022
c43cdf7
refactor: Add typing annotations on `registers`
samueldsr99 Feb 23, 2022
698fa4f
refactor: Move some register methods to `mips.py`
samueldsr99 Feb 23, 2022
0cc81f6
refactor: fixed annotations of mips.py classes
svex99 Feb 23, 2022
fc6d553
Merged samuel changes
svex99 Feb 23, 2022
98f57ff
refactor: Fix some shitty code
samueldsr99 Feb 23, 2022
40f388c
build: Update `.gitignore`
samueldsr99 Feb 23, 2022
ec53ad7
build: Update `makefile`
samueldsr99 Feb 23, 2022
3a6be9d
fix: Fix new names for `mip` classes
samueldsr99 Feb 23, 2022
b0a0b0f
feat: Update `FunctionNode` in cli2mips visitor
samueldsr99 Feb 23, 2022
cc90fe8
Add test cil
svex99 Feb 23, 2022
24cea3e
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
svex99 Feb 23, 2022
be26052
fix: Fix string representations on mips formatter
samueldsr99 Feb 23, 2022
7792745
fix: Remove UUID generation on mips
samueldsr99 Feb 23, 2022
cb428b3
fix: Bug in CILFormatter with DataNode
svex99 Feb 23, 2022
687453f
refacto: Change name of entry to main
svex99 Feb 24, 2022
c350244
Implemented basic type as objects & setted functions as attributes
svex99 Feb 24, 2022
e9ee2d4
fix: Fix mips formatter on strings
samueldsr99 Feb 24, 2022
a495f9d
feat: Add methods for get offset address on Types
samueldsr99 Feb 24, 2022
bdcee08
refactor: Remove `RegisterLocation`
samueldsr99 Feb 24, 2022
1fe0120
refactor: Remove `FP` from methods return
samueldsr99 Feb 24, 2022
c271746
feat: Add `templates` logic for mips base code
samueldsr99 Feb 24, 2022
d8f587f
Improved CIL
svex99 Feb 24, 2022
d6ec7d6
Implemented basic type as objects & setted functions as attributes
svex99 Feb 24, 2022
0c4dcef
Improved CIL
svex99 Feb 24, 2022
476661b
Merge branch 'all-obj' of https://github.com/Team-Secrett/cool-compil…
samueldsr99 Feb 24, 2022
861c322
fix: Change name of type void to 'Void'
svex99 Feb 24, 2022
0ba8fa4
Merge branch 'all-obj' of https://github.com/Team-Secrett/cool-compil…
samueldsr99 Feb 24, 2022
7abddfd
feat: Add `PlusNode`
samueldsr99 Feb 24, 2022
b5616ce
feat: Add prototypes and dispatch labels
samueldsr99 Feb 24, 2022
11d5b6d
feat: Add `copy.mips` template & add spaces to `malloc.mips`
samueldsr99 Feb 24, 2022
779aae7
refactor: Remove unnecesary comments
samueldsr99 Feb 24, 2022
34ec4f9
feat: Add more basic functions
svex99 Feb 24, 2022
e327aeb
Merge branch 'all-obj' of https://github.com/Team-Secrett/cool-compil…
samueldsr99 Feb 24, 2022
2dc5ab6
fix: Fix CIL visitor. Add more nodes to CIL
svex99 Feb 24, 2022
1765295
fix: Fix default types attributes name
svex99 Feb 24, 2022
1f05c46
Merge branch 'all-obj' of https://github.com/Team-Secrett/cool-compil…
samueldsr99 Feb 24, 2022
fe4393e
feat: Add new mips nodes & create object method
samueldsr99 Feb 24, 2022
3bc3956
feat: Add `Allocate` & `Load` logic
samueldsr99 Feb 25, 2022
b6500fa
feat: print templates
samueldsr99 Feb 25, 2022
5420fd3
feat: Add formatter for new mips nodes
samueldsr99 Feb 25, 2022
4cfef11
feat: Add AssignNode in mips visitor
svex99 Feb 25, 2022
95af326
Upload test examples
samueldsr99 Feb 25, 2022
6353a6f
Merge branch 'all-obj' of https://github.com/Team-Secrett/cool-compil…
samueldsr99 Feb 25, 2022
39479d0
refactor: Improve formatter code for show registers
samueldsr99 Feb 26, 2022
aa84780
refactor: Add method add_inst to cil2mips visitor
svex99 Feb 26, 2022
9776002
fix: Remove type names from cil .data
svex99 Feb 26, 2022
429691a
feat: Add new types template on mips file
samueldsr99 Feb 26, 2022
2b3d4d0
Add ReturnNode to cil2mips and basic MinusNode
svex99 Feb 26, 2022
0b71607
fix: Fix `ReturnNode` logic
samueldsr99 Feb 26, 2022
830bdb3
feat: Add test for sum
samueldsr99 Feb 26, 2022
6147a7d
feat: Add build_init method
svex99 Feb 27, 2022
a39d093
feat: Added inits to formatter
svex99 Feb 27, 2022
731b7a7
fix: Bug with type pointer in init
svex99 Feb 27, 2022
5d29a47
feat: Add a lot of stuff not working yet
svex99 Feb 28, 2022
fa74bc7
fix: Bug with method names
svex99 Mar 1, 2022
7e6d1bd
fix: Invert params address offsets
samueldsr99 Mar 2, 2022
d962aaa
fix: Add self as ArgNode in cil
svex99 Mar 2, 2022
5faeaa9
fix: Fix bug with names in .data in inheritance
svex99 Mar 2, 2022
0306451
fix: Fixed set attribute in mips
svex99 Mar 2, 2022
936d6d0
semifix: Work in out_string mips code
svex99 Mar 2, 2022
ddf1cf0
fix: Fix `PrintStringNode` in `cil2mips_visitor`
samueldsr99 Mar 2, 2022
b723597
fix: Fix error retrieving string address
samueldsr99 Mar 2, 2022
17f61ec
feat: Add get attr to mips visitor
svex99 Mar 3, 2022
03f56bb
fix: Fix error when settatr int value
samueldsr99 Mar 3, 2022
042ef97
refactor: Change `jal` register jumps to `jalr`
samueldsr99 Mar 3, 2022
e4098c1
feat: Work on substring instruction
samueldsr99 Mar 3, 2022
b3c627b
feat: Add `jalr` node
samueldsr99 Mar 3, 2022
c8e78eb
fix: Fix default function nodes en cil
svex99 Mar 3, 2022
5f327cf
feat: Add substring method
samueldsr99 Mar 3, 2022
641ce3b
Merge conflict
svex99 Mar 3, 2022
c17f6cf
fix: Fix string representation error
samueldsr99 Mar 3, 2022
db584fd
fix: Fixed type_name in mips
svex99 Mar 3, 2022
15c6174
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
samueldsr99 Mar 3, 2022
d32ad97
feat: Add printint
samueldsr99 Mar 3, 2022
c2edcaa
feat: Finish plus and minus node
samueldsr99 Mar 3, 2022
55abafd
refactor: Remove unused prints
samueldsr99 Mar 3, 2022
6bfecbe
feat: Add isvoid to mips
svex99 Mar 3, 2022
32a635b
fix: Add template file isvoid.mips
svex99 Mar 3, 2022
87dc2e7
Undo changes to test file
svex99 Mar 3, 2022
17b2398
refactor: Refact assign node in mips
svex99 Mar 4, 2022
e5038fa
fix: Missed visit to 'in' expression in cool2cil visitor
svex99 Mar 4, 2022
c13cc9a
refactor: Remove shitty code
samueldsr99 Mar 4, 2022
3ef6098
build: Setup `coolc.sh` for tests
samueldsr99 Mar 4, 2022
3c780a0
refactor: Change register names
samueldsr99 Mar 4, 2022
3184d1e
feat: `out_string` & `out_int` returns IO
samueldsr99 Mar 4, 2022
161f88c
feat: Add gotoif & fix bug in amount of args poped
svex99 Mar 4, 2022
7064ded
feat: Add `ReadIntNode` visitor
samueldsr99 Mar 6, 2022
4b4b5f2
feat: Add `LengthNode` visitor
samueldsr99 Mar 6, 2022
c271d4c
feat: Add `ConcatNode`
samueldsr99 Mar 6, 2022
c6efdee
feat: Add `AbortNode`
samueldsr99 Mar 6, 2022
e5cc908
feat: Setup for tests
samueldsr99 Mar 6, 2022
336ef54
Add inits as function nodes
svex99 Mar 5, 2022
7cf888f
fix: Fix set attr in inits
svex99 Mar 5, 2022
d7eb412
fix: Put main as first function
svex99 Mar 6, 2022
5e518a8
fix: Fix error with inits
svex99 Mar 7, 2022
44db03b
refactor: Remove commented code
svex99 Mar 7, 2022
c95800e
build: Solve merge conflicts
samueldsr99 Mar 7, 2022
0085176
Merge branch 'feat/utils'
samueldsr99 Mar 7, 2022
d000e89
feat: Finish `ReadStringNode`
samueldsr99 Mar 7, 2022
3cac5b6
feat: Add comparison operators
svex99 Mar 7, 2022
ab03234
--amend
svex99 Mar 7, 2022
c65daae
Merge commit
svex99 Mar 8, 2022
c6a3b24
feat: Add complement
svex99 Mar 8, 2022
48c3747
feat: Add parents to type definitions in mips
svex99 Mar 8, 2022
d801533
feat: Add `StartNode` & `DivNode`
samueldsr99 Mar 8, 2022
a357bfc
feat: Add `NegateNode`
samueldsr99 Mar 8, 2022
98f72a7
fix: Fix some nodes
samueldsr99 Mar 8, 2022
7dcfd4f
fix: Fix scopes and set attr in methods
svex99 Mar 8, 2022
1740be1
fix: Fix bug with scope of let in
svex99 Mar 9, 2022
0a3c305
feat: Work on `CaseNode`
samueldsr99 Mar 9, 2022
59c3d3d
feat: Handle runtime errors on `CaseNode`
samueldsr99 Mar 9, 2022
12d2e27
fix: Parent position in mips types
svex99 Mar 9, 2022
c8b9971
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
svex99 Mar 9, 2022
bb928f7
fix: Push args in reverse order
svex99 Mar 9, 2022
6848238
feat: Add static dispatch
svex99 Mar 9, 2022
94caa94
feat: Work on `CaseNode`
samueldsr99 Mar 10, 2022
1659f1b
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
samueldsr99 Mar 10, 2022
45c5c73
fix: Fix error on `SubstringNode`
samueldsr99 Mar 10, 2022
93b0154
fix: Fix scope error on `CaseNode`
samueldsr99 Mar 10, 2022
282f6ec
fix: Add a scope for every case branch
svex99 Mar 10, 2022
3589ed1
fix: Fix instatiation with new of Int, String and Bool types
svex99 Mar 10, 2022
853d9a7
fix: Fix uncontrolled exception in semantic analysis
samueldsr99 Mar 10, 2022
c28c152
semifix: Avoid use self as instance in init
svex99 Mar 10, 2022
7f480ce
fix: Fix init self reference & if else visitor in cil
svex99 Mar 10, 2022
aa49e0b
fix: Return expr in casenode
samueldsr99 Mar 10, 2022
2bedc48
fix: Add self to class scope
svex99 Mar 10, 2022
ce011ca
fix: Fix return type of `CaseNode`
samueldsr99 Mar 10, 2022
45fee63
fix: Fix invocations in init
svex99 Mar 11, 2022
6154edc
fix: Sort case branches in casenode
samueldsr99 Mar 11, 2022
42d6f3e
fix: Fix remove_eol
samueldsr99 Mar 11, 2022
de4f129
fix: Fix `ComplementNode`
samueldsr99 Mar 11, 2022
879a36e
fix: Collect attributes before visitor
samueldsr99 Mar 11, 2022
9392fbd
fix: Fix malloc function
samueldsr99 Mar 11, 2022
13716ca
fix: Fix scopes of inherited attributes
svex99 Mar 11, 2022
eaee769
build: Merge conflicts
svex99 Mar 11, 2022
35fbed1
fix: Fix casenode
samueldsr99 Mar 11, 2022
35dd29f
fix: ALL GREEEENmake testmake test
svex99 Mar 11, 2022
efe7e61
build: Reverted change to test output
svex99 Mar 11, 2022
ba3c600
build: Create & work on `report.md`
samueldsr99 Mar 11, 2022
339ecec
build: Add documentation in Readme
svex99 Mar 11, 2022
e360734
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
svex99 Mar 11, 2022
bb287ea
doc: Update `report.md`
samueldsr99 Mar 11, 2022
a6c7904
doc: Update `report.md`
samueldsr99 Mar 11, 2022
b05547d
build: Add documentation
svex99 Mar 11, 2022
354c251
build: Add documentation
svex99 Mar 11, 2022
d19a64d
build: More doc
svex99 Mar 11, 2022
0884606
Fix typos
svex99 Mar 11, 2022
26b00b4
doc: Remove TODOs
samueldsr99 Mar 12, 2022
0468f7b
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
samueldsr99 Mar 12, 2022
daf68c5
Add instrucitons to report
svex99 Mar 12, 2022
2096194
Merge branch 'master' of https://github.com/Team-Secrett/cool-compile…
samueldsr99 Mar 12, 2022
9e372b7
doc: Add `report.pdf`
samueldsr99 Mar 12, 2022
413f799
fix: Change path of .mips file to the same of the .cl file
svex99 Mar 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,8 @@ dmypy.json

# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)

env/
.idea/

settings.json
code.mips
Binary file added doc/MIPS_Instruction_Set.pdf
Binary file not shown.
46 changes: 27 additions & 19 deletions doc/Readme.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
# Documentación

## Readme
## Como usar el compilador

Modifique el contenido de este documento para documentar de forma clara y concisa los siguientes aspectos:
Para compilar un fichero de COOL se puede usar el comando:

- Cómo ejecutar (y compilar si es necesario) su compilador.
- Requisitos adicionales, dependencias, configuración, etc.
- Opciones adicionales que tenga su compilador.
```
python3 coolc.py "path/to/file.cl"
```

## Sobre los Equipos de Desarrollo
Este compila el fichero `file.cl` y almacena el código generado en un fichero del mismo nombre pero pero con extension `.mips`.

Para desarrollar el compilador del lenguaje COOL se trabajará en equipos de 2 o 3 integrantes. El proyecto de Compilación será recogido y evaluado únicamente a través de Github. Es imprescindible tener una cuenta de Github para cada participante, y que su proyecto esté correctamente hosteado en esta plataforma.
Se pueden consultar las demás opciones de la línea de comandos para el compilador ejecutando `python3 coolc.py -h`.

**⚠️ NOTA**: Debe completar el archivo `team.yml` con los datos correctos de cada miembro de su equipo.
```
usage: coolc.py [-h] [--out OUT] [--run | --no-run] [--verbose | --no-verbose] file

## Sobre los Materiales a Entregar
positional arguments:
file COOL source file.

Para la evaluación del proyecto Ud. debe entregar un informe en formato PDF (`report.pdf`) en esta carpeta, que resuma de manera organizada y comprensible la arquitectura e implementación de su compilador.
El documento no tiene límite de extensión.
En él explicará en más detalle su solución a los problemas que, durante la implementación de cada una de las fases del proceso de compilación, hayan requerido de Ud. especial atención.
optional arguments:
-h, --help show this help message and exit
--out OUT Name for .mips generated file after compilation.
--run, --no-run Execute the file compiled with SPIM. (default: False)
--verbose, --no-verbose
Verbose output. (default: False)
```

## Estructura del reporte
- `--out`: modifica el fichero de salida para el `.mips` generado, que por defecto es creado con el mismo nombre del fichero de COOL.
- `--run`: facilita la ejecución del programa escrito en COOL ejecutando automáticamente el fichero `.mips` de salida. Para realizar dicha acción es necesario tener `spim` instalado y en el path.
- `--verbose`: imprime en consola el AST generado después de concluido el análisis lexico, parsing y análisis semántico, asi como el código intermedio (CIL) generado previamente a la generación de código final.

Usted es libre de estructurar su reporte escrito como más conveniente le parezca. A continuación le sugerimos algunas secciones que no deberían faltar, aunque puede mezclar, renombrar y organizarlas de la manera que mejor le parezca:
## Requerimientos

- **Uso del compilador**: detalles sobre las opciones de líneas de comando, si tiene opciones adicionales (e.j., `--ast` genera un AST en JSON, etc.). Básicamente lo mismo que pondrá en este Readme.
- **Arquitectura del compilador**: una explicación general de la arquitectura, en cuántos módulos se divide el proyecto, cuantas fases tiene, qué tipo de gramática se utiliza, y en general, como se organiza el proyecto. Una buena imagen siempre ayuda.
- **Problemas técnicos**: detalles sobre cualquier problema teórico o técnico interesante que haya necesitado resolver de forma particular.
### Ambiente de ejecución

## Sobre la Fecha de Entrega
El proyecto fue desarrollado y probado bajo un ambiente en `Python 3.9.5`, asi que se espera compatibilidad con esta version y superiores (`3.9+`). No se garantiza la correctitud del compilador o que este sea ejecutable en versiones inferiores.

Se realizarán recogidas parciales del proyecto a lo largo del curso. En el Canal de Telegram se anunciará la fecha y requisitos de cada entrega.
### Dependencias

La única dependencia del compilador es `ply==3.11`, la cual puede ser instalada ejecutando el comando `python3 -m pip install ply==3.11`.
Binary file added doc/SPIM_Manual.pdf
Binary file not shown.
161 changes: 161 additions & 0 deletions doc/report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# Proyecto de compilación

## Integrantes

- Enmanuel Verdesia Suárez C-411
- Samuel David Suárez Rodríguez C-412

## Instalación / Ejecución

Para compilar un fichero de COOL se puede usar el comando:

```
python3 coolc.py "path/to/file.cl"
```

Este compila el fichero `file.cl` y almacena el código generado en un fichero del mismo nombre pero pero con extension `.mips`.

Se pueden consultar las demás opciones de la línea de comandos para el compilador ejecutando `python3 coolc.py -h`.

```
usage: coolc.py [-h] [--out OUT] [--run | --no-run] [--verbose | --no-verbose] file

positional arguments:
file COOL source file.

optional arguments:
-h, --help show this help message and exit
--out OUT Name for .mips generated file after compilation.
--run, --no-run Execute the file compiled with SPIM. (default: False)
--verbose, --no-verbose
Verbose output. (default: False)
```

- `--out`: modifica el fichero de salida para el `.mips` generado, que por defecto es creado con el mismo nombre del fichero de COOL.
- `--run`: facilita la ejecución del programa escrito en COOL ejecutando automáticamente el fichero `.mips` de salida. Para realizar dicha acción es necesario tener `spim` instalado y en el path.
- `--verbose`: imprime en consola el AST generado después de concluido el análisis lexico, parsing y análisis semántico, asi como el código intermedio (CIL) generado previamente a la generación de código final.

### Requerimientos

El proyecto fue desarrollado y probado bajo un ambiente en `Python 3.9.5`, asi que se espera compatibilidad con esta version y superiores (`3.9+`). No se garantiza la correctitud del compilador o que este sea ejecutable en versiones inferiores.

La única dependencia del compilador es `ply==3.11`, la cual puede ser instalada ejecutando el comando `python3 -m pip install ply==3.11`.


## Arquitectura

Para la implementación del compilador de `COOL` se dividió el proceso de desarrollo en las etapas siguientes:

- Análisis Sintáctico
- Lexing
- Parsing
- Análisis Semántico
- Recolección de tipos (Type collection)
- Construcción de tipos (Type building)
- Chequeo de tipos (Type checking)
- Generación de código (Code generation)
- COOL -> CIL
- CIL -> MIPS

## Lexing

Para el análisis léxico se utilizó el módulo `ply` de `Python`, el cual permite generar esta parte del proceso de manera automática simplemente definiendo el conjunto de tokens del lenguaje.

Se emplearon dos estados exclusivos para el automata además del incial, uno para tokenizar los string y otros para los comentarios que ocupan multiples líneas.

Al concluir esta fase se obtuvo cada uno de los tokens relevantes involcrados en el código fuente, estos almacenan su lexema y tipo de token.

## Parsing

De igual manera se utilizó `ply` para la fase de parsing debido a que soporta varios tipos de parsers como el parser `LALR(1)` que resuelve de manera eficiente la gramática de `COOL`, esta gramática se definió en base al manual oficial de `COOL` [cool-manual](./cool-manual.pdf), definida en su página 16.

En esta fase se estableció la precedencia de los operadores de acuerdo al manual en la sección 11.1. Se establecieron las reglas de la gramática de forma apropiada para obtener el AST una vez finalizado el proceso de parsing de los tokens y asegurar que cada nodo almacena la línea y columna correspondiente al token, esto permite mejorar la información de los errores en el chequeo semántico.

## Recolección de tipos

Esta fase se encarga de recorrer el AST generado previamente y definir los tipos del lenguaje. Entre estos tipos tenemos los BUILT_IN (Bool, String, Int, IO, Object), así como los tipos definidos en el código por el usuario en las declaraciones de clases. En un recorrido posterior se realiza el chequeo y asignación de padres de tipos, debido a que en el lenguaje las declaraciones de clases se pueden encontrar en cualquier orden, por lo que es necesario recolectar los tipos primeramente. En esta fase se resuelven también las excepciones de herencia cíclica.

La lógica para esta fase se implementó en el archivo `collector.py`

## Construcción de tipos

En esta fase se recorre el AST con el objetivo de visitar cada `feature`(método o atributo) de las clases para asignarla a cada tipo y chequear la existencia de una clase `Main` con el método `main`.

La lógica para esta fase se implementó en el archivo `builder.py`

## Chequeo de tipos

Esta fase es la encargada de validar el uso correcto de los tipos definidos en el programa y detectar otros errores definidos dentro de la semántica de COOL, estos errores con su correspondiente descripcion pueden ser encontrados bajo el fichero `errors.py`.

Por ejemplo entre ellos se encuentran:
- Verificar que las asignaciones de las variables sea el tipo adecuado a su definición, así como los argumentos de funciones.
- `self` es de solo lectura.
- no violar el número de argumentos y los tipos de estos cuando se sobreescribe una función.
- No usar variables que no estén definidas previamente en el contexto.
- Evitar herencia de los tipos Int, String y Bool.
- Verificar el correcto uso de los operadores +, -, /, *, <, <=, =, etc.
- Evitar ramas duplicadas en el `case of`.

En este recorrido sobre el AST además se crea el scope del programa para cada una de las clases, funciones, el `let in` y el `case of`. Los scopes establecen una jerarquía de herencia, de tal forma que el scope de una clase es hijo del scope de la clase que esta hereda, el scope de una función es hijo del scope de la clase en que esta se encuentra definida y los scopes de los `let in` y `case of` son hijos del scope del contexto en que se encuentren.

Los scopes permiten ocultar las definiciones de variables de los contextos superiores. La salida de este recorrido sobre el AST es el scope raíz resultante de la visita a cada uno de los nodos.

La lógica para esta fase se implementó en el archivo `checker.py`

## Generación de código intermedio COOL -> CIL

Para compilar el código en `COOL` a un lenguaje de bajo nivel como `MIPS`, se utilizó un lenguaje intermedio para disminuir la dificultad en la generación de código entre estas dos partes. Para ello definimos un pseudolenguaje (`CIL`) que posee elementos similares al estudiado en clase más algunos agregados y permiten controlar de una manera más sencilla el flujo del programa al generar el código en `MIPS`. Entre estos añadidos tenemos:

- Abort

`ABORT`: Termina el programa con un mensaje indicando el tipo desde el cual se llamó esta instrucción.

- Errores en tiempo de ejecución:

`CASE_MATCH_RUNTIME_ERROR`: Devuelve un error en tiempo de ejecución con el mensaje `"RuntimeError: Case statement without a match branch"`. Se usa en las expresiones de tipo case of cuando ninguna rama conforma el resultado de la expresión.

`EXPR_VOID_RUNTIME_ERROR`: Devuelve un error en tiempo de ejecución con el mensaje: `"RuntimeError: Expression is void"`. Usado para controlar excepciones con expresiones de tipo `void`

- Conforms

`<var> = CONFORMS <expr> <Type>`: Usada para saber si el resultado de `<expr>` conforma el tipo `<Type>`. Se creó por la necesidad de saber en tiempo de ejecución si el tipo que retorna la expresión en un `case of` podía ser asignado a una rama de un tipo dado.

Dicho esto, se implementaron 2 visitors encargados de generar el código en `CIL`. El primero se encuentra en el archivo `types_data_visitor.py` y es el encargado de definir las secciones `.TYPES` y `.DATA`, en donde se alojarán los tipos definidos en `COOL` y los datos constantes (mensajes de excepción, strings definidos en el código, ...) respectivamente. El segundo visitor encontrado en el archivo `code_visitor.py` se encarga de generar la sección `.CODE` en la cual se encuentra toda la lógica del programa. Ambos visitors fueron encargados de devolver un AST de `CIL` para el próximo paso de generación de código.

### Manejo de `case of`

Este tipo de expresión tuvo un tratamiento especial debido a que la evaluación del tipo de la expresión dentro del `case` se debe realizar en tiempo de ejecución, y en base a esta seleccionar la rama correspondiente como valor de retorno. Para resolver esto hacemos uso de la instrucción definida anteriormente en `CIL`: `CONFORMS`, sin embargo, con esto solo sabemos si el tipo de este resultado conforma el tipo de la rama, pero según la definición del `case of` queremos el tipo más específico que lo cumpla. Esto lo resolvimos reordenando las ramas del case en función a su profundidad en el árbol de tipos de mayor a menor, quedando como primeras ramas las más específicas. De esta manera, la primera rama que cumpla que `CONFORMS <expr> <branch.type>` sea verdadero, es la seleccionada, y será la más específica para ese tipo puesto que las de mayor profundidad ya fueron visitadas, por tanto se hace un salto para esa rama.

## Generación de código intermedio: CIL -> MIPS

Una vez tenemos el AST de `CIL`, solo resta el paso final, generar el código final `MIPS` que será el que se ejecutará desde el emulador `spim`. Para esto definimos un visitor encargado de traducir cada instrucción.

### Representación de Instancias en Memoria

Para representar los objetos de `CIL` en memoria desde `MIPS` usamos la siguiente notación:

```
Type: # Nombre del tipo
.word 4 # Espacio necesario para una instancia de este tipo
.word <Padre> # Label del tipo padre

# Métodos de la instancia
.word Type__init
.word Type__abort
.
.
.
#
.word Type_type_name # Label para direccionar el string del typename
.asciiz "Type" # Typename (String del tipo)
```

Esta definición se encuentra en la sección del `.data` de MIPS y se puede decir que sirve de esqueleto para la las instancias.

Por lo visto anteriormente cada tipo contiene información relacionada con este, como la lista de atributos, métodos, el string correspondiente a su typename, así como una referencia al address del label de su padre. Todos los tipos son tratados como instancias de clases, incluyendo los `BUILT_IN` como `Int, String y Bool` en los que podemos ver su valor en el offset 4 de su dirección. Los métodos se representan con labels que son definidos posteriormente en la sección `.text` de `MIPS`. Existe un label especial llamado `main` que será el encargado de correr el programa, su función es instanciar el tipo `Main` y ejecutar sus instrucciones.

Cada una de las instancias posee como primer atributo un puntero a su tipo correspondiente (ubicado en `.data`). En los bytes continuos almacena cada uno de sus atributos.

Para resolver el método de una instancia primeramente se resuelve el tipo de la instancia, al cual apunta el primer byte de esta. Este puntero más el offset del método permite encontrar el label de la función correspondiente en mips e invocarla.

Todos los procedimientos en mips esperan recibir las instancias por referencia, por tanto realizan internamente el unboxing de los atributos de estas. De igual forma al retornar un tipo Int, String, Bool, se retorna una nueva instancia con su tipo y valor correctamente asignados, no el valor que esta contiene.
Binary file added doc/report.pdf
Binary file not shown.
15 changes: 6 additions & 9 deletions doc/team.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
members:
- name: Nombre Apellido1 Apellido2
github: github_id
group: CXXX
- name: Nombre Apellido1 Apellido2
github: github_id
group: CXXX
- name: Nombre Apellido1 Apellido2
github: github_id
group: CXXX
- name: Samuel David Suarez Rodriguez
github: samueldsr99
group: C412
- name: Enmanuel Verdesia Suarez
github: svex99
group: C411
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pytest
pytest-ordering
ply==3.11
93 changes: 93 additions & 0 deletions src/coolc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""
Main entry point of COOL compiler
"""
import os
import subprocess

from coolcmp.codegen.cil2mips.mips_formatter import MIPSFormatter
from coolcmp.lexing_parsing.lexer import errors as lexer_errors
from coolcmp.lexing_parsing.parser import parser, errors as parser_errors
from coolcmp.semantics import check_semantics
from coolcmp.codegen.cool2cil import build_cil

from coolcmp.codegen.cil2mips import build_mips
from coolcmp.utils.ast_formatter import ASTFormatter
from coolcmp.utils.cil_formatter import CILFormatter

from coolcmp.utils.cil import ProgramNode


def main(filename: str, cool_code: str, run: bool, verbose: bool):
ast = parser.parse(cool_code)

if verbose:
ast_str = ASTFormatter().visit(ast)
print(ast_str)

if lexer_errors:
for error in lexer_errors:
print(error)
exit(1)

if parser_errors:
for error in parser_errors:
print(error)
exit(1)

sem_errors, ctx, scope = check_semantics(ast)
if sem_errors:
for error in sem_errors:
print(error)
exit(1)

cil: ProgramNode
cil = build_cil(ast, ctx, scope)

if verbose:
cil_str = CILFormatter().visit(cil)
print(cil_str)

mips = build_mips(cil, None, None)
mips_str = MIPSFormatter().visit(mips)

mips_file = filename + '.mips'

with open(mips_file, 'w') as fd:
fd.write(mips_str)

if run:
print('=' * 20, 'Running SPIM', '=' * 20)
subprocess.run(['spim', '-f', mips_file])


if __name__ == "__main__":
from argparse import ArgumentParser, FileType, BooleanOptionalAction

arg_parser = ArgumentParser()
arg_parser.add_argument(
'--out', required=False,
help='Name for .mips generated file after compilation.'
)
arg_parser.add_argument(
'--run', default=False, action=BooleanOptionalAction,
help='Execute the file compiled with SPIM.'
)
arg_parser.add_argument(
'--verbose', default=False, action=BooleanOptionalAction,
help='Verbose output.'
)
arg_parser.add_argument(
'file', type=FileType(mode='r', encoding='utf8'),
help='COOL source file.'
)
args = arg_parser.parse_args()

full_name = args.file.name
filename = full_name[:full_name.rfind('.')]
cool_code = args.file.read()
main(
filename=args.out or filename,
cool_code=cool_code,
run=args.run,
verbose=args.verbose
)
12 changes: 5 additions & 7 deletions src/coolc.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Incluya aquí las instrucciones necesarias para ejecutar su compilador

INPUT_FILE=$1
OUTPUT_FILE=${INPUT_FILE:0: -2}mips

# Si su compilador no lo hace ya, aquí puede imprimir la información de contacto
echo "LINEA_CON_NOMBRE_Y_VERSION_DEL_COMPILADOR" # TODO: Recuerde cambiar estas
echo "Copyright (c) 2019: Nombre1, Nombre2, Nombre3" # TODO: líneas a los valores correctos
echo "COOL-Compiler v1.0.0"
echo "Copyright (c) 2021: Samuel David Suárez Rodríguez, Enmanuel Verdesia Suárez"

# echo "Compiling $INPUT_FILE into $OUTPUT_FILE"

# Llamar al compilador
echo "Compiling $INPUT_FILE into $OUTPUT_FILE"
python3 coolc.py $INPUT_FILE
Empty file added src/coolcmp/__init__.py
Empty file.
Empty file added src/coolcmp/codegen/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions src/coolcmp/codegen/cil2mips/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .cil2mips_visitor import CILToMipsVisitor


def build_mips(ast, context, scope):
return CILToMipsVisitor().visit(ast)
Loading