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