1use super::*;
6use crate::files::Format;
7use rt::lir::Spacing;
8use rt::report::{ReportFile, ReportHost, ReportOp, UseEnd};
9use std::io::Write;
10use syntax::report::ReportStmt;
11
12impl<'p> Machine<'p, '_, '_> {
13 pub(super) fn report_statement(&mut self, s: &'p ReportStmt) -> R<Flow> {
14 let writer = self.report_writer;
15 let run = |m: &mut Self, op, pos| rt::report::run(m, writer, op, pos);
16 let ended = match s {
17 ReportStmt::Initiate { reports, pos } | ReportStmt::Terminate { reports, pos } => {
18 let mut ended = None;
19 for n in reports {
20 let ri = self.report_named(n, *pos)? as u32;
21 let op = if matches!(s, ReportStmt::Initiate { .. }) { ReportOp::Initiate(ri) } else { ReportOp::Terminate(ri) };
22 ended = run(self, op, *pos)?;
23 if ended.is_some() {
24 break;
25 }
26 }
27 ended
28 }
29 ReportStmt::Generate { name, qualifier, pos } => {
30 let (ri, detail) = crate::report::generate_target(&writer.reports, name, qualifier.as_deref())
31 .ok_or_else(|| Abend::ironwork(format!("GENERATE {name}: no such DETAIL group or report"), *pos))?;
32 run(self, ReportOp::Generate { report: ri as u32, detail: detail.map(|d| d as u32) }, *pos)?
33 }
34 ReportStmt::Suppress { pos } => run(self, ReportOp::Suppress, *pos)?,
35 };
36 Ok(match ended {
37 Some(e) => Flow::End(e),
38 None => Flow::Next,
39 })
40 }
41
42 fn report_named(&self, name: &str, pos: Pos) -> R<usize> {
43 self.report_writer.reports.iter().position(|r| r.name == name).ok_or_else(|| Abend::ironwork(format!("{name} is not a report of this program"), pos))
44 }
45}
46
47impl<'p> ReportHost<'p, Expr, Ref, Literal, crate::report::Section> for Machine<'p, '_, '_> {
48 fn value(&mut self, expr: &Expr, pos: Pos) -> R<Val> {
49 self.expr_value(expr, pos)
50 }
51
52 fn operand(&mut self, expr: &Expr, pos: Pos) -> Option<R<(Val, Option<Loc>)>> {
53 match expr {
54 Expr::Operand(op) => Some(self.operand_with_loc(op, pos)),
55 _ => None,
56 }
57 }
58
59 fn literal(&mut self, value: &Literal, pos: Pos) -> R<Val> {
60 self.literal_value(value, pos)
61 }
62
63 fn item(&self, item: usize) -> Loc {
64 let it = &self.layout.items[item];
65 Loc { offset: self.base + it.offset as usize, len: it.size as usize, kind: it.kind, item }
66 }
67
68 fn store_value(&mut self, dest: Loc, value: Val, rounded: bool, keep_on_size_error: bool, pos: Pos) -> R<bool> {
69 store::store_value(&self.facts(), self.unit, dest, value, rounded, keep_on_size_error, pos)
70 }
71
72 fn store_checked(&mut self, dest: Loc, value: &Fixed, pos: Pos) -> R<bool> {
73 store::store_fixed_checked(&self.facts(), self.unit, dest, value, false, true, pos)
74 }
75
76 fn report_file(&mut self, k: usize) -> ReportFile {
77 ReportFile {
78 area: self.area(k),
79 variable: self.unit.programs[self.me].files[k].as_ref().is_some_and(|f| f.format == Format::Variable),
80 reserved: self.carriage[k].is_some_and(|c| c.reserved),
81 record_min: self.program.files[k].record_min,
82 }
83 }
84
85 fn write_line(&mut self, k: usize, loc: Loc, space: Spacing, pos: Pos) -> R<()> {
86 self.write_stream(k, loc, false, space, pos)
87 }
88
89 fn use_before_reporting(&mut self, &(first, last): &crate::report::Section, pos: Pos) -> R<UseEnd> {
90 self.unit.enter(pos)?;
91 self.uses.arrival = declaratives::Arrival::Use;
92 let flow = self.run_paragraphs(first, last);
93 self.unit.depth -= 1;
94 Ok(match flow? {
95 Flow::End(e) => UseEnd::End(e),
96 Flow::GoTo(_) => UseEnd::GoTo,
97 leaving @ (Flow::Resume(..) | Flow::Return(_)) => {
98 self.uses.leaving = Some(leaving);
99 UseEnd::Left
100 }
101 _ => UseEnd::Completed,
102 })
103 }
104
105 fn err(&mut self) -> &mut dyn Write {
106 &mut *self.unit.err
107 }
108}