onion_vm/types/
pair.rs

1use std::{collections::VecDeque, fmt::Debug};
2
3use arc_gc::{
4    arc::{GCArc, GCArcWeak},
5    traceable::GCTraceable,
6};
7
8use crate::lambda::runnable::RuntimeError;
9
10use super::object::{OnionObject, OnionObjectCell, OnionStaticObject};
11
12#[derive(Clone)]
13pub struct OnionPair {
14    key: OnionObject,   // 使用 Box 避免递归
15    value: OnionObject, // 使用 Box 避免递归
16}
17
18impl GCTraceable<OnionObjectCell> for OnionPair {
19    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
20        self.key.collect(queue);
21        self.value.collect(queue);
22    }
23}
24
25impl Debug for OnionPair {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "{:?} : {:?}", self.key, self.value)
28    }
29}
30
31impl OnionPair {
32    pub fn new(key: OnionObject, value: OnionObject) -> Self {
33        OnionPair {
34            key: key.into(),
35            value: value.into(),
36        }
37    }
38
39    pub fn new_static(key: &OnionStaticObject, value: &OnionStaticObject) -> OnionStaticObject {
40        OnionObject::Pair(
41            OnionPair {
42                key: key.weak().clone(),
43                value: value.weak().clone(),
44            }
45            .into(),
46        )
47        .consume_and_stabilize()
48    }
49
50    #[inline(always)]
51    pub fn get_key(&self) -> &OnionObject {
52        &self.key
53    }
54
55    #[inline(always)]
56    pub fn get_value(&self) -> &OnionObject {
57        &self.value
58    }
59
60    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
61        self.key.upgrade(collected);
62        self.value.upgrade(collected)
63    }
64}
65
66impl OnionPair {
67    pub fn equals(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
68        match other {
69            OnionObject::Pair(pair) => {
70                if self.key.equals(&pair.key)? && self.value.equals(&pair.value)? {
71                    return Ok(true);
72                }
73            }
74            _ => {}
75        }
76        Ok(false)
77    }
78
79    pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
80    where
81        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
82    {
83        self.value
84            .with_attribute(key, f)
85            .or_else(|_| self.key.with_attribute(key, f))
86    }
87}
88
89impl OnionPair {
90    pub fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError> {
91        Ok(OnionObject::Pair(
92            OnionPair {
93                key: self.key.clone(),
94                value: self.value.clone(),
95            }
96            .into(),
97        ))
98    }
99}