onion_vm/lambda/scheduler/
map_scheduler.rs

1use 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; // 移动到下一个元素
39                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                    // 使用索引获取当前元素
53                    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 OnionObject::Tuple(params) = lambda.parameter.try_borrow()?
58                                // else {
59                                //     return Err(RuntimeError::InvalidType(format!(
60                                //         "Map's parameter must be a tuple, got {:?}",
61                                //         lambda.parameter
62                                //     )));
63                                // };
64                                // let argument =
65                                //     params.clone_and_named_assignment(&OnionTuple::new(vec![
66                                //         element_clone,
67                                //     ]))?;
68                                // let runnable = lambda.create_runnable(argument, &self.mapper, gc)?;
69                                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                        // 所有元素都处理完了
87                        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}