|
Creador de PowerRustCOBOL
|
27.10.2026 07:38
|
|
Posts: 396
|
|
Enviados: 31
|
|
Recibidos: 172
|
|
• Corregido: un ítem con nombres de condición de nivel 88 no aportaba bytes
04 RDF3-5-15 PIC 9. con 88 HARD / 88 SOFT debajo era tratado como un grupo por el constructor de imágenes de REDEFINES, porque cualquier hijo convertía un ítem en grupo. Los nombres de condición nombran valores de un ítem, no campos dentro de él, así que el ítem desaparecía por completo de la imagen de su padre y conservaba su valor por defecto mientras el campo siguiente tomaba su byte. El mismo recuento erróneo dejaba a un ítem así fuera de la ordenación del RENAMES de nivel 66.
• Corregido: FILLER era invisible para el RENAMES de nivel 66
Un FILLER contiene bytes como cualquier otro ítem elemental, pero nunca se registraba en el orden de declaración que un rango de RENAMES rebana, de modo que un rango que abarcaba uno cerraba el hueco que ocupa: 66 RENAMES-TEST-3 RENAMES SUB-GRP-FOR-RENAMES-1 THRU ELEM-FOR-RENAMES-2 leía X123 en lugar de "X 123".
• Corregido: MOVE ALL literal a un receptor RENAMES escribía un solo carácter
Un receptor de nivel 66 abarca bytes reales exactamente igual que un grupo, y el literal repetido tiene que alcanzarlos todos. MOVE ALL "X" TO RENAME1 rellenaba un único carácter y dejaba los otros diecinueve como estaban.
=== PowerRustCOBOL 1.62.25 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): ejecución 66 -> 68 de 95, aserciones 191 -> 183 fallando. La compilación se mantiene en 94 / 95 y la del conjunto completo en 419 / 434. NC215A y NC219A pasaron ambos de fallar a limpios. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Añadido: ALPHABET y PROGRAM COLLATING SEQUENCE
SPECIAL-NAMES. ALPHABET <name> IS … y OBJECT-COMPUTER. … PROGRAM COLLATING SEQUENCE IS <name> se omitían ambos. Un programa que nombra un alfabeto ordena ahora todas las comparaciones alfanuméricas que hace por esa secuencia, y no por el orden nativo de caracteres.
La frase de literales es una lista ordenada de posiciones: un literal solo aporta cada uno de sus caracteres por turno, lit-1 THRU lit-2 se expande a una posición por carácter del rango, y ALSO pliega los operandos que une en una única posición compartida — que es lo que hace que "I" ALSO "J" comparen iguales. Cualquier carácter que el alfabeto no menciona se ordena después de todos los que sí menciona, en orden nativo entre ellos. Una constante figurativa usada como operando nombra su carácter nativo, así que ALSO HIGH-VALUE da a 0xFF la posición escrita. La cláusula también redefine las constantes figurativas: LOW-VALUE y HIGH-VALUE nombran los caracteres de los extremos de la secuencia del programa, de modo que bajo ALPHABET COLLATING-SEQ-1 IS "F" "U" "N" … el LOW-VALUE del programa es la letra F.
NATIVE, STANDARD-1 y STANDARD-2 son el orden nativo y no necesitan tabla. EBCDIC no está implementado y deja en vigor el orden nativo — registrado en la lista de carencias conocidas de docs/cobol85-supported-syntax-en.md. Program ganó alphabets y collating_sequence, y cobolt_ast::program::AlphabetSpec es nuevo — todos al final de sus declaraciones, según la regla de ordinales de bincode.
• Corregido: una cadena no numérica comparaba igual a cero
COBOL-85 (VI-15 4.5.4) hace alfanumérica una comparación en cuanto uno de los operandos es alfanumérico; el operando numérico se lee como sus caracteres. El runtime coaccionaba en cambio el lado de texto a f64, y un parseo fallido es 0.0 — así que IF WS-TEXT = 0 era verdadero para cualquier texto, IF "A" < 0 era falso e IF 9 < SPACE era falso. El texto que realmente es un número conserva la lectura numérica, de modo que IF WS-DIGITS = WS-NUM sigue comparando 42 con 42, y un ítem sin inicializar — que no tiene caracteres en absoluto — también la conserva, así que IF WS-PTR = NULL sobre un POINTER al que nunca se hizo SET no se ve afectado.
=== PowerRustCOBOL 1.62.26 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): aserciones 183 -> 181 fallando. La ejecución se mantiene en 68 / 95 y la compilación en 94 / 95. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Corregido: BLANK WHEN ZERO se ignoraba en un PICTURE sin edición
La cláusula se registraba sólo para los ítems de edición numérica, así que 77 DATA-F PICTURE IS 9(10) BLANK WHEN ZERO. con valor cero seguía leyéndose como diez caracteres 0 en lugar de diez espacios. Ahora se aplica a cualquier ítem DISPLAY numérico, que es lo que el estándar permite, y el blanqueo cubre el ítem entero — incluida una posición SIGN … SEPARATE, puesto que la cláusula deja en blanco el ítem y no sólo sus dígitos.
El valor almacenado sigue siendo numérico, así que la aritmética sobre un ítem así no cambia; sólo su forma de caracteres queda en blanco. Una comparación contra un operando alfanumérico lee esa forma de caracteres, que es lo que necesita IF DATA-F EQUAL TO " " (NC107A BZERO-TEST-1/BZERO-TEST-2).
Nota sobre el recuento de NC107A: los fallos del programa pasaron de 9 a 10 entre 1.62.25 y 1.62.26 aunque aquí se corrigieron dos de ellos. RDF-TEST-9 pasaba únicamente porque una cadena no numérica se coaccionaba a 0.0: RDFDATA18 contiene en realidad espacios, no "00000000000000", porque una descripción REDEFINES más ancha que el almacenamiento que redescribe no está respaldada más allá del final de su destino. Ese defecto es preexistente y ajeno a estos cambios — era invisible mientras toda cadena era igual a cero, y ahora es visible.
=== PowerRustCOBOL 1.62.27 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): ejecución 68 -> 69 de 95, aserciones 181 -> 172 fallando. NC225A pasa de 9 fallos a 0. La compilación se mantiene en 94 / 95. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Corregido: una palabra suelta en EVALUATE se leía como prueba de verdad, no como operando
Dos lecturas de una palabra suelta eran erróneas, y ambas fallaban en la misma dirección: hacían que un WHEN coincidiera cuando no debía. Como el error sólo añadía coincidencias, la mitad de esperar-igualdad de cada prueba pasaba por accidente y la funcionalidad parecía implementada.
Como objeto de selección: en EVALUATE 1234 WHEN WRK-DU-08V00 el objeto es un operando que se compara contra el sujeto. Se parseaba como condición, y un nombre suelto que no es un nivel 88 declarado caía al comportamiento de reserva de "verdadero si no es cero" — así que el ítem que contenía 78 coincidía con el sujeto 1234, y cualquier objeto distinto de cero coincidía con cualquier sujeto. Un objeto que es un nivel 88 declarado sigue siendo una condición; la ambigüedad se resuelve contra la tabla de símbolos exactamente como Condition::NameOrAbbrev ya la resuelve para las relaciones combinadas abreviadas.
Como sujeto de selección: en EVALUATE IT-IS-81 WHEN TRUE el sujeto es un sujeto condicional — selecciona según si la condición se cumple. Leído como ítem de datos, el nombre no resolvía a ningún slot, se evaluaba a 0 y WHEN TRUE nunca coincidía. Un sujeto suelto que nombra un nivel 88 declarado se reescribe ahora a sujeto condicional, que las ramas existentes de comparación de verdad ya manejan; la reescritura se omite por completo cuando ningún sujeto es un nombre de condición, así que el EVALUATE COBOL-CONTROL-ID del bucle de eventos generado no paga nada por evento. Juntas, estas dos correcciones resuelven el caso ALSO de seis sujetos de NC225A (EVA-TEST-GF-31), donde cinco columnas coincidían y la columna del nombre de condición no, de modo que la selección caía a una rama posterior. Pruebas nuevas: test_evaluate_selection.rs (9).
=== PowerRustCOBOL 1.62.28 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): ejecución 69 -> 71 de 95, aserciones 172 -> 151 fallando. NC247A y NC235A quedan en 0 fallos; NC216A pasa de 13 a 7. La compilación se mantiene en 94 / 95 (conjunto completo 419 / 434). Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Corregido: INSPECT no leía nada en absoluto de un ítem de grupo
Un grupo no posee slot de valor propio — su valor se sintetiza a partir de sus ítems subordinados — e INSPECT leía su operando a través del almacén plano, así que veía la cadena vacía. INSPECT <grupo> TALLYING … contaba cero en todo grupo, incluidos los de longitud fija, y REPLACING escribía el resultado en un slot que el grupo no tiene. Ambas direcciones pasan ahora por los accesores de grupo.
Ésta era la mayor causa individual: además de NC247A, despejó seis fallos en NC216A.
• Corregido: un grupo de longitud variable tenía una sola longitud
Un grupo que contiene una tabla OCCURS … DEPENDING ON tiene dos longitudes, y cuál se aplica depende de la dirección de la referencia (VI-26 5.8.3 SR5). Usábamos el máximo declarado para todo.
Al enviar, sólo participan las ocurrencias que el ítem dependiente cuenta en ese momento. Un grupo con 3 de 9 entradas activas mide 13 bytes, no 19, y eso es lo que ven una comparación, STRING, UNSTRING e INSPECT; las ocurrencias durmientes conservan su contenido pero no forman parte del grupo.
Al recibir se aplica el máximo declarado. El movimiento es lo que escribe el ítem dependiente, así que su valor antiguo no puede acotar al receptor: MOVE ODO-RECORD TO NEW-RECORD copia las nueve ocurrencias en un registro cuyo propio ítem dependiente aún lee 3. NC247A además coloca el ítem dependiente en el primer byte del propio grupo, de modo que un movimiento receptor sobrescribe su propio contador a mitad de camino — medir contra el valor que el movimiento acababa de escribir truncaba la tabla. Leer el contador actual en todas las direcciones es tan erróneo como leer el máximo en todas; las pruebas nuevas cubren ambas mitades.
• Corregido: SEARCH y SEARCH ALL recorrían más allá del final de una tabla variable
Ambos se acotaban por el máximo declarado del OCCURS, así que un valor situado en una ocurrencia durmiente aún se encontraba. Ahora recorren la longitud activa, que es lo que exigen los dos casos AT END de NC247A. Esto también despejó NC235A por completo. Pruebas nuevas: test_odo_group_length.rs (13).
=== PowerRustCOBOL 1.62.29 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): ejecución 71 -> 72 de 95, aserciones 151 -> 136 fallando (97.0 %). NC234A pasa de 15 fallos a 0. La compilación se mantiene en 94 / 95 (conjunto completo 419 / 434). Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Corregido: una superposición REDEFINES grande perdía todas las escrituras
Dos descripciones de los mismos bytes se mantenían coherentes copiando una en la otra en cada escritura. Eso es asequible para los registros planos de veinte bytes para los que existe el mecanismo y ruinoso para una tabla redefinida de 10×10×10, donde un MOVE recorre mil ocurrencias dos veces — así que las descripciones que superaban REDEFINE_SYNC_BUDGET se rendían y conservaban almacenamiento separado. Cada nombre de la descripción redefinidora se leía entonces como espacios, por mucho que se hubiera rellenado la tabla redefinida.
Cuando las dos descripciones tienen el mismo trazado — los mismos ítems, en el mismo orden, con las mismas dimensiones OCCURS y los mismos PICTURE — no hay nada que copiar: son los mismos bytes leídos de la misma manera, así que ahora comparten directamente los slots de almacenamiento. Exacto, O(1) por acceso, y sin presupuesto que aplicar. Una descripción que contiene un FILLER sin nombre no tiene entrada de símbolo que comparar y conserva la superposición por copia, igual que cualquier pareja cuyos trazados difieran. La compartición es sólo de almacenamiento: cada descripción conserva su propia entrada de símbolo y, en particular, sus propios nombres INDEXED BY — SEARCH GRP-ENTRY-1 debe ser conducido por IDX-1-1, no por el IDX-1 de la tabla redefinida. Por eso el alias se sitúa en los accesores de almacenamiento y no en la resolución de nombres, donde habría entregado en silencio a la búsqueda el índice equivocado.
Medido, no supuesto: primero se probó simplemente subir el presupuesto hasta cubrir la tabla; NC234A tardó entonces 20 s y chocó con el tiempo límite del arnés, cambiando 15 fallos por un programa que no termina. La compartición lo ejecuta en 0.09 s. Sobre la etiqueta: esos 15 fallos estaban agrupados bajo SEARCH VARYING LEV y MULTIPLE SEARCH STMT, que es la funcionalidad que NC234A prueba, no el defecto — SEARCH … VARYING ya era correcto; las pruebas buscan en una tabla redefinidora que nunca había recibido los datos. Una categoría de causa nombra la prueba, no el defecto. Pruebas nuevas: test_redefines_shared_storage.rs (6).
=== PowerRustCOBOL 1.62.30 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): ejecución 72 -> 76 de 95. Cuatro programas quedan limpios de una vez — NC109M, NC110M, NC302M y NC303M — y la columna "printed no report" pasa de 3 -> 0. La compilación se mantiene en 94 / 95. Ningún otro módulo fue tocado (GOLDEN RULE #9). Estos cuatro se describían antes como inalcanzables sin trabajo en el arnés. Lo eran, y ese trabajo llega aquí; detrás se escondían dos defectos reales del runtime, más el análisis de marcado de conformidad que el estándar exige y que este compilador nunca tuvo.
• Corregido — ACCEPT hacia un grupo dejaba el receptor vacío
Un grupo no posee slot de almacenamiento propio: su valor se sintetiza a partir de sus ítems subordinados. ACCEPT escribía mediante set_str, que dejaba la línea completa del operador en un slot que nada vuelve a leer, de modo que un receptor de grupo quedaba exactamente como estaba y la lectura parecía tener éxito. NC109M acepta en ACCEPT-D1 (dos ítems subordinados) y en X80-CHARACTER-FIELD (un FILLER), y ambos comparaban después igual a nada.
Es el mismo defecto que INSPECT arrastró hasta 1.62.28, y el despacho vive ahora en un solo sitio — Interpreter::store_text — para que el próximo verbo que lo necesite no tenga que redescubrirlo. Toda fuente de ACCEPT con valor de texto pasa por él, no solo el Formato 1: ACCEPT WS-TODAY FROM DATE hacia un grupo de YY/MM/DD es la manera ordinaria de escribir eso.
• Corregido — VALUE QUOTE inicializaba el ítem con espacios
Una constante figurativa en una cláusula VALUE rellena su ítem, exactamente igual que VALUE SPACE. QUOTE caía al caso de "conservar el valor por defecto", así que PICTURE X VALUE QUOTE contenía un espacio. ACCEPT-D18 de NC109M es precisamente esa declaración, y el valor contra el que se comparaba nunca fue por tanto una comilla.
• Añadido — marcado de conformidad para los elementos obsoletos de COBOL-85
cobolt_semantic::flagging::flag_obsolete informa de los elementos del lenguaje que el estándar lista como obsoletos: los cinco párrafos opcionales de la IDENTIFICATION DIVISION, MEMORY SIZE, ALTER, STOP con literal y GO TO sin nombre de procedimiento. No es comprobación de errores: todos ellos compilan y se ejecutan como siempre, y ninguno se convierte en error ni en aviso en la ruta de compilación ordinaria. Es un punto de entrada separado precisamente para que una compilación normal no empiece a quejarse de AUTHOR.
El análisis lee el flujo de tokens, no el AST: la mayoría de los elementos obsoletos son párrafos de la IDENTIFICATION DIVISION y la cláusula MEMORY SIZE, que el parser consume y descarta porque no llevan significado que preservar. Registrarlos en Program solo para que una pasada de diagnóstico pudiera reencontrarlos engordaría el AST para algo que ninguna ruta de ejecución lee.
• Arnés — los cuatro miembros que no podían puntuarse
- NC109M lee once valores del operador. Ahora los recibe: el mazo de entrada se recupera del fuente en vez de inventarse, ya que cada valor aceptado se compara contra un literal VALUE emparejado en la propia DATA DIVISION del programa. 0 pass / 24 fail -> 16 pass / 0 fail.
- NC110M escribe su informe con DISPLAY, a la consola, nunca al fichero de impresión de CCVS. La consola ahora se captura y se puntúa. Sus dos tests enuncian su propio contrato en el texto que imprimen, y ese contrato contiene el marcador literal "PASS " que el puntuador genérico cuenta — así que la lectura específica del miembro corre primero, o la descripción de un test se puntúa como el resultado de uno.
- NC302M y NC303M son miembros de marcado sin maquinaria PASS/FAIL alguna. Cada construcción obsoleta lleva un comentario *Message expected for above statement: OBSOLETE y el programa declara *TOTAL NUMBER OF FLAGS EXPECTED = N.; ese contrato es legible por máquina, así que se lee y se coteja contra flag_obsolete en lugar de transcribirse. 7 / 7 y 4 / 4.
Un miembro de marcado se puntúa ahora en tiempo de compilación y nunca se ejecuta — ejecutarlo no puntúa nada, haga lo que haga. Eso también saca a NC401M de la columna de timeouts, aunque sigue puntuando 0 de sus 40: NC401M valida una clase distinta, NON-CONFORMING STANDARD, que marca construcciones fuera del high subset de COBOL-85 y no las obsoletas. Sus 44 fallos honestos son la razón de que el recuento de aserciones lea 4386 pass / 168 fail frente a 4375 / 124 — los programas que antes no podían puntuarse no estaban pasando: eran invisibles.
Con esto se fueron dos bloqueos latentes: run_one entregaba al proceso hijo una tubería para stdout y otra para stderr y luego no leía ninguna, así que cualquier programa que mostrara más que el búfer de tubería del sistema operativo se bloqueaba para siempre y se puntuaba como timeout. Ambas van ahora a ficheros.
=== PowerRustCOBOL 1.62.31 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): compilación 94 -> 95 de 95, ejecución 76 -> 77. El módulo ya compila al completo; la suite entera pasa de 419 -> 420 de 434. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Añadido — SPECIAL-NAMES. CURRENCY [SIGN] [IS] literal
NC108M era el último fallo de compilación del Nucleus y estaba registrado como necesitado de una "implementor-defined editing picture", <(3),<<<.99. No necesita tal cosa. Veinte líneas antes el programa declara CURRENCY "<", así que aquello es una picture ordinaria de moneda flotante con < en el papel que normalmente juega $ — COBOL-85 puro, y una laguna más que una extensión. La cláusula se parseaba y se tiraba.
El símbolo declarado reemplaza a $ en vez de sumarse a él, que es lo que dice el estándar: un programa que nombra un signo de moneda ya no puede escribir $ en una picture. La plantilla de PICTURE sigue escribiendo una posición de moneda como $, llame el programa al símbolo como lo llame — $ es el marcador interno de "posición de moneda", de modo que cada regla de anchura y de recuento de dígitos queda escrita una sola vez y solo el formateador sustituye en el momento de emitir uno.
• Corregido — un solapamiento REDEFINES dimensionaba mal todo ítem numérico editado
El trazado del registro tomaba la anchura de un ítem elemental como digits + decimals. Esos cuentan posiciones de dígito, y para una picture numérica editada no son la anchura: PIC $$$,$$$.99 ocupa diez caracteres pero informa dos dígitos y ningún decimal, porque analyze_pic separa las partes entera y fraccionaria por V y el separador de esta picture es un . real — así que ambos nueves caen en la parte entera y las posiciones de $, , y . no las cuenta nadie.
Un solapamiento que creía que el ítem medía dos bytes truncaba todo lo que realmente contenía y desplazaba cada campo posterior del registro ocho posiciones arriba. COMPLETE-FORMAT (19) de NC108M leía < donde estaba almacenado " <1,1". La anchura viene ahora de numedit::edited_width, que es lo que formatea el valor de todos modos.
Esto es anterior al trabajo de moneda y no tenía nada que ver con él: el mismo fallo se reproduce con una picture de $ normal sin cláusula SPECIAL-NAMES alguna.
• Corregido — un VALUE alfanumérico cambiaba la categoría de un ítem numérico
PICTURE IS 9 VALUE IS "5" almacenaba una cadena donde corresponde el número del ítem, así que toda regla que pregunta si el ítem es numérico respondía que no. BLANK WHEN ZERO era una de ellas: se aplica en la ruta de visualización numérica, de modo que el ítem conservaba su dígito donde el estándar exige espacios (NC108M FMT-TEST-GF-3). Un ítem numérico conserva ahora su categoría sea cual sea la del literal, y un literal que no deletrea ningún número deja el ítem en su valor por defecto en vez de adivinar.
=== PowerRustCOBOL 1.62.32 — 2026-08-27 ===
NIST CCVS85 Nucleus (NC): aserciones 168 -> 161 fallando (96.5 %). La ejecución se mantiene en 77 de 95 y la compilación en 95 de 95. NC252A pasa de 13 fallos -> 10, NC250A 14 -> 11, NC105A 20 -> 18, NC107A 10 -> 9, NC103A 2 -> 1. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Corregido — un MOVE de grupo descartaba cada porción que un hijo numérico no podía interpretar
Cuando el ítem receptor es un grupo, el estándar hace todo el movimiento alfanumérico: cada porción aterriza en su ítem subordinado tal cual está, diga lo que diga la PICTURE de ese ítem. Un hijo numérico tiene por tanto que poder contener caracteres que no son dígitos.
set_group almacenaba la porción cuando deletreaba un número, la almacenaba cuando era enteramente blanca, y la descartaba en cualquier otro caso — así que el hijo conservaba en silencio lo que tuviera antes. MOVE REDEF13 TO REDEF12 en NC252A mueve 120 bytes de A a un grupo cuyos hijos incluyen PIC 9(5) y seis PIC 9, y el registro volvía leyendo AAA 0AA 0AAAA, con los dígitos viejos asomando allí donde había un hijo numérico. El comentario sobre ese código ya decía que una porción no numérica "lands in the child as it stands"; solo el caso en blanco lo cumplía.
Un ítem numérico conteniendo caracteres es exactamente lo que el programa pidió. Usarlo después en aritmética es indefinido en COBOL-85, no algo que el runtime tenga que impedir.
• No hecho, y por qué — movimientos de grupo exactos al byte
Estrictamente el estándar no cambia ningún byte en un movimiento de grupo, así que una porción que sí deletrea un número debería conservar también sus propios caracteres: " 123" hacia un hijo PIC 9(5) debería quedarse " 123" en vez de re-renderizarse como 00123 a través de la PICTURE del hijo.
Se implementó y se midió: NC cayó de 77 programas limpios a 74, y las aserciones de 4406/161 a 4386/182. Muchísimos programas mueven un grupo numérico y luego calculan con sus hijos, y la normalización es lo que los mantiene funcionando. La lectura más estricta queda por tanto registrada — en set_group, y como test que fija el comportamiento actual con la medición al lado — y sin aplicar. Revertirlo exige un censo NC nuevo, no una apelación al texto.
=== PowerRustCOBOL 1.62.33 — 2026-08-28 ===
NIST CCVS85 Nucleus (NC): ejecución 77 -> 78 de 95, aserciones 117 fallando (97.4 %). NC401M pasa de 40 fallos -> 0, el último de los cinco miembros que no podían puntuarse en absoluto cuando empezó este trabajo. La compilación se mantiene en 95 de 95, la suite completa en 420 de 434. Ningún otro módulo fue tocado (GOLDEN RULE #9).
• Añadido — marcado de conformidad del high subset
|