seq_runtime/
variant_ops.rs

1//! Variant field access operations for Seq
2//!
3//! Provides runtime functions for accessing variant fields, tags, and metadata.
4//! These are used to work with composite data created by operations like string-split.
5
6use crate::stack::{Stack, pop, push};
7use crate::value::Value;
8use std::sync::Arc;
9
10/// Get the number of fields in a variant
11///
12/// Stack effect: ( Variant -- Int )
13///
14/// # Safety
15/// Stack must have a Variant on top
16#[unsafe(no_mangle)]
17pub unsafe extern "C" fn patch_seq_variant_field_count(stack: Stack) -> Stack {
18    unsafe {
19        let (stack, value) = pop(stack);
20
21        match value {
22            Value::Variant(variant_data) => {
23                let count = variant_data.fields.len() as i64;
24                push(stack, Value::Int(count))
25            }
26            _ => panic!("variant-field-count: expected Variant, got {:?}", value),
27        }
28    }
29}
30
31/// Get the tag of a variant
32///
33/// Stack effect: ( Variant -- Int )
34///
35/// # Safety
36/// Stack must have a Variant on top
37#[unsafe(no_mangle)]
38pub unsafe extern "C" fn patch_seq_variant_tag(stack: Stack) -> Stack {
39    unsafe {
40        let (stack, value) = pop(stack);
41
42        match value {
43            Value::Variant(variant_data) => {
44                let tag = variant_data.tag as i64;
45                push(stack, Value::Int(tag))
46            }
47            _ => panic!("variant-tag: expected Variant, got {:?}", value),
48        }
49    }
50}
51
52/// Get a field from a variant at the given index
53///
54/// Stack effect: ( Variant Int -- Value )
55///
56/// Returns a clone of the field value at the specified index.
57/// Panics if index is out of bounds.
58///
59/// # Safety
60/// Stack must have a Variant and Int on top
61#[unsafe(no_mangle)]
62pub unsafe extern "C" fn patch_seq_variant_field_at(stack: Stack) -> Stack {
63    unsafe {
64        let (stack, index_val) = pop(stack);
65        let index = match index_val {
66            Value::Int(i) => i,
67            _ => panic!(
68                "variant-field-at: expected Int (index), got {:?}",
69                index_val
70            ),
71        };
72
73        if index < 0 {
74            panic!("variant-field-at: index cannot be negative: {}", index);
75        }
76
77        let (stack, variant_val) = pop(stack);
78
79        match variant_val {
80            Value::Variant(variant_data) => {
81                let idx = index as usize;
82                if idx >= variant_data.fields.len() {
83                    panic!(
84                        "variant-field-at: index {} out of bounds (variant has {} fields)",
85                        index,
86                        variant_data.fields.len()
87                    );
88                }
89
90                // Clone the field value and push it
91                let field = variant_data.fields[idx].clone();
92                push(stack, field)
93            }
94            _ => panic!("variant-field-at: expected Variant, got {:?}", variant_val),
95        }
96    }
97}
98
99// ============================================================================
100// Type-safe variant constructors with fixed arity
101// ============================================================================
102
103/// Create a variant with 0 fields (just a tag)
104///
105/// Stack effect: ( tag -- Variant )
106///
107/// # Safety
108/// Stack must have at least one Int (the tag) on top
109#[unsafe(no_mangle)]
110pub unsafe extern "C" fn patch_seq_make_variant_0(stack: Stack) -> Stack {
111    use crate::value::VariantData;
112
113    unsafe {
114        let (stack, tag_val) = pop(stack);
115        let tag = match tag_val {
116            Value::Int(t) => {
117                if t < 0 {
118                    panic!("make-variant-0: tag cannot be negative: {}", t);
119                }
120                t as u32
121            }
122            _ => panic!("make-variant-0: expected Int (tag), got {:?}", tag_val),
123        };
124
125        let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![])));
126        push(stack, variant)
127    }
128}
129
130/// Create a variant with 1 field
131///
132/// Stack effect: ( field1 tag -- Variant )
133///
134/// # Safety
135/// Stack must have field1 and tag on top
136#[unsafe(no_mangle)]
137pub unsafe extern "C" fn patch_seq_make_variant_1(stack: Stack) -> Stack {
138    use crate::value::VariantData;
139
140    unsafe {
141        let (stack, tag_val) = pop(stack);
142        let tag = match tag_val {
143            Value::Int(t) => {
144                if t < 0 {
145                    panic!("make-variant-1: tag cannot be negative: {}", t);
146                }
147                t as u32
148            }
149            _ => panic!("make-variant-1: expected Int (tag), got {:?}", tag_val),
150        };
151
152        let (stack, field1) = pop(stack);
153        let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![field1])));
154        push(stack, variant)
155    }
156}
157
158/// Create a variant with 2 fields
159///
160/// Stack effect: ( field1 field2 tag -- Variant )
161///
162/// # Safety
163/// Stack must have field1, field2, and tag on top
164#[unsafe(no_mangle)]
165pub unsafe extern "C" fn patch_seq_make_variant_2(stack: Stack) -> Stack {
166    use crate::value::VariantData;
167
168    unsafe {
169        let (stack, tag_val) = pop(stack);
170        let tag = match tag_val {
171            Value::Int(t) => {
172                if t < 0 {
173                    panic!("make-variant-2: tag cannot be negative: {}", t);
174                }
175                t as u32
176            }
177            _ => panic!("make-variant-2: expected Int (tag), got {:?}", tag_val),
178        };
179
180        let (stack, field2) = pop(stack);
181        let (stack, field1) = pop(stack);
182        let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![field1, field2])));
183        push(stack, variant)
184    }
185}
186
187/// Create a variant with 3 fields
188///
189/// Stack effect: ( field1 field2 field3 tag -- Variant )
190///
191/// # Safety
192/// Stack must have field1, field2, field3, and tag on top
193#[unsafe(no_mangle)]
194pub unsafe extern "C" fn patch_seq_make_variant_3(stack: Stack) -> Stack {
195    use crate::value::VariantData;
196
197    unsafe {
198        let (stack, tag_val) = pop(stack);
199        let tag = match tag_val {
200            Value::Int(t) => {
201                if t < 0 {
202                    panic!("make-variant-3: tag cannot be negative: {}", t);
203                }
204                t as u32
205            }
206            _ => panic!("make-variant-3: expected Int (tag), got {:?}", tag_val),
207        };
208
209        let (stack, field3) = pop(stack);
210        let (stack, field2) = pop(stack);
211        let (stack, field1) = pop(stack);
212        let variant = Value::Variant(Arc::new(VariantData::new(
213            tag,
214            vec![field1, field2, field3],
215        )));
216        push(stack, variant)
217    }
218}
219
220/// Create a variant with 4 fields
221///
222/// Stack effect: ( field1 field2 field3 field4 tag -- Variant )
223///
224/// # Safety
225/// Stack must have field1, field2, field3, field4, and tag on top
226#[unsafe(no_mangle)]
227pub unsafe extern "C" fn patch_seq_make_variant_4(stack: Stack) -> Stack {
228    use crate::value::VariantData;
229
230    unsafe {
231        let (stack, tag_val) = pop(stack);
232        let tag = match tag_val {
233            Value::Int(t) => {
234                if t < 0 {
235                    panic!("make-variant-4: tag cannot be negative: {}", t);
236                }
237                t as u32
238            }
239            _ => panic!("make-variant-4: expected Int (tag), got {:?}", tag_val),
240        };
241
242        let (stack, field4) = pop(stack);
243        let (stack, field3) = pop(stack);
244        let (stack, field2) = pop(stack);
245        let (stack, field1) = pop(stack);
246        let variant = Value::Variant(Arc::new(VariantData::new(
247            tag,
248            vec![field1, field2, field3, field4],
249        )));
250        push(stack, variant)
251    }
252}
253
254// Re-exports for internal use
255pub use patch_seq_make_variant_0 as make_variant_0;
256pub use patch_seq_make_variant_1 as make_variant_1;
257pub use patch_seq_make_variant_2 as make_variant_2;
258pub use patch_seq_make_variant_3 as make_variant_3;
259pub use patch_seq_make_variant_4 as make_variant_4;
260
261/// Append a value to a variant, returning a new variant
262///
263/// Stack effect: ( Variant Value -- Variant' )
264///
265/// Creates a new variant with the same tag as the input, but with
266/// the new value appended to its fields. The original variant is
267/// not modified (functional/immutable style).
268///
269/// Example: For arrays, `[1, 2] 3 variant-append` produces `[1, 2, 3]`
270/// Example: For objects, `{} "key" variant-append "val" variant-append` builds `{"key": "val"}`
271///
272/// # Safety
273/// Stack must have a Variant and a Value on top
274#[unsafe(no_mangle)]
275pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
276    use crate::value::VariantData;
277
278    unsafe {
279        // Pop the value to append
280        let (stack, value) = pop(stack);
281
282        // Pop the variant
283        let (stack, variant_val) = pop(stack);
284
285        match variant_val {
286            Value::Variant(variant_data) => {
287                // Create new fields vector with the appended value
288                let mut new_fields = variant_data.fields.to_vec();
289                new_fields.push(value);
290
291                // Create new variant with same tag
292                let new_variant =
293                    Value::Variant(Arc::new(VariantData::new(variant_data.tag, new_fields)));
294
295                push(stack, new_variant)
296            }
297            _ => panic!("variant-append: expected Variant, got {:?}", variant_val),
298        }
299    }
300}
301
302/// Get the last field from a variant
303///
304/// Stack effect: ( Variant -- Value )
305///
306/// Returns a clone of the last field. Panics if the variant has no fields.
307/// This is the "peek" operation for using variants as stacks.
308///
309/// # Safety
310/// Stack must have a Variant on top
311#[unsafe(no_mangle)]
312pub unsafe extern "C" fn patch_seq_variant_last(stack: Stack) -> Stack {
313    unsafe {
314        let (stack, variant_val) = pop(stack);
315
316        match variant_val {
317            Value::Variant(variant_data) => {
318                if variant_data.fields.is_empty() {
319                    panic!("variant-last: variant has no fields");
320                }
321
322                let last = variant_data.fields.last().unwrap().clone();
323                push(stack, last)
324            }
325            _ => panic!("variant-last: expected Variant, got {:?}", variant_val),
326        }
327    }
328}
329
330/// Get all but the last field from a variant
331///
332/// Stack effect: ( Variant -- Variant' )
333///
334/// Returns a new variant with the same tag but without the last field.
335/// Panics if the variant has no fields.
336/// This is the "pop" operation for using variants as stacks (without returning the popped value).
337///
338/// # Safety
339/// Stack must have a Variant on top
340#[unsafe(no_mangle)]
341pub unsafe extern "C" fn patch_seq_variant_init(stack: Stack) -> Stack {
342    use crate::value::VariantData;
343
344    unsafe {
345        let (stack, variant_val) = pop(stack);
346
347        match variant_val {
348            Value::Variant(variant_data) => {
349                if variant_data.fields.is_empty() {
350                    panic!("variant-init: variant has no fields");
351                }
352
353                // Create new fields without the last element
354                let new_fields: Vec<Value> =
355                    variant_data.fields[..variant_data.fields.len() - 1].to_vec();
356
357                let new_variant =
358                    Value::Variant(Arc::new(VariantData::new(variant_data.tag, new_fields)));
359
360                push(stack, new_variant)
361            }
362            _ => panic!("variant-init: expected Variant, got {:?}", variant_val),
363        }
364    }
365}
366
367/// Unpack a variant's fields onto the stack
368///
369/// Takes a field count as parameter and:
370/// - Pops the variant from the stack
371/// - Pushes each field (0..field_count) in order
372///
373/// Stack effect: ( Variant -- field0 field1 ... fieldN-1 )
374///
375/// Used by match expression codegen to extract variant fields.
376///
377/// # Safety
378/// Stack must have a Variant on top with at least `field_count` fields
379#[unsafe(no_mangle)]
380pub unsafe extern "C" fn patch_seq_unpack_variant(stack: Stack, field_count: i64) -> Stack {
381    unsafe {
382        let (mut stack, variant_val) = pop(stack);
383
384        match variant_val {
385            Value::Variant(variant_data) => {
386                let count = field_count as usize;
387                if count > variant_data.fields.len() {
388                    panic!(
389                        "unpack-variant: requested {} fields but variant only has {}",
390                        count,
391                        variant_data.fields.len()
392                    );
393                }
394
395                // Push each field in order (field0 first, then field1, etc.)
396                for i in 0..count {
397                    stack = push(stack, variant_data.fields[i].clone());
398                }
399
400                stack
401            }
402            _ => panic!("unpack-variant: expected Variant, got {:?}", variant_val),
403        }
404    }
405}
406
407// Public re-exports with short names for internal use
408pub use patch_seq_unpack_variant as unpack_variant;
409pub use patch_seq_variant_append as variant_append;
410pub use patch_seq_variant_field_at as variant_field_at;
411pub use patch_seq_variant_field_count as variant_field_count;
412pub use patch_seq_variant_init as variant_init;
413pub use patch_seq_variant_last as variant_last;
414pub use patch_seq_variant_tag as variant_tag;
415
416#[cfg(test)]
417mod tests {
418    use super::*;
419    use crate::seqstring::global_string;
420    use crate::value::VariantData;
421
422    #[test]
423    fn test_variant_field_count() {
424        unsafe {
425            // Create a variant with 3 fields
426            let variant = Value::Variant(Arc::new(VariantData::new(
427                0,
428                vec![Value::Int(10), Value::Int(20), Value::Int(30)],
429            )));
430
431            let stack = std::ptr::null_mut();
432            let stack = push(stack, variant);
433            let stack = variant_field_count(stack);
434
435            let (stack, result) = pop(stack);
436            assert_eq!(result, Value::Int(3));
437            assert!(stack.is_null());
438        }
439    }
440
441    #[test]
442    fn test_variant_tag() {
443        unsafe {
444            // Create a variant with tag 42
445            let variant = Value::Variant(Arc::new(VariantData::new(42, vec![Value::Int(10)])));
446
447            let stack = std::ptr::null_mut();
448            let stack = push(stack, variant);
449            let stack = variant_tag(stack);
450
451            let (stack, result) = pop(stack);
452            assert_eq!(result, Value::Int(42));
453            assert!(stack.is_null());
454        }
455    }
456
457    #[test]
458    fn test_variant_field_at() {
459        unsafe {
460            let str1 = global_string("hello".to_string());
461            let str2 = global_string("world".to_string());
462
463            // Create a variant with mixed fields
464            let variant = Value::Variant(Arc::new(VariantData::new(
465                0,
466                vec![
467                    Value::String(str1.clone()),
468                    Value::Int(42),
469                    Value::String(str2.clone()),
470                ],
471            )));
472
473            // Test accessing field 0
474            let stack = std::ptr::null_mut();
475            let stack = push(stack, variant.clone());
476            let stack = push(stack, Value::Int(0));
477            let stack = variant_field_at(stack);
478
479            let (stack, result) = pop(stack);
480            assert_eq!(result, Value::String(str1.clone()));
481            assert!(stack.is_null());
482
483            // Test accessing field 1
484            let stack = push(stack, variant.clone());
485            let stack = push(stack, Value::Int(1));
486            let stack = variant_field_at(stack);
487
488            let (stack, result) = pop(stack);
489            assert_eq!(result, Value::Int(42));
490            assert!(stack.is_null());
491
492            // Test accessing field 2
493            let stack = push(stack, variant.clone());
494            let stack = push(stack, Value::Int(2));
495            let stack = variant_field_at(stack);
496
497            let (stack, result) = pop(stack);
498            assert_eq!(result, Value::String(str2));
499            assert!(stack.is_null());
500        }
501    }
502
503    #[test]
504    fn test_variant_field_count_empty() {
505        unsafe {
506            // Create a variant with no fields
507            let variant = Value::Variant(Arc::new(VariantData::new(0, vec![])));
508
509            let stack = std::ptr::null_mut();
510            let stack = push(stack, variant);
511            let stack = variant_field_count(stack);
512
513            let (stack, result) = pop(stack);
514            assert_eq!(result, Value::Int(0));
515            assert!(stack.is_null());
516        }
517    }
518
519    #[test]
520    fn test_make_variant_with_fields() {
521        unsafe {
522            // Create: 10 20 30 42 make-variant-3
523            // Should produce variant with tag 42 and fields [10, 20, 30]
524            let stack = std::ptr::null_mut();
525            let stack = push(stack, Value::Int(10)); // field 0
526            let stack = push(stack, Value::Int(20)); // field 1
527            let stack = push(stack, Value::Int(30)); // field 2
528            let stack = push(stack, Value::Int(42)); // tag
529
530            let stack = make_variant_3(stack);
531
532            let (stack, result) = pop(stack);
533
534            match result {
535                Value::Variant(v) => {
536                    assert_eq!(v.tag, 42);
537                    assert_eq!(v.fields.len(), 3);
538                    assert_eq!(v.fields[0], Value::Int(10));
539                    assert_eq!(v.fields[1], Value::Int(20));
540                    assert_eq!(v.fields[2], Value::Int(30));
541                }
542                _ => panic!("Expected Variant"),
543            }
544            assert!(stack.is_null());
545        }
546    }
547
548    #[test]
549    fn test_make_variant_empty() {
550        unsafe {
551            // Create: 0 make-variant-0
552            // Should produce variant with tag 0 and no fields
553            let stack = std::ptr::null_mut();
554            let stack = push(stack, Value::Int(0)); // tag
555
556            let stack = make_variant_0(stack);
557
558            let (stack, result) = pop(stack);
559
560            match result {
561                Value::Variant(v) => {
562                    assert_eq!(v.tag, 0);
563                    assert_eq!(v.fields.len(), 0);
564                }
565                _ => panic!("Expected Variant"),
566            }
567            assert!(stack.is_null());
568        }
569    }
570
571    #[test]
572    fn test_make_variant_with_mixed_types() {
573        unsafe {
574            let s = global_string("hello".to_string());
575
576            // Create variant with mixed field types using make-variant-3
577            let stack = std::ptr::null_mut();
578            let stack = push(stack, Value::Int(42));
579            let stack = push(stack, Value::String(s.clone()));
580            let stack = push(stack, Value::Float(3.5));
581            let stack = push(stack, Value::Int(1)); // tag
582
583            let stack = make_variant_3(stack);
584
585            let (stack, result) = pop(stack);
586
587            match result {
588                Value::Variant(v) => {
589                    assert_eq!(v.tag, 1);
590                    assert_eq!(v.fields.len(), 3);
591                    assert_eq!(v.fields[0], Value::Int(42));
592                    assert_eq!(v.fields[1], Value::String(s));
593                    assert_eq!(v.fields[2], Value::Float(3.5));
594                }
595                _ => panic!("Expected Variant"),
596            }
597            assert!(stack.is_null());
598        }
599    }
600
601    #[test]
602    fn test_variant_append() {
603        unsafe {
604            // Create an empty variant (tag 4 for array)
605            let stack = std::ptr::null_mut();
606            let stack = push(stack, Value::Int(4)); // tag (array)
607            let stack = make_variant_0(stack);
608
609            // Append a value
610            let stack = push(stack, Value::Int(42));
611            let stack = variant_append(stack);
612
613            // Check result
614            let (stack, result) = pop(stack);
615            match result {
616                Value::Variant(v) => {
617                    assert_eq!(v.tag, 4);
618                    assert_eq!(v.fields.len(), 1);
619                    assert_eq!(v.fields[0], Value::Int(42));
620                }
621                _ => panic!("Expected Variant"),
622            }
623            assert!(stack.is_null());
624        }
625    }
626
627    #[test]
628    fn test_variant_append_multiple() {
629        unsafe {
630            // Create an empty variant (tag 5 for object)
631            let stack = std::ptr::null_mut();
632            let stack = push(stack, Value::Int(5)); // tag (object)
633            let stack = make_variant_0(stack);
634
635            // Append key
636            let key = global_string("name".to_string());
637            let stack = push(stack, Value::String(key.clone()));
638            let stack = variant_append(stack);
639
640            // Append value
641            let val = global_string("John".to_string());
642            let stack = push(stack, Value::String(val.clone()));
643            let stack = variant_append(stack);
644
645            // Check result - should have 2 fields
646            let (stack, result) = pop(stack);
647            match result {
648                Value::Variant(v) => {
649                    assert_eq!(v.tag, 5);
650                    assert_eq!(v.fields.len(), 2);
651                    assert_eq!(v.fields[0], Value::String(key));
652                    assert_eq!(v.fields[1], Value::String(val));
653                }
654                _ => panic!("Expected Variant"),
655            }
656            assert!(stack.is_null());
657        }
658    }
659
660    #[test]
661    fn test_variant_last() {
662        unsafe {
663            // Create a variant with 3 fields
664            let variant = Value::Variant(Arc::new(VariantData::new(
665                0,
666                vec![Value::Int(10), Value::Int(20), Value::Int(30)],
667            )));
668
669            let stack = std::ptr::null_mut();
670            let stack = push(stack, variant);
671            let stack = variant_last(stack);
672
673            let (stack, result) = pop(stack);
674            assert_eq!(result, Value::Int(30));
675            assert!(stack.is_null());
676        }
677    }
678
679    #[test]
680    fn test_variant_init() {
681        unsafe {
682            // Create a variant with 3 fields
683            let variant = Value::Variant(Arc::new(VariantData::new(
684                42,
685                vec![Value::Int(10), Value::Int(20), Value::Int(30)],
686            )));
687
688            let stack = std::ptr::null_mut();
689            let stack = push(stack, variant);
690            let stack = variant_init(stack);
691
692            let (stack, result) = pop(stack);
693            match result {
694                Value::Variant(v) => {
695                    assert_eq!(v.tag, 42); // tag preserved
696                    assert_eq!(v.fields.len(), 2);
697                    assert_eq!(v.fields[0], Value::Int(10));
698                    assert_eq!(v.fields[1], Value::Int(20));
699                }
700                _ => panic!("Expected Variant"),
701            }
702            assert!(stack.is_null());
703        }
704    }
705
706    #[test]
707    fn test_variant_stack_operations() {
708        // Test using variant as a stack: append, append, last, init, last
709        unsafe {
710            // Create empty "stack" variant (tag 99)
711            let stack = std::ptr::null_mut();
712            let stack = push(stack, Value::Int(99)); // tag
713            let stack = make_variant_0(stack);
714
715            // Append 10
716            let stack = push(stack, Value::Int(10));
717            let stack = variant_append(stack);
718
719            // Append 20
720            let stack = push(stack, Value::Int(20));
721            let stack = variant_append(stack);
722
723            // Now have variant with [10, 20] on stack
724            // Dup and get last (should be 20)
725            let (stack, variant) = pop(stack);
726            let stack = push(stack, variant.clone());
727            let stack = push(stack, variant);
728            let stack = variant_last(stack);
729            let (stack, top) = pop(stack);
730            assert_eq!(top, Value::Int(20));
731
732            // Now use init to remove last element
733            let stack = variant_init(stack);
734
735            // Dup and get last (should now be 10)
736            let (stack, variant) = pop(stack);
737            let stack = push(stack, variant.clone());
738            let stack = push(stack, variant);
739            let stack = variant_last(stack);
740            let (stack, top) = pop(stack);
741            assert_eq!(top, Value::Int(10));
742
743            // Verify remaining variant has 1 field
744            let (stack, result) = pop(stack);
745            match result {
746                Value::Variant(v) => {
747                    assert_eq!(v.fields.len(), 1);
748                    assert_eq!(v.fields[0], Value::Int(10));
749                }
750                _ => panic!("Expected Variant"),
751            }
752            assert!(stack.is_null());
753        }
754    }
755
756    #[test]
757    fn test_variant_clone_is_o1() {
758        // Regression test: Ensure deeply nested variants clone in O(1) time
759        // This would have been O(2^n) with Box before the Arc change
760        let mut variant = Value::Variant(Arc::new(VariantData::new(0, vec![])));
761
762        // Build a deeply nested structure (100 levels)
763        for i in 0..100 {
764            variant = Value::Variant(Arc::new(VariantData::new(i, vec![variant.clone()])));
765        }
766
767        // Clone should be O(1) - just incrementing Arc refcount
768        let start = std::time::Instant::now();
769        for _ in 0..1000 {
770            let _copy = variant.clone();
771        }
772        let elapsed = start.elapsed();
773
774        // 1000 clones of a 100-deep structure should take < 1ms with Arc
775        // With Box it would take seconds or longer
776        assert!(
777            elapsed.as_millis() < 10,
778            "Clone took {:?} - should be O(1) with Arc",
779            elapsed
780        );
781    }
782
783    #[test]
784    fn test_variant_arc_sharing() {
785        // Test that Arc properly shares data (refcount increases, not deep copy)
786        let inner = Value::Variant(Arc::new(VariantData::new(0, vec![Value::Int(42)])));
787        let outer = Value::Variant(Arc::new(VariantData::new(1, vec![inner.clone()])));
788
789        // Clone should share the same Arc, not deep copy
790        let outer_clone = outer.clone();
791
792        // Both should have the same inner value
793        match (&outer, &outer_clone) {
794            (Value::Variant(a), Value::Variant(b)) => {
795                // Arc::ptr_eq would be ideal but fields are Box<[Value]>
796                // Instead verify the values are equal (they share the same data)
797                assert_eq!(a.tag, b.tag);
798                assert_eq!(a.fields.len(), b.fields.len());
799            }
800            _ => panic!("Expected Variants"),
801        }
802    }
803
804    #[test]
805    fn test_variant_thread_safe_sharing() {
806        // Test that variants can be safely shared between threads
807        // This validates the Send + Sync implementation
808        use std::sync::Arc as StdArc;
809        use std::thread;
810
811        let variant = Value::Variant(Arc::new(VariantData::new(
812            42,
813            vec![Value::Int(1), Value::Int(2), Value::Int(3)],
814        )));
815
816        // Wrap in Arc for thread sharing
817        let shared = StdArc::new(variant);
818
819        let handles: Vec<_> = (0..4)
820            .map(|_| {
821                let v = StdArc::clone(&shared);
822                thread::spawn(move || {
823                    // Access the variant from another thread
824                    match &*v {
825                        Value::Variant(data) => {
826                            assert_eq!(data.tag, 42);
827                            assert_eq!(data.fields.len(), 3);
828                        }
829                        _ => panic!("Expected Variant"),
830                    }
831                })
832            })
833            .collect();
834
835        for h in handles {
836            h.join().expect("Thread panicked");
837        }
838    }
839}