Skip to main content

ironwork_rt/lir/
text.rs

1//! INSPECT, STRING and UNSTRING (lir.md ยง9.1): the operands and receivers `crate::strings` works over,
2//! in the order the walker evaluates them.
3
4use super::{MovePlan, Operand, PlaceId, StepPlan, StorePlan};
5use crate::vocab::InspectMode;
6use crate::{codec_enum, codec_struct};
7
8/// An operand as STRING, UNSTRING, INSPECT and CALL BY CONTENT take it: bytes, not a value.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub enum Chars<P = PlaceId, O = Operand> {
11    /// A literal or figurative constant, its bytes made at lowering.
12    Literal(Vec<u8>),
13    /// A data item's storage.
14    Place(P),
15    /// FUNCTION, LENGTH OF or ADDRESS OF, converted as the statement converts a value.
16    Value(O),
17}
18
19#[derive(Clone, Debug, PartialEq, Eq)]
20pub struct InspectPlan<P = PlaceId, O = Operand> {
21    pub target: P,
22    pub tallying: Vec<InspectPhrase<P, O>>,
23    pub replacing: Vec<InspectPhrase<P, O>>,
24    pub converting: Option<Converting<P, O>>,
25}
26
27/// `pattern` is None for CHARACTERS; `by` is REPLACING's, and `counter` TALLYING's with its add.
28#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct InspectPhrase<P = PlaceId, O = Operand> {
30    pub mode: InspectMode,
31    pub pattern: Option<Chars<P, O>>,
32    pub by: Option<Replacement<P, O>>,
33    pub counter: Option<(P, StepPlan)>,
34    /// BEFORE and AFTER INITIAL as written; the last of each applies.
35    pub bounds: Vec<Bound<P, O>>,
36}
37
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub enum Replacement<P = PlaceId, O = Operand> {
40    Chars(Chars<P, O>),
41    /// A figurative constant's byte, as many times as the pattern is long.
42    Fill(u8),
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
46pub struct Bound<P = PlaceId, O = Operand> {
47    pub after: bool,
48    pub value: Chars<P, O>,
49}
50
51#[derive(Clone, Debug, PartialEq, Eq)]
52pub struct Converting<P = PlaceId, O = Operand> {
53    pub table: ConvertTable<P, O>,
54    pub bounds: Vec<Bound<P, O>>,
55}
56
57#[derive(Clone, Debug, PartialEq, Eq)]
58pub enum ConvertTable<P = PlaceId, O = Operand> {
59    /// Both operands literals: each distinct byte of the first with its byte of the second.
60    Built(Vec<(u8, u8)>),
61    /// Operands of different lengths abend when the statement runs.
62    Operands { from: Chars<P, O>, to: Chars<P, O> },
63}
64
65/// The op returns Arm(1) on overflow and Arm(0) otherwise.
66#[derive(Clone, Debug, PartialEq, Eq)]
67pub struct StringPlan<P = PlaceId, O = Operand> {
68    pub into: P,
69    /// WITH POINTER: read as an integer before the first source, stored after the last.
70    pub pointer: Option<(P, StorePlan)>,
71    pub sources: Vec<StringSource<P, O>>,
72}
73
74/// `delimiter` is None for DELIMITED BY SIZE.
75#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct StringSource<P = PlaceId, O = Operand> {
77    pub chars: Chars<P, O>,
78    pub delimiter: Option<Chars<P, O>>,
79}
80
81/// The op returns Arm(1) on overflow and Arm(0) otherwise.
82#[derive(Clone, Debug, PartialEq, Eq)]
83pub struct UnstringPlan<P = PlaceId, O = Operand> {
84    pub source: P,
85    pub pointer: Option<(P, StorePlan)>,
86    /// Each DELIMITED BY operand, true for ALL.
87    pub delimiters: Vec<(bool, Chars<P, O>)>,
88    pub into: Vec<UnstringInto<P>>,
89    /// TALLYING IN, which the count of fields filled is added to.
90    pub tallying: Option<(P, StepPlan)>,
91}
92
93/// `plan` moves the field's bytes as an alphanumeric sender; COUNT IN stores the field's length.
94#[derive(Clone, Copy, Debug, PartialEq, Eq)]
95pub struct UnstringInto<P = PlaceId> {
96    pub target: P,
97    pub plan: MovePlan,
98    pub delimiter: Option<DelimiterIn<P>>,
99    pub count: Option<(P, StorePlan)>,
100}
101
102/// `found` moves the delimiter that ended the field, and `none` moves SPACE when none did.
103#[derive(Clone, Copy, Debug, PartialEq, Eq)]
104pub struct DelimiterIn<P = PlaceId> {
105    pub target: P,
106    pub found: MovePlan,
107    pub none: MovePlan,
108}
109
110codec_enum!(Chars { Literal(bytes) = 0, Place(place) = 1, Value(value) = 2 });
111codec_struct!(InspectPlan { target, tallying, replacing, converting });
112codec_struct!(InspectPhrase { mode, pattern, by, counter, bounds });
113codec_enum!(Replacement { Chars(chars) = 0, Fill(byte) = 1 });
114codec_struct!(Bound { after, value });
115codec_struct!(Converting { table, bounds });
116codec_enum!(ConvertTable { Built(pairs) = 0, Operands { from, to } = 1 });
117codec_struct!(StringPlan { into, pointer, sources });
118codec_struct!(StringSource { chars, delimiter });
119codec_struct!(UnstringPlan { source, pointer, delimiters, into, tallying });
120codec_struct!(UnstringInto { target, plan, delimiter, count });
121codec_struct!(DelimiterIn { target, found, none });