feat(charka): charka-codegen — emisión de Rust desde el IR

La etapa final del transpilador. generate(&Ir) -> String produce un
fuente Rust (un main.rs) que, compilado contra charka-runtime, ejecuta
la lógica del programa COBOL.

- struct Program con un campo Num/Text por dato elemental; new() lo
  inicializa desde las cláusulas VALUE.
- Un método p_<párrafo> por párrafo del PROCEDURE; run() los encadena
  en orden (el «caer» de COBOL); main() construye y corre.
- Cada Stmt -> código Rust: MOVE->.store/.fill, DISPLAY->println!,
  COMPUTE y aritmética -> expresiones Decimal, IF->if/else,
  PERFORM-> llamada / for / while, STOP RUN->process::exit.
- Tolerante: lo no transpilable (Stmt::Unknown, dato sin resolver, **)
  se emite como comentario // charka: — el código generado compila.
- Saneado de identificadores COBOL->Rust (choques con keywords).
- Verificado de punta a punta: un programa COBOL demo transpila a Rust
  que compila contra charka-runtime y produce la salida esperada.
- Módulos: emit / sym / expr / stmt. 14 tests; fmt + clippy limpios.

El pipeline COBOL->Rust corre de punta a punta. Falta sólo
charka-shadow (validador en sombra).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 20:36:26 +00:00
parent 85156c1509
commit e52b3fb572
10 changed files with 1237 additions and 4 deletions
+26 -4
View File
@@ -15,6 +15,7 @@ embebido, dialectos IBM Enterprise) es un esfuerzo multi-mes.
| `charka-parser` | lib | Parser COBOL'85 (subconjunto): tokens → AST (`Program`) |
| `charka-ir` | lib | Representación intermedia: el AST con los statements del PROCEDURE ya tipados |
| `charka-runtime` | lib | Soporte de ejecución de los programas transpilados: campos `Num` y `Text` |
| `charka-codegen` | lib | Emisión de Rust: IR → fuente Rust sobre `charka-runtime` |
## charka-bcd
@@ -113,16 +114,37 @@ los listaba al revés): el codegen emite llamadas contra esta API, así
que el runtime debe existir primero — y es un crate autocontenido,
verificable sin depender del código emitido.
## charka-codegen
La etapa final: `generate(&Ir) -> String` produce un fuente Rust (un
`main.rs`) que, compilado contra `charka-runtime`, ejecuta la lógica
del programa COBOL.
- Un `struct Program` con un campo por cada dato elemental (`Num` /
`Text`); `Program::new()` lo inicializa desde las cláusulas `VALUE`.
- Un método `p_<párrafo>(&mut self)` por párrafo; `run()` los encadena
en orden (el «caer» de COBOL); `main()` construye y corre.
- Cada `Stmt` → líneas Rust: `MOVE`→`.store`, `DISPLAY`→`println!`,
`COMPUTE`/aritmética → expresiones `Decimal`, `IF`→`if`, `PERFORM`→
llamada / `for` / `while`, `STOP RUN`→`process::exit`.
- **Tolerante**: lo no transpilable (`Stmt::Unknown`, dato sin
resolver, `**`) se emite como comentario `// charka:` — el código
generado siempre compila.
- 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.
## Estado
`charka-bcd` (22 tests), `charka-lexer` (17 tests), `charka-parser`
(15 tests), `charka-ir` (17 tests) y `charka-runtime` (17 tests)
implementados y verdes. **Pendiente** — el resto del transpilador
(Fase D del plan macro):
(15 tests), `charka-ir` (17 tests), `charka-runtime` (17 tests) y
`charka-codegen` (14 tests) implementados y verdes. El pipeline
COBOL→Rust corre de punta a punta. **Pendiente** — el último crate:
| crate pendiente | rol |
| ----------------- | ---------------------------------------------------- |
| `charka-codegen` | emisión de Rust (IR → fuente Rust sobre el runtime) |
| `charka-shadow` | validador en sombra (original vs transpilado) |
Hito intermedio sugerido: subconjunto COBOL'85 puro antes de CICS/SQL.