onion_vm/lambda/scheduler/
map_scheduler.rs1use arc_gc::gc::GC;
2
3use crate::{
4 lambda::runnable::{Runnable, RuntimeError, StepResult},
5 types::{
6 lambda::launcher::OnionLambdaRunnableLauncher,
7 object::{OnionObject, OnionObjectCell, OnionStaticObject},
8 tuple::OnionTuple,
9 },
10 utils::format_object_summary,
11};
12
13#[derive(Clone)]
14pub struct Mapping {
15 pub(crate) container: OnionStaticObject,
16 pub(crate) mapper: OnionStaticObject,
17 pub(crate) collected: Vec<OnionStaticObject>,
18 pub(crate) current_index: usize,
19}
20
21impl Runnable for Mapping {
22 fn receive(
23 &mut self,
24 step_result: &StepResult,
25 _gc: &mut GC<OnionObjectCell>,
26 ) -> Result<(), RuntimeError> {
27 match step_result {
28 StepResult::Return(result) => {
29 self.collected.push(result.as_ref().clone());
30 self.current_index += 1; Ok(())
32 }
33 _ => Err(RuntimeError::DetailedError(
34 "Unexpected step result in mapping".into(),
35 )),
36 }
37 }
38
39 fn step(&mut self, _gc: &mut GC<OnionObjectCell>) -> StepResult {
40 self.container
41 .weak()
42 .with_data(|container| match container {
43 OnionObject::Tuple(tuple) => {
44 if let Some(element) = tuple.get_elements().get(self.current_index) {
46 let element_clone = element.clone();
47 self.mapper.weak().with_data(|mapper_obj| match mapper_obj {
48 OnionObject::Lambda(_) => {
49 let runnable = Box::new(OnionLambdaRunnableLauncher::new_static(
50 mapper_obj,
51 element.stabilize(),
52 &|r| Ok(r),
53 )?);
54 Ok(StepResult::NewRunnable(runnable))
55 }
56 OnionObject::Boolean(false) => Ok(StepResult::Continue),
57 _ => {
58 self.collected.push(element_clone.stabilize());
59 Ok(StepResult::Continue)
60 }
61 })
62 } else {
63 Ok(StepResult::Return(
65 OnionTuple::new_static_no_ref(&self.collected).into(),
66 ))
67 }
68 }
69 _ => Err(RuntimeError::InvalidType(
70 "Container must be a tuple".into(),
71 )),
72 })
73 .unwrap_or_else(|e| StepResult::Error(e))
74 }
75 fn format_context(&self) -> String {
76 format!(
78 "-> In 'map' operation:\n - Mapper: {}\n - Container: {}\n - Progress: Processing element {} / {}\n - Collected Items: {}",
79 format_object_summary(self.mapper.weak()),
82 format_object_summary(self.container.weak()),
84 self.current_index,
86 self.container
87 .weak()
88 .with_data(|c| {
89 Ok(if let OnionObject::Tuple(t) = c {
90 t.get_elements().len()
91 } else {
92 0 })
94 })
95 .unwrap_or(0), self.collected.len()
98 )
99 }
100}