onion_vm/types/
object.rs

1use std::{
2    collections::VecDeque,
3    fmt::{Debug, Display},
4    ptr::addr_eq,
5    sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
6};
7
8use arc_gc::{
9    arc::{GCArc, GCArcWeak},
10    gc::GC,
11    traceable::GCTraceable,
12};
13use base64::{engine::general_purpose, Engine as _};
14
15use crate::lambda::runnable::RuntimeError;
16
17use super::{
18    lambda::{
19        definition::OnionLambdaDefinition, vm_instructions::instruction_set::VMInstructionPackage,
20    },
21    lazy_set::OnionLazySet,
22    named::OnionNamed,
23    pair::OnionPair,
24    tuple::OnionTuple,
25};
26
27// Newtype wrapper to allow implementing GCTraceable for RefCell<OnionObject>
28pub struct OnionObjectCell(pub RwLock<OnionObject>);
29
30impl OnionObjectCell {
31    #[inline(always)]
32    pub fn with_data<T, F>(&self, f: F) -> Result<T, RuntimeError>
33    where
34        F: FnOnce(&OnionObject) -> Result<T, RuntimeError>,
35    {
36        self.0
37            .read()
38            .map_err(|_| {
39                RuntimeError::BorrowError(
40                    "Failed to borrow OnionObjectCell at `with_data`"
41                        .to_string()
42                        .into(),
43                )
44            })?
45            .with_data(f)
46    }
47    #[inline(always)]
48    pub fn with_data_mut<T, F>(&self, f: F) -> Result<T, RuntimeError>
49    where
50        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
51    {
52        self.0
53            .write()
54            .map_err(|_| {
55                RuntimeError::BorrowError(
56                    "Failed to borrow OnionObjectCell at `with_data_mut`"
57                        .to_string()
58                        .into(),
59                )
60            })?
61            .with_data_mut(f)
62    }
63
64    #[inline(always)]
65    pub fn with_data_ref_mut<T, F>(&self, f: F) -> Result<T, RuntimeError>
66    where
67        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
68    {
69        self.0
70            .write()
71            .map_err(|_| {
72                RuntimeError::BorrowError(
73                    "Failed to borrow OnionObjectCell at `with_data_ref_mut`"
74                        .to_string()
75                        .into(),
76                )
77            })?
78            .with_data_ref_mut(f)
79    }
80
81    #[inline(always)]
82    pub fn with_attribute<T, F>(&self, key: &OnionObject, f: &F) -> Result<T, RuntimeError>
83    where
84        F: Fn(&OnionObject) -> Result<T, RuntimeError>,
85    {
86        self.0
87            .read()
88            .map_err(|_| {
89                RuntimeError::BorrowError(
90                    "Failed to borrow OnionObjectCell at `with_attribute`"
91                        .to_string()
92                        .into(),
93                )
94            })?
95            .with_attribute(key, f)
96    }
97
98    #[inline(always)]
99    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
100        match self.0.read() {
101            Ok(obj) => obj.upgrade(collected),
102            Err(_) => {
103                // 如果无法借用,可能是因为对象已经被回收或正在被其他线程使用
104                // 这里选择忽略
105            }
106        }
107    }
108
109    #[inline(always)]
110    pub fn stabilize(self) -> OnionStaticObject {
111        OnionStaticObject::new(self.try_borrow().unwrap().clone())
112    }
113
114    #[inline(always)]
115    pub fn equals(&self, other: &Self) -> Result<bool, RuntimeError> {
116        self.with_data(|obj| other.with_data(|other_obj| obj.equals(other_obj)))
117    }
118
119    #[inline(always)]
120    pub fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
121        self.with_data(|obj| obj.repr(ptrs))
122    }
123
124    #[inline(always)]
125    pub fn try_borrow(&self) -> Result<RwLockReadGuard<OnionObject>, RuntimeError> {
126        self.0.read().map_err(|_| {
127            RuntimeError::BorrowError(
128                "Failed to borrow OnionObjectCell at `try_borrow`"
129                    .to_string()
130                    .into(),
131            )
132        })
133    }
134    #[inline(always)]
135    pub fn try_borrow_mut(&self) -> Result<RwLockWriteGuard<OnionObject>, RuntimeError> {
136        self.0.write().map_err(|_| {
137            RuntimeError::BorrowError(
138                "Failed to borrow OnionObjectCell at `try_borrow_mut`"
139                    .to_string()
140                    .into(),
141            )
142        })
143    }
144}
145
146impl std::ops::Deref for OnionObjectCell {
147    type Target = RwLock<OnionObject>;
148
149    fn deref(&self) -> &Self::Target {
150        &self.0
151    }
152}
153
154impl std::ops::DerefMut for OnionObjectCell {
155    fn deref_mut(&mut self) -> &mut Self::Target {
156        &mut self.0
157    }
158}
159
160impl From<RwLock<OnionObject>> for OnionObjectCell {
161    fn from(cell: RwLock<OnionObject>) -> Self {
162        OnionObjectCell(cell)
163    }
164}
165
166impl From<OnionObject> for OnionObjectCell {
167    fn from(obj: OnionObject) -> Self {
168        OnionObjectCell(RwLock::new(obj))
169    }
170}
171
172impl GCTraceable<OnionObjectCell> for OnionObjectCell {
173    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
174            if let Ok(obj) = self.0.read() {
175                obj.collect(queue);
176            }
177        }
178}
179
180impl Debug for OnionObjectCell {
181    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182        write!(f, "{:?}", self.0.read())
183    }
184}
185
186impl Display for OnionObjectCell {
187    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188        write!(f, "{:?}", self.0.read())
189    }
190}
191
192#[derive(Clone)]
193/// OnionObject is the main type for all objects in the Onion VM.
194/// The VM's types are all immutable(Mut is a immutable pointer to a VM object)
195/// If we need to `mutate` an object, it is IMPOSSIBLE to mutate the object itself, we can only let the Mut object point to a `reconstructed` object.
196/// `reconstruct_container` is used to reconstruct the container object, which is used to regenerate all `Arc` references to the object.
197pub enum OnionObject {
198    // immutable basic types
199    Integer(i64),
200    Float(f64),
201    String(Arc<String>),
202    Bytes(Arc<Vec<u8>>),
203    Boolean(bool),
204    Range(i64, i64),
205    Null,
206    Undefined(Option<Arc<String>>),
207    InstructionPackage(Arc<VMInstructionPackage>),
208
209    // immutable container types, need `reconstruct_container` for clone to solve circular references
210    Tuple(Arc<OnionTuple>),
211    Pair(Arc<OnionPair>),
212    Named(Arc<OnionNamed>),
213    LazySet(Arc<OnionLazySet>),
214    Lambda(Arc<OnionLambdaDefinition>),
215
216    Custom(Arc<dyn OnionObjectExt>),
217    // mutable? types, DO NOT USE THIS TYPE DIRECTLY, use `mutablize` instead
218    Mut(GCArcWeak<OnionObjectCell>),
219}
220
221pub trait OnionObjectExt: GCTraceable<OnionObjectCell> + Debug + Send + Sync + 'static {
222    // Type introspection for downcasting
223    fn as_any(&self) -> &dyn std::any::Any;
224
225    // GC and memory management
226    fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>);
227
228    fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError>;
229
230    // Basic type conversions
231    fn to_integer(&self) -> Result<i64, RuntimeError> {
232        Err(RuntimeError::InvalidType(
233            format!("Cannot convert {:?} to Integer", self).into(),
234        ))
235    }
236    fn to_float(&self) -> Result<f64, RuntimeError> {
237        Err(RuntimeError::InvalidType(
238            format!("Cannot convert {:?} to Float", self).into(),
239        ))
240    }
241    #[allow(unused_variables)]
242    fn to_string(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
243        Err(RuntimeError::InvalidType(
244            format!("Cannot convert {:?} to String", self).into(),
245        ))
246    }
247    fn to_bytes(&self) -> Result<Vec<u8>, RuntimeError> {
248        Err(RuntimeError::InvalidType(
249            format!("Cannot convert {:?} to Bytes", self).into(),
250        ))
251    }
252    fn to_boolean(&self) -> Result<bool, RuntimeError> {
253        Err(RuntimeError::InvalidType(
254            format!("Cannot convert {:?} to Boolean", self).into(),
255        ))
256    }
257    #[allow(unused_variables)]
258    fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
259        Ok(format!("{:?}", self))
260    }
261    fn type_of(&self) -> Result<String, RuntimeError> {
262        Err(RuntimeError::InvalidType(
263            format!("Cannot get type of {:?}", self).into(),
264        ))
265    }
266
267    // Container operations
268    fn len(&self) -> Result<OnionStaticObject, RuntimeError> {
269        Err(RuntimeError::InvalidOperation(
270            format!("len() not supported for {:?}", self).into(),
271        ))
272    }
273    fn contains(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
274        Err(RuntimeError::InvalidOperation(
275            format!("contains() not supported for {:?} and {:?}", self, other).into(),
276        ))
277    }
278    fn at(&self, index: i64) -> Result<OnionStaticObject, RuntimeError> {
279        Err(RuntimeError::InvalidOperation(
280            format!("at() not supported for {:?} with index {}", self, index).into(),
281        ))
282    }
283
284    // Key-value operations
285    fn key_of(&self) -> Result<OnionStaticObject, RuntimeError> {
286        Err(RuntimeError::InvalidOperation(
287            format!("key_of() not supported for {:?}", self).into(),
288        ))
289    }
290    fn value_of(&self) -> Result<OnionStaticObject, RuntimeError> {
291        Err(RuntimeError::InvalidOperation(
292            format!("value_of() not supported for {:?}", self).into(),
293        ))
294    }
295    #[allow(unused_variables)]
296    fn with_attribute(
297        &self,
298        key: &OnionObject,
299        f: &mut dyn FnMut(&OnionObject) -> Result<(), RuntimeError>,
300    ) -> Result<(), RuntimeError> {
301        Err(RuntimeError::InvalidOperation(
302            format!(
303                "with_attribute() not supported for {:?} with key {:?}",
304                self, key
305            )
306            .into(),
307        ))
308    }
309
310    // Comparison operations
311    fn equals(&self, other: &OnionObject) -> Result<bool, RuntimeError>;
312    fn is_same(&self, other: &OnionObject) -> Result<bool, RuntimeError>;
313    fn binary_eq(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
314        Err(RuntimeError::InvalidOperation(
315            format!("binary_eq() not supported for {:?} and {:?}", self, other).into(),
316        ))
317    }
318    fn binary_lt(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
319        Err(RuntimeError::InvalidOperation(
320            format!("binary_lt() not supported for {:?} and {:?}", self, other).into(),
321        ))
322    }
323    fn binary_gt(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
324        Err(RuntimeError::InvalidOperation(
325            format!("binary_gt() not supported for {:?} and {:?}", self, other).into(),
326        ))
327    }
328
329    // Binary arithmetic operations
330    fn binary_add(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
331        Err(RuntimeError::InvalidOperation(
332            format!("binary_add() not supported for {:?} and {:?}", self, other).into(),
333        ))
334    }
335    fn binary_sub(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
336        Err(RuntimeError::InvalidOperation(
337            format!("binary_sub() not supported for {:?} and {:?}", self, other).into(),
338        ))
339    }
340    fn binary_mul(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
341        Err(RuntimeError::InvalidOperation(
342            format!("binary_mul() not supported for {:?} and {:?}", self, other).into(),
343        ))
344    }
345    fn binary_div(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
346        Err(RuntimeError::InvalidOperation(
347            format!("binary_div() not supported for {:?} and {:?}", self, other).into(),
348        ))
349    }
350    fn binary_mod(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
351        Err(RuntimeError::InvalidOperation(
352            format!("binary_mod() not supported for {:?} and {:?}", self, other).into(),
353        ))
354    }
355    fn binary_pow(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
356        Err(RuntimeError::InvalidOperation(
357            format!("binary_pow() not supported for {:?} and {:?}", self, other).into(),
358        ))
359    }
360
361    // Binary logical operations
362    fn binary_and(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
363        Err(RuntimeError::InvalidOperation(
364            format!("binary_and() not supported for {:?} and {:?}", self, other).into(),
365        ))
366    }
367    fn binary_or(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
368        Err(RuntimeError::InvalidOperation(
369            format!("binary_or() not supported for {:?} and {:?}", self, other).into(),
370        ))
371    }
372    fn binary_xor(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
373        Err(RuntimeError::InvalidOperation(
374            format!("binary_xor() not supported for {:?} and {:?}", self, other).into(),
375        ))
376    }
377
378    // Binary shift operations
379    fn binary_shl(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
380        Err(RuntimeError::InvalidOperation(
381            format!("binary_shl() not supported for {:?} and {:?}", self, other).into(),
382        ))
383    }
384    fn binary_shr(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
385        Err(RuntimeError::InvalidOperation(
386            format!("binary_shr() not supported for {:?} and {:?}", self, other).into(),
387        ))
388    }
389
390    // Unary operations
391    fn unary_neg(&self) -> Result<OnionStaticObject, RuntimeError> {
392        Err(RuntimeError::InvalidOperation(
393            format!("unary_neg() not supported for {:?}", self).into(),
394        ))
395    }
396    fn unary_plus(&self) -> Result<OnionStaticObject, RuntimeError> {
397        Err(RuntimeError::InvalidOperation(
398            format!("unary_plus() not supported for {:?}", self).into(),
399        ))
400    }
401    fn unary_not(&self) -> Result<OnionStaticObject, RuntimeError> {
402        Err(RuntimeError::InvalidOperation(
403            format!("unary_not() not supported for {:?}", self).into(),
404        ))
405    }
406}
407
408impl Debug for OnionObject {
409    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
410        // 使用 repr
411        write!(
412            f,
413            "{}",
414            self.repr(&vec![])
415                .unwrap_or_else(|_| "BrokenReference".to_string())
416        )
417    }
418}
419
420impl GCTraceable<OnionObjectCell> for OnionObject {
421    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
422        match self {
423            OnionObject::Mut(weak) => {
424                queue.push_back(weak.clone());
425            }
426            OnionObject::Tuple(tuple) => tuple.collect(queue),
427            OnionObject::Pair(pair) => pair.collect(queue),
428            OnionObject::Named(named) => named.collect(queue),
429            OnionObject::LazySet(lazy_set) => lazy_set.collect(queue),
430            OnionObject::Lambda(lambda) => lambda.collect(queue),
431            OnionObject::Custom(custom) => custom.collect(queue),
432
433            _ => {}
434        }
435    }
436}
437impl OnionObject {
438    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
439        match self {
440            OnionObject::Mut(weak) => {
441                if let Some(strong) = weak.upgrade() {
442                    collected.push(strong);
443                }
444            }
445            OnionObject::Tuple(tuple) => tuple.upgrade(collected),
446            OnionObject::Pair(pair) => pair.upgrade(collected),
447            OnionObject::Named(named) => named.upgrade(collected),
448            OnionObject::LazySet(lazy_set) => lazy_set.upgrade(collected),
449            OnionObject::Lambda(lambda) => lambda.upgrade(collected),
450            OnionObject::Custom(custom) => custom.upgrade(collected),
451            _ => {}
452        }
453    }
454
455    #[inline(always)]
456    pub fn to_cell(self) -> OnionObjectCell {
457        OnionObjectCell(RwLock::new(self))
458    }
459
460    #[inline(always)]
461    pub fn stabilize(&self) -> OnionStaticObject {
462        OnionStaticObject::new(self.clone())
463    }
464
465    #[inline(always)]
466    pub fn consume_and_stabilize(self) -> OnionStaticObject {
467        OnionStaticObject::new(self)
468    }
469    pub fn len(&self) -> Result<OnionStaticObject, RuntimeError> {
470        self.with_data(|obj| match obj {
471            OnionObject::Tuple(tuple) => tuple.len(),
472            OnionObject::String(s) => {
473                Ok(OnionStaticObject::new(OnionObject::Integer(s.len() as i64)))
474            }
475            OnionObject::Bytes(b) => {
476                Ok(OnionStaticObject::new(OnionObject::Integer(b.len() as i64)))
477            }
478            OnionObject::Range(start, end) => Ok(OnionStaticObject::new(OnionObject::Integer(
479                (end - start) as i64,
480            ))),
481            OnionObject::Custom(custom) => custom.len(),
482            _ => Err(RuntimeError::InvalidOperation(
483                format!("len() not supported for {:?}", self).into(),
484            )),
485        })
486    }
487
488    pub fn contains(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
489        self.with_data(|obj| {
490            other.with_data(|other_obj| match (obj, other_obj) {
491                (OnionObject::Tuple(tuple), _) => tuple.contains(other_obj),
492                (OnionObject::String(s), OnionObject::String(other_s)) => {
493                    Ok(s.contains(other_s.as_ref()))
494                }
495                (OnionObject::Bytes(b), OnionObject::Bytes(other_b)) => Ok(b
496                    .windows(other_b.len())
497                    .any(|window| window == other_b.as_slice())),
498                (OnionObject::Range(l, r), OnionObject::Integer(i)) => Ok(*i >= *l && *i < *r),
499                (OnionObject::Range(start, end), OnionObject::Float(f)) => {
500                    Ok(*f >= *start as f64 && *f < *end as f64)
501                }
502                (OnionObject::Range(start, end), OnionObject::Range(other_start, other_end)) => {
503                    Ok(*other_start >= *start && *other_end <= *end)
504                }
505                (OnionObject::Custom(custom), _) => custom.contains(other_obj),
506                _ => Err(RuntimeError::InvalidOperation(
507                    format!("contains() not supported for {:?}", obj).into(),
508                )),
509            })
510        })
511    }
512
513    /// Warning: This method can cause stack overflow if there are nested Mut references.
514    ///
515    /// TODO: Add recursion depth limit after VM core is complete.
516    pub fn clone_value(&self) -> Result<OnionStaticObject, RuntimeError> {
517        self.with_data(|obj| Ok(obj.reconstruct_container()?.consume_and_stabilize()))
518    }
519
520    /// Warning: This method can cause stack overflow if there are nested Mut references.
521    ///
522    /// TODO: Add recursion depth limit after VM core is complete.
523    pub fn with_data<T, F>(&self, f: F) -> Result<T, RuntimeError>
524    where
525        F: FnOnce(&OnionObject) -> Result<T, RuntimeError>,
526    {
527        match self {
528            OnionObject::Mut(weak) => {
529                if let Some(strong) = weak.upgrade() {
530                    // FIXME: Potential infinite recursion if Mut contains another Mut
531                    strong.as_ref().with_data(f)
532                } else {
533                    Err(RuntimeError::BrokenReference)
534                }
535            }
536            _ => f(self),
537        }
538    }
539
540    /// Warning: This method can cause stack overflow if there are nested Mut references.
541    ///
542    /// TODO: Add recursion depth limit after VM core is complete.
543    pub fn with_data_mut<T, F>(&mut self, f: F) -> Result<T, RuntimeError>
544    where
545        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
546    {
547        match self {
548            OnionObject::Mut(weak) => {
549                if let Some(strong) = weak.upgrade() {
550                    // FIXME: Potential infinite recursion if Mut contains another Mut
551                    strong.as_ref().with_data_mut(f)
552                } else {
553                    Err(RuntimeError::BrokenReference)
554                }
555            }
556            _ => f(self),
557        }
558    }
559    /// Assign a new value to a mutable object.
560    pub fn assign(&self, other: &OnionObject) -> Result<(), RuntimeError> {
561        // 由于我们无法保证赋值后GCArcWeak指向对象的稳定性,对不可变对象进行赋值操作会导致潜在的内存安全问题。
562        // Mut类型由于是被GC管理的,因此可以安全地进行赋值操作(前提是GCArcWeak指向的对象仍然存在)。
563        let OnionObject::Mut(weak) = self else {
564            return Err(RuntimeError::InvalidOperation(
565                format!("Cannot assign to non-mutable object: {:?}", self).into(),
566            ));
567        };
568        match weak.upgrade() {
569            Some(strong) => {
570                // 先克隆要赋值的内容,避免借用冲突
571                let new_value = other.with_data(|other| other.reconstruct_container())?;
572
573                // 然后进行赋值
574                strong.as_ref().with_data_mut(|obj| {
575                    *obj = new_value;
576                    Ok(())
577                })
578            }
579            None => Err(RuntimeError::BrokenReference),
580        }
581    }
582    pub fn with_data_ref_mut<T, F>(&self, f: F) -> Result<T, RuntimeError>
583    where
584        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
585    {
586        let OnionObject::Mut(weak) = self else {
587            return Err(RuntimeError::InvalidOperation(
588                format!("Cannot mutate non-mutable object: {:?}", self).into(),
589            ));
590        };
591        match weak.upgrade() {
592            Some(strong) => strong.as_ref().with_data_mut(f),
593            None => Err(RuntimeError::BrokenReference),
594        }
595    }
596    /// 重建容器对象,主要用于 mutable_obj1 = obj2 这种赋值
597    pub fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError> {
598        match self {
599            OnionObject::Tuple(tuple) => tuple.reconstruct_container(),
600            OnionObject::Pair(pair) => pair.reconstruct_container(),
601            OnionObject::Named(named) => named.reconstruct_container(),
602            OnionObject::LazySet(lazy_set) => lazy_set.reconstruct_container(),
603            OnionObject::Lambda(lambda) => lambda.reconstruct_container(),
604            OnionObject::Custom(custom) => custom.reconstruct_container(),
605            _ => Ok(self.clone()), // 对于其他类型,直接克隆(由于Mut自身就是不可变地址,因此直接
606                                   // 克隆即可,并且只有容器才可能造成循环)
607        }
608    }
609    pub fn to_integer(&self) -> Result<i64, RuntimeError> {
610        self.with_data(|obj| match obj {
611            OnionObject::Integer(i) => Ok(*i),
612            OnionObject::Float(f) => Ok(*f as i64),
613            OnionObject::String(s) => s
614                .parse::<i64>()
615                .map_err(|e| RuntimeError::InvalidType(e.to_string().into())),
616            OnionObject::Boolean(b) => Ok(if *b { 1 } else { 0 }),
617            OnionObject::Custom(custom) => custom.to_integer(),
618            _ => Err(RuntimeError::InvalidType(
619                format!("Cannot convert {:?} to Integer", obj).into(),
620            )),
621        })
622    }
623    pub fn to_float(&self) -> Result<f64, RuntimeError> {
624        self.with_data(|obj| match obj {
625            OnionObject::Integer(i) => Ok(*i as f64),
626            OnionObject::Float(f) => Ok(*f),
627            OnionObject::String(s) => s
628                .parse::<f64>()
629                .map_err(|e| RuntimeError::InvalidType(e.to_string().into())),
630            OnionObject::Boolean(b) => Ok(if *b { 1.0 } else { 0.0 }),
631            OnionObject::Custom(custom) => custom.to_float(),
632            _ => Err(RuntimeError::InvalidType(
633                format!("Cannot convert {:?} to Float", obj).into(),
634            )),
635        })
636    }
637
638    pub fn to_string(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
639        self.with_data(|obj| {
640            for ptr in ptrs {
641                if addr_eq(obj, *ptr) {
642                    return Ok("...".to_string());
643                }
644            }
645            let mut new_ptrs = ptrs.clone();
646            new_ptrs.push(obj);
647            match obj {
648                OnionObject::Integer(i) => Ok(i.to_string()),
649                OnionObject::Float(f) => Ok(f.to_string()),
650                OnionObject::String(s) => Ok(s.as_ref().clone()),
651                OnionObject::Bytes(b) => Ok(format!(
652                    "$\"{}\"",
653                    general_purpose::STANDARD.encode(b.as_ref())
654                )),
655                OnionObject::Boolean(b) => Ok(if *b {
656                    "true".to_string()
657                } else {
658                    "false".to_string()
659                }),
660                OnionObject::Null => Ok("null".to_string()),
661                OnionObject::Undefined(s) => Ok(match s {
662                    Some(s) => format!("undefined({:?})", s),
663                    None => "undefined".to_string(),
664                }),
665                OnionObject::Range(start, end) => Ok(format!("{}..{}", start, end)),
666                OnionObject::Tuple(tuple) => match tuple.get_elements().len() {
667                    0 => Ok("()".to_string()),
668                    1 => {
669                        let first = tuple.get_elements().first().unwrap();
670                        Ok(format!("({},)", first.repr(&new_ptrs)?))
671                    }
672                    _ => {
673                        let elements: Result<Vec<String>, RuntimeError> = tuple
674                            .get_elements()
675                            .iter()
676                            .map(|e| e.repr(&new_ptrs))
677                            .collect();
678                        Ok(format!("({})", elements?.join(", ")))
679                    }
680                },
681                OnionObject::Pair(pair) => {
682                    let left = pair.get_key().repr(&new_ptrs)?;
683                    let right = pair.get_value().repr(&new_ptrs)?;
684                    Ok(format!("{} : {}", left, right))
685                }
686                OnionObject::Named(named) => {
687                    let name = named.get_key().repr(&new_ptrs)?;
688                    let value = named.get_value().repr(&new_ptrs)?;
689                    Ok(format!("{} => {}", name, value))
690                }
691                OnionObject::LazySet(lazy_set) => {
692                    let container = lazy_set.get_container().repr(&new_ptrs)?;
693                    let filter = lazy_set.get_filter().repr(&new_ptrs)?;
694                    Ok(format!("[{} | {}]", container, filter))
695                }
696                OnionObject::InstructionPackage(_) => Ok("InstructionPackage(...)".to_string()),
697                OnionObject::Lambda(lambda) => {
698                    let params = lambda.get_parameter().repr(&new_ptrs)?;
699                    let body = lambda.get_body().to_string();
700                    Ok(format!(
701                        "{}::{} -> {}",
702                        lambda.get_signature(),
703                        params,
704                        body
705                    ))
706                }
707                OnionObject::Custom(custom) => custom.to_string(&new_ptrs),
708                _ => {
709                    // 使用 Debug trait来处理其他类型的转换
710                    Ok(format!("{:?}", obj))
711                }
712            }
713        })
714    }
715
716    pub fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
717        self.with_data(|obj| {
718            for ptr in ptrs {
719                if addr_eq(obj, *ptr) {
720                    return Ok("...".to_string());
721                }
722            }
723            let mut new_ptrs = ptrs.clone();
724            new_ptrs.push(obj);
725            match obj {
726                OnionObject::Integer(i) => Ok(format!("{}", i)),
727                OnionObject::Float(f) => Ok(format!("{}", f)),
728                OnionObject::String(s) => Ok(format!("{:?}", s)),
729                OnionObject::Bytes(b) => Ok(format!(
730                    "$\"{}\"",
731                    general_purpose::STANDARD.encode(b.as_ref())
732                )),
733                OnionObject::Boolean(b) => Ok(format!("{}", b)),
734                OnionObject::Null => Ok("null".to_string()),
735                OnionObject::Undefined(s) => Ok(match s {
736                    Some(s) => format!("undefined({:?})", s),
737                    None => "undefined".to_string(),
738                }),
739                OnionObject::Range(start, end) => Ok(format!("{}..{}", start, end)),
740                OnionObject::Tuple(tuple) => match tuple.get_elements().len() {
741                    0 => Ok("()".to_string()),
742                    1 => {
743                        let first = tuple.get_elements().first().unwrap();
744                        Ok(format!("({},)", first.repr(&new_ptrs)?))
745                    }
746                    _ => {
747                        let elements: Result<Vec<String>, RuntimeError> = tuple
748                            .get_elements()
749                            .iter()
750                            .map(|e| e.repr(&new_ptrs))
751                            .collect();
752                        Ok(format!("({})", elements?.join(", ")))
753                    }
754                },
755                OnionObject::Pair(pair) => {
756                    let left = pair.get_key().repr(&new_ptrs)?;
757                    let right = pair.get_value().repr(&new_ptrs)?;
758                    Ok(format!("{} : {}", left, right))
759                }
760                OnionObject::Named(named) => {
761                    let name = named.get_key().repr(&new_ptrs)?;
762                    let value = named.get_value().repr(&new_ptrs)?;
763                    Ok(format!("{} => {}", name, value))
764                }
765                OnionObject::LazySet(lazy_set) => {
766                    let container = lazy_set.get_container().repr(&new_ptrs)?;
767                    let filter = lazy_set.get_filter().repr(&new_ptrs)?;
768                    Ok(format!("[{} | {}]", container, filter))
769                }
770                OnionObject::InstructionPackage(_) => Ok("InstructionPackage(...)".to_string()),
771                OnionObject::Lambda(lambda) => {
772                    let params = lambda.get_parameter().repr(&new_ptrs)?;
773                    Ok(format!(
774                        "{}::{} -> {}",
775                        lambda.get_signature(),
776                        params,
777                        lambda.get_body()
778                    ))
779                }
780                OnionObject::Mut(weak) => {
781                    if let Some(strong) = weak.upgrade() {
782                        let inner_repr = strong
783                            .as_ref()
784                            .try_borrow()
785                            .map_err(|_| {
786                                RuntimeError::BorrowError(
787                                    "Failed to borrow Mut object at `repr`".to_string().into(),
788                                )
789                            })?
790                            .repr(&new_ptrs)?;
791                        Ok(format!("mut ({})", inner_repr))
792                    } else {
793                        Ok("Mut(BrokenReference)".to_string())
794                    }
795                }
796                OnionObject::Custom(custom) => {
797                    let custom_repr = custom.repr(&new_ptrs)?;
798                    Ok(format!("Custom({})", custom_repr))
799                }
800            }
801        })
802    }
803    pub fn to_bytes(&self) -> Result<Vec<u8>, RuntimeError> {
804        self.with_data(|obj| match obj {
805            OnionObject::Integer(i) => Ok(i.to_string().into_bytes()),
806            OnionObject::Float(f) => Ok(f.to_string().into_bytes()),
807            OnionObject::String(s) => Ok(s.as_bytes().to_vec()),
808            OnionObject::Bytes(b) => Ok(b.as_ref().clone()),
809            OnionObject::Boolean(b) => Ok(if *b {
810                b"true".to_vec()
811            } else {
812                b"false".to_vec()
813            }),
814            OnionObject::Custom(custom) => custom.to_bytes(),
815            _ => Err(RuntimeError::InvalidType(
816                format!("Cannot convert {:?} to Bytes", obj).into(),
817            )),
818        })
819    }
820
821    pub fn to_boolean(&self) -> Result<bool, RuntimeError> {
822        self.with_data(|obj| match obj {
823            OnionObject::Integer(i) => Ok(*i != 0),
824            OnionObject::Float(f) => Ok(*f != 0.0),
825            OnionObject::String(s) => Ok(!s.is_empty()),
826            OnionObject::Bytes(b) => Ok(!b.is_empty()),
827            OnionObject::Boolean(b) => Ok(*b),
828            OnionObject::Null => Ok(false),
829            OnionObject::Undefined(_) => Ok(false),
830            OnionObject::Custom(custom) => custom.to_boolean(),
831            _ => Err(RuntimeError::InvalidType(
832                format!("Cannot convert {:?} to Boolean", obj).into(),
833            )),
834        })
835    }
836    pub fn mutablize(self, gc: &mut GC<OnionObjectCell>) -> OnionStaticObject {
837        let arc = gc.create(OnionObjectCell::from(self));
838        OnionStaticObject {
839            obj: OnionObject::Mut(arc.as_weak()),
840            _arcs: GCArcStorage::Single(arc),
841        }
842    }
843}
844
845impl OnionObject {
846    pub fn equals(&self, other: &Self) -> Result<bool, RuntimeError> {
847        self.with_data(|left| {
848            other.with_data(|right| {
849                match (left, right) {
850                    (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 == i2),
851                    (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 == f2),
852                    (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok(*i1 as f64 == *f2),
853                    (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 == *i2 as f64),
854                    (OnionObject::String(s1), OnionObject::String(s2)) => Ok(s1 == s2),
855                    (OnionObject::Bytes(b1), OnionObject::Bytes(b2)) => Ok(b1 == b2),
856                    (OnionObject::Boolean(b1), OnionObject::Boolean(b2)) => Ok(b1 == b2),
857                    (OnionObject::Range(start1, end1), OnionObject::Range(start2, end2)) => {
858                        Ok(start1 == start2 && end1 == end2)
859                    }
860                    (OnionObject::Null, OnionObject::Null) => Ok(true),
861                    (OnionObject::Undefined(_), OnionObject::Undefined(_)) => Ok(true),
862                    (OnionObject::Tuple(t1), _) => t1.equals(other),
863                    (OnionObject::Pair(p1), _) => p1.equals(other),
864                    (OnionObject::Named(n1), _) => n1.equals(other),
865                    (OnionObject::Custom(c1), _) => c1.equals(other),
866
867                    // 理论上Mut类型不应该出现在这里
868                    _ => Ok(false),
869                }
870            })
871        })
872    }
873    pub fn is_same(&self, other: &Self) -> Result<bool, RuntimeError> {
874        match (self, other) {
875            (OnionObject::Mut(weak1), OnionObject::Mut(weak2)) => {
876                if let (Some(strong1), Some(strong2)) = (weak1.upgrade(), weak2.upgrade()) {
877                    Ok(addr_eq(strong1.as_ref(), strong2.as_ref()))
878                } else {
879                    Ok(false)
880                }
881            }
882            (OnionObject::Custom(c1), _) => c1.is_same(other),
883            _ => self.equals(other),
884        }
885    }
886
887    pub fn binary_add(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
888        self.with_data(|obj| {
889            other.with_data(|other_obj| match (obj, other_obj) {
890                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
891                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 + i2)))
892                }
893                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
894                    Ok(OnionStaticObject::new(OnionObject::Float(f1 + f2)))
895                }
896                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
897                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 + f2)))
898                }
899                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
900                    Ok(OnionStaticObject::new(OnionObject::Float(f1 + *i2 as f64)))
901                }
902                (OnionObject::String(s1), OnionObject::String(s2)) => Ok(OnionStaticObject::new(
903                    OnionObject::String(Arc::new(format!("{}{}", s1, s2))),
904                )),
905                (OnionObject::Bytes(b1), OnionObject::Bytes(b2)) => {
906                    let mut new_bytes = b1.as_ref().clone();
907                    new_bytes.extend_from_slice(b2);
908                    Ok(OnionStaticObject::new(OnionObject::Bytes(Arc::new(
909                        new_bytes,
910                    ))))
911                }
912                (OnionObject::Range(start1, end1), OnionObject::Range(start2, end2)) => Ok(
913                    OnionStaticObject::new(OnionObject::Range(start1 + start2, end1 + end2)),
914                ),
915                (OnionObject::Tuple(t1), _) => t1.binary_add(other_obj),
916                (OnionObject::Custom(c1), _) => c1.binary_add(other_obj),
917                _ => Err(RuntimeError::InvalidOperation(
918                    format!(
919                        "Invalid binary add operation for {:?} and {:?}",
920                        obj, other_obj
921                    )
922                    .into(),
923                )),
924            })
925        })
926    }
927
928    pub fn binary_sub(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
929        self.with_data(|obj| {
930            other.with_data(|other_obj| match (obj, other_obj) {
931                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
932                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 - i2)))
933                }
934                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
935                    Ok(OnionStaticObject::new(OnionObject::Float(f1 - f2)))
936                }
937                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
938                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 - f2)))
939                }
940                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
941                    Ok(OnionStaticObject::new(OnionObject::Float(f1 - *i2 as f64)))
942                }
943                (OnionObject::Custom(c1), _) => c1.binary_sub(other_obj),
944                _ => Err(RuntimeError::InvalidOperation(
945                    format!(
946                        "Invalid binary sub operation for {:?} and {:?}",
947                        obj, other_obj
948                    )
949                    .into(),
950                )),
951            })
952        })
953    }
954
955    pub fn binary_mul(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
956        self.with_data(|obj| {
957            other.with_data(|other_obj| match (obj, other_obj) {
958                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
959                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 * i2)))
960                }
961                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
962                    Ok(OnionStaticObject::new(OnionObject::Float(f1 * f2)))
963                }
964                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
965                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 * f2)))
966                }
967                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
968                    Ok(OnionStaticObject::new(OnionObject::Float(f1 * *i2 as f64)))
969                }
970                (OnionObject::Custom(c1), _) => c1.binary_mul(other_obj),
971                _ => Err(RuntimeError::InvalidOperation(
972                    format!(
973                        "Invalid binary mul operation for {:?} and {:?}",
974                        obj, other_obj
975                    )
976                    .into(),
977                )),
978            })
979        })
980    }
981
982    pub fn binary_div(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
983        self.with_data(|obj| {
984            other.with_data(|other_obj| match (obj, other_obj) {
985                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
986                    if *i2 == 0 {
987                        return Err(RuntimeError::InvalidOperation(
988                            "Division by zero".to_string().into(),
989                        ));
990                    }
991                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 / i2)))
992                }
993                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
994                    Ok(OnionStaticObject::new(OnionObject::Float(f1 / f2)))
995                }
996                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
997                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 / f2)))
998                }
999                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
1000                    Ok(OnionStaticObject::new(OnionObject::Float(f1 / *i2 as f64)))
1001                }
1002                (OnionObject::Custom(c1), _) => c1.binary_div(other_obj),
1003                _ => Err(RuntimeError::InvalidOperation(
1004                    format!(
1005                        "Invalid binary div operation for {:?} and {:?}",
1006                        obj, other_obj
1007                    )
1008                    .into(),
1009                )),
1010            })
1011        })
1012    }
1013
1014    pub fn binary_mod(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1015        self.with_data(|obj| {
1016            other.with_data(|other_obj| match (obj, other_obj) {
1017                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1018                    if *i2 == 0 {
1019                        return Err(RuntimeError::InvalidOperation(
1020                            "Division by zero".to_string().into(),
1021                        ));
1022                    }
1023                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 % i2)))
1024                }
1025                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
1026                    Ok(OnionStaticObject::new(OnionObject::Float(f1 % f2)))
1027                }
1028                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
1029                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 % f2)))
1030                }
1031                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
1032                    Ok(OnionStaticObject::new(OnionObject::Float(f1 % *i2 as f64)))
1033                }
1034                (OnionObject::Custom(c1), _) => c1.binary_mod(other_obj),
1035                _ => Err(RuntimeError::InvalidOperation(
1036                    format!(
1037                        "Invalid binary mod operation for {:?} and {:?}",
1038                        obj, other_obj
1039                    )
1040                    .into(),
1041                )),
1042            })
1043        })
1044    }
1045
1046    pub fn binary_pow(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1047        self.with_data(|obj| {
1048            other.with_data(|other_obj| match (obj, other_obj) {
1049                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(OnionStaticObject::new(
1050                    OnionObject::Integer(i1.pow(*i2 as u32)),
1051                )),
1052                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
1053                    Ok(OnionStaticObject::new(OnionObject::Float(f1.powf(*f2))))
1054                }
1055                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok(OnionStaticObject::new(
1056                    OnionObject::Float((*i1 as f64).powf(*f2)),
1057                )),
1058                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(OnionStaticObject::new(
1059                    OnionObject::Float(f1.powi(*i2 as i32)),
1060                )),
1061                (OnionObject::Custom(c1), _) => c1.binary_pow(other_obj),
1062                _ => Err(RuntimeError::InvalidOperation(
1063                    format!(
1064                        "Invalid binary pow operation for {:?} and {:?}",
1065                        obj, other_obj
1066                    )
1067                    .into(),
1068                )),
1069            })
1070        })
1071    }
1072
1073    pub fn binary_and(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1074        self.with_data(|obj| {
1075            other.with_data(|other_obj| match (obj, other_obj) {
1076                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1077                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 & i2)))
1078                }
1079                (OnionObject::Boolean(f1), OnionObject::Boolean(f2)) => {
1080                    Ok(OnionStaticObject::new(OnionObject::Boolean(*f1 && *f2)))
1081                }
1082                (OnionObject::Custom(c1), _) => c1.binary_and(other_obj),
1083                _ => Err(RuntimeError::InvalidOperation(
1084                    format!(
1085                        "Invalid binary and operation for {:?} and {:?}",
1086                        obj, other_obj
1087                    )
1088                    .into(),
1089                )),
1090            })
1091        })
1092    }
1093
1094    pub fn binary_or(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1095        self.with_data(|obj| {
1096            other.with_data(|other_obj| match (obj, other_obj) {
1097                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1098                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 | i2)))
1099                }
1100                (OnionObject::Boolean(f1), OnionObject::Boolean(f2)) => {
1101                    Ok(OnionStaticObject::new(OnionObject::Boolean(*f1 || *f2)))
1102                }
1103                (OnionObject::Custom(c1), _) => c1.binary_or(other_obj),
1104                _ => Err(RuntimeError::InvalidOperation(
1105                    format!(
1106                        "Invalid binary or operation for {:?} and {:?}",
1107                        obj, other_obj
1108                    )
1109                    .into(),
1110                )),
1111            })
1112        })
1113    }
1114
1115    pub fn binary_xor(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1116        self.with_data(|obj| {
1117            other.with_data(|other_obj| match (obj, other_obj) {
1118                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1119                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 ^ i2)))
1120                }
1121                (OnionObject::Custom(c1), _) => c1.binary_xor(other_obj),
1122                _ => Err(RuntimeError::InvalidOperation(
1123                    format!(
1124                        "Invalid binary xor operation for {:?} and {:?}",
1125                        obj, other_obj
1126                    )
1127                    .into(),
1128                )),
1129            })
1130        })
1131    }
1132
1133    pub fn binary_shl(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1134        self.with_data(|obj| {
1135            other.with_data(|other_obj| match (obj, other_obj) {
1136                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1137                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 << i2)))
1138                }
1139                (OnionObject::Custom(c1), _) => c1.binary_shl(other_obj),
1140                _ => Err(RuntimeError::InvalidOperation(
1141                    format!(
1142                        "Invalid binary shl operation for {:?} and {:?}",
1143                        obj, other_obj
1144                    )
1145                    .into(),
1146                )),
1147            })
1148        })
1149    }
1150
1151    pub fn binary_shr(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1152        self.with_data(|obj| {
1153            other.with_data(|other_obj| match (obj, other_obj) {
1154                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1155                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 >> i2)))
1156                }
1157                (OnionObject::Custom(c1), _) => c1.binary_shr(other_obj),
1158                _ => Err(RuntimeError::InvalidOperation(
1159                    format!(
1160                        "Invalid binary shr operation for {:?} and {:?}",
1161                        obj, other_obj
1162                    )
1163                    .into(),
1164                )),
1165            })
1166        })
1167    }
1168
1169    pub fn binary_eq(&self, other: &Self) -> Result<bool, RuntimeError> {
1170        self.equals(other)
1171    }
1172
1173    pub fn binary_lt(&self, other: &Self) -> Result<bool, RuntimeError> {
1174        self.with_data(|obj| {
1175            other.with_data(|other_obj| match (obj, other_obj) {
1176                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 < i2),
1177                (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 < f2),
1178                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok((*i1 as f64) < *f2),
1179                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 < *i2 as f64),
1180                (OnionObject::Custom(c1), _) => c1.binary_lt(other_obj),
1181                _ => Err(RuntimeError::InvalidOperation(
1182                    format!(
1183                        "Invalid binary lt operation for {:?} and {:?}",
1184                        obj, other_obj
1185                    )
1186                    .into(),
1187                )),
1188            })
1189        })
1190    }
1191
1192    pub fn binary_gt(&self, other: &Self) -> Result<bool, RuntimeError> {
1193        self.with_data(|obj| {
1194            other.with_data(|other_obj| match (obj, other_obj) {
1195                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 > i2),
1196                (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 > f2),
1197                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok((*i1 as f64) > *f2),
1198                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 > *i2 as f64),
1199                (OnionObject::Custom(c1), _) => c1.binary_gt(other_obj),
1200                _ => Err(RuntimeError::InvalidOperation(
1201                    format!(
1202                        "Invalid binary gt operation for {:?} and {:?}",
1203                        obj, other_obj
1204                    )
1205                    .into(),
1206                )),
1207            })
1208        })
1209    }
1210
1211    pub fn unary_neg(&self) -> Result<OnionStaticObject, RuntimeError> {
1212        self.with_data(|obj| match obj {
1213            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(-i))),
1214            OnionObject::Float(f) => Ok(OnionStaticObject::new(OnionObject::Float(-f))),
1215            OnionObject::Custom(custom) => custom.unary_neg(),
1216            _ => Err(RuntimeError::InvalidOperation(
1217                format!("Invalid unary neg operation for {:?}", obj).into(),
1218            )),
1219        })
1220    }
1221
1222    pub fn unary_plus(&self) -> Result<OnionStaticObject, RuntimeError> {
1223        self.with_data(|obj| match obj {
1224            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(i.abs()))),
1225            OnionObject::Float(f) => Ok(OnionStaticObject::new(OnionObject::Float(f.abs()))),
1226            OnionObject::Custom(custom) => custom.unary_plus(),
1227            _ => Err(RuntimeError::InvalidOperation(
1228                format!("Invalid unary plus operation for {:?}", obj).into(),
1229            )),
1230        })
1231    }
1232
1233    pub fn unary_not(&self) -> Result<OnionStaticObject, RuntimeError> {
1234        self.with_data(|obj| match obj {
1235            OnionObject::Boolean(b) => Ok(OnionStaticObject::new(OnionObject::Boolean(!b))),
1236            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(!i))),
1237            OnionObject::Custom(custom) => custom.unary_not(),
1238            _ => Err(RuntimeError::InvalidOperation(
1239                format!("Invalid unary not operation for {:?}", obj).into(),
1240            )),
1241        })
1242    }
1243
1244    pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
1245    where
1246        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
1247    {
1248        self.with_data(|obj| match obj {
1249            OnionObject::Tuple(tuple) => tuple.with_attribute(key, f),
1250            OnionObject::Named(named) => named.with_attribute(key, f),
1251            OnionObject::Pair(pair) => pair.with_attribute(key, f),
1252            OnionObject::Lambda(lambda) => lambda.with_attribute(key, f),
1253            OnionObject::LazySet(lazy_set) => lazy_set.with_attribute(key, f),
1254            OnionObject::String(s) => {
1255                if let OnionObject::String(key_str) = key {
1256                    if key_str.as_ref().eq("length") {
1257                        return f(&OnionObject::Integer(s.len() as i64));
1258                    }
1259                    if key_str.as_ref().eq("elements") {
1260                        let elements = OnionTuple::new_static_no_ref(
1261                            &s.chars()
1262                                .map(|c| {
1263                                    OnionStaticObject::new(OnionObject::String(Arc::new(
1264                                        c.to_string(),
1265                                    )))
1266                                })
1267                                .collect::<Vec<_>>(),
1268                        );
1269                        return f(elements.weak());
1270                    }
1271                }
1272                Err(RuntimeError::InvalidOperation(
1273                    format!("with_attribute() not supported for String: {}", s).into(),
1274                ))
1275            }
1276            OnionObject::Bytes(b) => {
1277                if let OnionObject::String(key_str) = key {
1278                    if key_str.as_ref().eq("length") {
1279                        return f(&OnionObject::Integer(b.len() as i64));
1280                    }
1281                    if key_str.as_ref().eq("elements") {
1282                        let elements = OnionTuple::new_static_no_ref(
1283                            &b.iter()
1284                                .map(|byte| {
1285                                    OnionStaticObject::new(OnionObject::Integer(*byte as i64))
1286                                })
1287                                .collect::<Vec<_>>(),
1288                        );
1289                        return f(elements.weak());
1290                    }
1291                }
1292                Err(RuntimeError::InvalidOperation(
1293                    format!("with_attribute() not supported for Bytes: {:?}", b).into(),
1294                ))
1295            }
1296            OnionObject::Range(start, end) => {
1297                if let OnionObject::String(key_str) = key {
1298                    if key_str.as_ref().eq("length") {
1299                        return f(&OnionObject::Integer((end - start) as i64));
1300                    }
1301                    if key_str.as_ref().eq("elements") {
1302                        let elements = OnionTuple::new_static_no_ref(
1303                            &(*start..*end)
1304                                .map(|i| OnionStaticObject::new(OnionObject::Integer(i as i64)))
1305                                .collect::<Vec<_>>(),
1306                        );
1307                        return f(elements.weak());
1308                    }
1309                }
1310                Err(RuntimeError::InvalidOperation(
1311                    format!(
1312                        "with_attribute() not supported for Range: {}..{}",
1313                        start, end
1314                    )
1315                    .into(),
1316                ))
1317            }
1318            OnionObject::Custom(custom) => {
1319                let mut result: Result<R, RuntimeError> = Err(RuntimeError::InvalidOperation(
1320                    "Custom with_attribute not called".to_string().into(),
1321                ));
1322                let mut closure = |obj: &OnionObject| -> Result<(), RuntimeError> {
1323                    result = f(obj);
1324                    Ok(())
1325                };
1326                custom.with_attribute(key, &mut closure)?;
1327                result
1328            }
1329            _ => Err(RuntimeError::InvalidOperation(
1330                format!("with_attribute() not supported for {:?}", self).into(),
1331            )),
1332        })
1333    }
1334    pub fn at(&self, index: i64) -> Result<OnionStaticObject, RuntimeError> {
1335        self.with_data(|obj| match obj {
1336            OnionObject::Tuple(tuple) => tuple.at(index),
1337            OnionObject::String(s) => {
1338                if index < 0 || index >= s.len() as i64 {
1339                    return Err(RuntimeError::InvalidOperation(
1340                        format!("Index out of bounds for String: {}", s).into(),
1341                    ));
1342                }
1343                Ok(OnionStaticObject::new(OnionObject::String(Arc::new(
1344                    s.chars().nth(index as usize).unwrap().to_string(),
1345                ))))
1346            }
1347            OnionObject::Bytes(b) => {
1348                if index < 0 || index >= b.len() as i64 {
1349                    return Err(RuntimeError::InvalidOperation(
1350                        format!("Index out of bounds for Bytes: {:?}", b).into(),
1351                    ));
1352                }
1353                Ok(OnionStaticObject::new(OnionObject::Bytes(Arc::new(vec![
1354                    b[index as usize],
1355                ]))))
1356            }
1357            OnionObject::Custom(custom) => custom.at(index),
1358            _ => Err(RuntimeError::InvalidOperation(
1359                format!("index_of() not supported for {:?}", self).into(),
1360            )),
1361        })
1362    }
1363
1364    pub fn key_of(&self) -> Result<OnionStaticObject, RuntimeError> {
1365        self.with_data(|obj| match obj {
1366            OnionObject::Named(named) => Ok(named.get_key().stabilize()),
1367            OnionObject::Pair(pair) => Ok(pair.get_key().stabilize()),
1368            OnionObject::Custom(custom) => custom.key_of(),
1369            _ => Err(RuntimeError::InvalidOperation(
1370                format!("key_of() not supported for {:?}", obj).into(),
1371            )),
1372        })
1373    }
1374
1375    pub fn value_of(&self) -> Result<OnionStaticObject, RuntimeError> {
1376        self.with_data(|obj| match obj {
1377            OnionObject::Named(named) => Ok(named.get_value().stabilize()),
1378            OnionObject::Pair(pair) => Ok(pair.get_value().stabilize()),
1379            OnionObject::Undefined(s) => Ok(OnionStaticObject::new(OnionObject::String(Arc::new(
1380                s.as_ref()
1381                    .map(|o| o.as_ref().clone())
1382                    .unwrap_or_else(|| "".to_string()),
1383            )))),
1384            OnionObject::Custom(custom) => custom.value_of(),
1385            _ => Err(RuntimeError::InvalidOperation(
1386                format!("value_of() not supported for {:?}", obj).into(),
1387            )),
1388        })
1389    }
1390
1391    pub fn type_of(&self) -> Result<String, RuntimeError> {
1392        self.with_data(|obj| match obj {
1393            OnionObject::Integer(_) => Ok("Integer".to_string()),
1394            OnionObject::Float(_) => Ok("Float".to_string()),
1395            OnionObject::String(_) => Ok("String".to_string()),
1396            OnionObject::Bytes(_) => Ok("Bytes".to_string()),
1397            OnionObject::Boolean(_) => Ok("Boolean".to_string()),
1398            OnionObject::Null => Ok("Null".to_string()),
1399            OnionObject::Undefined(_) => Ok("Undefined".to_string()),
1400            OnionObject::Tuple(_) => Ok("Tuple".to_string()),
1401            OnionObject::Pair(_) => Ok("Pair".to_string()),
1402            OnionObject::Named(_) => Ok("Named".to_string()),
1403            OnionObject::LazySet(_) => Ok("LazySet".to_string()),
1404            OnionObject::InstructionPackage(_) => Ok("InstructionPackage".to_string()),
1405            OnionObject::Lambda(_) => Ok("Lambda".to_string()),
1406            OnionObject::Custom(custom) => custom.type_of(),
1407            _ => Err(RuntimeError::InvalidOperation(
1408                format!("type_of() not supported for {:?}", obj).into(),
1409            )),
1410        })
1411    }
1412
1413    #[inline(always)]
1414    pub fn copy(&self) -> Result<OnionStaticObject, RuntimeError> {
1415        self.with_data(|obj| Ok(obj.stabilize()))
1416    }
1417}
1418
1419#[derive(Clone)]
1420pub enum GCArcStorage {
1421    None,
1422    Single(GCArc<OnionObjectCell>),
1423    Multiple(Arc<Vec<GCArc<OnionObjectCell>>>),
1424}
1425
1426// impl GCArcStorage {
1427//     #[inline(always)]
1428//     pub fn from_vec(v: Vec<GCArc<OnionObjectCell>>) -> Self {
1429//         match v.len() {
1430//             0 => Self::None,
1431//             1 => Self::Single(v[0].clone()),
1432//             _ => Self::Multiple(v),
1433//         }
1434//     }
1435// }
1436
1437#[derive(Clone)]
1438pub struct OnionStaticObject {
1439    _arcs: GCArcStorage,
1440    obj: OnionObject,
1441}
1442
1443impl Default for OnionStaticObject {
1444    fn default() -> Self {
1445        OnionStaticObject {
1446            obj: OnionObject::Undefined(None),
1447            _arcs: GCArcStorage::None,
1448        }
1449    }
1450}
1451
1452impl Debug for OnionStaticObject {
1453    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1454        write!(f, "OnionStaticObject({:?})", self.obj)
1455    }
1456}
1457
1458impl Display for OnionStaticObject {
1459    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1460        write!(f, "OnionStaticObject({:?})", self.obj)
1461    }
1462}
1463
1464impl OnionStaticObject {
1465    #[inline(always)]
1466    pub fn new(obj: OnionObject) -> Self {
1467        let arcs = match &obj {
1468            OnionObject::Mut(obj) => match obj.upgrade() {
1469                None => GCArcStorage::None,
1470                Some(arc) => GCArcStorage::Single(arc),
1471            },
1472            OnionObject::Boolean(_)
1473            | OnionObject::Integer(_)
1474            | OnionObject::Float(_)
1475            | OnionObject::String(_)
1476            | OnionObject::Bytes(_)
1477            | OnionObject::Null
1478            | OnionObject::Undefined(_)
1479            | OnionObject::Range(_, _)
1480            | OnionObject::InstructionPackage(_) => GCArcStorage::None,
1481            _ => {
1482                let mut arcs = vec![];
1483                obj.upgrade(&mut arcs);
1484                GCArcStorage::Multiple(Arc::new(arcs))
1485            }
1486        };
1487        OnionStaticObject {
1488            obj: obj,
1489            _arcs: arcs,
1490        }
1491    }
1492
1493    #[inline(always)]
1494    pub fn weak(&self) -> &OnionObject {
1495        &self.obj
1496    }
1497
1498    #[inline(always)]
1499    pub fn mutablize(
1500        &self,
1501        gc: &mut GC<OnionObjectCell>,
1502    ) -> Result<OnionStaticObject, RuntimeError> {
1503        self.obj.with_data(|obj| Ok(obj.clone().mutablize(gc)))
1504    }
1505}
1506
1507#[macro_export]
1508macro_rules! unwrap_object {
1509    ($obj:expr, $variant:path) => {
1510        match $obj {
1511            $variant(o) => Ok(o),
1512            _ => Err(RuntimeError::InvalidType(
1513                format!("Expected {}, found {:?}", stringify!($variant), $obj).into(),
1514            )),
1515        }
1516    };
1517}
1518
1519#[cfg(test)]
1520mod tests {
1521    use super::*;
1522    use std::time::Instant;
1523
1524    #[test]
1525    fn test_detailed_memory_sizes() {
1526        println!("详细内存分析:");
1527        println!(
1528            "OnionObjectCell: {} bytes",
1529            std::mem::size_of::<OnionObjectCell>()
1530        );
1531        println!("OnionObject: {} bytes", std::mem::size_of::<OnionObject>());
1532        println!(
1533            "OnionStaticObject: {} bytes",
1534            std::mem::size_of::<OnionStaticObject>()
1535        );
1536        println!(
1537            "GCArcStorage: {} bytes",
1538            std::mem::size_of::<GCArcStorage>()
1539        );
1540        println!(
1541            "GCArc<OnionObjectCell>: {} bytes",
1542            std::mem::size_of::<GCArc<OnionObjectCell>>()
1543        );
1544        println!("Arc<String>: {} bytes", std::mem::size_of::<Arc<String>>());
1545        println!(
1546            "Arc<Vec<u8>>: {} bytes",
1547            std::mem::size_of::<Arc<Vec<u8>>>()
1548        );
1549        println!(
1550            "GCArcWeak<OnionObjectCell>: {} bytes",
1551            std::mem::size_of::<GCArcWeak<OnionObjectCell>>()
1552        );
1553        println!("OnionTuple: {} bytes", std::mem::size_of::<OnionTuple>());
1554        println!("OnionNamed: {} bytes", std::mem::size_of::<OnionNamed>());
1555        println!("OnionPair: {} bytes", std::mem::size_of::<OnionPair>());
1556        println!(
1557            "OnionLazySet: {} bytes",
1558            std::mem::size_of::<OnionLazySet>()
1559        );
1560    }
1561
1562    #[test]
1563    fn benchmark_realistic_vm_operations() {
1564        println!("真实VM操作性能测试 (使用OnionStaticObject + clone):");
1565
1566        // 模拟VM中的整数运算
1567        let start = Instant::now();
1568        let mut result_sum = 0i64;
1569
1570        for i in 0..5_000_000 {
1571            // 创建OnionStaticObject(模拟从栈或常量池加载)
1572            let obj1 = OnionObject::Integer(i).stabilize();
1573            let obj2 = OnionObject::Integer(i + 1).stabilize();
1574
1575            // 通过with_data访问(模拟VM的实际访问模式)
1576            let result = obj1.weak().with_data(|data1| {
1577                obj2.weak().with_data(|data2| {
1578                    // 模拟binary_add操作
1579                    match (data1, data2) {
1580                        (OnionObject::Integer(a), OnionObject::Integer(b)) => {
1581                            Ok(OnionObject::Integer(a + b).stabilize())
1582                        }
1583                        _ => Err(RuntimeError::InvalidOperation(
1584                            "Type error".to_string().into(),
1585                        )),
1586                    }
1587                })
1588            });
1589
1590            if let Ok(sum) = result {
1591                // 提取结果值(模拟VM获取计算结果)
1592                if let Ok(val) = sum.weak().with_data(|data| match data {
1593                    OnionObject::Integer(v) => Ok(*v),
1594                    _ => Err(RuntimeError::InvalidType("Not integer".to_string().into())),
1595                }) {
1596                    result_sum += val;
1597                }
1598            }
1599        }
1600
1601        let duration = start.elapsed();
1602        println!("500万次VM风格整数运算: {:.2}s", duration.as_secs_f64());
1603        println!("每秒操作数: {:.0}", 5_000_000.0 / duration.as_secs_f64());
1604        println!("结果校验: {}", result_sum);
1605    }
1606
1607    #[test]
1608    fn benchmark_vm_style_arithmetic() {
1609        println!("VM风格算术运算性能测试:");
1610
1611        let start = Instant::now();
1612        let mut final_result = 0i64;
1613
1614        for i in 0..2_000_000 {
1615            // 创建操作数
1616            let left = OnionObject::Integer(i).stabilize();
1617            let right = OnionObject::Integer(i + 1).stabilize();
1618
1619            // 使用实际的binary_add方法
1620            if let Ok(result) = left
1621                .weak()
1622                .with_data(|l_data| right.weak().with_data(|r_data| l_data.binary_add(r_data)))
1623            {
1624                // 继续进行乘法运算
1625                let multiplier = OnionObject::Integer(2).stabilize();
1626                if let Ok(mul_result) = result.weak().with_data(|add_data| {
1627                    multiplier
1628                        .weak()
1629                        .with_data(|mul_data| add_data.binary_mul(mul_data))
1630                }) {
1631                    // 提取最终结果
1632                    if let Ok(val) = mul_result.weak().with_data(|data| data.to_integer()) {
1633                        final_result += val;
1634                    }
1635                }
1636            }
1637        }
1638
1639        let duration = start.elapsed();
1640        println!("200万次复合运算: {:.2}s", duration.as_secs_f64());
1641        println!("每秒操作数: {:.0}", 2_000_000.0 / duration.as_secs_f64());
1642        println!("最终结果: {}", final_result);
1643    }
1644
1645    #[test]
1646    fn benchmark_object_creation_overhead() {
1647        println!("对象创建开销测试:");
1648
1649        // 测试OnionStaticObject创建性能
1650        let start = Instant::now();
1651        let mut objects = Vec::with_capacity(1_000_000);
1652
1653        for i in 0..1_000_000 {
1654            let obj = OnionObject::Integer(i).stabilize();
1655            objects.push(obj);
1656        }
1657
1658        let creation_time = start.elapsed();
1659        println!(
1660            "100万个OnionStaticObject创建: {:.2}s",
1661            creation_time.as_secs_f64()
1662        );
1663
1664        // 测试访问性能
1665        let start = Instant::now();
1666        let mut sum = 0i64;
1667
1668        for obj in &objects {
1669            if let Ok(val) = obj.weak().with_data(|data| data.to_integer()) {
1670                sum += val;
1671            }
1672        }
1673
1674        let access_time = start.elapsed();
1675        println!("100万次对象访问: {:.2}s", access_time.as_secs_f64());
1676        println!("访问校验和: {}", sum);
1677
1678        // 测试克隆性能
1679        let start = Instant::now();
1680        let mut cloned_objects = Vec::with_capacity(objects.len());
1681
1682        for obj in &objects[..100_000] {
1683            // 只测试10万个避免内存不足
1684            cloned_objects.push(obj.clone());
1685        }
1686
1687        let clone_time = start.elapsed();
1688        println!("10万个对象克隆: {:.2}s", clone_time.as_secs_f64());
1689    }
1690
1691    #[test]
1692    fn benchmark_string_operations_realistic() {
1693        println!("真实字符串操作性能测试:");
1694
1695        let start = Instant::now();
1696        let mut total_length = 0usize;
1697
1698        for i in 0..500_000 {
1699            // 创建字符串对象
1700            let str_obj = OnionObject::String(Arc::new(format!("string_{}", i))).stabilize();
1701
1702            // 获取字符串长度(模拟len()操作)
1703            if let Ok(len_obj) = str_obj.weak().with_data(|data| data.len()) {
1704                if let Ok(length) = len_obj.weak().with_data(|data| data.to_integer()) {
1705                    total_length += length as usize;
1706                }
1707            }
1708
1709            // 字符串拼接操作
1710            let suffix = OnionObject::String(Arc::new("_suffix".to_string())).stabilize();
1711            if let Ok(concat_result) = str_obj.weak().with_data(|str_data| {
1712                suffix
1713                    .weak()
1714                    .with_data(|suffix_data| str_data.binary_add(suffix_data))
1715            }) {
1716                // 模拟使用拼接结果
1717                if let Ok(concat_str) = concat_result
1718                    .weak()
1719                    .with_data(|data| data.to_string(&mut vec![]))
1720                {
1721                    total_length += concat_str.len();
1722                }
1723            }
1724        }
1725
1726        let duration = start.elapsed();
1727        println!("50万次字符串操作: {:.2}s", duration.as_secs_f64());
1728        println!("每秒操作数: {:.0}", 500_000.0 / duration.as_secs_f64());
1729        println!("总字符串长度: {}", total_length);
1730    }
1731
1732    #[test]
1733    fn benchmark_refcell_overhead() {
1734        println!("RefCell开销分析:");
1735
1736        // 测试直接访问vs RefCell访问的性能差异
1737        let direct_integers: Vec<i64> = (0..1_000_000).collect();
1738        let wrapped_integers: Vec<OnionStaticObject> = (0..1_000_000)
1739            .map(|i| OnionObject::Integer(i).stabilize())
1740            .collect();
1741
1742        // 直接访问基准
1743        let start = Instant::now();
1744        let mut sum1 = 0i64;
1745        for &val in &direct_integers {
1746            sum1 += val * 2;
1747        }
1748        let direct_time = start.elapsed();
1749
1750        // RefCell访问
1751        let start = Instant::now();
1752        let mut sum2 = 0i64;
1753        for obj in &wrapped_integers {
1754            if let Ok(val) = obj.weak().with_data(|data| match data {
1755                OnionObject::Integer(i) => Ok(*i),
1756                _ => Err(RuntimeError::InvalidType("Not integer".to_string().into())),
1757            }) {
1758                sum2 += val * 2;
1759            }
1760        }
1761        let refcell_time = start.elapsed();
1762
1763        println!("直接访问100万个i64: {:.2}s", direct_time.as_secs_f64());
1764        println!(
1765            "RefCell访问100万个OnionObject: {:.2}s",
1766            refcell_time.as_secs_f64()
1767        );
1768        println!(
1769            "RefCell开销倍数: {:.1}x",
1770            refcell_time.as_secs_f64() / direct_time.as_secs_f64()
1771        );
1772        println!("校验: {} vs {}", sum1, sum2);
1773    }
1774}