Skip to main content

ironwork_rt/lir/
value.rs

1//! Values, expressions and conditions (lir.md §6).
2
3use super::{AbendId, CondId, ConstId, ExprId, FunctionId, Mode, Odo, PlaceId, TempId, UserFunctionId};
4use crate::codec_enum;
5use crate::vocab::{BinOp, Figurative, RelOp};
6use numeric::precision::Fixed;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum Operand {
10    Load(PlaceId),
11    Const(ConstId),
12    LengthOf(PlaceId),
13    AddressOf(PlaceId),
14    Function(FunctionId),
15    UserFunction(UserFunctionId),
16}
17
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub enum Const {
20    Bytes(Vec<u8>),
21    National(Vec<u8>),
22    Number(Fixed),
23    Figurative(Figurative),
24    All(Vec<u8>),
25    /// ALL with a national literal, its UTF-16 units.
26    AllNational(Vec<u8>),
27    /// An alphanumeric literal, or ALL one, the code page cannot encode: reading it abends, as
28    /// `literal_value` does each time it converts the literal.
29    Refused(AbendId),
30    /// A DBCS literal's bytes in the code page's DBCS component.
31    Dbcs(Vec<u8>),
32}
33
34/// `Fixed` locates each place of `prepass` before it evaluates `expr`, as the walker's dmax pass
35/// does; static places are left out.
36#[derive(Clone, Debug, PartialEq, Eq)]
37pub enum IntExpr {
38    Const(i64),
39    Item(PlaceId),
40    Fixed { expr: ExprId, dmax: u32, prepass: Vec<PlaceId> },
41    /// Subscript k of the JSON walk in progress (lir.md §9.13): FROM's subscripts, then the
42    /// occurrence of each table the walk has entered. Only a markup payload's places hold it.
43    Walk(u8),
44}
45
46#[derive(Clone, Debug, PartialEq, Eq)]
47pub enum Expr {
48    Operand(Operand),
49    Neg(ExprId),
50    Bin(ExprId, BinOp, ExprId),
51    /// In fixed point an exponent from 0 to 31, else abend IRONWORK; in floating point any (C334).
52    Pow(ExprId, IntExpr),
53}
54
55#[derive(Clone, Debug, PartialEq, Eq)]
56pub enum Cond {
57    Rel { a: Comparand, op: RelOp, b: Comparand, how: Compare },
58    Class { place: PlaceId, test: ByteClass },
59    Sign { value: Comparand, test: SignTest },
60    /// A level-88 name: equal to any value, or within any THRU pair.
61    Name { subject: PlaceId, values: Vec<(ConstId, Option<ConstId>)>, how: Compare },
62    Not(CondId),
63    And(CondId, CondId),
64    Or(CondId, CondId),
65    Counter(TempId),
66    InTable { index: PlaceId, count: Count },
67    Sql(SqlTest),
68}
69
70/// `Expr` locates each place of `prepass` (the float test's, then for `Mode::Fixed` the dmax pass's,
71/// static ones left out) before it evaluates `expr` in `mode`.
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub enum Comparand {
74    Operand(Operand),
75    Expr { expr: ExprId, dmax: u32, mode: Mode, prepass: Vec<PlaceId> },
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq)]
79pub enum Compare {
80    PackedPfd,
81    Address,
82    Float,
83    Fixed,
84    National,
85    Alphanumeric,
86    Refused(AbendId),
87    /// Two addresses, one side an object reference: equal when both identify the same object, else
88    /// less. Each side is looked up, the first first, and one that was freed or never given abends.
89    References,
90    /// A zoned integer, the first operand when `zoned_first`, against a nonnumeric one: its bytes
91    /// as `rt::store::compared_zoned_bytes` gives them, never its value, compared as alphanumeric.
92    ZonedBytes { zoned_first: bool },
93    /// A DBCS operand against DBCS, SPACE, ALL or a group, padded with DBCS spaces and in binary
94    /// order, or against national through the code page.
95    Dbcs,
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99pub enum ByteClass {
100    Packed { signed: bool },
101    Zoned { signed: bool },
102    Digits,
103    Alphabetic,
104    AlphabeticLower,
105    AlphabeticUpper,
106    /// Two bytes a character, each X'41' to X'FE', or X'4040'.
107    Dbcs,
108    /// Two bytes a character, the first X'41' to X'7E' and the second X'41' to X'FE', or X'4040'.
109    Kanji,
110    /// Every byte one of a SPECIAL-NAMES class-name's characters: bit b % 8 of `bits[b / 8]`.
111    Set { bits: [u8; 32] },
112}
113
114#[derive(Clone, Copy, Debug, PartialEq, Eq)]
115pub enum SignTest {
116    Positive,
117    Negative,
118    Zero,
119}
120
121#[derive(Clone, Debug, PartialEq, Eq)]
122pub enum Count {
123    Fixed(u32),
124    Odo(Odo),
125    /// The count `Op::SetCount` held in the top frame's counter earlier in the statement.
126    Temp(TempId),
127}
128
129/// WHENEVER's classes: SQLCODE < 0, SQLCODE = 100, or a warning.
130#[derive(Clone, Copy, Debug, PartialEq, Eq)]
131pub enum SqlTest {
132    Error,
133    NotFound,
134    Warning,
135}
136
137codec_enum!(Operand { Load(place) = 0, Const(id) = 1, LengthOf(place) = 2, AddressOf(place) = 3, Function(id) = 4, UserFunction(id) = 5 });
138codec_enum!(Const { Bytes(b) = 0, National(n) = 1, Number(f) = 2, Figurative(f) = 3, All(b) = 4, Refused(abend) = 5, AllNational(n) = 6, Dbcs(b) = 7 });
139codec_enum!(IntExpr { Const(n) = 0, Item(place) = 1, Fixed { expr, dmax, prepass } = 2, Walk(k) = 3 });
140codec_enum!(Expr { Operand(o) = 0, Neg(e) = 1, Bin(a, op, b) = 2, Pow(base, exponent) = 3 });
141codec_enum!(Cond {
142    Rel { a, op, b, how } = 0,
143    Class { place, test } = 1,
144    Sign { value, test } = 2,
145    Name { subject, values, how } = 3,
146    Not(c) = 4,
147    And(a, b) = 5,
148    Or(a, b) = 6,
149    Counter(t) = 7,
150    InTable { index, count } = 8,
151    Sql(test) = 9,
152});
153codec_enum!(Comparand { Operand(o) = 0, Expr { expr, dmax, mode, prepass } = 1 });
154codec_enum!(Compare {
155    PackedPfd = 0,
156    Address = 1,
157    Float = 2,
158    Fixed = 3,
159    National = 4,
160    Alphanumeric = 5,
161    Refused(abend) = 6,
162    References = 7,
163    ZonedBytes { zoned_first } = 8,
164    Dbcs = 9,
165});
166codec_enum!(ByteClass { Packed { signed } = 0, Zoned { signed } = 1, Digits = 2, Alphabetic = 3, AlphabeticLower = 4, AlphabeticUpper = 5, Dbcs = 6, Kanji = 7, Set { bits } = 8 });
167codec_enum!(SignTest { Positive = 0, Negative = 1, Zero = 2 });
168codec_enum!(Count { Fixed(n) = 0, Odo(odo) = 1, Temp(temp) = 2 });
169codec_enum!(SqlTest { Error = 0, NotFound = 1, Warning = 2 });