tawasuyu

tawasuyu/brahman

Rust 506TOML 198Markdown 56JSON 197212 Sutichaykuna

⎇ 321e6f8e27aea06b5a868b37598148e15bf71f57 crates/modules/charka/charka-ir/src/ast.rs Rust · 209 siq'ikuna · 5.5 KB Ñawpa willay Pi imata llamkarqan ch'uya

feat(charka): PERFORM VARYING — el bucle con variable de control 321e6f8e2 · 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 modelo de datos — el árbol de [`DataItem`] tal cual lo
12    /// produjo `charka-parser`. Sirve de tabla de símbolos.
13    pub data: Vec<DataItem>,
14    /// Los párrafos del PROCEDURE, con sus statements ya tipados.
15    pub procedures: Vec<Procedure>,
16}
17
18/// Un párrafo del PROCEDURE: un nombre y un cuerpo de statements.
19#[derive(Debug, Clone, PartialEq, Default)]
20pub struct Procedure {
21    /// Nombre del párrafo en mayúsculas; "" para el párrafo implícito.
22    pub name: String,
23    /// Los statements del párrafo, en orden.
24    pub body: Vec<Stmt>,
25}
26
27/// Un operando: lo que puede ir donde se espera un valor.
28#[derive(Debug, Clone, PartialEq)]
29pub enum Operand {
30    /// Referencia a un dato, por nombre (en mayúsculas).
31    Data(String),
32    /// Literal numérico (texto, posiblemente con signo).
33    Num(String),
34    /// Literal de texto.
35    Str(String),
36    /// Constante figurativa (`ZERO`, `SPACE`...).
37    Figurative(Figurative),
38}
39
40/// Las constantes figurativas de COBOL.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub enum Figurative {
43    Zero,
44    Space,
45    HighValue,
46    LowValue,
47    Quote,
48    Null,
49}
50
51/// Una expresión aritmética (la parte derecha de un `COMPUTE`).
52#[derive(Debug, Clone, PartialEq)]
53pub enum Expr {
54    /// Un operando hoja.
55    Operand(Operand),
56    /// Negación unaria.
57    Neg(Box<Expr>),
58    /// Operación binaria.
59    Binary {
60        op: BinOp,
61        lhs: Box<Expr>,
62        rhs: Box<Expr>,
63    },
64}
65
66/// Operador aritmético binario.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum BinOp {
69    Add,
70    Sub,
71    Mul,
72    Div,
73    /// Exponenciación (`**`).
74    Pow,
75}
76
77/// Una condición (la guarda de un `IF` o de un `PERFORM UNTIL`).
78#[derive(Debug, Clone, PartialEq)]
79pub enum Cond {
80    /// Comparación relacional `lhs op rhs`.
81    Compare {
82        lhs: Operand,
83        op: CmpOp,
84        rhs: Operand,
85    },
86    /// Un nombre de condición (un dato de nivel 88) usado solo.
87    Named(String),
88    /// Negación lógica.
89    Not(Box<Cond>),
90    /// Conjunción lógica.
91    And(Box<Cond>, Box<Cond>),
92    /// Disyunción lógica.
93    Or(Box<Cond>, Box<Cond>),
94}
95
96/// Operador relacional.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum CmpOp {
99    Eq,
100    Ne,
101    Lt,
102    Gt,
103    Le,
104    Ge,
105}
106
107/// Un statement del PROCEDURE division.
108#[derive(Debug, Clone, PartialEq)]
109pub enum Stmt {
110    /// `MOVE from TO to...`
111    Move { from: Operand, to: Vec<String> },
112    /// `DISPLAY items...`
113    Display { items: Vec<Operand> },
114    /// `ACCEPT into`
115    Accept { into: String },
116    /// `COMPUTE targets... [ROUNDED] = expr`
117    Compute {
118        targets: Vec<String>,
119        rounded: bool,
120        expr: Expr,
121    },
122    /// `ADD addends... TO to... [GIVING giving...]`
123    Add {
124        addends: Vec<Operand>,
125        to: Vec<String>,
126        giving: Vec<String>,
127        rounded: bool,
128    },
129    /// `SUBTRACT amounts... FROM from... [GIVING giving...]`
130    Subtract {
131        amounts: Vec<Operand>,
132        from: Vec<String>,
133        giving: Vec<String>,
134        rounded: bool,
135    },
136    /// `MULTIPLY left BY by [GIVING giving...]`
137    Multiply {
138        left: Operand,
139        by: Operand,
140        giving: Vec<String>,
141        rounded: bool,
142    },
143    /// `DIVIDE left {BY|INTO} right [GIVING giving...]`. `by_form` es
144    /// true para `BY` (`left/right`), false para `INTO` (`right/left`).
145    Divide {
146        left: Operand,
147        right: Operand,
148        by_form: bool,
149        giving: Vec<String>,
150        rounded: bool,
151    },
152    /// `IF cond [THEN] then_branch [ELSE else_branch] [END-IF]`
153    If {
154        cond: Cond,
155        then_branch: Vec<Stmt>,
156        else_branch: Vec<Stmt>,
157    },
158    /// `PERFORM ...` — ver [`Perform`].
159    Perform(Perform),
160    /// `GO TO target`
161    GoTo { target: String },
162    /// `STOP RUN`
163    StopRun,
164    /// `GOBACK`
165    Goback,
166    /// `EXIT` (y sus variantes `EXIT PROGRAM`/`PARAGRAPH`...).
167    Exit,
168    /// `CONTINUE` — el no-op de COBOL.
169    Continue,
170    /// Un verbo que la v1 no parsea: se conserva crudo para que las
171    /// etapas siguientes (o un humano) lo revisen.
172    Unknown { verb: String, tokens: Vec<Token> },
173}
174
175/// Un statement `PERFORM`: a quién ejecuta y cuántas veces.
176#[derive(Debug, Clone, PartialEq)]
177pub struct Perform {
178    pub target: PerformTarget,
179    pub control: PerformControl,
180}
181
182/// El cuerpo que un `PERFORM` ejecuta.
183#[derive(Debug, Clone, PartialEq)]
184pub enum PerformTarget {
185    /// `PERFORM PARA [THRU PARA2]` — ejecuta uno o un rango de párrafos.
186    Paragraph { name: String, thru: Option<String> },
187    /// `PERFORM ... statements ... END-PERFORM` — cuerpo en línea.
188    Inline(Vec<Stmt>),
189}
190
191/// Cuántas veces se ejecuta el cuerpo de un `PERFORM`.
192#[derive(Debug, Clone, PartialEq)]
193pub enum PerformControl {
194    /// Una sola vez.
195    Once,
196    /// `n TIMES`.
197    Times(Operand),
198    /// `UNTIL cond`.
199    Until(Cond),
200    /// `VARYING var FROM from BY by UNTIL until` — el bucle con
201    /// variable de control: `var = from`; mientras no se cumpla
202    /// `until`, ejecuta el cuerpo y hace `var = var + by`.
203    Varying {
204        var: String,
205        from: Operand,
206        by: Operand,
207        until: Cond,
208    },
209}