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>
7.4 KiB
Changelog — charka
Transpilador COBOL → Rust. El módulo más grande del ecosistema (Fase D del plan macro) — el parser COBOL completo es un esfuerzo multi-mes.
feat(charka-codegen): emisión de Rust desde el IR
Crate nuevo crates/modules/charka/charka-codegen — la etapa final del
pipeline. generate(&Ir) -> String produce un fuente Rust (un
main.rs) que, compilado contra charka-runtime, ejecuta la lógica
del programa COBOL.
- Un
struct Programcon un campo por cada dato elemental —Numpara los numéricos,Textpara los alfanuméricos;Program::new()los inicializa desde sus cláusulasVALUE. - Un método
p_<párrafo>(&mut self)por cada párrafo del PROCEDURE;run()los encadena en orden (el «caer» de COBOL);main()construye elProgramy lo corre. - Cada
Stmt→ código Rust:MOVE→.store/.fill,DISPLAY→println!,COMPUTEy la aritmética → expresionesDecimal,IF→if/else,PERFORM→ llamada de método /for/while,GO TO→ llamada +return,STOP RUN→process::exit. - Tolerante: lo no transpilable (
Stmt::Unknown, un dato sin resolver, el operador**) se emite como comentario// charka:; el código generado siempre compila. - Saneado de identificadores COBOL→Rust (incl. choques con keywords).
- Verificado de punta a punta: un programa COBOL de demostración
transpila a Rust que compila contra
charka-runtimey produce la salida esperada (COMPUTE,IF,PERFORM,DISPLAY). - 14 tests del fuente emitido; fuera de alcance v1: grupos como campo,
REDEFINES,OCCURS,PERFORM ... THRUcomo rango, E/S.
feat(charka-runtime): soporte de ejecución — campos Num y Text
Crate nuevo crates/modules/charka/charka-runtime — el soporte que los
programas COBOL transpilados enlazan. charka-codegen no emitirá Rust
autónomo: emitirá Rust que llama a esta biblioteca.
Num— campo numérico (PIC 9(5)V99): unDecimalconformado a suPicture.storetrunca a la escala declarada;store_roundedredondea; al desbordar la parte entera conserva los dígitos de bajo orden (elON SIZE ERRORde COBOL sin cláusula).displayda los dígitos con relleno de ceros y signo si corresponde.Text— campo alfanumérico (PIC X(n)) de longitud fija:storejustifica a la izquierda y rellena con espacios o trunca;fillmueve las constantes figurativas (SPACES,ZEROS).cobol_text_cmp— comparación alfanumérica que rellena el más corto con espacios.- Reexporta
Decimal/Picture/Roundingdecharka-bcd. - Construido antes que
charka-codegen(la nota de orden del plan los listaba al revés): el codegen emite contra esta API, así que el runtime debe existir primero — y se verifica solo, sin el codegen. - 17 tests: campo en cero,
VALUEinicial, truncado y redondeo, desbordamiento que conserva bajo orden, magnitud sin signo y signo con signo, justificación y relleno de texto,fill, comparación.
feat(charka-ir): representación intermedia — statements tipados
Crate nuevo crates/modules/charka/charka-ir — la tercera etapa del
pipeline: Program → Ir. El PROCEDURE division pasa de sentencias
con tokens crudos a un árbol de instrucciones tipadas.
lower(&Program) -> Ir— total y tolerante: nunca falla.Ir { program_id, data, procedures }. El modelo de datos (la DATA division) pasa tal cual — sirve de tabla de símbolos.StmtcubreMOVE,DISPLAY,ACCEPT,COMPUTE,ADD,SUBTRACT,MULTIPLY,DIVIDE,IF/ELSE/END-IF,PERFORM(fuera de línea, en línea,TIMES,UNTIL),GO TO,STOP RUN,GOBACK,EXIT,CONTINUE.- Expresiones de
COMPUTEcon precedencia y paréntesis (+ -<* /<**asociativo a derecha). Condiciones deIF/UNTILcon comparadores en forma símbolo (= < > <= >= <>) o palabra (EQUAL TO,GREATER THAN...),AND/OR/NOTy nombres de condición (datos de nivel 88). - COBOL no termina los statements con un símbolo: el parser delimita
las listas de operandos con palabras "frontera" (verbos,
terminadores
END-*/ELSE, conectoresTO/GIVING/BY...). - Un verbo no soportado se conserva como
Stmt::Unknown { verb, tokens }— el lowering nunca aborta. - Fuera de alcance v1:
EVALUATE,STRING/UNSTRING, E/S de ficheros,PERFORM VARYING, CICS, SQL embebido. - 17 tests: MOVE simple y multi-destino, DISPLAY con figurativas, precedencia de COMPUTE, flag ROUNDED, ADD in-place vs GIVING, SUBTRACT, DIVIDE BY/INTO, IF/ELSE, condiciones con AND, nombre de condición, PERFORM párrafo/TIMES/UNTIL en línea, varios statements en una sentencia, verbo desconocido, programa completo.
feat(charka-parser): parser COBOL'85 → AST
Crate nuevo crates/modules/charka/charka-parser — la segunda etapa del
pipeline: Vec<Token> → Program (AST). Alcance v1: el esqueleto del
programa.
parse(&[Token]) -> Result<Program, ParseError>. El AST:Program(program_id,data,paragraphs),DataItem,Paragraph,Sentence.- Particiona el flujo de tokens en las cuatro divisiones por sus
encabezados (
X DIVISION); de la IDENTIFICATION extrae elPROGRAM-ID. - DATA division → árbol de
DataItem: número de nivel, nombre, cláusulaPICTUREreensamblada (S9(5)V99→S9(5)V99) yVALUE. Anida por número de nivel — 01 y 77 son raíces, 88 cuelga del ítem precedente. - PROCEDURE division →
Vec<Paragraph>, cada párrafo con susSentence(tokens crudos; sin parseo a nivel de statement, eso escharka-ir). Las sentencias previas al primer encabezado van a un párrafo implícito de nombre "". - Parser tolerante: salta encabezados de
SECTION, entradasFD/SDy cláusulas de datos que no seanPICTURE/VALUE.ParseErrorsólo ante un número de nivel inválido o un dato sin nombre. - 15 tests: PROGRAM-ID (forma larga y
IDcorta), ítems planos y anidados, reensamblado de PICTURE, variantes de VALUE, niveles 88,FILLER, párrafos y párrafo implícito, encabezado de sección, programa completo de punta a punta, nivel inválido.
feat(charka-lexer): tokenizador de COBOL
Crate nuevo crates/modules/charka/charka-lexer — la primera etapa del
pipeline del transpilador: texto COBOL → secuencia de Token.
- Lexer deliberadamente tonto: no conoce keywords ni la cláusula
PICTURE; emiteWordpara todo identificador y deja la clasificación al parser. - Tokens:
Word(palabras COBOL con guiones internos),Number(literal sin signo),String(comillas dobladas colapsadas),Period(el.terminador),Symbol(paréntesis, separadores y operadores+ - * / ** = < > <= >= <>). - Dos formatos de fuente: fijo (la tarjeta de 80 columnas — cols
1-6 secuencia, 7 indicadora, 8-72 código, 73-80 identificación) y
libre. Comentarios por la columna indicadora (
*//) o por*inicial en formato libre. - Cada
Tokenlleva línea y columna 1-based;LexErrortipado (literal sin cerrar, carácter inesperado). - Limitación v1 documentada: no soporta continuación de literales entre
líneas (indicador
-). Subconjunto COBOL'85, el hito intermedio. - 17 tests: sentencias, palabras con guiones, literales y comillas dobladas, números vs terminador, operadores, ambos formatos, tracking de posición, errores.
feat(charka-bcd): aritmética decimal con semántica COBOL
(Pre-existente.) Picture + Decimal de punto fijo exacto — ver el
SDD del módulo. 22 tests.