onion_vm/types/
tuple.rs

1//! Onion 元组(Tuple)类型模块。
2//!
3//! 提供 Onion 语言运行时的元组类型实现,支持任意对象的有序集合表达,
4//! 并支持 GC 跟踪、静态构造、索引访问、属性查找等功能。
5//!
6//! # 主要功能
7//! - 元组的构造与静态化
8//! - 元素访问、索引与属性查找
9//! - 元组拼接与包含关系判断
10//! - GC 跟踪与升级
11
12use std::{collections::VecDeque, fmt::Debug, sync::Arc};
13
14use arc_gc::{
15    arc::{GCArc, GCArcWeak},
16    traceable::GCTraceable,
17};
18
19use crate::lambda::runnable::RuntimeError;
20
21use super::object::{OnionObject, OnionObjectCell, OnionStaticObject};
22
23/// Onion 元组类型。
24///
25/// 封装有序对象集合,支持高效的索引访问与属性查找。
26///
27/// # 字段
28/// - `elements`: 元组元素的有序对象数组
29#[derive(Clone)]
30pub struct OnionTuple {
31    elements: Arc<[OnionObject]>,
32}
33
34impl GCTraceable<OnionObjectCell> for OnionTuple {
35    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
36        for element in self.elements.as_ref() {
37            element.collect(queue);
38        }
39    }
40}
41
42impl Debug for OnionTuple {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        match self.elements.len() {
45            0 => write!(f, "()"),
46            1 => write!(f, "({:?},)", self.elements[0]),
47            _ => {
48                let elements: Vec<String> =
49                    self.elements.iter().map(|e| format!("{:?}", e)).collect();
50                write!(f, "({})", elements.join(", "))
51            }
52        }
53    }
54}
55
56#[macro_export]
57macro_rules! onion_tuple {
58    ($($x:expr),*) => {
59        OnionTuple::new_static(vec![$($x),*])
60    };
61    () => {
62
63    };
64}
65
66impl OnionTuple {
67    /// 创建新的元组。
68    ///
69    /// # 参数
70    /// - `elements`: 元组元素对象列表
71    ///
72    /// # 返回
73    /// 新的元组实例
74    pub fn new(elements: Vec<OnionObject>) -> Self {
75        OnionTuple {
76            elements: elements.into(),
77        }
78    }
79
80    /// 创建静态元组对象(元素为静态对象)。
81    ///
82    /// # 参数
83    /// - `elements`: 静态对象引用列表
84    ///
85    /// # 返回
86    /// 稳定化后的静态元组对象
87    pub fn new_static(elements: Vec<&OnionStaticObject>) -> OnionStaticObject {
88        OnionStaticObject::new(OnionObject::Tuple(
89            OnionTuple {
90                elements: elements
91                    .into_iter()
92                    .map(|e| e.weak().clone())
93                    .collect::<Vec<_>>()
94                    .into(),
95            }
96            .into(),
97        ))
98    }
99
100    /// 创建静态元组对象(元素为静态对象,参数为 Vec 所有权)。
101    ///
102    /// # 参数
103    /// - `elements`: 静态对象列表
104    ///
105    /// # 返回
106    /// 稳定化后的静态元组对象
107    pub fn new_static_no_ref(elements: &Vec<OnionStaticObject>) -> OnionStaticObject {
108        OnionObject::Tuple(
109            OnionTuple {
110                elements: elements
111                    .into_iter()
112                    .map(|e| e.weak().clone())
113                    .collect::<Vec<_>>()
114                    .into(),
115            }
116            .into(),
117        )
118        .consume_and_stabilize()
119    }
120
121    /// 创建静态元组对象(元素为静态对象,参数为切片)。
122    ///
123    /// # 参数
124    /// - `elements`: 静态对象切片
125    ///
126    /// # 返回
127    /// 稳定化后的静态元组对象
128    pub fn new_from_slice(elements: &[OnionStaticObject]) -> OnionStaticObject {
129        OnionObject::Tuple(
130            OnionTuple {
131                elements: elements
132                    .iter()
133                    .map(|e| e.weak().clone())
134                    .collect::<Vec<_>>()
135                    .into(),
136            }
137            .into(),
138        )
139        .consume_and_stabilize()
140    }
141
142    /// 获取元组元素的引用。
143    #[inline(always)]
144    pub fn get_elements(&self) -> &[OnionObject] {
145        self.elements.as_ref()
146    }
147
148    /// 升级元组中所有元素的对象引用。
149    ///
150    /// 用于 GC 跟踪,防止元素被提前回收。
151    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
152        self.elements.iter().for_each(|e| e.upgrade(collected));
153    }
154
155    /// 获取元组长度。
156    ///
157    /// # 返回
158    /// 元组长度的静态整数对象
159    pub fn len(&self) -> Result<OnionStaticObject, RuntimeError> {
160        Ok(OnionStaticObject::new(OnionObject::Integer(
161            self.elements.len() as i64,
162        )))
163    }
164
165    /// 按索引访问元组元素。
166    ///
167    /// # 参数
168    /// - `index`: 元组索引(从 0 开始)
169    ///
170    /// # 返回
171    /// 对应索引的静态对象
172    ///
173    /// # 错误
174    /// - `InvalidOperation`: 索引越界
175    pub fn at(&self, index: i64) -> Result<OnionStaticObject, RuntimeError> {
176        if index < 0 || index >= self.elements.len() as i64 {
177            return Err(RuntimeError::InvalidOperation(
178                format!("Index out of bounds: {}", index).into(),
179            ));
180        }
181        Ok(OnionStaticObject::new(
182            self.elements[index as usize].clone(),
183        ))
184    }
185
186    /// 按索引借用元组元素并应用函数。
187    ///
188    /// # 参数
189    /// - `index`: 元组索引
190    /// - `f`: 处理函数
191    ///
192    /// # 返回
193    /// 处理函数的返回值
194    ///
195    /// # 错误
196    /// - `InvalidOperation`: 索引越界
197    pub fn with_index<F, R>(&self, index: i64, f: &F) -> Result<R, RuntimeError>
198    where
199        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
200    {
201        if index < 0 || index >= self.elements.len() as i64 {
202            return Err(RuntimeError::InvalidOperation(
203                format!("Index out of bounds: {}", index).into(),
204            ));
205        }
206        let borrowed = &self.elements[index as usize];
207        f(borrowed)
208    }
209
210    /// 按属性名查找元组中的键值对元素。
211    ///
212    /// # 参数
213    /// - `key`: 属性名对象
214    /// - `f`: 处理函数,对应值作为参数
215    ///
216    /// # 返回
217    /// - `Ok(R)`: 查找成功,返回处理函数结果
218    /// - `Err(RuntimeError)`: 未找到属性
219    pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
220    where
221        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
222    {
223        for element in self.elements.as_ref() {
224            match element {
225                OnionObject::Pair(pair) => {
226                    if pair.get_key().equals(key)? {
227                        return f(&pair.get_value());
228                    }
229                }
230                _ => {}
231            }
232        }
233        Err(RuntimeError::InvalidOperation(
234            format!("Attribute {:?} not found in tuple", key).into(),
235        ))
236    }
237
238    /// 元组拼接(二元加法)。
239    ///
240    /// # 参数
241    /// - `other`: 另一个元组对象
242    ///
243    /// # 返回
244    /// 拼接后的新元组对象
245    pub fn binary_add(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
246        match other {
247            OnionObject::Tuple(other_tuple) => {
248                let new_elements: Arc<[OnionObject]> = self
249                    .elements
250                    .iter()
251                    .chain(other_tuple.elements.iter())
252                    .cloned()
253                    .collect();
254                Ok(OnionStaticObject::new(OnionObject::Tuple(
255                    OnionTuple {
256                        elements: new_elements,
257                    }
258                    .into(),
259                )))
260            }
261            _ => Ok(OnionStaticObject::new(OnionObject::Undefined(Some(
262                format!("Cannot add tuple with {:?}", other).into(),
263            )))),
264        }
265    }
266
267    /// 判断元组是否包含指定对象。
268    ///
269    /// # 参数
270    /// - `other`: 要查找的对象
271    ///
272    /// # 返回
273    /// - `true`: 包含
274    /// - `false`: 不包含
275    pub fn contains(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
276        for element in self.elements.as_ref() {
277            if element.equals(other)? {
278                return Ok(true);
279            }
280        }
281        Ok(false)
282    }
283}
284
285impl OnionTuple {
286    pub fn equals(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
287        match other {
288            OnionObject::Tuple(other_tuple) => {
289                if self.elements.len() != other_tuple.elements.len() {
290                    return Ok(false);
291                }
292                for (a, b) in self.elements.iter().zip(other_tuple.elements.as_ref()) {
293                    if a.equals(b)? {
294                        return Ok(false);
295                    }
296                }
297                Ok(true)
298            }
299            _ => Ok(false),
300        }
301    }
302}