1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use arc_gc::gc::GC;
use crate::{
lambda::runnable::{Runnable, RuntimeError, StepResult},
types::{
lambda::launcher::OnionLambdaRunnableLauncher,
object::{OnionObject, OnionObjectCell, OnionStaticObject},
tuple::OnionTuple,
},
};
#[derive(Clone)]
pub struct Mapping {
pub(crate) container: OnionStaticObject,
pub(crate) mapper: OnionStaticObject,
pub(crate) collected: Vec<OnionStaticObject>,
pub(crate) current_index: usize,
}
impl Runnable for Mapping {
fn copy(&self) -> Box<dyn Runnable> {
Box::new(Mapping {
container: self.container.clone(),
mapper: self.mapper.clone(),
collected: self.collected.clone(),
current_index: self.current_index,
})
}
fn receive(
&mut self,
step_result: &StepResult,
_gc: &mut GC<OnionObjectCell>,
) -> Result<(), RuntimeError> {
match step_result {
StepResult::Return(result) => {
self.collected.push(result.as_ref().clone());
self.current_index += 1; // 移动到下一个元素
Ok(())
}
_ => Err(RuntimeError::DetailedError(
"Unexpected step result in mapping".to_string().into(),
)),
}
}
fn step(&mut self, _gc: &mut GC<OnionObjectCell>) -> StepResult {
self.container
.weak()
.with_data(|container| match container {
OnionObject::Tuple(tuple) => {
// 使用索引获取当前元素
if let Some(element) = tuple.get_elements().get(self.current_index) {
let element_clone = element.clone();
self.mapper.weak().with_data(|mapper_obj| match mapper_obj {
OnionObject::Lambda(_) => {
// let OnionObject::Tuple(params) = &*lambda.parameter.try_borrow()?
// else {
// return Err(RuntimeError::InvalidType(format!(
// "Map's parameter must be a tuple, got {:?}",
// lambda.parameter
// )));
// };
// let argument =
// params.clone_and_named_assignment(&OnionTuple::new(vec![
// element_clone,
// ]))?;
// let runnable = lambda.create_runnable(argument, &self.mapper, gc)?;
let argument =
OnionObject::Tuple(OnionTuple::new(vec![element_clone]).into())
.stabilize();
let runnable = Box::new(OnionLambdaRunnableLauncher::new_static(
&self.mapper,
&argument,
&|r| Ok(r),
)?);
Ok(StepResult::NewRunnable(runnable))
}
OnionObject::Boolean(false) => Ok(StepResult::Continue),
_ => {
self.collected.push(element_clone.stabilize());
Ok(StepResult::Continue)
}
})
} else {
// 所有元素都处理完了
Ok(StepResult::Return(
OnionTuple::new_static_no_ref(self.collected.clone()).into(),
))
}
}
_ => Err(RuntimeError::InvalidType(
"Container must be a tuple".to_string().into(),
)),
})
.unwrap_or_else(|e| StepResult::Error(e))
}
fn format_context(&self) -> Result<serde_json::Value, RuntimeError> {
return Ok(serde_json::json!({
"type": "Mapping",
"container": self.container.to_string(),
"mapper": self.mapper.to_string(),
"collected": self.collected.iter().map(|o| o.to_string()).collect::<Vec<_>>(),
"current_index": self.current_index,
}));
}
}