1use super::*;
5use crate::collating::Sequence;
6use crate::picture::Sym;
7use crate::files::{Dd, Keying, Open};
8use crate::printer::{self, Space};
9use rt::callee::Arguments;
10use rt::fileio::{self, Advance, Files};
11use rt::host::{Host, Values};
12use rt::lir::{self, Chars, Replacement};
13use rt::store::{LaxRedefinition, ProgramFacts};
14use rt::text;
15use rt::unit::UnitHost;
16use std::rc::Rc;
17
18#[derive(Clone, Copy)]
19pub struct Facts<'p> {
20 layout: &'p Layout,
21 collating: &'p Sequence,
22 options: Options,
23 page: &'static CodePage,
24 decimal_point: char,
25}
26
27impl ProgramFacts for Facts<'_> {
28 fn options(&self) -> Options {
29 self.options
30 }
31
32 fn page(&self) -> &'static CodePage {
33 self.page
34 }
35
36 fn figurative(&self, f: Figurative) -> u8 {
37 self.collating.figurative(f)
38 }
39
40 fn collation(&self) -> &Collation {
41 self.collating.collation()
42 }
43
44 fn ordinal(&self, byte: u8) -> u16 {
45 self.collating.ordinal(byte)
46 }
47
48 fn character(&self, ordinal: i64) -> Option<u8> {
49 self.collating.character(ordinal)
50 }
51
52 fn characters(&self) -> usize {
53 self.collating.count()
54 }
55
56 fn decimal_point(&self) -> char {
57 self.decimal_point
58 }
59
60 fn edit(&self, edit: u32) -> (&[Sym], &str) {
61 (&self.layout.edits[edit as usize], &self.layout.currencies[edit as usize])
62 }
63
64 fn scaling(&self, item: usize) -> u32 {
65 self.layout.items.get(item).map_or(0, |i| i.scaling)
66 }
67
68 fn item_name(&self, item: usize) -> String {
70 self.layout.items.get(item).map_or("RETURN-CODE".into(), |i| i.name.clone().unwrap_or_else(|| "FILLER".into()))
71 }
72
73 fn lax_redefinition(&self, item: usize) -> Option<LaxRedefinition> {
74 self.layout.numcheck.lax(item)
75 }
76
77 fn numcheck_removed(&self, item: usize, pos: Pos) -> bool {
78 self.layout.numcheck.removed(item, pos)
79 }
80}
81
82impl<'p> Machine<'p, '_, '_> {
83 pub(super) fn facts(&self) -> Facts<'p> {
85 Facts { layout: self.layout, collating: self.collating, options: self.options, page: self.page, decimal_point: self.decimal_point() }
86 }
87}
88
89pub(super) fn inspect_phrase(p: &InspectPhrase) -> text::InspectPhrase<&Ref, &Operand> {
91 let by = p.by.as_ref().map(|op| Replacement::Chars(chars(op)));
92 text::InspectPhrase { mode: p.mode, pattern: p.pattern.as_ref().map(chars), by, counter: p.counter.as_ref(), bounds: bounds(&p.bounds) }
93}
94
95pub(super) fn chars(op: &Operand) -> Chars<&Ref, &Operand> {
97 match op {
98 Operand::Ref(r) => Chars::Place(r),
99 other => Chars::Value(other),
100 }
101}
102
103pub(super) fn bounds(bounds: &[Bound]) -> Vec<lir::Bound<&Ref, &Operand>> {
104 bounds.iter().map(|b| lir::Bound { after: b.after, value: chars(&b.value) }).collect()
105}
106
107impl<'a, 'p> Host<&'a Ref> for Machine<'p, '_, '_> {
108 type Facts = Facts<'p>;
109
110 fn facts(&self) -> Facts<'p> {
111 Machine::facts(self)
112 }
113
114 fn mem(&mut self) -> &mut [u8] {
115 &mut self.unit.mem
116 }
117
118 fn taint(&mut self) -> Option<&mut rt::taint::Taint> {
119 self.unit.taint.as_mut()
120 }
121
122 fn locate(&mut self, place: &'a Ref, receiving: bool) -> R<Loc> {
123 self.locate_as(place, receiving)
124 }
125
126 fn integer(&mut self, place: &'a Ref, pos: Pos) -> R<i64> {
127 Machine::integer(self, &Expr::Operand(Operand::Ref(place.clone())), pos)
128 }
129
130 fn assign(&mut self, dest: Loc, val: Val, src: Option<Loc>, pos: Pos) -> R<()> {
131 store::assign(&self.facts(), self.unit, dest, val, src, pos)
132 }
133
134 fn store_fixed(&mut self, dest: Loc, value: &Fixed, pos: Pos) -> R<()> {
135 store::store_fixed(&self.facts(), self.unit, dest, value, false, pos)
136 }
137}
138
139impl<'a> Values<&'a Ref, &'a Operand> for Machine<'_, '_, '_> {
140 fn value(&mut self, operand: &&'a Operand, pos: Pos) -> R<Val> {
141 self.operand(operand, pos)
142 }
143}
144
145impl<'w> UnitHost<'w> for Machine<'_, '_, 'w> {
146 type Program = Rc<Compiled>;
147 type Loader = crate::unit::Library;
148
149 fn unit(&mut self) -> &mut RunUnit<'w> {
150 self.unit
151 }
152}
153
154impl<'a, 'w> Arguments<'w, &'a Ref, &'a Operand> for Machine<'_, '_, 'w> {
155 fn item(&self, operand: &&'a Operand) -> Option<&'a Ref> {
156 match *operand {
157 Operand::Ref(r) => Some(r),
158 _ => None,
159 }
160 }
161
162 fn length_of(&self, operand: &&'a Operand) -> bool {
163 matches!(operand, Operand::LengthOf(_))
164 }
165
166 fn content_item(&mut self, place: &'a Ref) -> R<Loc> {
167 let loc = self.locate(place)?;
168 self.numcheck(loc, false, place.pos)?;
169 Ok(loc)
170 }
171}
172
173#[derive(Clone, Copy)]
175pub(super) enum Int<'a> {
176 Linage(&'a LinageValue),
177 Count(&'a Expr),
178}
179
180impl<'p> Machine<'p, '_, '_> {
181 pub(super) fn file_desc(&self, k: usize) -> fileio::File<'p, &'p Ref, Int<'p>> {
183 let (program, layout) = (self.program, self.layout);
184 let decl = &program.files[k];
185 let counter = layout.linage_counters.get(k).copied().flatten().map(|i| {
186 let item = &layout.items[i];
187 Loc { offset: self.base + item.offset as usize, len: item.size as usize, kind: item.kind, item: i }
188 });
189 fileio::File {
190 index: k,
191 name: &decl.name,
192 assign: &decl.assign,
193 assign_item: decl.assign_item.as_ref().map(|a| (&a.reference, decl.pos)),
194 organization: match decl.organization {
195 Organization::Sequential => lir::Organization::Sequential,
196 Organization::LineSequential => lir::Organization::LineSequential,
197 Organization::Indexed => lir::Organization::Indexed,
198 Organization::Relative => lir::Organization::Relative,
199 },
200 access: match decl.access {
201 Access::Sequential => lir::Access::Sequential,
202 Access::Random => lir::Access::Random,
203 Access::Dynamic => lir::Access::Dynamic,
204 },
205 optional: decl.optional,
206 format: self.described_format(k),
207 status: decl.status.as_ref(),
208 relative: decl.relative_key.as_ref(),
209 linage: decl.linage.as_ref().map(|l| fileio::Linage {
210 lines: Int::Linage(&l.lines),
211 footing: l.footing.as_ref().map(Int::Linage),
212 top: l.top.as_ref().map(Int::Linage),
213 bottom: l.bottom.as_ref().map(Int::Linage),
214 counter,
215 }),
216 carriage: self.carriage[k].map(|c| lir::Carriage { machine: c.machine, reserved: c.reserved }),
217 area: self.area(k),
218 read_lengths: {
219 let (shortest, longest) = compile::read_lengths(decl, layout, k, self.options.vlr);
220 (shortest as usize, longest as usize)
221 },
222 depending: decl.record_depending.as_ref().map(|item| {
223 let (shortest, longest) = compile::varying_lengths(decl, layout, k);
224 fileio::Depending { item, lengths: (shortest as usize, longest as usize) }
225 }),
226 }
227 }
228}
229
230pub(super) fn spacing(space: Space) -> lir::Spacing {
231 match space {
232 Space::Lines(n) => lir::Spacing::Lines(n),
233 Space::Channel(c) => lir::Spacing::Channel(c),
234 Space::PageMode => lir::Spacing::PageMode,
235 }
236}
237
238pub(super) fn advance(a: &Advancing) -> Advance<'_, Int<'_>> {
239 match a {
240 Advancing::Lines { before, count } => Advance::Lines { before: *before, count: Int::Count(count) },
241 Advancing::Page { before } => Advance::Page { before: *before },
242 Advancing::Mnemonic { before, name, environment } => Advance::Mnemonic { before: *before, space: printer::mnemonic_space(environment).map(spacing), name, environment },
243 }
244}
245
246impl<'a> Files<&'a Ref, Int<'a>> for Machine<'_, '_, '_> {
247 fn slot(&mut self, k: usize) -> &mut Option<Open> {
248 self.unit.file(self.me, k)
249 }
250
251 fn locked(&mut self, k: usize) -> &mut bool {
252 self.unit.locked(self.me, k)
253 }
254
255 fn dd(&self, assign: &str) -> Option<Dd> {
256 self.unit.dds.get(assign)
257 }
258
259 fn notify(&mut self, event: Event<'_>) {
260 self.unit.notify(event);
261 }
262
263 fn sink(&mut self, kind: &'static str, pos: Pos, operand: &str) {
264 Machine::sink(self, kind, pos, operand);
265 }
266
267 fn int(&mut self, value: Int<'a>, pos: Pos) -> R<i64> {
268 match value {
269 Int::Linage(v) => self.linage_value(v, pos),
270 Int::Count(e) => self.integer(e, pos),
271 }
272 }
273
274 fn keying(&mut self, k: usize, pos: Pos) -> R<Keying> {
275 Machine::keying(self, k, pos)
276 }
277
278 fn key_value(&mut self, k: usize, keying: &Keying, key: &'a Ref, partial: bool, pos: Pos) -> R<(usize, Vec<u8>)> {
279 self.key_named(k, keying, key, partial, pos)
280 }
281}