# Laboratorio de la semana 7: un valor con varios tipos

Esta semana hay una sola sesión de laboratorio, porque la otra es para la Práctica 2. Está
pensada para unos 90 minutos de trabajo. Los comandos se corren desde `code/week-07`. Las
ideas están en los apuntes, en la sección "El laboratorio, paso a paso".

| Archivo | Qué es | ¿Lo cambian? |
|---|---|---|
| `value.h` | La interfaz de `Value`: lo que promete cada función | No |
| `value.c` | `value_none`, `value_int` y `value_parse` hechos, lo demás por escribir | **Sí** |
| `value_tests.c` | Sus pruebas con `assert` | **Sí** |
| `table.h` | La interfaz de la tabla, con un tipo opaco | No |
| `table.c` | La lectura del archivo hecha; `add_row`, `table_free` y `table_summary` por escribir | **Sí** |
| `report.c` | El programa que escribe las filas y el resumen | No |
| `data/` | `viajes.csv` y `alturas.csv`, para probar | No |

```sh
make lab                  # compila value_tests y report en build/lab/
build/lab/value_tests     # corre sus pruebas
build/lab/report lab/data/viajes.csv
make test-lab             # comprueba todo el laboratorio; falla hasta que terminen
```

Todo se compila con ASan: si una cadena no se libera, el programa termina con un informe de
LeakSanitizer y un código de error, y la prueba falla.

## Parte 1: leer (unos 15 minutos)

Lean `value.h` completo, luego la parte hecha de `value.c`, y luego `table.h`. Respondan por
escrito, sin ejecutar nada.

1. ¿Por qué `value_none` no le da ningún valor a `v.as`? ¿Qué parte del programa podría notarlo?
2. En `value_parse`, ¿qué devuelve el campo `2147483648`? ¿En qué línea se decide, y por qué esa
   revisión va antes de multiplicar?
3. ¿Por qué `Value` deja ver sus campos, y `Table` no?
4. `table_cell` devuelve un `const Value *`. ¿Quién libera esa celda? ¿Qué dice el `const`?

## Parte 2: el módulo `Value` (unos 35 minutos)

Escriban en `value.c`, en este orden, y corran sus pruebas después de cada una:

1. `value_double`, igual que `value_int`.
2. `value_string` y `value_free`. Aquí está la memoria: `value_string` copia, y `value_free` libera
   solo si la variante es una cadena.
3. `value_print` y `value_equal`, cada una con un `switch` sobre la etiqueta y **sin `default`**, para
   que `-Wall` les avise si falta un caso.

Agreguen a `value_tests.c` pruebas de `value_double`, `value_string`, `value_equal` y `value_free`,
con `test_value_int` como modelo. Toda cadena que cree una prueba se libera en esa prueba.

## Parte 3: la tabla y el resumen (unos 40 minutos)

Lean primero `table_load` y `read_rows` en `table.c`. El `main` de `report.c` usa `argv`, y los apuntes explican por qué. Luego escriban:

1. `add_row`: parte la línea con `split_line`, revisa el número de campos, asegura espacio con
   `reserve_row` y guarda en cada celda lo que devuelve `value_parse`. Son pocas líneas.
2. `table_free`: cada celda posee su cadena, así que primero las celdas, luego el arreglo y al final la
   tabla. Debe aceptar `NULL`.
3. `table_summary`: un `switch` por celda. Decidan cómo fijar el mínimo y el máximo: una columna con
   solo números negativos no tiene máximo 0, y una con solo positivos no tiene mínimo 0.

Con eso, esto debe coincidir con los apuntes:

```sh
build/lab/report lab/data/viajes.csv
```

Corran también `build/lab/report lab/data/alturas.csv`, calculen a mano la fila de `minima`, y al final
`make test-lab`.

**Si no alcanza el tiempo:** lo que no terminen lo terminan antes de la próxima clase. El orden de arriba
deja lo más importante primero: `Value`, y después la tabla.

## Si sobra tiempo

1. Escriban `Value value_copy(const Value *v)`, que devuelva un valor independiente. ¿Qué variante necesita
   más que una asignación?
2. Agreguen una variante `VALUE_BOOL`, para los campos `true` y `false`. Compilen antes de tocar los `switch`
   y lean lo que dice `gcc`: esa lista es la de los lugares por cambiar.
