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};
11
12#[derive(Clone)]
13pub struct Mapping {
14 pub(crate) container: OnionStaticObject,
15 pub(crate) mapper: OnionStaticObject,
16 pub(crate) collected: Vec<OnionStaticObject>,
17 pub(crate) current_index: usize,
18}
19
20impl Runnable for Mapping {
21 fn copy(&self) -> Box<dyn Runnable> {
22 Box::new(Mapping {
23 container: self.container.clone(),
24 mapper: self.mapper.clone(),
25 collected: self.collected.clone(),
26 current_index: self.current_index,
27 })
28 }
29
30 fn receive(
31 &mut self,
32 step_result: &StepResult,
33 _gc: &mut GC<OnionObjectCell>,
34 ) -> Result<(), RuntimeError> {
35 match step_result {
36 StepResult::Return(result) => {
37 self.collected.push(result.as_ref().clone());
38 self.current_index += 1; Ok(())
40 }
41 _ => Err(RuntimeError::DetailedError(
42 "Unexpected step result in mapping".to_string().into(),
43 )),
44 }
45 }
46
47 fn step(&mut self, _gc: &mut GC<OnionObjectCell>) -> StepResult {
48 self.container
49 .weak()
50 .with_data(|container| match container {
51 OnionObject::Tuple(tuple) => {
52 if let Some(element) = tuple.get_elements().get(self.current_index) {
54 let element_clone = element.clone();
55 self.mapper.weak().with_data(|mapper_obj| match mapper_obj {
56 OnionObject::Lambda(_) => {
57 let argument =
70 OnionObject::Tuple(OnionTuple::new(vec![element_clone]).into())
71 .stabilize();
72 let runnable = Box::new(OnionLambdaRunnableLauncher::new_static(
73 &self.mapper,
74 &argument,
75 &|r| Ok(r),
76 )?);
77 Ok(StepResult::NewRunnable(runnable))
78 }
79 OnionObject::Boolean(false) => Ok(StepResult::Continue),
80 _ => {
81 self.collected.push(element_clone.stabilize());
82 Ok(StepResult::Continue)
83 }
84 })
85 } else {
86 Ok(StepResult::Return(
88 OnionTuple::new_static_no_ref(&self.collected).into(),
89 ))
90 }
91 }
92 _ => Err(RuntimeError::InvalidType(
93 "Container must be a tuple".to_string().into(),
94 )),
95 })
96 .unwrap_or_else(|e| StepResult::Error(e))
97 }
98
99 fn format_context(&self) -> Result<serde_json::Value, RuntimeError> {
100 return Ok(serde_json::json!({
101 "type": "Mapping",
102 "container": self.container.to_string(),
103 "mapper": self.mapper.to_string(),
104 "collected": self.collected.iter().map(|o| o.to_string()).collect::<Vec<_>>(),
105 "current_index": self.current_index,
106 }));
107 }
108}