-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,768 additions
and
1 deletion.
There are no files selected for viewing
File renamed without changes
File renamed without changes
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# Lab 1 \(COOL\) | ||
|
||
Para este lab, deben hacer los ejercicios que se les pide a continuación, estos ejercicios son bastante básicos y están con el único propósito de que ustedes sepan qué se puede hacer en el lenguaje COOL. Este lab será la única vez en que sea necesario programar en COOL, pero no significa que luego pueda olvidar el lenguaje, ya que para los proyectos es necesario que ustedes sean capaces de crear sus propios archivos de pruebas para probar sus implementaciones. | ||
|
||
## 1. Hola Mundo | ||
|
||
Cree un archivo llamado **hello.cl** e imprima "Hola mundo" en consola. Esto ya lo tenemos en algún ejemplo, escríbalo sin consultar esos archivos. | ||
|
||
## 2. IO | ||
|
||
En un archivo llamado **io.cl**, escriban un programa en COOL que pregunte al usuario su nombre, luego su edad, luego que despliegue el nombre de la persona y cuantos años tendrá al graduarse. \(Sean optimistas, no le sumen tantos años a la edad actual\). | ||
|
||
Su programa debe de funcionar de la siguiente manera: | ||
|
||
```bash | ||
Ingrese su nombre: Pepe | ||
Ingrese su edad: 19 | ||
|
||
Pepe tendrá 22 años al graduarse :) | ||
``` | ||
|
||
## 3. Métodos | ||
|
||
En un archivo llamado **methods.cl**, hagan un programa que le pida al usuario un número en grados Celsius y los convierta en Fahrenheit. Ustedes tiene que crear un método llamado `toFahrenheit` que efectúe esta conversión: | ||
|
||
```kotlin | ||
toFahrenheit(x: Int): Int { | ||
// su codigo aqui | ||
}; | ||
``` | ||
|
||
Su programa debe de funcionar de la siguiente manera: | ||
|
||
```bash | ||
Ingrese grados Celsius: 32 | ||
|
||
32 Celsius son 89 Fahrenheit | ||
``` | ||
|
||
!!!info "Punto flotante" | ||
COOL no tiene punto flotante, por que su implementación no tiene que ser exacta, si por ejemplo el usuario ingresa 32 Celsius, su salida debe de ser 89 Fahrenheit a pesar de que la respuesta exacta es 89.6 | ||
|
||
|
||
## 3. Ciclos | ||
|
||
En un archivo llamado **loop.cl**, escriban un programa que despliegue una tabla de conversion de -50 a 150 grados Celsius hacia grados Fahrenheit en incrementos de 10. Para este ejercico es obligatorio que utilicen un `while`. | ||
|
||
Su programa debe de producir el siguiente resultado: | ||
|
||
```bash | ||
-50 Celsius son -58 Fahrenheit | ||
-40 Celsius son -40 Fahrenheit | ||
-30 Celsius son -22 Fahrenheit | ||
-20 Celsius son -4 Fahrenheit | ||
-10 Celsius son 14 Fahrenheit | ||
0 Celsius son 32 Fahrenheit | ||
10 Celsius son 50 Fahrenheit | ||
20 Celsius son 68 Fahrenheit | ||
30 Celsius son 86 Fahrenheit | ||
40 Celsius son 104 Fahrenheit | ||
50 Celsius son 122 Fahrenheit | ||
60 Celsius son 140 Fahrenheit | ||
70 Celsius son 158 Fahrenheit | ||
80 Celsius son 176 Fahrenheit | ||
90 Celsius son 194 Fahrenheit | ||
100 Celsius son 212 Fahrenheit | ||
``` | ||
|
||
## 4. Calculadora | ||
|
||
En un archivo llamado **calc.cl**, hagan un programa que reciba una string y despliegue el resultado de la operación, las operaciones válidas son: | ||
|
||
* + | ||
* - | ||
* \* | ||
* / | ||
|
||
Su calculadora debería de aceptar operaciones simples como `3 + 4`, `125 - 70`, etc. Noten que el formato siempre es el mismo de acuerdo a la siguiente expresión regular: `( )*[0-9]+( )+[+-*/]( )+[0-9]+( )*`. | ||
|
||
!!!info "Recomendación | ||
Creen un método para buscar espacios. | ||
|
||
Las operaciones que van a ser ingresadas por el usuario siempre son binarias, y no algo como esto: `3 + 2 - 5 / 3 * 2` así que no se compliquen la vida. | ||
|
||
Su programa debe de funcionar de la siguiente manera: | ||
|
||
```bash | ||
>>> 2 + 2 | ||
= 4 | ||
>>> 3 * 2 | ||
= 6 | ||
>>> 6 / 2 | ||
= 3 | ||
>>> 3 - 3 | ||
= 0 | ||
``` | ||
|
||
## 6. Strings | ||
|
||
En un archivo llamado **str.cl**, escriban un programa que le pida al usuario 2 Strings y verifiquen si el segundo String está contenido en el primero. | ||
|
||
Su programa debe de funcionar de la siguiente manera: | ||
|
||
```bash | ||
Ingrese String 1: Anita lava la tina. | ||
Ingrese String 2: lava | ||
|
||
lava está contenido en Anita lava la tina. | ||
|
||
Ingrese String 1: Anita lava la tina. | ||
Ingrese String 2: shampoo | ||
|
||
shampoo no está contenido en Anita lava la tina. | ||
``` | ||
|
||
!!!info "Recomendación" | ||
En el manual de referencia de COOL hay algo que podría ayudarnos, página número 14, en específico el método: `substr(i : Int, l : Int)`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
# Lab 7 \(Análisis Semántico II\) | ||
|
||
En este laboratorio van a continuar con el análisis semántico del lenguaje Viper y así ganar aún más intuición en esta fase del compilador y que plasmar estas ideas en su proyecto sea bastante sencillo. | ||
|
||
Antes de empezar, vamos a obtener los archivos necesarios desde Github Classroom: | ||
|
||
```bash | ||
https://classroom.github.com/a/bs9-cgvz | ||
``` | ||
|
||
!!! danger "" | ||
Por favor lean todas las instrucciones del lab, antes de empezar. | ||
|
||
## Reglas de Inferencia | ||
|
||
Vamos a continuar utilizando el archivo que tiene todas las reglas de inferencia del lenguaje, pueden descargar este archivo aquí: | ||
|
||
[Reglas de inferencia de Viper](../cc4/viper_language_type_rules.pdf) | ||
|
||
### ¿Qué tienen que hacer? | ||
|
||
Como se pudieron dar cuenta en el laboratorio pasado en **src/viper/tree** están definidos los nodos que representan el AST de Viper. En este laboratorio ustedes tienen que completar los 10 nodos restantes, estos nodos son los siguientes: | ||
|
||
1. **Assign** | ||
2. **Call** | ||
3. **Declaration** | ||
4. **Equal** | ||
5. **Id** | ||
6. **If** | ||
7. **LessEqual** | ||
8. **LessThan** | ||
9. **Not** | ||
10. **While** | ||
|
||
!!! danger "Lab anterior" | ||
Ustedes tienen que copiar lo que implementaron en el laboratorio pasado, de lo contrario el autograder no les dará todos los puntos, simplemente tienen que copiar y reemplazar los archivos. | ||
|
||
Para algunos de estos nodos como **LessEqual**, **LessThan**, **Not** su código debería de ser bastante similar a lo que hicieron con las operaciones artiméticas, incluso para **Equal**, solo que aquí tenemos la restricción que ambos operandos tienen que ser del mismo tipo ya sea **int**, **bool** o **str**. Para los demás nodos si van a tener que hacer un par de cosas más. | ||
|
||
Para que tengan una referencia de que tanto tendrían que agregar a los diferentes archivos, aquí están las estadísticas de nuestra implementación: | ||
|
||
```bash | ||
src/viper/tree/Assign.java | 12 +++++++++++- | ||
src/viper/tree/Call.java | 22 +++++++++++++++++++++- | ||
src/viper/tree/Declaration.java | 10 +++++++++- | ||
src/viper/tree/Equal.java | 7 ++++++- | ||
src/viper/tree/Id.java | 8 +++++++- | ||
src/viper/tree/If.java | 11 ++++++++++- | ||
src/viper/tree/LessEqual.java | 7 ++++++- | ||
src/viper/tree/LessThan.java | 7 ++++++- | ||
src/viper/tree/Not.java | 6 +++++- | ||
src/viper/tree/While.java | 8 +++++++- | ||
10 files changed, 88 insertions(+), 10 deletions(-) | ||
``` | ||
|
||
### Implementación | ||
|
||
Para cada nodo del AST hay una serie de pasos que se tienen que realizar para garantizar que el análisis semántico capture todos los errores posibles, recuerden que esta es nuestra última barrera antes de **codegen** para atrapar errores. | ||
|
||
#### Assign | ||
|
||
Para el assign primero deben llamar recursivamente a semant de `e`. Luego verificar que la variable a la se se le está asignando un valor exista en algún scope, si esta variable no existe deberían devolver el siguiente error e indicar que el tipo de la expresión es **void**. | ||
|
||
```java | ||
SemantErrors.cannotFindSymbol(line, col, name); | ||
``` | ||
|
||
!!!info "void" | ||
En general cuando no se pueda recuperar del error y no se le pueda asignar un tipo a una expresión, el tipo de la expresión será **void**. En el proyecto haremos algo similar con **Object**. | ||
|
||
Si la variable a la que se le está asignando un valor existe, pero tiene un tipo diferente que el de la expresión, deberían de devolver el siguiente error: | ||
|
||
```java | ||
SemantErrors.incompatibleTypes(e.line, e.col, e.getType(), t); | ||
// t debería de ser el tipo que devolvio su entorno O | ||
``` | ||
|
||
Como en este error si se pueden recuperar porque si saben cual es el tipo de la variable, tienen que poner que el tipo del nodo es el tipo de la variable. Si ambos tipos coinciden de igual forma tienen que indicar que el tipo del nodo es el tipo de la variable. | ||
|
||
#### Call | ||
|
||
El análisis semántico de **Call** es lo más complicado que realizarán en este laboratorio, primero deberían llamar recursivamente a `semant` de cada **actual** que tenga el nodo, y atrapar sus errores. Luego si la función que se está mandando a llamar no existe deberían de devolver el siguiente error e indicar que el tipo es **void**: | ||
|
||
```java | ||
SemantErrors.cannotFindSymbol(line, col, name); | ||
``` | ||
|
||
!!!info "O" | ||
Van a encontrar útil el entorno **O** en esta parte del laboratorio. | ||
|
||
Si la función si existe, ustedes deberían verificar que la cantidad de argumentos \(actuals\) sea igual a la cantidad de parámetros formales, si no es así devolver el siguiente error: | ||
|
||
```java | ||
SemantErrors.functionCalledWithWrongNumberOfArgs(line, col, name); | ||
``` | ||
|
||
Si ocurre este error todavía es posible recuperarse del error porque sabemos el tipo de retorno de la función, entonces tienen que indicar que el tipo del nodo es el tipo de retorno de la expresión. Por último \(si el tamaño de actuals es igual al de los formals\) deberían de verificar que cada actual sea del mismo tipo, si no es así indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.incompatibleTypes(e.line, e.col, e.getType(), f.type); | ||
``` | ||
|
||
!!!info "Tipo de retorno" | ||
Siempre que sepan que la función existe, el tipo del nodo debería de ser igual al tipo de retorno de la función. | ||
|
||
#### Declaration | ||
|
||
Como este nodo no es una expresión, no es necesario anotarlo con un tipo, de todos modos es necesario hacerle su respectivo análisis semántico. Primero deberían de comenzar llamando recursivamente a `semant` de **init**. Luego verificar que la variable no haya sido declarada ya en el **scope** actual, si ya existe indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.variableIsAlreadyDefined(line, col, name); | ||
``` | ||
|
||
!!!info "Shadowing" | ||
El error anterior solo debería ocurrir si la variable es declarada más de una vez en el scope actual, algo como esto: | ||
|
||
```python | ||
def foo(x: int): void { | ||
int x = 10; | ||
} | ||
``` | ||
|
||
y no en el siguiente caso: | ||
|
||
```python | ||
def foo(x: int): void { | ||
int y = 10; | ||
while (true) { | ||
int y = 20; | ||
} | ||
} | ||
``` | ||
|
||
ya que el lenguaje **Viper**, lastimosamente, permite **shadowing** como en el lenguage **COOL** y otros lenguajes populares como **java** o **C**. ¿Qué método de **O** les conviene más utilizar?. | ||
|
||
Si no es el caso que la variable está declarada más de una vez en el **scope** actual, deberían de agregarla a este. Recuerden que lo que nos interesa guardar de las variables en **O** es el tipo y nada más. Por último verificar que el tipo de **init** sea el mismo tipo que el tipo declarado, de lo contrario indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.incompatibleTypes(init.line, init.col, init.getType(), type); | ||
``` | ||
|
||
#### Equal | ||
|
||
Para este nodo tienen que hacer algo similar a lo que hicieron en las expresiones aritméticas, llamar recursivamente a `semant` de cada operando, en este caso **ambos** operandos tienen que ser del mismo tipo para poderse comparar, si no indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.incomparableTypes(line, col, e1.getType(), e2.getType()); | ||
``` | ||
|
||
Si este error sucede es fácil recuperarse porque sabemos que el tipo que devuelve una comparación siempre es **bool**, deberían de anotar este nodo con el tipo **bool**. | ||
|
||
#### LessEqual, LessThan | ||
|
||
Lo mismo que **Equal**, lo único que cambia aquí es que ambos operandos del nodo tienen que ser de tipo **int**, si alguno no lo es indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.badOperandTypesForBinaryOp(line, col, operator); | ||
// cambien operator con el operador del nodo, i.e, <= o < | ||
``` | ||
|
||
No se olviden anotar el nodo con el tipo **bool.** | ||
|
||
#### Id | ||
|
||
Este es nodo es bastante fácil, unicamente tienen que buscar en el entorno **O** si la variable existe en algún **scope** si no existe indicar el siguiente error y anotar el nodo con **void**: | ||
|
||
```java | ||
SemantErrors.cannotFindSymbol(line, col, name); | ||
``` | ||
|
||
Si la variable existe, anotar el nodo con el tipo que nos indica **O**. | ||
|
||
#### If | ||
|
||
Para el if ustedes deberían de mandar a llamar recursivamente a `semant` de **pred** verificar si este es de tipo **bool** y si no lo es indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.incompatibleTypes(pred.line, pred.col, pred.getType(), Type.BOOL); | ||
``` | ||
|
||
Luego mandar a llamar recursivamente a `semant` de **thenp** y luego **elsep**, recuerden que en Viper cada par de llaves `{}` abre un **scope** nuevo. Nuevamente este nodo no es una expresión entonces no es necesario anotarlo. | ||
|
||
!!!info "Scope nuevo" | ||
Cuando nos referimos a que se abre un scope nuevo, su código debería de verse algo así: | ||
|
||
```java | ||
O.enterScope(); | ||
// analisis semantico de algo | ||
O.exitScope() | ||
``` | ||
|
||
#### While | ||
|
||
El while es muy similar al **if**, tienen que llamar recursivamente de **cond**, verificar que sea de tipo **bool**, si no lo es indicar el siguiente error: | ||
|
||
```java | ||
SemantErrors.incompatibleTypes(cond.line, cond.col, cond.getType(), Type.BOOL); | ||
``` | ||
|
||
Luego mandar a llamar recursivamente a **body**, nuevamente abriendo un **scope** nuevo. Nuevamente este nodo no es una expresión entonces no es necesario anotarlo. | ||
|
||
### Autograder | ||
|
||
Para probar su implementación pueden utitlizar lo siguiente: | ||
|
||
```bash | ||
sudo ./gradlew build | ||
./check | ||
``` | ||
|
||
Si todo lo tienen bien, les debería de salir lo siguiente: | ||
|
||
```bash | ||
Autograder | ||
|
||
|
||
+1 (badassign2) | ||
+1 (compare) | ||
+1 (unexpectedreturn) | ||
+1 (diffrettype) | ||
+1 (call) | ||
+1 (arith) | ||
+1 (mainwithargs) | ||
+1 (baddecl2) | ||
+1 (badid) | ||
+1 (fact) | ||
+1 (basic) | ||
+1 (badarith) | ||
+1 (if) | ||
+1 (mainnoint) | ||
+1 (badcall2) | ||
+1 (badcall3) | ||
+1 (id) | ||
+1 (badassign) | ||
+1 (good) | ||
+1 (while) | ||
+1 (assign) | ||
+1 (shadowing) | ||
+1 (badif) | ||
+1 (badcall1) | ||
+1 (badformals) | ||
+1 (badequal) | ||
+1 (decl) | ||
+1 (string) | ||
+1 (badwhile) | ||
+1 (nomain) | ||
+1 (bool) | ||
+1 (equal) | ||
+1 (missingret) | ||
+1 (baddecl1) | ||
+1 (badcompare) | ||
|
||
|
||
=> You got a score of 35 out of 35. | ||
``` | ||
|
||
Si ustedes desean probar en un archivo en específico pueden hacer lo siguiente: | ||
|
||
```bash | ||
sudo ./gradlew build | ||
./run <archivo> | ||
``` | ||
|
||
En la carpeta **examples/** hay algunos ejemplos para que puedan probar. | ||
|
||
**¡LISTO!** Han terminado el análisis semántico de **Viper**, es hora de lograr terminar el análisis semántico de **COOL**, esperamos que esta serie de laboratorios les hayan ayudado bastante. | ||
|
Oops, something went wrong.