use crate::abend::{Abend, AbendCode};
use crate::unit::{Loader, RunUnit};
use crate::vocab::Pos;
type R<T> = Result<T, Abend>;
pub fn set<H, L: Loader<H>>(unit: &mut RunUnit<'_, H, L>, base: usize, buffer: Option<(u32, u32)>) {
if let Some((offset, len)) = buffer {
let at = base + offset as usize;
unit.mem[at..at + len as usize].fill(0xAA);
unit.mark(at, len as usize);
}
}
#[allow(clippy::too_many_arguments)]
pub fn test<'a, H, L: Loader<H>>(
unit: &mut RunUnit<'_, H, L>,
base: usize,
buffer: Option<(u32, u32)>,
arguments: impl IntoIterator<Item = (usize, &'a str)>,
called: impl FnOnce(&RunUnit<'_, H, L>) -> String,
caller: &str,
abd: bool,
pos: Pos,
) -> R<()> {
let Some((offset, len)) = buffer else { return Ok(()) };
let at = base + offset as usize;
if unit.mem[at..at + len as usize].iter().all(|&b| b == 0xAA) {
return Ok(());
}
let parameter = arguments.into_iter().filter(|&(a, _)| (base..at).contains(&a)).max_by_key(|&(a, _)| a);
let beyond = parameter.map_or(String::new(), |(_, name)| format!(", beyond parameter {name}"));
let message = format!("PARMCHECK: {}, called at line {} of program {caller}, wrote past the end of WORKING-STORAGE{beyond}", called(unit), pos.line);
if abd {
return Err(Abend { code: AbendCode::user(4038), message, pos, file: None });
}
let _ = writeln!(unit.err, "ironwork: {pos}: {message}");
Ok(())
}