tawasuyu

tawasuyu/brahman

Rust 582TOML 222Markdown 83JSON 198635 Definitions

⎇ fa65f202065abca26e0fb28581427117b84af85c crates/modules/charka/charka-ir/src/ast.rs Rust · 272 lines · 7.8 KB History Who touched what raw

feat(charka): INITIALIZE — resetear datos y grupos fa65f2020 · sergio ·

1//! Los tipos del IR: el programa COBOL con su PROCEDURE division ya
2//! parseada a instrucciones tipadas.
3
4pub use charka_parser::{DataItem, Token};
5
6/// Un programa COBOL en representación intermedia.
7#[derive(Debug, Clone, PartialEq, Default)]
8pub struct Ir {
9    /// El `PROGRAM-ID` ("" si el programa no lo declara).
10    pub program_id: String,
11    /// El árbol de [`DataItem`] tal cual lo produjo `charka-parser`,
12    /// con su estructura de grupos.
13    pub data: Vec<DataItem>,
14    /// El modelo de datos resuelto: los datos elementales aplanados y
15    /// los nombres de condición (nivel 88).
16    pub model: crate::model::DataModel,
17    /// Los párrafos del PROCEDURE, con sus statements ya tipados.
18    pub procedures: Vec<Procedure>,
19}
20
21/// Un párrafo del PROCEDURE: un nombre y un cuerpo de statements.
22#[derive(Debug, Clone, PartialEq, Default)]
23pub struct Procedure {
24    /// Nombre del párrafo en mayúsculas; "" para el párrafo implícito.
25    pub name: String,
26    /// Los statements del párrafo, en orden.
27    pub body: Vec<Stmt>,
28}
29
30/// Un operando: lo que puede ir donde se espera un valor.
31#[derive(Debug, Clone, PartialEq)]
32pub enum Operand {
33    /// Referencia a un dato, por nombre (en mayúsculas).
34    Data(String),
35    /// Referencia a un elemento de tabla: `name(index)`. El subíndice
36    /// es 1-based, como en COBOL.
37    Indexed { name: String, index: Box<Operand> },
38    /// Literal numérico (texto, posiblemente con signo).
39    Num(String),
40    /// Literal de texto.
41    Str(String),
42    /// Constante figurativa (`ZERO`, `SPACE`...).
43    Figurative(Figurative),
44}
45
46/// Las constantes figurativas de COBOL.
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum Figurative {
49    Zero,
50    Space,
51    HighValue,
52    LowValue,
53    Quote,
54    Null,
55}
56
57/// Una expresión aritmética (la parte derecha de un `COMPUTE`).
58#[derive(Debug, Clone, PartialEq)]
59pub enum Expr {
60    /// Un operando hoja.
61    Operand(Operand),
62    /// Negación unaria.
63    Neg(Box<Expr>),
64    /// Operación binaria.
65    Binary {
66        op: BinOp,
67        lhs: Box<Expr>,
68        rhs: Box<Expr>,
69    },
70}
71
72/// Operador aritmético binario.
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub enum BinOp {
75    Add,
76    Sub,
77    Mul,
78    Div,
79    /// Exponenciación (`**`).
80    Pow,
81}
82
83/// Una condición (la guarda de un `IF` o de un `PERFORM UNTIL`).
84#[derive(Debug, Clone, PartialEq)]
85pub enum Cond {
86    /// Comparación relacional `lhs op rhs`.
87    Compare {
88        lhs: Operand,
89        op: CmpOp,
90        rhs: Operand,
91    },
92    /// Un nombre de condición (un dato de nivel 88) usado solo.
93    Named(String),
94    /// Negación lógica.
95    Not(Box<Cond>),
96    /// Conjunción lógica.
97    And(Box<Cond>, Box<Cond>),
98    /// Disyunción lógica.
99    Or(Box<Cond>, Box<Cond>),
100}
101
102/// Operador relacional.
103#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104pub enum CmpOp {
105    Eq,
106    Ne,
107    Lt,
108    Gt,
109    Le,
110    Ge,
111}
112
113/// Un statement del PROCEDURE division.
114#[derive(Debug, Clone, PartialEq)]
115pub enum Stmt {
116    /// `MOVE from TO to...`
117    Move { from: Operand, to: Vec<Operand> },
118    /// `DISPLAY items...`
119    Display { items: Vec<Operand> },
120    /// `ACCEPT into`
121    Accept { into: Operand },
122    /// `COMPUTE targets... [ROUNDED] = expr`
123    Compute {
124        targets: Vec<Operand>,
125        rounded: bool,
126        expr: Expr,
127    },
128    /// `ADD addends... TO to... [GIVING giving...]`
129    Add {
130        addends: Vec<Operand>,
131        to: Vec<Operand>,
132        giving: Vec<Operand>,
133        rounded: bool,
134    },
135    /// `SUBTRACT amounts... FROM from... [GIVING giving...]`
136    Subtract {
137        amounts: Vec<Operand>,
138        from: Vec<Operand>,
139        giving: Vec<Operand>,
140        rounded: bool,
141    },
142    /// `MULTIPLY left BY by [GIVING giving...]`
143    Multiply {
144        left: Operand,
145        by: Operand,
146        giving: Vec<Operand>,
147        rounded: bool,
148    },
149    /// `DIVIDE left {BY|INTO} right [GIVING giving...]`. `by_form` es
150    /// true para `BY` (`left/right`), false para `INTO` (`right/left`).
151    Divide {
152        left: Operand,
153        right: Operand,
154        by_form: bool,
155        giving: Vec<Operand>,
156        rounded: bool,
157    },
158    /// `IF cond [THEN] then_branch [ELSE else_branch] [END-IF]`
159    If {
160        cond: Cond,
161        then_branch: Vec<Stmt>,
162        else_branch: Vec<Stmt>,
163    },
164    /// `EVALUATE subject WHEN ... [WHEN OTHER ...] END-EVALUATE` — el
165    /// `case` de COBOL. Una rama se elige si `subject` es igual a
166    /// alguno de sus valores; sin caída entre ramas.
167    Evaluate {
168        subject: Operand,
169        whens: Vec<WhenBranch>,
170        /// El cuerpo de `WHEN OTHER` (vacío si no hay).
171        other: Vec<Stmt>,
172    },
173    /// `STRING sources... DELIMITED BY SIZE INTO into` — concatena el
174    /// texto de los `sources` en `into`.
175    StringConcat {
176        sources: Vec<Operand>,
177        into: Operand,
178    },
179    /// `UNSTRING source DELIMITED BY delimiter INTO into...` — parte el
180    /// texto de `source` por `delimiter` y reparte los trozos.
181    Unstring {
182        source: Operand,
183        delimiter: Operand,
184        into: Vec<Operand>,
185    },
186    /// `INSPECT target ...` — cuenta o reemplaza caracteres.
187    Inspect { target: Operand, op: InspectOp },
188    /// `INITIALIZE targets...` — pone cada dato (o grupo) en su valor
189    /// por defecto: 0 los numéricos, espacios los alfanuméricos.
190    Initialize { targets: Vec<Operand> },
191    /// `PERFORM ...` — ver [`Perform`].
192    Perform(Perform),
193    /// `GO TO target`
194    GoTo { target: String },
195    /// `STOP RUN`
196    StopRun,
197    /// `GOBACK`
198    Goback,
199    /// `EXIT` (y sus variantes `EXIT PROGRAM`/`PARAGRAPH`...).
200    Exit,
201    /// `CONTINUE` — el no-op de COBOL.
202    Continue,
203    /// Un verbo que la v1 no parsea: se conserva crudo para que las
204    /// etapas siguientes (o un humano) lo revisen.
205    Unknown { verb: String, tokens: Vec<Token> },
206}
207
208/// La operación de un `INSPECT`.
209#[derive(Debug, Clone, PartialEq)]
210pub enum InspectOp {
211    /// `TALLYING counter FOR ALL search` — suma a `counter` la cantidad
212    /// de apariciones de `search` en el destino.
213    TallyingForAll { counter: Operand, search: Operand },
214    /// `REPLACING ALL from BY to` — reemplaza las apariciones de `from`.
215    ReplacingAll { from: Operand, to: Operand },
216}
217
218/// Cómo una rama `WHEN` decide si se dispara.
219#[derive(Debug, Clone, PartialEq)]
220pub enum WhenTest {
221    /// El sujeto es igual a este valor.
222    Value(Operand),
223    /// El sujeto está en el rango `[lo, hi]` (`WHEN lo THRU hi`).
224    Range(Operand, Operand),
225    /// La condición se cumple — la forma `EVALUATE TRUE WHEN cond`.
226    Cond(Cond),
227}
228
229/// Una rama `WHEN` de un `EVALUATE`: las pruebas que la disparan
230/// (varios `WHEN` apilados comparten cuerpo) y el cuerpo a ejecutar.
231/// La rama se dispara si **alguna** de sus pruebas pasa.
232#[derive(Debug, Clone, PartialEq)]
233pub struct WhenBranch {
234    pub tests: Vec<WhenTest>,
235    pub body: Vec<Stmt>,
236}
237
238/// Un statement `PERFORM`: a quién ejecuta y cuántas veces.
239#[derive(Debug, Clone, PartialEq)]
240pub struct Perform {
241    pub target: PerformTarget,
242    pub control: PerformControl,
243}
244
245/// El cuerpo que un `PERFORM` ejecuta.
246#[derive(Debug, Clone, PartialEq)]
247pub enum PerformTarget {
248    /// `PERFORM PARA [THRU PARA2]` — ejecuta uno o un rango de párrafos.
249    Paragraph { name: String, thru: Option<String> },
250    /// `PERFORM ... statements ... END-PERFORM` — cuerpo en línea.
251    Inline(Vec<Stmt>),
252}
253
254/// Cuántas veces se ejecuta el cuerpo de un `PERFORM`.
255#[derive(Debug, Clone, PartialEq)]
256pub enum PerformControl {
257    /// Una sola vez.
258    Once,
259    /// `n TIMES`.
260    Times(Operand),
261    /// `UNTIL cond`.
262    Until(Cond),
263    /// `VARYING var FROM from BY by UNTIL until` — el bucle con
264    /// variable de control: `var = from`; mientras no se cumpla
265    /// `until`, ejecuta el cuerpo y hace `var = var + by`.
266    Varying {
267        var: String,
268        from: Operand,
269        by: Operand,
270        until: Cond,
271    },
272}