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