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::{
16    lambda::runnable::RuntimeError,
17    onion_tuple,
18    types::lambda::native::{
19        native_bool_converter, native_bytes_converter, native_elements_method,
20        native_float_converter, native_int_converter, native_length_method,
21        native_string_converter, wrap_native_function,
22    },
23};
24
25use super::{
26    lambda::{
27        definition::OnionLambdaDefinition, vm_instructions::instruction_set::VMInstructionPackage,
28    },
29    lazy_set::OnionLazySet,
30    named::OnionNamed,
31    pair::OnionPair,
32    tuple::OnionTuple,
33};
34
35// Newtype wrapper to allow implementing GCTraceable for RefCell<OnionObject>
36pub struct OnionObjectCell(pub RwLock<OnionObject>);
37
38impl OnionObjectCell {
39    #[inline(always)]
40    /// 严格遵循幂等律的情况下,Cell里不可能出现Mut对象。
41    /// 如果出现了Mut对象,说明VM对象分配或GC逻辑有bug
42    pub fn with_data<T, F>(&self, f: F) -> Result<T, RuntimeError>
43    where
44        F: FnOnce(&OnionObject) -> Result<T, RuntimeError>,
45    {
46        match self.0.read() {
47            Ok(guard) => match &*guard {
48                OnionObject::Mut(_) => {
49                    panic!("CRITICAL: OnionObjectCell contains Mut object. This indicates a bug in VM object allocation or GC logic. Check mutablize() and object creation paths.")
50                }
51                obj => f(obj),
52            },
53            Err(_) => Err(RuntimeError::BorrowError(
54                "Failed to borrow OnionObjectCell at `with_data`"
55                    .to_string()
56                    .into(),
57            )),
58        }
59    }
60    #[inline(always)]
61    /// 严格遵循幂等律的情况下,Cell里不可能出现Mut对象。
62    /// 如果出现了Mut对象,说明VM对象分配或GC逻辑有bug
63    pub fn with_data_mut<T, F>(&self, f: F) -> Result<T, RuntimeError>
64    where
65        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
66    {
67        match self.0.write() {
68            Ok(mut guard) => match &mut *guard {
69                OnionObject::Mut(_) => {
70                    panic!("CRITICAL: OnionObjectCell contains Mut object. This indicates a bug in VM object allocation or GC logic. Check mutablize() and object creation paths.")
71                }
72                obj => f(obj),
73            },
74            Err(_) => Err(RuntimeError::BorrowError(
75                "Failed to borrow OnionObjectCell at `with_data_mut`"
76                    .to_string()
77                    .into(),
78            )),
79        }
80    }
81
82    #[inline(always)]
83    pub fn with_attribute<T, F>(&self, key: &OnionObject, f: &F) -> Result<T, RuntimeError>
84    where
85        F: Fn(&OnionObject) -> Result<T, RuntimeError>,
86    {
87        self.0
88            .read()
89            .map_err(|_| {
90                RuntimeError::BorrowError(
91                    "Failed to borrow OnionObjectCell at `with_attribute`"
92                        .to_string()
93                        .into(),
94                )
95            })?
96            .with_attribute(key, f)
97    }
98
99    #[inline(always)]
100    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
101        match self.0.read() {
102            Ok(obj) => obj.upgrade(collected),
103            Err(_) => {
104                // 如果无法借用,可能是因为对象已经被回收或正在被其他线程使用
105                // 这里选择忽略
106            }
107        }
108    }
109
110    #[inline(always)]
111    pub fn stabilize(self) -> OnionStaticObject {
112        OnionStaticObject::new(self.try_borrow().unwrap().clone())
113    }
114
115    #[inline(always)]
116    pub fn equals(&self, other: &Self) -> Result<bool, RuntimeError> {
117        self.with_data(|obj| other.with_data(|other_obj| obj.equals(other_obj)))
118    }
119
120    #[inline(always)]
121    pub fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
122        self.with_data(|obj| obj.repr(ptrs))
123    }
124
125    #[inline(always)]
126    pub fn try_borrow(&self) -> Result<RwLockReadGuard<OnionObject>, RuntimeError> {
127        self.0.read().map_err(|_| {
128            RuntimeError::BorrowError(
129                "Failed to borrow OnionObjectCell at `try_borrow`"
130                    .to_string()
131                    .into(),
132            )
133        })
134    }
135    #[inline(always)]
136    pub fn try_borrow_mut(&self) -> Result<RwLockWriteGuard<OnionObject>, RuntimeError> {
137        self.0.write().map_err(|_| {
138            RuntimeError::BorrowError(
139                "Failed to borrow OnionObjectCell at `try_borrow_mut`"
140                    .to_string()
141                    .into(),
142            )
143        })
144    }
145}
146
147impl std::ops::Deref for OnionObjectCell {
148    type Target = RwLock<OnionObject>;
149
150    fn deref(&self) -> &Self::Target {
151        &self.0
152    }
153}
154
155impl std::ops::DerefMut for OnionObjectCell {
156    fn deref_mut(&mut self) -> &mut Self::Target {
157        &mut self.0
158    }
159}
160
161impl From<RwLock<OnionObject>> for OnionObjectCell {
162    fn from(cell: RwLock<OnionObject>) -> Self {
163        OnionObjectCell(cell)
164    }
165}
166
167impl From<OnionObject> for OnionObjectCell {
168    fn from(obj: OnionObject) -> Self {
169        OnionObjectCell(RwLock::new(obj))
170    }
171}
172
173impl GCTraceable<OnionObjectCell> for OnionObjectCell {
174    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
175        if let Ok(obj) = self.0.read() {
176            obj.collect(queue);
177        }
178    }
179}
180
181impl Debug for OnionObjectCell {
182    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183        write!(f, "{:?}", self.0.read())
184    }
185}
186
187impl Display for OnionObjectCell {
188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189        write!(f, "{:?}", self.0.read())
190    }
191}
192
193#[derive(Clone)]
194/// OnionObject is the main type for all objects in the Onion VM.
195/// The VM's types are all immutable(Mut is a immutable pointer to a VM object)
196/// 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.
197/// `reconstruct_container` is used to reconstruct the container object, which is used to regenerate all `Arc` references to the object.
198pub enum OnionObject {
199    // immutable basic types
200    Integer(i64),
201    Float(f64),
202    String(Arc<String>),
203    Bytes(Arc<Vec<u8>>),
204    Boolean(bool),
205    Range(i64, i64),
206    Null,
207    Undefined(Option<Arc<String>>),
208    InstructionPackage(Arc<VMInstructionPackage>),
209
210    // immutable container types, need `reconstruct_container` for clone to solve circular references
211    Tuple(Arc<OnionTuple>),
212    Pair(Arc<OnionPair>),
213    Named(Arc<OnionNamed>),
214    LazySet(Arc<OnionLazySet>),
215    Lambda(Arc<OnionLambdaDefinition>),
216
217    Custom(Arc<dyn OnionObjectExt>),
218    // mutable? types, DO NOT USE THIS TYPE DIRECTLY, use `mutablize` instead
219    Mut(GCArcWeak<OnionObjectCell>),
220}
221
222pub trait OnionObjectExt: GCTraceable<OnionObjectCell> + Debug + Send + Sync + 'static {
223    // Type introspection for downcasting
224    fn as_any(&self) -> &dyn std::any::Any;
225
226    // GC and memory management
227    fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>);
228
229    fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError>;
230
231    // Basic type conversions
232    fn to_integer(&self) -> Result<i64, RuntimeError> {
233        Err(RuntimeError::InvalidType(
234            format!("Cannot convert {:?} to Integer", self).into(),
235        ))
236    }
237    fn to_float(&self) -> Result<f64, RuntimeError> {
238        Err(RuntimeError::InvalidType(
239            format!("Cannot convert {:?} to Float", self).into(),
240        ))
241    }
242    #[allow(unused_variables)]
243    fn to_string(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
244        Err(RuntimeError::InvalidType(
245            format!("Cannot convert {:?} to String", self).into(),
246        ))
247    }
248    fn to_bytes(&self) -> Result<Vec<u8>, RuntimeError> {
249        Err(RuntimeError::InvalidType(
250            format!("Cannot convert {:?} to Bytes", self).into(),
251        ))
252    }
253    fn to_boolean(&self) -> Result<bool, RuntimeError> {
254        Err(RuntimeError::InvalidType(
255            format!("Cannot convert {:?} to Boolean", self).into(),
256        ))
257    }
258    #[allow(unused_variables)]
259    fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
260        Ok(format!("{:?}", self))
261    }
262    fn type_of(&self) -> Result<String, RuntimeError> {
263        Err(RuntimeError::InvalidType(
264            format!("Cannot get type of {:?}", self).into(),
265        ))
266    }
267
268    // Container operations
269    fn len(&self) -> Result<OnionStaticObject, RuntimeError> {
270        Err(RuntimeError::InvalidOperation(
271            format!("len() not supported for {:?}", self).into(),
272        ))
273    }
274    fn contains(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
275        Err(RuntimeError::InvalidOperation(
276            format!("contains() not supported for {:?} and {:?}", self, other).into(),
277        ))
278    }
279    fn at(&self, index: i64) -> Result<OnionStaticObject, RuntimeError> {
280        Err(RuntimeError::InvalidOperation(
281            format!("at() not supported for {:?} with index {}", self, index).into(),
282        ))
283    }
284
285    // Key-value operations
286    fn key_of(&self) -> Result<OnionStaticObject, RuntimeError> {
287        Err(RuntimeError::InvalidOperation(
288            format!("key_of() not supported for {:?}", self).into(),
289        ))
290    }
291    fn value_of(&self) -> Result<OnionStaticObject, RuntimeError> {
292        Err(RuntimeError::InvalidOperation(
293            format!("value_of() not supported for {:?}", self).into(),
294        ))
295    }
296    #[allow(unused_variables)]
297    fn with_attribute(
298        &self,
299        key: &OnionObject,
300        f: &mut dyn FnMut(&OnionObject) -> Result<(), RuntimeError>,
301    ) -> Result<(), RuntimeError> {
302        Err(RuntimeError::InvalidOperation(
303            format!(
304                "with_attribute() not supported for {:?} with key {:?}",
305                self, key
306            )
307            .into(),
308        ))
309    }
310
311    // Comparison operations
312    fn equals(&self, other: &OnionObject) -> Result<bool, RuntimeError>;
313    fn is_same(&self, other: &OnionObject) -> Result<bool, RuntimeError>;
314    fn binary_eq(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
315        Err(RuntimeError::InvalidOperation(
316            format!("binary_eq() not supported for {:?} and {:?}", self, other).into(),
317        ))
318    }
319    fn binary_lt(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
320        Err(RuntimeError::InvalidOperation(
321            format!("binary_lt() not supported for {:?} and {:?}", self, other).into(),
322        ))
323    }
324    fn binary_gt(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
325        Err(RuntimeError::InvalidOperation(
326            format!("binary_gt() not supported for {:?} and {:?}", self, other).into(),
327        ))
328    }
329
330    // Binary arithmetic operations
331    fn binary_add(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
332        Err(RuntimeError::InvalidOperation(
333            format!("binary_add() not supported for {:?} and {:?}", self, other).into(),
334        ))
335    }
336    fn binary_sub(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
337        Err(RuntimeError::InvalidOperation(
338            format!("binary_sub() not supported for {:?} and {:?}", self, other).into(),
339        ))
340    }
341    fn binary_mul(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
342        Err(RuntimeError::InvalidOperation(
343            format!("binary_mul() not supported for {:?} and {:?}", self, other).into(),
344        ))
345    }
346    fn binary_div(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
347        Err(RuntimeError::InvalidOperation(
348            format!("binary_div() not supported for {:?} and {:?}", self, other).into(),
349        ))
350    }
351    fn binary_mod(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
352        Err(RuntimeError::InvalidOperation(
353            format!("binary_mod() not supported for {:?} and {:?}", self, other).into(),
354        ))
355    }
356    fn binary_pow(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
357        Err(RuntimeError::InvalidOperation(
358            format!("binary_pow() not supported for {:?} and {:?}", self, other).into(),
359        ))
360    }
361
362    // Binary logical operations
363    fn binary_and(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
364        Err(RuntimeError::InvalidOperation(
365            format!("binary_and() not supported for {:?} and {:?}", self, other).into(),
366        ))
367    }
368    fn binary_or(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
369        Err(RuntimeError::InvalidOperation(
370            format!("binary_or() not supported for {:?} and {:?}", self, other).into(),
371        ))
372    }
373    fn binary_xor(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
374        Err(RuntimeError::InvalidOperation(
375            format!("binary_xor() not supported for {:?} and {:?}", self, other).into(),
376        ))
377    }
378
379    // Binary shift operations
380    fn binary_shl(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
381        Err(RuntimeError::InvalidOperation(
382            format!("binary_shl() not supported for {:?} and {:?}", self, other).into(),
383        ))
384    }
385    fn binary_shr(&self, other: &OnionObject) -> Result<OnionStaticObject, RuntimeError> {
386        Err(RuntimeError::InvalidOperation(
387            format!("binary_shr() not supported for {:?} and {:?}", self, other).into(),
388        ))
389    }
390
391    // Unary operations
392    fn unary_neg(&self) -> Result<OnionStaticObject, RuntimeError> {
393        Err(RuntimeError::InvalidOperation(
394            format!("unary_neg() not supported for {:?}", self).into(),
395        ))
396    }
397    fn unary_plus(&self) -> Result<OnionStaticObject, RuntimeError> {
398        Err(RuntimeError::InvalidOperation(
399            format!("unary_plus() not supported for {:?}", self).into(),
400        ))
401    }
402    fn unary_not(&self) -> Result<OnionStaticObject, RuntimeError> {
403        Err(RuntimeError::InvalidOperation(
404            format!("unary_not() not supported for {:?}", self).into(),
405        ))
406    }
407}
408
409impl Debug for OnionObject {
410    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
411        // 使用 repr
412        write!(
413            f,
414            "{}",
415            self.repr(&vec![])
416                .unwrap_or_else(|_| "BrokenReference".to_string())
417        )
418    }
419}
420
421impl GCTraceable<OnionObjectCell> for OnionObject {
422    fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
423        match self {
424            OnionObject::Mut(weak) => {
425                queue.push_back(weak.clone());
426            }
427            OnionObject::Tuple(tuple) => tuple.collect(queue),
428            OnionObject::Pair(pair) => pair.collect(queue),
429            OnionObject::Named(named) => named.collect(queue),
430            OnionObject::LazySet(lazy_set) => lazy_set.collect(queue),
431            OnionObject::Lambda(lambda) => lambda.collect(queue),
432            OnionObject::Custom(custom) => custom.collect(queue),
433
434            _ => {}
435        }
436    }
437}
438impl OnionObject {
439    pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
440        match self {
441            OnionObject::Mut(weak) => {
442                if let Some(strong) = weak.upgrade() {
443                    collected.push(strong);
444                }
445            }
446            OnionObject::Tuple(tuple) => tuple.upgrade(collected),
447            OnionObject::Pair(pair) => pair.upgrade(collected),
448            OnionObject::Named(named) => named.upgrade(collected),
449            OnionObject::LazySet(lazy_set) => lazy_set.upgrade(collected),
450            OnionObject::Lambda(lambda) => lambda.upgrade(collected),
451            OnionObject::Custom(custom) => custom.upgrade(collected),
452            _ => {}
453        }
454    }
455
456    #[inline(always)]
457    pub fn to_cell(self) -> OnionObjectCell {
458        OnionObjectCell(RwLock::new(self))
459    }
460
461    #[inline(always)]
462    pub fn stabilize(&self) -> OnionStaticObject {
463        OnionStaticObject::new(self.clone())
464    }
465
466    #[inline(always)]
467    pub fn consume_and_stabilize(self) -> OnionStaticObject {
468        OnionStaticObject::new(self)
469    }
470    pub fn len(&self) -> Result<OnionStaticObject, RuntimeError> {
471        self.with_data(|obj| match obj {
472            OnionObject::Tuple(tuple) => tuple.len(),
473            OnionObject::String(s) => {
474                Ok(OnionStaticObject::new(OnionObject::Integer(s.len() as i64)))
475            }
476            OnionObject::Bytes(b) => {
477                Ok(OnionStaticObject::new(OnionObject::Integer(b.len() as i64)))
478            }
479            OnionObject::Range(start, end) => Ok(OnionStaticObject::new(OnionObject::Integer(
480                (end - start) as i64,
481            ))),
482            OnionObject::Custom(custom) => custom.len(),
483            _ => Err(RuntimeError::InvalidOperation(
484                format!("len() not supported for {:?}", self).into(),
485            )),
486        })
487    }
488
489    pub fn contains(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
490        self.with_data(|obj| {
491            other.with_data(|other_obj| match (obj, other_obj) {
492                (OnionObject::Tuple(tuple), _) => tuple.contains(other_obj),
493                (OnionObject::String(s), OnionObject::String(other_s)) => {
494                    Ok(s.contains(other_s.as_ref()))
495                }
496                (OnionObject::Bytes(b), OnionObject::Bytes(other_b)) => Ok(b
497                    .windows(other_b.len())
498                    .any(|window| window == other_b.as_slice())),
499                (OnionObject::Range(l, r), OnionObject::Integer(i)) => Ok(*i >= *l && *i < *r),
500                (OnionObject::Range(start, end), OnionObject::Float(f)) => {
501                    Ok(*f >= *start as f64 && *f < *end as f64)
502                }
503                (OnionObject::Range(start, end), OnionObject::Range(other_start, other_end)) => {
504                    Ok(*other_start >= *start && *other_end <= *end)
505                }
506                (OnionObject::Custom(custom), _) => custom.contains(other_obj),
507                _ => Err(RuntimeError::InvalidOperation(
508                    format!("contains() not supported for {:?}", obj).into(),
509                )),
510            })
511        })
512    }
513
514    #[inline(always)]
515    pub fn with_data<T, F>(&self, f: F) -> Result<T, RuntimeError>
516    where
517        F: FnOnce(&OnionObject) -> Result<T, RuntimeError>,
518    {
519        match self {
520            OnionObject::Mut(weak) => {
521                if let Some(strong) = weak.upgrade() {
522                    strong.as_ref().with_data(f)
523                } else {
524                    Err(RuntimeError::BrokenReference)
525                }
526            }
527            _ => f(self),
528        }
529    }
530
531    #[inline(always)]
532    pub fn with_data_mut<T, F>(&mut self, f: F) -> Result<T, RuntimeError>
533    where
534        F: FnOnce(&mut OnionObject) -> Result<T, RuntimeError>,
535    {
536        match self {
537            OnionObject::Mut(weak) => {
538                if let Some(strong) = weak.upgrade() {
539                    strong.as_ref().with_data_mut(f)
540                } else {
541                    Err(RuntimeError::BrokenReference)
542                }
543            }
544            _ => f(self),
545        }
546    }
547
548    #[inline(always)]
549    /// Assign a new value to a mutable object.
550    pub fn assign(&self, other: &OnionObject) -> Result<(), RuntimeError> {
551        // 由于我们无法保证赋值后GCArcWeak指向对象的稳定性,对不可变对象进行赋值操作会导致潜在的内存安全问题。
552        // Mut类型由于是被GC管理的,因此可以安全地进行赋值操作(前提是GCArcWeak指向的对象仍然存在)。
553        let OnionObject::Mut(weak) = self else {
554            return Err(RuntimeError::InvalidOperation(
555                format!("Cannot assign to non-mutable object: {:?}", self).into(),
556            ));
557        };
558        match weak.upgrade() {
559            Some(strong) => {
560                // 先克隆要赋值的内容,避免借用冲突
561                let new_value = other.with_data(|other| other.reconstruct_container())?;
562
563                // 然后进行赋值
564                strong.as_ref().with_data_mut(|obj| {
565                    *obj = new_value;
566                    Ok(())
567                })
568            }
569            None => Err(RuntimeError::BrokenReference),
570        }
571    }
572
573    /// 重建容器对象,主要用于 mutable_obj1 = obj2 这种赋值
574    pub fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError> {
575        match self {
576            OnionObject::Tuple(tuple) => tuple.reconstruct_container(),
577            OnionObject::Pair(pair) => pair.reconstruct_container(),
578            OnionObject::Named(named) => named.reconstruct_container(),
579            OnionObject::LazySet(lazy_set) => lazy_set.reconstruct_container(),
580            OnionObject::Lambda(lambda) => lambda.reconstruct_container(),
581            OnionObject::Custom(custom) => custom.reconstruct_container(),
582            _ => Ok(self.clone()), // 对于其他类型,直接克隆(由于Mut自身就是不可变地址,因此直接
583                                   // 克隆即可,并且只有容器才可能造成循环)
584        }
585    }
586    pub fn to_integer(&self) -> Result<i64, RuntimeError> {
587        self.with_data(|obj| match obj {
588            OnionObject::Integer(i) => Ok(*i),
589            OnionObject::Float(f) => Ok(*f as i64),
590            OnionObject::String(s) => s
591                .parse::<i64>()
592                .map_err(|e| RuntimeError::InvalidType(e.to_string().into())),
593            OnionObject::Boolean(b) => Ok(if *b { 1 } else { 0 }),
594            OnionObject::Custom(custom) => custom.to_integer(),
595            _ => Err(RuntimeError::InvalidType(
596                format!("Cannot convert {:?} to Integer", obj).into(),
597            )),
598        })
599    }
600    pub fn to_float(&self) -> Result<f64, RuntimeError> {
601        self.with_data(|obj| match obj {
602            OnionObject::Integer(i) => Ok(*i as f64),
603            OnionObject::Float(f) => Ok(*f),
604            OnionObject::String(s) => s
605                .parse::<f64>()
606                .map_err(|e| RuntimeError::InvalidType(e.to_string().into())),
607            OnionObject::Boolean(b) => Ok(if *b { 1.0 } else { 0.0 }),
608            OnionObject::Custom(custom) => custom.to_float(),
609            _ => Err(RuntimeError::InvalidType(
610                format!("Cannot convert {:?} to Float", obj).into(),
611            )),
612        })
613    }
614
615    pub fn to_string(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
616        self.with_data(|obj| {
617            for ptr in ptrs {
618                if addr_eq(obj, *ptr) {
619                    return Ok("...".to_string());
620                }
621            }
622            let mut new_ptrs = ptrs.clone();
623            new_ptrs.push(obj);
624            match obj {
625                OnionObject::Integer(i) => Ok(i.to_string()),
626                OnionObject::Float(f) => Ok(f.to_string()),
627                OnionObject::String(s) => Ok(s.as_ref().clone()),
628                OnionObject::Bytes(b) => Ok(format!(
629                    "$\"{}\"",
630                    general_purpose::STANDARD.encode(b.as_ref())
631                )),
632                OnionObject::Boolean(b) => Ok(if *b {
633                    "true".to_string()
634                } else {
635                    "false".to_string()
636                }),
637                OnionObject::Null => Ok("null".to_string()),
638                OnionObject::Undefined(s) => Ok(match s {
639                    Some(s) => format!("undefined({:?})", s),
640                    None => "undefined".to_string(),
641                }),
642                OnionObject::Range(start, end) => Ok(format!("{}..{}", start, end)),
643                OnionObject::Tuple(tuple) => match tuple.get_elements().len() {
644                    0 => Ok("()".to_string()),
645                    1 => {
646                        let first = tuple.get_elements().first().unwrap();
647                        Ok(format!("({},)", first.repr(&new_ptrs)?))
648                    }
649                    _ => {
650                        let elements: Result<Vec<String>, RuntimeError> = tuple
651                            .get_elements()
652                            .iter()
653                            .map(|e| e.repr(&new_ptrs))
654                            .collect();
655                        Ok(format!("({})", elements?.join(", ")))
656                    }
657                },
658                OnionObject::Pair(pair) => {
659                    let left = pair.get_key().repr(&new_ptrs)?;
660                    let right = pair.get_value().repr(&new_ptrs)?;
661                    Ok(format!("{} : {}", left, right))
662                }
663                OnionObject::Named(named) => {
664                    let name = named.get_key().repr(&new_ptrs)?;
665                    let value = named.get_value().repr(&new_ptrs)?;
666                    Ok(format!("{} => {}", name, value))
667                }
668                OnionObject::LazySet(lazy_set) => {
669                    let container = lazy_set.get_container().repr(&new_ptrs)?;
670                    let filter = lazy_set.get_filter().repr(&new_ptrs)?;
671                    Ok(format!("[{} | {}]", container, filter))
672                }
673                OnionObject::InstructionPackage(_) => Ok("InstructionPackage(...)".to_string()),
674                OnionObject::Lambda(lambda) => {
675                    let params = lambda.get_parameter().repr(&new_ptrs)?;
676                    let body = lambda.get_body().to_string();
677                    Ok(format!(
678                        "{}::{} -> {}",
679                        lambda.get_signature(),
680                        params,
681                        body
682                    ))
683                }
684                OnionObject::Custom(custom) => custom.to_string(&new_ptrs),
685                _ => {
686                    // 使用 Debug trait来处理其他类型的转换
687                    Ok(format!("{:?}", obj))
688                }
689            }
690        })
691    }
692
693    pub fn repr(&self, ptrs: &Vec<*const OnionObject>) -> Result<String, RuntimeError> {
694        self.with_data(|obj| {
695            for ptr in ptrs {
696                if addr_eq(obj, *ptr) {
697                    return Ok("...".to_string());
698                }
699            }
700            let mut new_ptrs = ptrs.clone();
701            new_ptrs.push(obj);
702            match obj {
703                OnionObject::Integer(i) => Ok(format!("{}", i)),
704                OnionObject::Float(f) => Ok(format!("{}", f)),
705                OnionObject::String(s) => Ok(format!("{:?}", s)),
706                OnionObject::Bytes(b) => Ok(format!(
707                    "$\"{}\"",
708                    general_purpose::STANDARD.encode(b.as_ref())
709                )),
710                OnionObject::Boolean(b) => Ok(format!("{}", b)),
711                OnionObject::Null => Ok("null".to_string()),
712                OnionObject::Undefined(s) => Ok(match s {
713                    Some(s) => format!("undefined({:?})", s),
714                    None => "undefined".to_string(),
715                }),
716                OnionObject::Range(start, end) => Ok(format!("{}..{}", start, end)),
717                OnionObject::Tuple(tuple) => match tuple.get_elements().len() {
718                    0 => Ok("()".to_string()),
719                    1 => {
720                        let first = tuple.get_elements().first().unwrap();
721                        Ok(format!("({},)", first.repr(&new_ptrs)?))
722                    }
723                    _ => {
724                        let elements: Result<Vec<String>, RuntimeError> = tuple
725                            .get_elements()
726                            .iter()
727                            .map(|e| e.repr(&new_ptrs))
728                            .collect();
729                        Ok(format!("({})", elements?.join(", ")))
730                    }
731                },
732                OnionObject::Pair(pair) => {
733                    let left = pair.get_key().repr(&new_ptrs)?;
734                    let right = pair.get_value().repr(&new_ptrs)?;
735                    Ok(format!("{} : {}", left, right))
736                }
737                OnionObject::Named(named) => {
738                    let name = named.get_key().repr(&new_ptrs)?;
739                    let value = named.get_value().repr(&new_ptrs)?;
740                    Ok(format!("{} => {}", name, value))
741                }
742                OnionObject::LazySet(lazy_set) => {
743                    let container = lazy_set.get_container().repr(&new_ptrs)?;
744                    let filter = lazy_set.get_filter().repr(&new_ptrs)?;
745                    Ok(format!("[{} | {}]", container, filter))
746                }
747                OnionObject::InstructionPackage(_) => Ok("InstructionPackage(...)".to_string()),
748                OnionObject::Lambda(lambda) => {
749                    let params = lambda.get_parameter().repr(&new_ptrs)?;
750                    Ok(format!(
751                        "{}::{} -> {}",
752                        lambda.get_signature(),
753                        params,
754                        lambda.get_body()
755                    ))
756                }
757                OnionObject::Mut(weak) => {
758                    if let Some(strong) = weak.upgrade() {
759                        let inner_repr = strong
760                            .as_ref()
761                            .try_borrow()
762                            .map_err(|_| {
763                                RuntimeError::BorrowError(
764                                    "Failed to borrow Mut object at `repr`".to_string().into(),
765                                )
766                            })?
767                            .repr(&new_ptrs)?;
768                        Ok(format!("mut ({})", inner_repr))
769                    } else {
770                        Ok("Mut(BrokenReference)".to_string())
771                    }
772                }
773                OnionObject::Custom(custom) => {
774                    let custom_repr = custom.repr(&new_ptrs)?;
775                    Ok(format!("Custom({})", custom_repr))
776                }
777            }
778        })
779    }
780    pub fn to_bytes(&self) -> Result<Vec<u8>, RuntimeError> {
781        self.with_data(|obj| match obj {
782            OnionObject::Integer(i) => Ok(i.to_string().into_bytes()),
783            OnionObject::Float(f) => Ok(f.to_string().into_bytes()),
784            OnionObject::String(s) => Ok(s.as_bytes().to_vec()),
785            OnionObject::Bytes(b) => Ok(b.as_ref().clone()),
786            OnionObject::Boolean(b) => Ok(if *b {
787                b"true".to_vec()
788            } else {
789                b"false".to_vec()
790            }),
791            OnionObject::Custom(custom) => custom.to_bytes(),
792            _ => Err(RuntimeError::InvalidType(
793                format!("Cannot convert {:?} to Bytes", obj).into(),
794            )),
795        })
796    }
797
798    pub fn to_boolean(&self) -> Result<bool, RuntimeError> {
799        self.with_data(|obj| match obj {
800            OnionObject::Integer(i) => Ok(*i != 0),
801            OnionObject::Float(f) => Ok(*f != 0.0),
802            OnionObject::String(s) => Ok(!s.is_empty()),
803            OnionObject::Bytes(b) => Ok(!b.is_empty()),
804            OnionObject::Boolean(b) => Ok(*b),
805            OnionObject::Null => Ok(false),
806            OnionObject::Undefined(_) => Ok(false),
807            OnionObject::Custom(custom) => custom.to_boolean(),
808            _ => Err(RuntimeError::InvalidType(
809                format!("Cannot convert {:?} to Boolean", obj).into(),
810            )),
811        })
812    }
813
814    #[inline(always)]
815    fn mutablize(self, gc: &mut GC<OnionObjectCell>) -> OnionStaticObject {
816        let arc = gc.create(OnionObjectCell::from(self));
817        OnionStaticObject {
818            obj: OnionObject::Mut(arc.as_weak()),
819            _arcs: GCArcStorage::Single(arc),
820        }
821    }
822}
823
824impl OnionObject {
825    pub fn equals(&self, other: &Self) -> Result<bool, RuntimeError> {
826        self.with_data(|left| {
827            other.with_data(|right| {
828                match (left, right) {
829                    (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 == i2),
830                    (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 == f2),
831                    (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok(*i1 as f64 == *f2),
832                    (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 == *i2 as f64),
833                    (OnionObject::String(s1), OnionObject::String(s2)) => Ok(s1 == s2),
834                    (OnionObject::Bytes(b1), OnionObject::Bytes(b2)) => Ok(b1 == b2),
835                    (OnionObject::Boolean(b1), OnionObject::Boolean(b2)) => Ok(b1 == b2),
836                    (OnionObject::Range(start1, end1), OnionObject::Range(start2, end2)) => {
837                        Ok(start1 == start2 && end1 == end2)
838                    }
839                    (OnionObject::Null, OnionObject::Null) => Ok(true),
840                    (OnionObject::Undefined(_), OnionObject::Undefined(_)) => Ok(true),
841                    (OnionObject::Tuple(t1), _) => t1.equals(other),
842                    (OnionObject::Pair(p1), _) => p1.equals(other),
843                    (OnionObject::Named(n1), _) => n1.equals(other),
844                    (OnionObject::Custom(c1), _) => c1.equals(other),
845
846                    // 理论上Mut类型不应该出现在这里
847                    _ => Ok(false),
848                }
849            })
850        })
851    }
852    pub fn is_same(&self, other: &Self) -> Result<bool, RuntimeError> {
853        match (self, other) {
854            (OnionObject::Mut(weak1), OnionObject::Mut(weak2)) => {
855                if let (Some(strong1), Some(strong2)) = (weak1.upgrade(), weak2.upgrade()) {
856                    Ok(addr_eq(strong1.as_ref(), strong2.as_ref()))
857                } else {
858                    Ok(false)
859                }
860            }
861            (OnionObject::Custom(c1), _) => c1.is_same(other),
862            _ => self.equals(other),
863        }
864    }
865
866    pub fn binary_add(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
867        self.with_data(|obj| {
868            other.with_data(|other_obj| match (obj, other_obj) {
869                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
870                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 + i2)))
871                }
872                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
873                    Ok(OnionStaticObject::new(OnionObject::Float(f1 + f2)))
874                }
875                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
876                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 + f2)))
877                }
878                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
879                    Ok(OnionStaticObject::new(OnionObject::Float(f1 + *i2 as f64)))
880                }
881                (OnionObject::String(s1), OnionObject::String(s2)) => Ok(OnionStaticObject::new(
882                    OnionObject::String(Arc::new(format!("{}{}", s1, s2))),
883                )),
884                (OnionObject::Bytes(b1), OnionObject::Bytes(b2)) => {
885                    let mut new_bytes = b1.as_ref().clone();
886                    new_bytes.extend_from_slice(b2);
887                    Ok(OnionStaticObject::new(OnionObject::Bytes(Arc::new(
888                        new_bytes,
889                    ))))
890                }
891                (OnionObject::Range(start1, end1), OnionObject::Range(start2, end2)) => Ok(
892                    OnionStaticObject::new(OnionObject::Range(start1 + start2, end1 + end2)),
893                ),
894                (OnionObject::Tuple(t1), _) => t1.binary_add(other_obj),
895                (OnionObject::Custom(c1), _) => c1.binary_add(other_obj),
896                _ => Err(RuntimeError::InvalidOperation(
897                    format!(
898                        "Invalid binary add operation for {:?} and {:?}",
899                        obj, other_obj
900                    )
901                    .into(),
902                )),
903            })
904        })
905    }
906
907    pub fn binary_sub(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
908        self.with_data(|obj| {
909            other.with_data(|other_obj| match (obj, other_obj) {
910                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
911                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 - i2)))
912                }
913                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
914                    Ok(OnionStaticObject::new(OnionObject::Float(f1 - f2)))
915                }
916                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
917                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 - f2)))
918                }
919                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
920                    Ok(OnionStaticObject::new(OnionObject::Float(f1 - *i2 as f64)))
921                }
922                (OnionObject::Custom(c1), _) => c1.binary_sub(other_obj),
923                _ => Err(RuntimeError::InvalidOperation(
924                    format!(
925                        "Invalid binary sub operation for {:?} and {:?}",
926                        obj, other_obj
927                    )
928                    .into(),
929                )),
930            })
931        })
932    }
933
934    pub fn binary_mul(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
935        self.with_data(|obj| {
936            other.with_data(|other_obj| match (obj, other_obj) {
937                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
938                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 * i2)))
939                }
940                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
941                    Ok(OnionStaticObject::new(OnionObject::Float(f1 * f2)))
942                }
943                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
944                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 * f2)))
945                }
946                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
947                    Ok(OnionStaticObject::new(OnionObject::Float(f1 * *i2 as f64)))
948                }
949                (OnionObject::Custom(c1), _) => c1.binary_mul(other_obj),
950                _ => Err(RuntimeError::InvalidOperation(
951                    format!(
952                        "Invalid binary mul operation for {:?} and {:?}",
953                        obj, other_obj
954                    )
955                    .into(),
956                )),
957            })
958        })
959    }
960
961    pub fn binary_div(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
962        self.with_data(|obj| {
963            other.with_data(|other_obj| match (obj, other_obj) {
964                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
965                    if *i2 == 0 {
966                        return Err(RuntimeError::InvalidOperation(
967                            "Division by zero".to_string().into(),
968                        ));
969                    }
970                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 / i2)))
971                }
972                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
973                    Ok(OnionStaticObject::new(OnionObject::Float(f1 / f2)))
974                }
975                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
976                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 / f2)))
977                }
978                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
979                    Ok(OnionStaticObject::new(OnionObject::Float(f1 / *i2 as f64)))
980                }
981                (OnionObject::Custom(c1), _) => c1.binary_div(other_obj),
982                _ => Err(RuntimeError::InvalidOperation(
983                    format!(
984                        "Invalid binary div operation for {:?} and {:?}",
985                        obj, other_obj
986                    )
987                    .into(),
988                )),
989            })
990        })
991    }
992
993    pub fn binary_mod(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
994        self.with_data(|obj| {
995            other.with_data(|other_obj| match (obj, other_obj) {
996                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
997                    if *i2 == 0 {
998                        return Err(RuntimeError::InvalidOperation(
999                            "Division by zero".to_string().into(),
1000                        ));
1001                    }
1002                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 % i2)))
1003                }
1004                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
1005                    Ok(OnionStaticObject::new(OnionObject::Float(f1 % f2)))
1006                }
1007                (OnionObject::Integer(i1), OnionObject::Float(f2)) => {
1008                    Ok(OnionStaticObject::new(OnionObject::Float(*i1 as f64 % f2)))
1009                }
1010                (OnionObject::Float(f1), OnionObject::Integer(i2)) => {
1011                    Ok(OnionStaticObject::new(OnionObject::Float(f1 % *i2 as f64)))
1012                }
1013                (OnionObject::Custom(c1), _) => c1.binary_mod(other_obj),
1014                _ => Err(RuntimeError::InvalidOperation(
1015                    format!(
1016                        "Invalid binary mod operation for {:?} and {:?}",
1017                        obj, other_obj
1018                    )
1019                    .into(),
1020                )),
1021            })
1022        })
1023    }
1024
1025    pub fn binary_pow(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1026        self.with_data(|obj| {
1027            other.with_data(|other_obj| match (obj, other_obj) {
1028                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(OnionStaticObject::new(
1029                    OnionObject::Integer(i1.pow(*i2 as u32)),
1030                )),
1031                (OnionObject::Float(f1), OnionObject::Float(f2)) => {
1032                    Ok(OnionStaticObject::new(OnionObject::Float(f1.powf(*f2))))
1033                }
1034                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok(OnionStaticObject::new(
1035                    OnionObject::Float((*i1 as f64).powf(*f2)),
1036                )),
1037                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(OnionStaticObject::new(
1038                    OnionObject::Float(f1.powi(*i2 as i32)),
1039                )),
1040                (OnionObject::Custom(c1), _) => c1.binary_pow(other_obj),
1041                _ => Err(RuntimeError::InvalidOperation(
1042                    format!(
1043                        "Invalid binary pow operation for {:?} and {:?}",
1044                        obj, other_obj
1045                    )
1046                    .into(),
1047                )),
1048            })
1049        })
1050    }
1051
1052    pub fn binary_and(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1053        self.with_data(|obj| {
1054            other.with_data(|other_obj| match (obj, other_obj) {
1055                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1056                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 & i2)))
1057                }
1058                (OnionObject::Boolean(f1), OnionObject::Boolean(f2)) => {
1059                    Ok(OnionStaticObject::new(OnionObject::Boolean(*f1 && *f2)))
1060                }
1061                (OnionObject::Custom(c1), _) => c1.binary_and(other_obj),
1062                _ => Err(RuntimeError::InvalidOperation(
1063                    format!(
1064                        "Invalid binary and operation for {:?} and {:?}",
1065                        obj, other_obj
1066                    )
1067                    .into(),
1068                )),
1069            })
1070        })
1071    }
1072
1073    pub fn binary_or(&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_or(other_obj),
1083                _ => Err(RuntimeError::InvalidOperation(
1084                    format!(
1085                        "Invalid binary or operation for {:?} and {:?}",
1086                        obj, other_obj
1087                    )
1088                    .into(),
1089                )),
1090            })
1091        })
1092    }
1093
1094    pub fn binary_xor(&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::Custom(c1), _) => c1.binary_xor(other_obj),
1101                _ => Err(RuntimeError::InvalidOperation(
1102                    format!(
1103                        "Invalid binary xor operation for {:?} and {:?}",
1104                        obj, other_obj
1105                    )
1106                    .into(),
1107                )),
1108            })
1109        })
1110    }
1111
1112    pub fn binary_shl(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1113        self.with_data(|obj| {
1114            other.with_data(|other_obj| match (obj, other_obj) {
1115                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1116                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 << i2)))
1117                }
1118                (OnionObject::Custom(c1), _) => c1.binary_shl(other_obj),
1119                _ => Err(RuntimeError::InvalidOperation(
1120                    format!(
1121                        "Invalid binary shl operation for {:?} and {:?}",
1122                        obj, other_obj
1123                    )
1124                    .into(),
1125                )),
1126            })
1127        })
1128    }
1129
1130    pub fn binary_shr(&self, other: &Self) -> Result<OnionStaticObject, RuntimeError> {
1131        self.with_data(|obj| {
1132            other.with_data(|other_obj| match (obj, other_obj) {
1133                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => {
1134                    Ok(OnionStaticObject::new(OnionObject::Integer(i1 >> i2)))
1135                }
1136                (OnionObject::Custom(c1), _) => c1.binary_shr(other_obj),
1137                _ => Err(RuntimeError::InvalidOperation(
1138                    format!(
1139                        "Invalid binary shr operation for {:?} and {:?}",
1140                        obj, other_obj
1141                    )
1142                    .into(),
1143                )),
1144            })
1145        })
1146    }
1147
1148    pub fn binary_eq(&self, other: &Self) -> Result<bool, RuntimeError> {
1149        self.equals(other)
1150    }
1151
1152    pub fn binary_lt(&self, other: &Self) -> Result<bool, RuntimeError> {
1153        self.with_data(|obj| {
1154            other.with_data(|other_obj| match (obj, other_obj) {
1155                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 < i2),
1156                (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 < f2),
1157                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok((*i1 as f64) < *f2),
1158                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 < *i2 as f64),
1159                (OnionObject::Custom(c1), _) => c1.binary_lt(other_obj),
1160                _ => Err(RuntimeError::InvalidOperation(
1161                    format!(
1162                        "Invalid binary lt operation for {:?} and {:?}",
1163                        obj, other_obj
1164                    )
1165                    .into(),
1166                )),
1167            })
1168        })
1169    }
1170
1171    pub fn binary_gt(&self, other: &Self) -> Result<bool, RuntimeError> {
1172        self.with_data(|obj| {
1173            other.with_data(|other_obj| match (obj, other_obj) {
1174                (OnionObject::Integer(i1), OnionObject::Integer(i2)) => Ok(i1 > i2),
1175                (OnionObject::Float(f1), OnionObject::Float(f2)) => Ok(f1 > f2),
1176                (OnionObject::Integer(i1), OnionObject::Float(f2)) => Ok((*i1 as f64) > *f2),
1177                (OnionObject::Float(f1), OnionObject::Integer(i2)) => Ok(*f1 > *i2 as f64),
1178                (OnionObject::Custom(c1), _) => c1.binary_gt(other_obj),
1179                _ => Err(RuntimeError::InvalidOperation(
1180                    format!(
1181                        "Invalid binary gt operation for {:?} and {:?}",
1182                        obj, other_obj
1183                    )
1184                    .into(),
1185                )),
1186            })
1187        })
1188    }
1189
1190    pub fn unary_neg(&self) -> Result<OnionStaticObject, RuntimeError> {
1191        self.with_data(|obj| match obj {
1192            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(-i))),
1193            OnionObject::Float(f) => Ok(OnionStaticObject::new(OnionObject::Float(-f))),
1194            OnionObject::Custom(custom) => custom.unary_neg(),
1195            _ => Err(RuntimeError::InvalidOperation(
1196                format!("Invalid unary neg operation for {:?}", obj).into(),
1197            )),
1198        })
1199    }
1200
1201    pub fn unary_plus(&self) -> Result<OnionStaticObject, RuntimeError> {
1202        self.with_data(|obj| match obj {
1203            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(i.abs()))),
1204            OnionObject::Float(f) => Ok(OnionStaticObject::new(OnionObject::Float(f.abs()))),
1205            OnionObject::Custom(custom) => custom.unary_plus(),
1206            _ => Err(RuntimeError::InvalidOperation(
1207                format!("Invalid unary plus operation for {:?}", obj).into(),
1208            )),
1209        })
1210    }
1211
1212    pub fn unary_not(&self) -> Result<OnionStaticObject, RuntimeError> {
1213        self.with_data(|obj| match obj {
1214            OnionObject::Boolean(b) => Ok(OnionStaticObject::new(OnionObject::Boolean(!b))),
1215            OnionObject::Integer(i) => Ok(OnionStaticObject::new(OnionObject::Integer(!i))),
1216            OnionObject::Custom(custom) => custom.unary_not(),
1217            _ => Err(RuntimeError::InvalidOperation(
1218                format!("Invalid unary not operation for {:?}", obj).into(),
1219            )),
1220        })
1221    }
1222
1223    pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
1224    where
1225        F: Fn(&OnionObject) -> Result<R, RuntimeError>,
1226    {
1227        self.with_data(|obj| match obj {
1228            OnionObject::Integer(_) => {
1229                if let OnionObject::String(key_str) = key {
1230                    match key_str.as_str() {
1231                        "int" => {
1232                            let converter = wrap_native_function(
1233                                &onion_tuple!(),
1234                                None,
1235                                Some(&self.stabilize()),
1236                                "converter::int".to_string(),
1237                                &native_int_converter,
1238                            );
1239                            return f(converter.weak());
1240                        }
1241                        "float" => {
1242                            let converter = wrap_native_function(
1243                                &onion_tuple!(),
1244                                None,
1245                                Some(&self.stabilize()),
1246                                "converter::float".to_string(),
1247                                &native_float_converter,
1248                            );
1249                            return f(converter.weak());
1250                        }
1251                        "string" => {
1252                            let converter = wrap_native_function(
1253                                &onion_tuple!(),
1254                                None,
1255                                Some(&self.stabilize()),
1256                                "converter::string".to_string(),
1257                                &native_string_converter,
1258                            );
1259                            return f(converter.weak());
1260                        }
1261                        "bool" => {
1262                            let converter = wrap_native_function(
1263                                &onion_tuple!(),
1264                                None,
1265                                Some(&self.stabilize()),
1266                                "converter::bool".to_string(),
1267                                &native_bool_converter,
1268                            );
1269                            return f(converter.weak());
1270                        }
1271                        "bytes" => {
1272                            let converter = wrap_native_function(
1273                                &onion_tuple!(),
1274                                None,
1275                                Some(&self.stabilize()),
1276                                "converter::bytes".to_string(),
1277                                &native_bytes_converter,
1278                            );
1279                            return f(converter.weak());
1280                        }
1281                        _ => {}
1282                    }
1283                }
1284                Err(RuntimeError::InvalidOperation(
1285                    format!(
1286                        "Attribute '{}' not found for Integer",
1287                        match key {
1288                            OnionObject::String(s) => s.as_ref(),
1289                            _ => "<non-string>",
1290                        }
1291                    )
1292                    .into(),
1293                ))
1294            }
1295            OnionObject::Float(_) => {
1296                if let OnionObject::String(key_str) = key {
1297                    match key_str.as_str() {
1298                        "int" => {
1299                            let converter = wrap_native_function(
1300                                &onion_tuple!(),
1301                                None,
1302                                Some(&self.stabilize()),
1303                                "converter::int".to_string(),
1304                                &native_int_converter,
1305                            );
1306                            return f(converter.weak());
1307                        }
1308                        "float" => {
1309                            let converter = wrap_native_function(
1310                                &onion_tuple!(),
1311                                None,
1312                                Some(&self.stabilize()),
1313                                "converter::float".to_string(),
1314                                &native_float_converter,
1315                            );
1316                            return f(converter.weak());
1317                        }
1318                        "string" => {
1319                            let converter = wrap_native_function(
1320                                &onion_tuple!(),
1321                                None,
1322                                Some(&self.stabilize()),
1323                                "converter::string".to_string(),
1324                                &native_string_converter,
1325                            );
1326                            return f(converter.weak());
1327                        }
1328                        "bool" => {
1329                            let converter = wrap_native_function(
1330                                &onion_tuple!(),
1331                                None,
1332                                Some(&self.stabilize()),
1333                                "converter::bool".to_string(),
1334                                &native_bool_converter,
1335                            );
1336                            return f(converter.weak());
1337                        }
1338                        "bytes" => {
1339                            let converter = wrap_native_function(
1340                                &onion_tuple!(),
1341                                None,
1342                                Some(&self.stabilize()),
1343                                "converter::bytes".to_string(),
1344                                &native_bytes_converter,
1345                            );
1346                            return f(converter.weak());
1347                        }
1348                        _ => {}
1349                    }
1350                }
1351                Err(RuntimeError::InvalidOperation(
1352                    format!(
1353                        "Attribute '{}' not found for Float",
1354                        match key {
1355                            OnionObject::String(s) => s.as_ref(),
1356                            _ => "<non-string>",
1357                        }
1358                    )
1359                    .into(),
1360                ))
1361            }
1362            OnionObject::Boolean(_) => {
1363                if let OnionObject::String(key_str) = key {
1364                    match key_str.as_str() {
1365                        "int" => {
1366                            let converter = wrap_native_function(
1367                                &onion_tuple!(),
1368                                None,
1369                                Some(&self.stabilize()),
1370                                "converter::int".to_string(),
1371                                &native_int_converter,
1372                            );
1373                            return f(converter.weak());
1374                        }
1375                        "float" => {
1376                            let converter = wrap_native_function(
1377                                &onion_tuple!(),
1378                                None,
1379                                Some(&self.stabilize()),
1380                                "converter::float".to_string(),
1381                                &native_float_converter,
1382                            );
1383                            return f(converter.weak());
1384                        }
1385                        "string" => {
1386                            let converter = wrap_native_function(
1387                                &onion_tuple!(),
1388                                None,
1389                                Some(&self.stabilize()),
1390                                "converter::string".to_string(),
1391                                &native_string_converter,
1392                            );
1393                            return f(converter.weak());
1394                        }
1395                        "bool" => {
1396                            let converter = wrap_native_function(
1397                                &onion_tuple!(),
1398                                None,
1399                                Some(&self.stabilize()),
1400                                "converter::bool".to_string(),
1401                                &native_bool_converter,
1402                            );
1403                            return f(converter.weak());
1404                        }
1405                        "bytes" => {
1406                            let converter = wrap_native_function(
1407                                &onion_tuple!(),
1408                                None,
1409                                Some(&self.stabilize()),
1410                                "converter::bytes".to_string(),
1411                                &native_bytes_converter,
1412                            );
1413                            return f(converter.weak());
1414                        }
1415                        _ => {}
1416                    }
1417                }
1418                Err(RuntimeError::InvalidOperation(
1419                    format!(
1420                        "Attribute '{}' not found for Boolean",
1421                        match key {
1422                            OnionObject::String(s) => s.as_ref(),
1423                            _ => "<non-string>",
1424                        }
1425                    )
1426                    .into(),
1427                ))
1428            }
1429            OnionObject::Tuple(tuple) => {
1430                // 先检查原型链/自定义属性
1431                if let Ok(result) = tuple.with_attribute(key, f) {
1432                    return Ok(result);
1433                }
1434
1435                // 再检查native方法
1436                if let OnionObject::String(key_str) = key {
1437                    match key_str.as_str() {
1438                        "int" => {
1439                            let converter = wrap_native_function(
1440                                &onion_tuple!(),
1441                                None,
1442                                Some(&self.stabilize()),
1443                                "converter::int".to_string(),
1444                                &native_int_converter,
1445                            );
1446                            return f(converter.weak());
1447                        }
1448                        "float" => {
1449                            let converter = wrap_native_function(
1450                                &onion_tuple!(),
1451                                None,
1452                                Some(&self.stabilize()),
1453                                "converter::float".to_string(),
1454                                &native_float_converter,
1455                            );
1456                            return f(converter.weak());
1457                        }
1458                        "string" => {
1459                            let converter = wrap_native_function(
1460                                &onion_tuple!(),
1461                                None,
1462                                Some(&self.stabilize()),
1463                                "converter::string".to_string(),
1464                                &native_string_converter,
1465                            );
1466                            return f(converter.weak());
1467                        }
1468                        "bool" => {
1469                            let converter = wrap_native_function(
1470                                &onion_tuple!(),
1471                                None,
1472                                Some(&self.stabilize()),
1473                                "converter::bool".to_string(),
1474                                &native_bool_converter,
1475                            );
1476                            return f(converter.weak());
1477                        }
1478                        "bytes" => {
1479                            let converter = wrap_native_function(
1480                                &onion_tuple!(),
1481                                None,
1482                                Some(&self.stabilize()),
1483                                "converter::bytes".to_string(),
1484                                &native_bytes_converter,
1485                            );
1486                            return f(converter.weak());
1487                        }
1488                        "length" => {
1489                            let length_method = wrap_native_function(
1490                                &onion_tuple!(),
1491                                None,
1492                                Some(&self.stabilize()),
1493                                "builtin::length".to_string(),
1494                                &native_length_method,
1495                            );
1496                            return f(length_method.weak());
1497                        }
1498                        "elements" => {
1499                            let elements_method = wrap_native_function(
1500                                &onion_tuple!(),
1501                                None,
1502                                Some(&self.stabilize()),
1503                                "builtin::elements".to_string(),
1504                                &native_elements_method,
1505                            );
1506                            return f(elements_method.weak());
1507                        }
1508                        _ => {}
1509                    }
1510                }
1511                Err(RuntimeError::InvalidOperation(
1512                    format!(
1513                        "Attribute '{}' not found for Tuple",
1514                        match key {
1515                            OnionObject::String(s) => s.as_ref(),
1516                            _ => "<non-string>",
1517                        }
1518                    )
1519                    .into(),
1520                ))
1521            }
1522            OnionObject::Named(named) => named.with_attribute(key, f),
1523            OnionObject::Pair(pair) => pair.with_attribute(key, f),
1524            OnionObject::Lambda(lambda) => lambda.with_attribute(key, f),
1525            OnionObject::LazySet(lazy_set) => lazy_set.with_attribute(key, f),
1526            OnionObject::String(_) => {
1527                if let OnionObject::String(key_str) = key {
1528                    match key_str.as_str() {
1529                        "int" => {
1530                            let converter = wrap_native_function(
1531                                &onion_tuple!(),
1532                                None,
1533                                Some(&self.stabilize()),
1534                                "converter::int".to_string(),
1535                                &native_int_converter,
1536                            );
1537                            return f(converter.weak());
1538                        }
1539                        "float" => {
1540                            let converter = wrap_native_function(
1541                                &onion_tuple!(),
1542                                None,
1543                                Some(&self.stabilize()),
1544                                "converter::float".to_string(),
1545                                &native_float_converter,
1546                            );
1547                            return f(converter.weak());
1548                        }
1549                        "string" => {
1550                            let converter = wrap_native_function(
1551                                &onion_tuple!(),
1552                                None,
1553                                Some(&self.stabilize()),
1554                                "converter::string".to_string(),
1555                                &native_string_converter,
1556                            );
1557                            return f(converter.weak());
1558                        }
1559                        "bool" => {
1560                            let converter = wrap_native_function(
1561                                &onion_tuple!(),
1562                                None,
1563                                Some(&self.stabilize()),
1564                                "converter::bool".to_string(),
1565                                &native_bool_converter,
1566                            );
1567                            return f(converter.weak());
1568                        }
1569                        "bytes" => {
1570                            let converter = wrap_native_function(
1571                                &onion_tuple!(),
1572                                None,
1573                                Some(&self.stabilize()),
1574                                "converter::bytes".to_string(),
1575                                &native_bytes_converter,
1576                            );
1577                            return f(converter.weak());
1578                        }
1579                        "length" => {
1580                            let length_method = wrap_native_function(
1581                                &onion_tuple!(),
1582                                None,
1583                                Some(&self.stabilize()),
1584                                "builtin::length".to_string(),
1585                                &native_length_method,
1586                            );
1587                            return f(length_method.weak());
1588                        }
1589                        "elements" => {
1590                            let elements_method = wrap_native_function(
1591                                &onion_tuple!(),
1592                                None,
1593                                Some(&self.stabilize()),
1594                                "builtin::elements".to_string(),
1595                                &native_elements_method,
1596                            );
1597                            return f(elements_method.weak());
1598                        }
1599                        _ => {}
1600                    }
1601                }
1602                Err(RuntimeError::InvalidOperation(
1603                    format!(
1604                        "Attribute '{}' not found for String",
1605                        match key {
1606                            OnionObject::String(s) => s.as_ref(),
1607                            _ => "<non-string>",
1608                        }
1609                    )
1610                    .into(),
1611                ))
1612            }
1613            OnionObject::Bytes(_) => {
1614                if let OnionObject::String(key_str) = key {
1615                    match key_str.as_str() {
1616                        "int" => {
1617                            let converter = wrap_native_function(
1618                                &onion_tuple!(),
1619                                None,
1620                                Some(&self.stabilize()),
1621                                "converter::int".to_string(),
1622                                &native_int_converter,
1623                            );
1624                            return f(converter.weak());
1625                        }
1626                        "float" => {
1627                            let converter = wrap_native_function(
1628                                &onion_tuple!(),
1629                                None,
1630                                Some(&self.stabilize()),
1631                                "converter::float".to_string(),
1632                                &native_float_converter,
1633                            );
1634                            return f(converter.weak());
1635                        }
1636                        "string" => {
1637                            let converter = wrap_native_function(
1638                                &onion_tuple!(),
1639                                None,
1640                                Some(&self.stabilize()),
1641                                "converter::string".to_string(),
1642                                &native_string_converter,
1643                            );
1644                            return f(converter.weak());
1645                        }
1646                        "bool" => {
1647                            let converter = wrap_native_function(
1648                                &onion_tuple!(),
1649                                None,
1650                                Some(&self.stabilize()),
1651                                "converter::bool".to_string(),
1652                                &native_bool_converter,
1653                            );
1654                            return f(converter.weak());
1655                        }
1656                        "bytes" => {
1657                            let converter = wrap_native_function(
1658                                &onion_tuple!(),
1659                                None,
1660                                Some(&self.stabilize()),
1661                                "converter::bytes".to_string(),
1662                                &native_bytes_converter,
1663                            );
1664                            return f(converter.weak());
1665                        }
1666                        "length" => {
1667                            let length_method = wrap_native_function(
1668                                &onion_tuple!(),
1669                                None,
1670                                Some(&self.stabilize()),
1671                                "builtin::length".to_string(),
1672                                &native_length_method,
1673                            );
1674                            return f(length_method.weak());
1675                        }
1676                        "elements" => {
1677                            let elements_method = wrap_native_function(
1678                                &onion_tuple!(),
1679                                None,
1680                                Some(&self.stabilize()),
1681                                "builtin::elements".to_string(),
1682                                &native_elements_method,
1683                            );
1684                            return f(elements_method.weak());
1685                        }
1686                        _ => {}
1687                    }
1688                }
1689                Err(RuntimeError::InvalidOperation(
1690                    format!(
1691                        "Attribute '{}' not found for Bytes",
1692                        match key {
1693                            OnionObject::String(s) => s.as_ref(),
1694                            _ => "<non-string>",
1695                        }
1696                    )
1697                    .into(),
1698                ))
1699            }
1700            OnionObject::Range(_, _) => {
1701                if let OnionObject::String(key_str) = key {
1702                    match key_str.as_str() {
1703                        "int" => {
1704                            let converter = wrap_native_function(
1705                                &onion_tuple!(),
1706                                None,
1707                                Some(&self.stabilize()),
1708                                "converter::int".to_string(),
1709                                &native_int_converter,
1710                            );
1711                            return f(converter.weak());
1712                        }
1713                        "float" => {
1714                            let converter = wrap_native_function(
1715                                &onion_tuple!(),
1716                                None,
1717                                Some(&self.stabilize()),
1718                                "converter::float".to_string(),
1719                                &native_float_converter,
1720                            );
1721                            return f(converter.weak());
1722                        }
1723                        "string" => {
1724                            let converter = wrap_native_function(
1725                                &onion_tuple!(),
1726                                None,
1727                                Some(&self.stabilize()),
1728                                "converter::string".to_string(),
1729                                &native_string_converter,
1730                            );
1731                            return f(converter.weak());
1732                        }
1733                        "bool" => {
1734                            let converter = wrap_native_function(
1735                                &onion_tuple!(),
1736                                None,
1737                                Some(&self.stabilize()),
1738                                "converter::bool".to_string(),
1739                                &native_bool_converter,
1740                            );
1741                            return f(converter.weak());
1742                        }
1743                        "bytes" => {
1744                            let converter = wrap_native_function(
1745                                &onion_tuple!(),
1746                                None,
1747                                Some(&self.stabilize()),
1748                                "converter::bytes".to_string(),
1749                                &native_bytes_converter,
1750                            );
1751                            return f(converter.weak());
1752                        }
1753                        "length" => {
1754                            let length_method = wrap_native_function(
1755                                &onion_tuple!(),
1756                                None,
1757                                Some(&self.stabilize()),
1758                                "builtin::length".to_string(),
1759                                &native_length_method,
1760                            );
1761                            return f(length_method.weak());
1762                        }
1763                        "elements" => {
1764                            let elements_method = wrap_native_function(
1765                                &onion_tuple!(),
1766                                None,
1767                                Some(&self.stabilize()),
1768                                "builtin::elements".to_string(),
1769                                &native_elements_method,
1770                            );
1771                            return f(elements_method.weak());
1772                        }
1773                        _ => {}
1774                    }
1775                }
1776                Err(RuntimeError::InvalidOperation(
1777                    format!(
1778                        "Attribute '{}' not found for Range",
1779                        match key {
1780                            OnionObject::String(s) => s.as_ref(),
1781                            _ => "<non-string>",
1782                        }
1783                    )
1784                    .into(),
1785                ))
1786            }
1787            OnionObject::Custom(custom) => {
1788                let mut result: Result<R, RuntimeError> = Err(RuntimeError::InvalidOperation(
1789                    "Custom with_attribute not called".to_string().into(),
1790                ));
1791                let mut closure = |obj: &OnionObject| -> Result<(), RuntimeError> {
1792                    result = f(obj);
1793                    Ok(())
1794                };
1795                custom.with_attribute(key, &mut closure)?;
1796                result
1797            }
1798            _ => Err(RuntimeError::InvalidOperation(
1799                format!("with_attribute() not supported for {:?}", self).into(),
1800            )),
1801        })
1802    }
1803    pub fn at(&self, index: i64) -> Result<OnionStaticObject, RuntimeError> {
1804        self.with_data(|obj| match obj {
1805            OnionObject::Tuple(tuple) => tuple.at(index),
1806            OnionObject::String(s) => {
1807                if index < 0 || index >= s.len() as i64 {
1808                    return Err(RuntimeError::InvalidOperation(
1809                        format!("Index out of bounds for String: {}", s).into(),
1810                    ));
1811                }
1812                Ok(OnionStaticObject::new(OnionObject::String(Arc::new(
1813                    s.chars().nth(index as usize).unwrap().to_string(),
1814                ))))
1815            }
1816            OnionObject::Bytes(b) => {
1817                if index < 0 || index >= b.len() as i64 {
1818                    return Err(RuntimeError::InvalidOperation(
1819                        format!("Index out of bounds for Bytes: {:?}", b).into(),
1820                    ));
1821                }
1822                Ok(OnionStaticObject::new(OnionObject::Bytes(Arc::new(vec![
1823                    b[index as usize],
1824                ]))))
1825            }
1826            OnionObject::Custom(custom) => custom.at(index),
1827            _ => Err(RuntimeError::InvalidOperation(
1828                format!("index_of() not supported for {:?}", self).into(),
1829            )),
1830        })
1831    }
1832
1833    pub fn key_of(&self) -> Result<OnionStaticObject, RuntimeError> {
1834        self.with_data(|obj| match obj {
1835            OnionObject::Named(named) => Ok(named.get_key().stabilize()),
1836            OnionObject::Pair(pair) => Ok(pair.get_key().stabilize()),
1837            OnionObject::Custom(custom) => custom.key_of(),
1838            _ => Err(RuntimeError::InvalidOperation(
1839                format!("key_of() not supported for {:?}", obj).into(),
1840            )),
1841        })
1842    }
1843
1844    pub fn value_of(&self) -> Result<OnionStaticObject, RuntimeError> {
1845        self.with_data(|obj| match obj {
1846            OnionObject::Named(named) => Ok(named.get_value().stabilize()),
1847            OnionObject::Pair(pair) => Ok(pair.get_value().stabilize()),
1848            OnionObject::Undefined(s) => Ok(OnionStaticObject::new(OnionObject::String(Arc::new(
1849                s.as_ref()
1850                    .map(|o| o.as_ref().clone())
1851                    .unwrap_or_else(|| "".to_string()),
1852            )))),
1853            OnionObject::Custom(custom) => custom.value_of(),
1854            _ => Err(RuntimeError::InvalidOperation(
1855                format!("value_of() not supported for {:?}", obj).into(),
1856            )),
1857        })
1858    }
1859
1860    pub fn type_of(&self) -> Result<String, RuntimeError> {
1861        self.with_data(|obj| match obj {
1862            OnionObject::Integer(_) => Ok("Integer".to_string()),
1863            OnionObject::Float(_) => Ok("Float".to_string()),
1864            OnionObject::String(_) => Ok("String".to_string()),
1865            OnionObject::Bytes(_) => Ok("Bytes".to_string()),
1866            OnionObject::Boolean(_) => Ok("Boolean".to_string()),
1867            OnionObject::Null => Ok("Null".to_string()),
1868            OnionObject::Undefined(_) => Ok("Undefined".to_string()),
1869            OnionObject::Tuple(_) => Ok("Tuple".to_string()),
1870            OnionObject::Pair(_) => Ok("Pair".to_string()),
1871            OnionObject::Named(_) => Ok("Named".to_string()),
1872            OnionObject::LazySet(_) => Ok("LazySet".to_string()),
1873            OnionObject::InstructionPackage(_) => Ok("InstructionPackage".to_string()),
1874            OnionObject::Lambda(_) => Ok("Lambda".to_string()),
1875            OnionObject::Custom(custom) => custom.type_of(),
1876            _ => Err(RuntimeError::InvalidOperation(
1877                format!("type_of() not supported for {:?}", obj).into(),
1878            )),
1879        })
1880    }
1881
1882    #[inline(always)]
1883    pub fn copy(&self) -> Result<OnionStaticObject, RuntimeError> {
1884        self.with_data(|obj| Ok(obj.stabilize()))
1885    }
1886}
1887
1888#[derive(Clone)]
1889pub enum GCArcStorage {
1890    None,
1891    Single(GCArc<OnionObjectCell>),
1892    Multiple(Arc<Vec<GCArc<OnionObjectCell>>>),
1893}
1894
1895// impl GCArcStorage {
1896//     #[inline(always)]
1897//     pub fn from_vec(v: Vec<GCArc<OnionObjectCell>>) -> Self {
1898//         match v.len() {
1899//             0 => Self::None,
1900//             1 => Self::Single(v[0].clone()),
1901//             _ => Self::Multiple(v),
1902//         }
1903//     }
1904// }
1905
1906#[derive(Clone)]
1907pub struct OnionStaticObject {
1908    _arcs: GCArcStorage,
1909    obj: OnionObject,
1910}
1911
1912impl Default for OnionStaticObject {
1913    fn default() -> Self {
1914        OnionStaticObject {
1915            obj: OnionObject::Undefined(None),
1916            _arcs: GCArcStorage::None,
1917        }
1918    }
1919}
1920
1921impl Debug for OnionStaticObject {
1922    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1923        write!(f, "OnionStaticObject({:?})", self.obj)
1924    }
1925}
1926
1927impl Display for OnionStaticObject {
1928    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1929        write!(f, "OnionStaticObject({:?})", self.obj)
1930    }
1931}
1932
1933impl OnionStaticObject {
1934    #[inline(always)]
1935    pub fn new(obj: OnionObject) -> Self {
1936        let arcs = match &obj {
1937            OnionObject::Mut(obj) => match obj.upgrade() {
1938                None => GCArcStorage::None,
1939                Some(arc) => GCArcStorage::Single(arc),
1940            },
1941            OnionObject::Boolean(_)
1942            | OnionObject::Integer(_)
1943            | OnionObject::Float(_)
1944            | OnionObject::String(_)
1945            | OnionObject::Bytes(_)
1946            | OnionObject::Null
1947            | OnionObject::Undefined(_)
1948            | OnionObject::Range(_, _)
1949            | OnionObject::InstructionPackage(_) => GCArcStorage::None,
1950            _ => {
1951                let mut arcs = vec![];
1952                obj.upgrade(&mut arcs);
1953                GCArcStorage::Multiple(Arc::new(arcs))
1954            }
1955        };
1956        OnionStaticObject {
1957            obj: obj,
1958            _arcs: arcs,
1959        }
1960    }
1961
1962    #[inline(always)]
1963    pub fn weak(&self) -> &OnionObject {
1964        &self.obj
1965    }
1966
1967    #[inline(always)]
1968    /// 将值装箱成可变容器,严格遵循幂等律的情况下,Cell里不可能出现Mut对象。
1969    /// 也就是说,mut mut x和mut x是等价的。
1970    pub fn mutablize(self, gc: &mut GC<OnionObjectCell>) -> OnionStaticObject {
1971        match self.weak() {
1972            OnionObject::Mut(_) => self,
1973            v => v.clone().mutablize(gc),
1974        }
1975    }
1976
1977    #[inline(always)]
1978    /// 将值从可变容器中卸载,严格遵循幂等律
1979    /// 也就是说,const const x和const x是等价的。
1980    pub fn immutablize(self) -> Result<OnionStaticObject, RuntimeError> {
1981        match self.weak() {
1982            OnionObject::Mut(v) => match v.upgrade() {
1983                None => Err(RuntimeError::BrokenReference),
1984                Some(arc) => match arc.as_ref().0.read() {
1985                    Ok(data) => Ok(OnionStaticObject::new(data.clone())),
1986                    Err(_) => Err(RuntimeError::BrokenReference),
1987                },
1988            },
1989            _ => Ok(self),
1990        }
1991    }
1992}
1993
1994#[macro_export]
1995macro_rules! unwrap_object {
1996    ($obj:expr, $variant:path) => {
1997        match $obj {
1998            $variant(o) => Ok(o),
1999            _ => Err(RuntimeError::InvalidType(
2000                format!("Expected {}, found {:?}", stringify!($variant), $obj).into(),
2001            )),
2002        }
2003    };
2004}
2005
2006#[cfg(test)]
2007mod tests {
2008    use super::*;
2009    use std::time::Instant;
2010
2011    #[test]
2012    fn test_detailed_memory_sizes() {
2013        println!("详细内存分析:");
2014        println!(
2015            "OnionObjectCell: {} bytes",
2016            std::mem::size_of::<OnionObjectCell>()
2017        );
2018        println!("OnionObject: {} bytes", std::mem::size_of::<OnionObject>());
2019        println!(
2020            "OnionStaticObject: {} bytes",
2021            std::mem::size_of::<OnionStaticObject>()
2022        );
2023        println!(
2024            "GCArcStorage: {} bytes",
2025            std::mem::size_of::<GCArcStorage>()
2026        );
2027        println!(
2028            "GCArc<OnionObjectCell>: {} bytes",
2029            std::mem::size_of::<GCArc<OnionObjectCell>>()
2030        );
2031        println!("Arc<String>: {} bytes", std::mem::size_of::<Arc<String>>());
2032        println!(
2033            "Arc<Vec<u8>>: {} bytes",
2034            std::mem::size_of::<Arc<Vec<u8>>>()
2035        );
2036        println!(
2037            "GCArcWeak<OnionObjectCell>: {} bytes",
2038            std::mem::size_of::<GCArcWeak<OnionObjectCell>>()
2039        );
2040        println!("OnionTuple: {} bytes", std::mem::size_of::<OnionTuple>());
2041        println!("OnionNamed: {} bytes", std::mem::size_of::<OnionNamed>());
2042        println!("OnionPair: {} bytes", std::mem::size_of::<OnionPair>());
2043        println!(
2044            "OnionLazySet: {} bytes",
2045            std::mem::size_of::<OnionLazySet>()
2046        );
2047    }
2048
2049    #[test]
2050    fn benchmark_realistic_vm_operations() {
2051        println!("真实VM操作性能测试 (使用OnionStaticObject + clone):");
2052
2053        // 模拟VM中的整数运算
2054        let start = Instant::now();
2055        let mut result_sum = 0i64;
2056
2057        for i in 0..5_000_000 {
2058            // 创建OnionStaticObject(模拟从栈或常量池加载)
2059            let obj1 = OnionObject::Integer(i).stabilize();
2060            let obj2 = OnionObject::Integer(i + 1).stabilize();
2061
2062            // 通过with_data访问(模拟VM的实际访问模式)
2063            let result = obj1.weak().with_data(|data1| {
2064                obj2.weak().with_data(|data2| {
2065                    // 模拟binary_add操作
2066                    match (data1, data2) {
2067                        (OnionObject::Integer(a), OnionObject::Integer(b)) => {
2068                            Ok(OnionObject::Integer(a + b).stabilize())
2069                        }
2070                        _ => Err(RuntimeError::InvalidOperation(
2071                            "Type error".to_string().into(),
2072                        )),
2073                    }
2074                })
2075            });
2076
2077            if let Ok(sum) = result {
2078                // 提取结果值(模拟VM获取计算结果)
2079                if let Ok(val) = sum.weak().with_data(|data| match data {
2080                    OnionObject::Integer(v) => Ok(*v),
2081                    _ => Err(RuntimeError::InvalidType("Not integer".to_string().into())),
2082                }) {
2083                    result_sum += val;
2084                }
2085            }
2086        }
2087
2088        let duration = start.elapsed();
2089        println!("500万次VM风格整数运算: {:.2}s", duration.as_secs_f64());
2090        println!("每秒操作数: {:.0}", 5_000_000.0 / duration.as_secs_f64());
2091        println!("结果校验: {}", result_sum);
2092    }
2093
2094    #[test]
2095    fn benchmark_vm_style_arithmetic() {
2096        println!("VM风格算术运算性能测试:");
2097
2098        let start = Instant::now();
2099        let mut final_result = 0i64;
2100
2101        for i in 0..2_000_000 {
2102            // 创建操作数
2103            let left = OnionObject::Integer(i).stabilize();
2104            let right = OnionObject::Integer(i + 1).stabilize();
2105
2106            // 使用实际的binary_add方法
2107            if let Ok(result) = left
2108                .weak()
2109                .with_data(|l_data| right.weak().with_data(|r_data| l_data.binary_add(r_data)))
2110            {
2111                // 继续进行乘法运算
2112                let multiplier = OnionObject::Integer(2).stabilize();
2113                if let Ok(mul_result) = result.weak().with_data(|add_data| {
2114                    multiplier
2115                        .weak()
2116                        .with_data(|mul_data| add_data.binary_mul(mul_data))
2117                }) {
2118                    // 提取最终结果
2119                    if let Ok(val) = mul_result.weak().with_data(|data| data.to_integer()) {
2120                        final_result += val;
2121                    }
2122                }
2123            }
2124        }
2125
2126        let duration = start.elapsed();
2127        println!("200万次复合运算: {:.2}s", duration.as_secs_f64());
2128        println!("每秒操作数: {:.0}", 2_000_000.0 / duration.as_secs_f64());
2129        println!("最终结果: {}", final_result);
2130    }
2131
2132    #[test]
2133    fn benchmark_object_creation_overhead() {
2134        println!("对象创建开销测试:");
2135
2136        // 测试OnionStaticObject创建性能
2137        let start = Instant::now();
2138        let mut objects = Vec::with_capacity(1_000_000);
2139
2140        for i in 0..1_000_000 {
2141            let obj = OnionObject::Integer(i).stabilize();
2142            objects.push(obj);
2143        }
2144
2145        let creation_time = start.elapsed();
2146        println!(
2147            "100万个OnionStaticObject创建: {:.2}s",
2148            creation_time.as_secs_f64()
2149        );
2150
2151        // 测试访问性能
2152        let start = Instant::now();
2153        let mut sum = 0i64;
2154
2155        for obj in &objects {
2156            if let Ok(val) = obj.weak().with_data(|data| data.to_integer()) {
2157                sum += val;
2158            }
2159        }
2160
2161        let access_time = start.elapsed();
2162        println!("100万次对象访问: {:.2}s", access_time.as_secs_f64());
2163        println!("访问校验和: {}", sum);
2164
2165        // 测试克隆性能
2166        let start = Instant::now();
2167        let mut cloned_objects = Vec::with_capacity(objects.len());
2168
2169        for obj in &objects[..100_000] {
2170            // 只测试10万个避免内存不足
2171            cloned_objects.push(obj.clone());
2172        }
2173
2174        let clone_time = start.elapsed();
2175        println!("10万个对象克隆: {:.2}s", clone_time.as_secs_f64());
2176    }
2177
2178    #[test]
2179    fn benchmark_string_operations_realistic() {
2180        println!("真实字符串操作性能测试:");
2181
2182        let start = Instant::now();
2183        let mut total_length = 0usize;
2184
2185        for i in 0..500_000 {
2186            // 创建字符串对象
2187            let str_obj = OnionObject::String(Arc::new(format!("string_{}", i))).stabilize();
2188
2189            // 获取字符串长度(模拟len()操作)
2190            if let Ok(len_obj) = str_obj.weak().with_data(|data| data.len()) {
2191                if let Ok(length) = len_obj.weak().with_data(|data| data.to_integer()) {
2192                    total_length += length as usize;
2193                }
2194            }
2195
2196            // 字符串拼接操作
2197            let suffix = OnionObject::String(Arc::new("_suffix".to_string())).stabilize();
2198            if let Ok(concat_result) = str_obj.weak().with_data(|str_data| {
2199                suffix
2200                    .weak()
2201                    .with_data(|suffix_data| str_data.binary_add(suffix_data))
2202            }) {
2203                // 模拟使用拼接结果
2204                if let Ok(concat_str) = concat_result
2205                    .weak()
2206                    .with_data(|data| data.to_string(&mut vec![]))
2207                {
2208                    total_length += concat_str.len();
2209                }
2210            }
2211        }
2212
2213        let duration = start.elapsed();
2214        println!("50万次字符串操作: {:.2}s", duration.as_secs_f64());
2215        println!("每秒操作数: {:.0}", 500_000.0 / duration.as_secs_f64());
2216        println!("总字符串长度: {}", total_length);
2217    }
2218
2219    #[test]
2220    fn benchmark_refcell_overhead() {
2221        println!("RefCell开销分析:");
2222
2223        // 测试直接访问vs RefCell访问的性能差异
2224        let direct_integers: Vec<i64> = (0..1_000_000).collect();
2225        let wrapped_integers: Vec<OnionStaticObject> = (0..1_000_000)
2226            .map(|i| OnionObject::Integer(i).stabilize())
2227            .collect();
2228
2229        // 直接访问基准
2230        let start = Instant::now();
2231        let mut sum1 = 0i64;
2232        for &val in &direct_integers {
2233            sum1 += val * 2;
2234        }
2235        let direct_time = start.elapsed();
2236
2237        // RefCell访问
2238        let start = Instant::now();
2239        let mut sum2 = 0i64;
2240        for obj in &wrapped_integers {
2241            if let Ok(val) = obj.weak().with_data(|data| match data {
2242                OnionObject::Integer(i) => Ok(*i),
2243                _ => Err(RuntimeError::InvalidType("Not integer".to_string().into())),
2244            }) {
2245                sum2 += val * 2;
2246            }
2247        }
2248        let refcell_time = start.elapsed();
2249
2250        println!("直接访问100万个i64: {:.2}s", direct_time.as_secs_f64());
2251        println!(
2252            "RefCell访问100万个OnionObject: {:.2}s",
2253            refcell_time.as_secs_f64()
2254        );
2255        println!(
2256            "RefCell开销倍数: {:.1}x",
2257            refcell_time.as_secs_f64() / direct_time.as_secs_f64()
2258        );
2259        println!("校验: {} vs {}", sum1, sum2);
2260    }
2261}