1use crate::stack::{Stack, peek_heap_mut_second, pop, push};
7use crate::value::Value;
8use std::sync::Arc;
9
10#[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#[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 push(stack, Value::Symbol(variant_data.tag.clone()))
46 }
47 _ => panic!("variant-tag: expected Variant, got {:?}", value),
48 }
49 }
50}
51
52#[unsafe(no_mangle)]
64pub unsafe extern "C" fn patch_seq_symbol_eq_cstr(stack: Stack, c_str: *const i8) -> Stack {
65 use std::ffi::CStr;
66
67 unsafe {
68 let (stack, value) = pop(stack);
69 let symbol_str = match value {
70 Value::Symbol(s) => s,
71 _ => panic!("symbol_eq_cstr: expected Symbol, got {:?}", value),
72 };
73
74 let expected = CStr::from_ptr(c_str)
75 .to_str()
76 .expect("Invalid UTF-8 in variant name");
77
78 let is_equal = symbol_str.as_str() == expected;
79 push(stack, Value::Bool(is_equal))
80 }
81}
82
83#[unsafe(no_mangle)]
94pub unsafe extern "C" fn patch_seq_variant_field_at(stack: Stack) -> Stack {
95 unsafe {
96 let (stack, index_val) = pop(stack);
97 let index = match index_val {
98 Value::Int(i) => i,
99 _ => panic!(
100 "variant-field-at: expected Int (index), got {:?}",
101 index_val
102 ),
103 };
104
105 if index < 0 {
106 panic!("variant-field-at: index cannot be negative: {}", index);
107 }
108
109 let (stack, variant_val) = pop(stack);
110
111 match variant_val {
112 Value::Variant(variant_data) => {
113 let idx = index as usize;
114 if idx >= variant_data.fields.len() {
115 panic!(
116 "variant-field-at: index {} out of bounds (variant has {} fields)",
117 index,
118 variant_data.fields.len()
119 );
120 }
121
122 let field = variant_data.fields[idx].clone();
124 push(stack, field)
125 }
126 _ => panic!("variant-field-at: expected Variant, got {:?}", variant_val),
127 }
128 }
129}
130
131#[unsafe(no_mangle)]
143pub unsafe extern "C" fn patch_seq_make_variant_0(stack: Stack) -> Stack {
144 use crate::value::VariantData;
145
146 unsafe {
147 let (stack, tag_val) = pop(stack);
148 let tag = match tag_val {
149 Value::Symbol(s) => s,
150 _ => panic!("make-variant-0: expected Symbol (tag), got {:?}", tag_val),
151 };
152
153 let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![])));
154 push(stack, variant)
155 }
156}
157
158#[unsafe(no_mangle)]
165pub unsafe extern "C" fn patch_seq_make_variant_1(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::Symbol(s) => s,
172 _ => panic!("make-variant-1: expected Symbol (tag), got {:?}", tag_val),
173 };
174
175 let (stack, field1) = pop(stack);
176 let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![field1])));
177 push(stack, variant)
178 }
179}
180
181#[unsafe(no_mangle)]
188pub unsafe extern "C" fn patch_seq_make_variant_2(stack: Stack) -> Stack {
189 use crate::value::VariantData;
190
191 unsafe {
192 let (stack, tag_val) = pop(stack);
193 let tag = match tag_val {
194 Value::Symbol(s) => s,
195 _ => panic!("make-variant-2: expected Symbol (tag), got {:?}", tag_val),
196 };
197
198 let (stack, field2) = pop(stack);
199 let (stack, field1) = pop(stack);
200 let variant = Value::Variant(Arc::new(VariantData::new(tag, vec![field1, field2])));
201 push(stack, variant)
202 }
203}
204
205#[unsafe(no_mangle)]
212pub unsafe extern "C" fn patch_seq_make_variant_3(stack: Stack) -> Stack {
213 use crate::value::VariantData;
214
215 unsafe {
216 let (stack, tag_val) = pop(stack);
217 let tag = match tag_val {
218 Value::Symbol(s) => s,
219 _ => panic!("make-variant-3: expected Symbol (tag), got {:?}", tag_val),
220 };
221
222 let (stack, field3) = pop(stack);
223 let (stack, field2) = pop(stack);
224 let (stack, field1) = pop(stack);
225 let variant = Value::Variant(Arc::new(VariantData::new(
226 tag,
227 vec![field1, field2, field3],
228 )));
229 push(stack, variant)
230 }
231}
232
233#[unsafe(no_mangle)]
240pub unsafe extern "C" fn patch_seq_make_variant_4(stack: Stack) -> Stack {
241 use crate::value::VariantData;
242
243 unsafe {
244 let (stack, tag_val) = pop(stack);
245 let tag = match tag_val {
246 Value::Symbol(s) => s,
247 _ => panic!("make-variant-4: expected Symbol (tag), got {:?}", tag_val),
248 };
249
250 let (stack, field4) = pop(stack);
251 let (stack, field3) = pop(stack);
252 let (stack, field2) = pop(stack);
253 let (stack, field1) = pop(stack);
254 let variant = Value::Variant(Arc::new(VariantData::new(
255 tag,
256 vec![field1, field2, field3, field4],
257 )));
258 push(stack, variant)
259 }
260}
261
262#[unsafe(no_mangle)]
269pub unsafe extern "C" fn patch_seq_make_variant_5(stack: Stack) -> Stack {
270 use crate::value::VariantData;
271
272 unsafe {
273 let (stack, tag_val) = pop(stack);
274 let tag = match tag_val {
275 Value::Symbol(s) => s,
276 _ => panic!("make-variant-5: expected Symbol (tag), got {:?}", tag_val),
277 };
278
279 let (stack, field5) = pop(stack);
280 let (stack, field4) = pop(stack);
281 let (stack, field3) = pop(stack);
282 let (stack, field2) = pop(stack);
283 let (stack, field1) = pop(stack);
284 let variant = Value::Variant(Arc::new(VariantData::new(
285 tag,
286 vec![field1, field2, field3, field4, field5],
287 )));
288 push(stack, variant)
289 }
290}
291
292#[unsafe(no_mangle)]
299pub unsafe extern "C" fn patch_seq_make_variant_6(stack: Stack) -> Stack {
300 use crate::value::VariantData;
301
302 unsafe {
303 let (stack, tag_val) = pop(stack);
304 let tag = match tag_val {
305 Value::Symbol(s) => s,
306 _ => panic!("make-variant-6: expected Symbol (tag), got {:?}", tag_val),
307 };
308
309 let (stack, field6) = pop(stack);
310 let (stack, field5) = pop(stack);
311 let (stack, field4) = pop(stack);
312 let (stack, field3) = pop(stack);
313 let (stack, field2) = pop(stack);
314 let (stack, field1) = pop(stack);
315 let variant = Value::Variant(Arc::new(VariantData::new(
316 tag,
317 vec![field1, field2, field3, field4, field5, field6],
318 )));
319 push(stack, variant)
320 }
321}
322
323#[unsafe(no_mangle)]
330pub unsafe extern "C" fn patch_seq_make_variant_7(stack: Stack) -> Stack {
331 use crate::value::VariantData;
332
333 unsafe {
334 let (stack, tag_val) = pop(stack);
335 let tag = match tag_val {
336 Value::Symbol(s) => s,
337 _ => panic!("make-variant-7: expected Symbol (tag), got {:?}", tag_val),
338 };
339
340 let (stack, field7) = pop(stack);
341 let (stack, field6) = pop(stack);
342 let (stack, field5) = pop(stack);
343 let (stack, field4) = pop(stack);
344 let (stack, field3) = pop(stack);
345 let (stack, field2) = pop(stack);
346 let (stack, field1) = pop(stack);
347 let variant = Value::Variant(Arc::new(VariantData::new(
348 tag,
349 vec![field1, field2, field3, field4, field5, field6, field7],
350 )));
351 push(stack, variant)
352 }
353}
354
355#[unsafe(no_mangle)]
362pub unsafe extern "C" fn patch_seq_make_variant_8(stack: Stack) -> Stack {
363 use crate::value::VariantData;
364
365 unsafe {
366 let (stack, tag_val) = pop(stack);
367 let tag = match tag_val {
368 Value::Symbol(s) => s,
369 _ => panic!("make-variant-8: expected Symbol (tag), got {:?}", tag_val),
370 };
371
372 let (stack, field8) = pop(stack);
373 let (stack, field7) = pop(stack);
374 let (stack, field6) = pop(stack);
375 let (stack, field5) = pop(stack);
376 let (stack, field4) = pop(stack);
377 let (stack, field3) = pop(stack);
378 let (stack, field2) = pop(stack);
379 let (stack, field1) = pop(stack);
380 let variant = Value::Variant(Arc::new(VariantData::new(
381 tag,
382 vec![
383 field1, field2, field3, field4, field5, field6, field7, field8,
384 ],
385 )));
386 push(stack, variant)
387 }
388}
389
390#[unsafe(no_mangle)]
397pub unsafe extern "C" fn patch_seq_make_variant_9(stack: Stack) -> Stack {
398 use crate::value::VariantData;
399
400 unsafe {
401 let (stack, tag_val) = pop(stack);
402 let tag = match tag_val {
403 Value::Symbol(s) => s,
404 _ => panic!("make-variant-9: expected Symbol (tag), got {:?}", tag_val),
405 };
406
407 let (stack, field9) = pop(stack);
408 let (stack, field8) = pop(stack);
409 let (stack, field7) = pop(stack);
410 let (stack, field6) = pop(stack);
411 let (stack, field5) = pop(stack);
412 let (stack, field4) = pop(stack);
413 let (stack, field3) = pop(stack);
414 let (stack, field2) = pop(stack);
415 let (stack, field1) = pop(stack);
416 let variant = Value::Variant(Arc::new(VariantData::new(
417 tag,
418 vec![
419 field1, field2, field3, field4, field5, field6, field7, field8, field9,
420 ],
421 )));
422 push(stack, variant)
423 }
424}
425
426#[unsafe(no_mangle)]
433pub unsafe extern "C" fn patch_seq_make_variant_10(stack: Stack) -> Stack {
434 use crate::value::VariantData;
435
436 unsafe {
437 let (stack, tag_val) = pop(stack);
438 let tag = match tag_val {
439 Value::Symbol(s) => s,
440 _ => panic!("make-variant-10: expected Symbol (tag), got {:?}", tag_val),
441 };
442
443 let (stack, field10) = pop(stack);
444 let (stack, field9) = pop(stack);
445 let (stack, field8) = pop(stack);
446 let (stack, field7) = pop(stack);
447 let (stack, field6) = pop(stack);
448 let (stack, field5) = pop(stack);
449 let (stack, field4) = pop(stack);
450 let (stack, field3) = pop(stack);
451 let (stack, field2) = pop(stack);
452 let (stack, field1) = pop(stack);
453 let variant = Value::Variant(Arc::new(VariantData::new(
454 tag,
455 vec![
456 field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
457 ],
458 )));
459 push(stack, variant)
460 }
461}
462
463#[unsafe(no_mangle)]
470pub unsafe extern "C" fn patch_seq_make_variant_11(stack: Stack) -> Stack {
471 use crate::value::VariantData;
472
473 unsafe {
474 let (stack, tag_val) = pop(stack);
475 let tag = match tag_val {
476 Value::Symbol(s) => s,
477 _ => panic!("make-variant-11: expected Symbol (tag), got {:?}", tag_val),
478 };
479
480 let (stack, field11) = pop(stack);
481 let (stack, field10) = pop(stack);
482 let (stack, field9) = pop(stack);
483 let (stack, field8) = pop(stack);
484 let (stack, field7) = pop(stack);
485 let (stack, field6) = pop(stack);
486 let (stack, field5) = pop(stack);
487 let (stack, field4) = pop(stack);
488 let (stack, field3) = pop(stack);
489 let (stack, field2) = pop(stack);
490 let (stack, field1) = pop(stack);
491 let variant = Value::Variant(Arc::new(VariantData::new(
492 tag,
493 vec![
494 field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
495 field11,
496 ],
497 )));
498 push(stack, variant)
499 }
500}
501
502#[unsafe(no_mangle)]
509pub unsafe extern "C" fn patch_seq_make_variant_12(stack: Stack) -> Stack {
510 use crate::value::VariantData;
511
512 unsafe {
513 let (stack, tag_val) = pop(stack);
514 let tag = match tag_val {
515 Value::Symbol(s) => s,
516 _ => panic!("make-variant-12: expected Symbol (tag), got {:?}", tag_val),
517 };
518
519 let (stack, field12) = pop(stack);
520 let (stack, field11) = pop(stack);
521 let (stack, field10) = pop(stack);
522 let (stack, field9) = pop(stack);
523 let (stack, field8) = pop(stack);
524 let (stack, field7) = pop(stack);
525 let (stack, field6) = pop(stack);
526 let (stack, field5) = pop(stack);
527 let (stack, field4) = pop(stack);
528 let (stack, field3) = pop(stack);
529 let (stack, field2) = pop(stack);
530 let (stack, field1) = pop(stack);
531 let variant = Value::Variant(Arc::new(VariantData::new(
532 tag,
533 vec![
534 field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
535 field11, field12,
536 ],
537 )));
538 push(stack, variant)
539 }
540}
541
542pub use patch_seq_make_variant_0 as make_variant_0;
544pub use patch_seq_make_variant_1 as make_variant_1;
545pub use patch_seq_make_variant_2 as make_variant_2;
546pub use patch_seq_make_variant_3 as make_variant_3;
547pub use patch_seq_make_variant_4 as make_variant_4;
548pub use patch_seq_make_variant_5 as make_variant_5;
549pub use patch_seq_make_variant_6 as make_variant_6;
550pub use patch_seq_make_variant_7 as make_variant_7;
551pub use patch_seq_make_variant_8 as make_variant_8;
552pub use patch_seq_make_variant_9 as make_variant_9;
553pub use patch_seq_make_variant_10 as make_variant_10;
554pub use patch_seq_make_variant_11 as make_variant_11;
555pub use patch_seq_make_variant_12 as make_variant_12;
556
557#[unsafe(no_mangle)]
571pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
572 use crate::value::VariantData;
573
574 unsafe {
575 if let Some(Value::Variant(variant_arc)) = peek_heap_mut_second(stack)
579 && let Some(data) = Arc::get_mut(variant_arc)
580 {
581 let (stack, value) = pop(stack);
586 data.fields.push(value);
587 return stack; }
589
590 let (stack, value) = pop(stack);
592 let (stack, variant_val) = pop(stack);
593
594 match variant_val {
595 Value::Variant(mut arc) => {
596 if let Some(data) = Arc::get_mut(&mut arc) {
597 data.fields.push(value);
598 push(stack, Value::Variant(arc))
599 } else {
600 let mut new_fields = Vec::with_capacity(arc.fields.len() + 1);
601 new_fields.extend(arc.fields.iter().cloned());
602 new_fields.push(value);
603 let new_variant =
604 Value::Variant(Arc::new(VariantData::new(arc.tag.clone(), new_fields)));
605 push(stack, new_variant)
606 }
607 }
608 _ => panic!("variant-append: expected Variant, got {:?}", variant_val),
609 }
610 }
611}
612
613#[unsafe(no_mangle)]
623pub unsafe extern "C" fn patch_seq_variant_last(stack: Stack) -> Stack {
624 unsafe {
625 let (stack, variant_val) = pop(stack);
626
627 match variant_val {
628 Value::Variant(variant_data) => {
629 if variant_data.fields.is_empty() {
630 panic!("variant-last: variant has no fields");
631 }
632
633 let last = variant_data.fields.last().unwrap().clone();
634 push(stack, last)
635 }
636 _ => panic!("variant-last: expected Variant, got {:?}", variant_val),
637 }
638 }
639}
640
641#[unsafe(no_mangle)]
652pub unsafe extern "C" fn patch_seq_variant_init(stack: Stack) -> Stack {
653 use crate::value::VariantData;
654
655 unsafe {
656 let (stack, variant_val) = pop(stack);
657
658 match variant_val {
659 Value::Variant(variant_data) => {
660 if variant_data.fields.is_empty() {
661 panic!("variant-init: variant has no fields");
662 }
663
664 let new_fields: Vec<Value> =
666 variant_data.fields[..variant_data.fields.len() - 1].to_vec();
667
668 let new_variant = Value::Variant(Arc::new(VariantData::new(
669 variant_data.tag.clone(),
670 new_fields,
671 )));
672
673 push(stack, new_variant)
674 }
675 _ => panic!("variant-init: expected Variant, got {:?}", variant_val),
676 }
677 }
678}
679
680#[unsafe(no_mangle)]
693pub unsafe extern "C" fn patch_seq_unpack_variant(stack: Stack, field_count: i64) -> Stack {
694 unsafe {
695 let (mut stack, variant_val) = pop(stack);
696
697 match variant_val {
698 Value::Variant(variant_data) => {
699 let count = field_count as usize;
700 if count > variant_data.fields.len() {
701 panic!(
702 "unpack-variant: requested {} fields but variant only has {}",
703 count,
704 variant_data.fields.len()
705 );
706 }
707
708 for i in 0..count {
710 stack = push(stack, variant_data.fields[i].clone());
711 }
712
713 stack
714 }
715 _ => panic!("unpack-variant: expected Variant, got {:?}", variant_val),
716 }
717 }
718}
719
720pub use patch_seq_unpack_variant as unpack_variant;
722pub use patch_seq_variant_append as variant_append;
723pub use patch_seq_variant_field_at as variant_field_at;
724pub use patch_seq_variant_field_count as variant_field_count;
725pub use patch_seq_variant_init as variant_init;
726pub use patch_seq_variant_last as variant_last;
727pub use patch_seq_variant_tag as variant_tag;
728
729#[cfg(test)]
730mod tests {
731 use super::*;
732 use crate::seqstring::global_string;
733 use crate::value::VariantData;
734
735 #[test]
736 fn test_variant_field_count() {
737 unsafe {
738 let variant = Value::Variant(Arc::new(VariantData::new(
740 global_string("TestTag".to_string()),
741 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
742 )));
743
744 let stack = crate::stack::alloc_test_stack();
745 let stack = push(stack, variant);
746 let stack = variant_field_count(stack);
747
748 let (_stack, result) = pop(stack);
749 assert_eq!(result, Value::Int(3));
750 }
751 }
752
753 #[test]
754 fn test_variant_tag() {
755 unsafe {
756 let variant = Value::Variant(Arc::new(VariantData::new(
758 global_string("MyTag".to_string()),
759 vec![Value::Int(10)],
760 )));
761
762 let stack = crate::stack::alloc_test_stack();
763 let stack = push(stack, variant);
764 let stack = variant_tag(stack);
765
766 let (_stack, result) = pop(stack);
767 assert_eq!(result, Value::Symbol(global_string("MyTag".to_string())));
768 }
769 }
770
771 #[test]
772 fn test_variant_field_at() {
773 unsafe {
774 let str1 = global_string("hello".to_string());
775 let str2 = global_string("world".to_string());
776
777 let variant = Value::Variant(Arc::new(VariantData::new(
779 global_string("TestTag".to_string()),
780 vec![
781 Value::String(str1.clone()),
782 Value::Int(42),
783 Value::String(str2.clone()),
784 ],
785 )));
786
787 let stack = crate::stack::alloc_test_stack();
789 let stack = push(stack, variant.clone());
790 let stack = push(stack, Value::Int(0));
791 let stack = variant_field_at(stack);
792
793 let (_stack, result) = pop(stack);
794 assert_eq!(result, Value::String(str1.clone()));
795
796 let stack = push(stack, variant.clone());
798 let stack = push(stack, Value::Int(1));
799 let stack = variant_field_at(stack);
800
801 let (_stack, result) = pop(stack);
802 assert_eq!(result, Value::Int(42));
803
804 let stack = push(stack, variant.clone());
806 let stack = push(stack, Value::Int(2));
807 let stack = variant_field_at(stack);
808
809 let (_stack, result) = pop(stack);
810 assert_eq!(result, Value::String(str2));
811 }
812 }
813
814 #[test]
815 fn test_variant_field_count_empty() {
816 unsafe {
817 let variant = Value::Variant(Arc::new(VariantData::new(
819 global_string("Empty".to_string()),
820 vec![],
821 )));
822
823 let stack = crate::stack::alloc_test_stack();
824 let stack = push(stack, variant);
825 let stack = variant_field_count(stack);
826
827 let (_stack, result) = pop(stack);
828 assert_eq!(result, Value::Int(0));
829 }
830 }
831
832 #[test]
833 fn test_make_variant_with_fields() {
834 unsafe {
835 let stack = crate::stack::alloc_test_stack();
838 let stack = push(stack, Value::Int(10)); let stack = push(stack, Value::Int(20)); let stack = push(stack, Value::Int(30)); let stack = push(stack, Value::Symbol(global_string("Tag".to_string()))); let stack = make_variant_3(stack);
844
845 let (_stack, result) = pop(stack);
846
847 match result {
848 Value::Variant(v) => {
849 assert_eq!(v.tag.as_str(), "Tag");
850 assert_eq!(v.fields.len(), 3);
851 assert_eq!(v.fields[0], Value::Int(10));
852 assert_eq!(v.fields[1], Value::Int(20));
853 assert_eq!(v.fields[2], Value::Int(30));
854 }
855 _ => panic!("Expected Variant"),
856 }
857 }
858 }
859
860 #[test]
861 fn test_make_variant_empty() {
862 unsafe {
863 let stack = crate::stack::alloc_test_stack();
866 let stack = push(stack, Value::Symbol(global_string("None".to_string()))); let stack = make_variant_0(stack);
869
870 let (_stack, result) = pop(stack);
871
872 match result {
873 Value::Variant(v) => {
874 assert_eq!(v.tag.as_str(), "None");
875 assert_eq!(v.fields.len(), 0);
876 }
877 _ => panic!("Expected Variant"),
878 }
879 }
880 }
881
882 #[test]
883 fn test_make_variant_with_mixed_types() {
884 unsafe {
885 let s = global_string("hello".to_string());
886
887 let stack = crate::stack::alloc_test_stack();
889 let stack = push(stack, Value::Int(42));
890 let stack = push(stack, Value::String(s.clone()));
891 let stack = push(stack, Value::Float(3.5));
892 let stack = push(stack, Value::Symbol(global_string("Mixed".to_string()))); let stack = make_variant_3(stack);
895
896 let (_stack, result) = pop(stack);
897
898 match result {
899 Value::Variant(v) => {
900 assert_eq!(v.tag.as_str(), "Mixed");
901 assert_eq!(v.fields.len(), 3);
902 assert_eq!(v.fields[0], Value::Int(42));
903 assert_eq!(v.fields[1], Value::String(s));
904 assert_eq!(v.fields[2], Value::Float(3.5));
905 }
906 _ => panic!("Expected Variant"),
907 }
908 }
909 }
910
911 #[test]
912 fn test_variant_append() {
913 unsafe {
914 let stack = crate::stack::alloc_test_stack();
916 let stack = push(stack, Value::Symbol(global_string("Array".to_string()))); let stack = make_variant_0(stack);
918
919 let stack = push(stack, Value::Int(42));
921 let stack = variant_append(stack);
922
923 let (_stack, result) = pop(stack);
925 match result {
926 Value::Variant(v) => {
927 assert_eq!(v.tag.as_str(), "Array");
928 assert_eq!(v.fields.len(), 1);
929 assert_eq!(v.fields[0], Value::Int(42));
930 }
931 _ => panic!("Expected Variant"),
932 }
933 }
934 }
935
936 #[test]
937 fn test_variant_append_multiple() {
938 unsafe {
939 let stack = crate::stack::alloc_test_stack();
941 let stack = push(stack, Value::Symbol(global_string("Object".to_string()))); let stack = make_variant_0(stack);
943
944 let key = global_string("name".to_string());
946 let stack = push(stack, Value::String(key.clone()));
947 let stack = variant_append(stack);
948
949 let val = global_string("John".to_string());
951 let stack = push(stack, Value::String(val.clone()));
952 let stack = variant_append(stack);
953
954 let (_stack, result) = pop(stack);
956 match result {
957 Value::Variant(v) => {
958 assert_eq!(v.tag.as_str(), "Object");
959 assert_eq!(v.fields.len(), 2);
960 assert_eq!(v.fields[0], Value::String(key));
961 assert_eq!(v.fields[1], Value::String(val));
962 }
963 _ => panic!("Expected Variant"),
964 }
965 }
966 }
967
968 #[test]
969 fn test_variant_last() {
970 unsafe {
971 let variant = Value::Variant(Arc::new(VariantData::new(
973 global_string("List".to_string()),
974 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
975 )));
976
977 let stack = crate::stack::alloc_test_stack();
978 let stack = push(stack, variant);
979 let stack = variant_last(stack);
980
981 let (_stack, result) = pop(stack);
982 assert_eq!(result, Value::Int(30));
983 }
984 }
985
986 #[test]
987 fn test_variant_init() {
988 unsafe {
989 let variant = Value::Variant(Arc::new(VariantData::new(
991 global_string("Custom".to_string()),
992 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
993 )));
994
995 let stack = crate::stack::alloc_test_stack();
996 let stack = push(stack, variant);
997 let stack = variant_init(stack);
998
999 let (_stack, result) = pop(stack);
1000 match result {
1001 Value::Variant(v) => {
1002 assert_eq!(v.tag.as_str(), "Custom"); assert_eq!(v.fields.len(), 2);
1004 assert_eq!(v.fields[0], Value::Int(10));
1005 assert_eq!(v.fields[1], Value::Int(20));
1006 }
1007 _ => panic!("Expected Variant"),
1008 }
1009 }
1010 }
1011
1012 #[test]
1013 fn test_variant_stack_operations() {
1014 unsafe {
1016 let stack = crate::stack::alloc_test_stack();
1018 let stack = push(stack, Value::Symbol(global_string("Stack".to_string()))); let stack = make_variant_0(stack);
1020
1021 let stack = push(stack, Value::Int(10));
1023 let stack = variant_append(stack);
1024
1025 let stack = push(stack, Value::Int(20));
1027 let stack = variant_append(stack);
1028
1029 let (stack, variant) = pop(stack);
1032 let stack = push(stack, variant.clone());
1033 let stack = push(stack, variant);
1034 let stack = variant_last(stack);
1035 let (stack, top) = pop(stack);
1036 assert_eq!(top, Value::Int(20));
1037
1038 let stack = variant_init(stack);
1040
1041 let (stack, variant) = pop(stack);
1043 let stack = push(stack, variant.clone());
1044 let stack = push(stack, variant);
1045 let stack = variant_last(stack);
1046 let (stack, top) = pop(stack);
1047 assert_eq!(top, Value::Int(10));
1048
1049 let (_stack, result) = pop(stack);
1051 match result {
1052 Value::Variant(v) => {
1053 assert_eq!(v.fields.len(), 1);
1054 assert_eq!(v.fields[0], Value::Int(10));
1055 }
1056 _ => panic!("Expected Variant"),
1057 }
1058 }
1059 }
1060
1061 #[test]
1062 fn test_variant_clone_is_o1() {
1063 let mut variant = Value::Variant(Arc::new(VariantData::new(
1066 global_string("Level0".to_string()),
1067 vec![],
1068 )));
1069
1070 for i in 0..100 {
1072 variant = Value::Variant(Arc::new(VariantData::new(
1073 global_string(format!("Level{}", i)),
1074 vec![variant.clone()],
1075 )));
1076 }
1077
1078 let start = std::time::Instant::now();
1080 for _ in 0..1000 {
1081 let _copy = variant.clone();
1082 }
1083 let elapsed = start.elapsed();
1084
1085 assert!(
1088 elapsed.as_millis() < 10,
1089 "Clone took {:?} - should be O(1) with Arc",
1090 elapsed
1091 );
1092 }
1093
1094 #[test]
1095 fn test_variant_arc_sharing() {
1096 let inner = Value::Variant(Arc::new(VariantData::new(
1098 global_string("Inner".to_string()),
1099 vec![Value::Int(42)],
1100 )));
1101 let outer = Value::Variant(Arc::new(VariantData::new(
1102 global_string("Outer".to_string()),
1103 vec![inner.clone()],
1104 )));
1105
1106 let outer_clone = outer.clone();
1108
1109 match (&outer, &outer_clone) {
1111 (Value::Variant(a), Value::Variant(b)) => {
1112 assert_eq!(a.tag, b.tag);
1115 assert_eq!(a.fields.len(), b.fields.len());
1116 }
1117 _ => panic!("Expected Variants"),
1118 }
1119 }
1120
1121 #[test]
1122 fn test_variant_thread_safe_sharing() {
1123 use std::sync::Arc as StdArc;
1126 use std::thread;
1127
1128 let variant = Value::Variant(Arc::new(VariantData::new(
1129 global_string("ThreadSafe".to_string()),
1130 vec![Value::Int(1), Value::Int(2), Value::Int(3)],
1131 )));
1132
1133 let shared = StdArc::new(variant);
1135
1136 let handles: Vec<_> = (0..4)
1137 .map(|_| {
1138 let v = StdArc::clone(&shared);
1139 thread::spawn(move || {
1140 match &*v {
1142 Value::Variant(data) => {
1143 assert_eq!(data.tag.as_str(), "ThreadSafe");
1144 assert_eq!(data.fields.len(), 3);
1145 }
1146 _ => panic!("Expected Variant"),
1147 }
1148 })
1149 })
1150 .collect();
1151
1152 for h in handles {
1153 h.join().expect("Thread panicked");
1154 }
1155 }
1156}