gioser

tawasuyu/brahman

Rust 321TOML 122JSON 14Markdown 114270 Sutichaykuna

⎇ 28ee1ae2602662b216549ba4db0d34a9b55b8deb crates/modules/charka/charka-ir/src/ast.rs Rust · 229 siq'ikuna · 6.2 KB Ñawpa willay Pi imata llamkarqan ch'uya

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