ironwork_exec/machine/
le_services.rs1use super::*;
5use crate::le::{self, LeHost};
6use std::rc::Rc;
7
8impl<'p> Machine<'p, '_, '_> {
9 pub(super) fn le_call(&mut self, c: &'p Call, name: &str) -> R<Flow> {
10 let mark = self.unit.mem.len();
11 let outcome = self.le_arguments(c).and_then(|args| {
12 self.parmcheck_set();
13 self.le_service(name, &args, c.pos).map(|()| args)
14 });
15 self.unit.release_temporaries(mark);
16 self.parmcheck_test(c, &outcome?, |_| name.to_owned())?;
17 match &c.not_on_exception {
18 Some(body) => self.run_block(body),
19 None => Ok(Flow::Next),
20 }
21 }
22
23 fn le_arguments(&mut self, c: &Call) -> R<Vec<Option<usize>>> {
25 let mut addresses = Vec::new();
26 for arg in &c.using {
27 let at = match (arg.mode, &arg.value) {
28 (_, None) => None,
29 (ArgMode::Reference, Some(Operand::Ref(r))) => Some(self.locate(r)?.offset),
30 (ArgMode::Value, Some(op)) => {
31 let bytes = self.value_argument(op, c.pos)?;
32 Some(self.unit.push_temporary(&bytes))
33 }
34 (_, Some(op)) => {
35 let bytes = self.content_argument(op, c.pos)?;
36 Some(self.unit.push_temporary(&bytes))
37 }
38 };
39 addresses.push(at);
40 }
41 Ok(addresses)
42 }
43
44 fn le_service(&mut self, name: &str, args: &[Option<usize>], pos: Pos) -> R<()> {
45 match le::service(name) {
46 Some(service) => le::call(self, service, args, pos),
47 None => Err(Abend::ironwork(format!("CALL {name}: not a service ironwork provides"), pos)),
48 }
49 }
50}
51
52impl<'w> LeHost<'w> for Machine<'_, '_, 'w> {
53 type Program = Rc<Compiled>;
54 type Loader = crate::unit::Library;
55
56 fn unit(&mut self) -> &mut RunUnit<'w> {
57 self.unit
58 }
59
60 fn page(&self) -> &'static CodePage {
61 self.page
62 }
63
64 fn method_name(program: &Rc<Compiled>) -> Option<String> {
65 program.program.oo.as_deref().and_then(|o| o.method()).map(|m| format!("{}.{}", m.class, m.name))
66 }
67}