feat(charka): OCCURS — tablas y referencias con subíndice

Los arrays de COBOL, que antes el transpilador descartaba en silencio.
Una rebanada vertical amplia que atraviesa el pipeline entero.

- Parser: la cláusula OCCURS n [TIMES] se captura en DataItem.
- IR: Operand::Indexed { name, index } — una referencia ELEM(I), con
  subíndice 1-based. Los destinos de los statements pasan de
  Vec<String> a Vec<Operand>, así que se puede escribir a un elemento
  de tabla (MOVE x TO ELEM(I), COMPUTE ELEM(I) = ...). model::Field
  gana occurs: Option<u32>.
- Codegen: un campo OCCURS se emite como Vec<Num>/Vec<Text>,
  inicializado con vec![..; n]; una referencia con subíndice indexa el
  vector (1-based -> 0-based).
- Shadow: en el intérprete todo campo es un vector — un escalar es de
  longitud 1, una tabla de n; las referencias se resuelven a
  (nombre, índice).
- Corpus: programa nuevo 11-tabla (llena una tabla con cuadrados y los
  suma). Verificado: el intérprete sombra y el crate compilado por
  scaffold dan ambos SUMA DE CUADRADOS = 000055.

Alcance v1: OCCURS elemental, una dimensión, subíndice de un operando.
Fuera: OCCURS de grupo, multidimensional, DEPENDING ON.

Tests: charka-parser 16, charka-ir 24, charka-codegen 18,
charka-shadow 16. fmt + clippy limpios.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 22:03:48 +00:00
parent 28ee1ae260
commit 3902763daa
18 changed files with 440 additions and 239 deletions
+11 -6
View File
@@ -143,11 +143,14 @@ del programa COBOL.
- **Tolerante**: lo no transpilable (`Stmt::Unknown`, dato sin
resolver, `**`) se emite como comentario `// charka:` — el código
generado siempre compila.
- **Tablas** (`OCCURS n`): un campo `OCCURS` se emite como `Vec<Num>`
/ `Vec<Text>`; una referencia con subíndice `ELEM(I)` indexa el
vector (subíndice 1-based de COBOL → 0-based de Rust).
- Verificado de punta a punta: un programa COBOL de demostración
transpila a Rust que compila contra `charka-runtime` y produce la
salida correcta.
- Fuera de alcance v1: grupos como campo propio, `REDEFINES`,
`OCCURS`/tablas, `PERFORM ... THRU` como rango, E/S de ficheros.
`OCCURS` de grupo, `PERFORM ... THRU` como rango, E/S de ficheros.
## charka-shadow
@@ -162,15 +165,17 @@ que corre el `Ir` directamente sobre `charka-runtime`, sin compilar.
divergieran, eso delataría un bug.
- Tope de pasos: un bucle que no termina se corta con
`Halt::StepLimit` en vez de colgarse.
- La referencia v1 es el **corpus** (`corpus/`): 7 programas COBOL de
- La referencia v1 es el **corpus** (`corpus/`): programas COBOL de
complejidad graduada con sus salidas esperadas verificadas a mano.
Un modo futuro, con GnuCOBOL, diferenciará contra el compilador real.
- En el intérprete todo campo es un vector — un escalar es de longitud
1, una tabla `OCCURS n` de longitud `n`.
## El corpus
`crates/modules/charka/corpus/` — 7 programas COBOL graduados
(`01-hola` … `07-clasificar`), cada uno con su `.expected`. Ejercita
el pipeline completo de punta a punta. Ver su `README.md`.
`crates/modules/charka/corpus/` — 11 programas COBOL graduados
(`01-hola` … `11-tabla`), cada uno con su `.expected`. Ejercita el
pipeline completo de punta a punta. Ver su `README.md`.
## La CLI
@@ -192,4 +197,4 @@ concuerdan.
Próximo hito mayor: salir del subconjunto COBOL'85 puro hacia CICS,
SQL embebido y los dialectos IBM Enterprise; ampliar el codegen
(grupos, `REDEFINES`, `OCCURS`/tablas, E/S de ficheros).
(grupos como campo, `REDEFINES`, `OCCURS` de grupo, E/S de ficheros).