3902763daa
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>
35 lines
1.1 KiB
Rust
35 lines
1.1 KiB
Rust
//! El estado de los datos durante la ejecución sombra: el modelo de
|
|
//! datos resuelto de `charka-ir` se materializa en campos vivos.
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use charka_ir::{DataModel, FieldKind};
|
|
use charka_runtime::{Num, Picture, Text};
|
|
|
|
/// Un campo vivo. Todo campo es un vector: un dato escalar es un
|
|
/// vector de un elemento; una tabla (`OCCURS n`) es de `n` elementos.
|
|
pub(crate) enum Cell {
|
|
Num(Vec<Num>),
|
|
Text(Vec<Text>),
|
|
}
|
|
|
|
/// Materializa los campos del modelo en un mapa `nombre → campo`.
|
|
pub(crate) fn build_fields(model: &DataModel) -> HashMap<String, Cell> {
|
|
let mut map = HashMap::new();
|
|
for f in &model.fields {
|
|
let n = f.occurs.unwrap_or(1).max(1) as usize;
|
|
let cell = match f.kind {
|
|
FieldKind::Num { int, frac, signed } => Cell::Num(vec![
|
|
Num::with_value(
|
|
Picture::new(int, frac, signed),
|
|
&f.init
|
|
);
|
|
n
|
|
]),
|
|
FieldKind::Text { len } => Cell::Text(vec![Text::with_value(len, &f.init); n]),
|
|
};
|
|
map.entry(f.name.clone()).or_insert(cell);
|
|
}
|
|
map
|
|
}
|