1use crate::stack::{Stack, 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 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#[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 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#[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#[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#[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#[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#[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
254pub 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#[unsafe(no_mangle)]
275pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
276 use crate::value::VariantData;
277
278 unsafe {
279 let (stack, value) = pop(stack);
281
282 let (stack, variant_val) = pop(stack);
284
285 match variant_val {
286 Value::Variant(variant_data) => {
287 let mut new_fields = variant_data.fields.to_vec();
289 new_fields.push(value);
290
291 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#[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#[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 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#[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 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
407pub 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 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 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 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 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 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 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 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 let stack = std::ptr::null_mut();
525 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::Int(42)); 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 let stack = std::ptr::null_mut();
554 let stack = push(stack, Value::Int(0)); 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 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)); 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 let stack = std::ptr::null_mut();
606 let stack = push(stack, Value::Int(4)); let stack = make_variant_0(stack);
608
609 let stack = push(stack, Value::Int(42));
611 let stack = variant_append(stack);
612
613 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 let stack = std::ptr::null_mut();
632 let stack = push(stack, Value::Int(5)); let stack = make_variant_0(stack);
634
635 let key = global_string("name".to_string());
637 let stack = push(stack, Value::String(key.clone()));
638 let stack = variant_append(stack);
639
640 let val = global_string("John".to_string());
642 let stack = push(stack, Value::String(val.clone()));
643 let stack = variant_append(stack);
644
645 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 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 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); 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 unsafe {
710 let stack = std::ptr::null_mut();
712 let stack = push(stack, Value::Int(99)); let stack = make_variant_0(stack);
714
715 let stack = push(stack, Value::Int(10));
717 let stack = variant_append(stack);
718
719 let stack = push(stack, Value::Int(20));
721 let stack = variant_append(stack);
722
723 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 let stack = variant_init(stack);
734
735 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 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 let mut variant = Value::Variant(Arc::new(VariantData::new(0, vec![])));
761
762 for i in 0..100 {
764 variant = Value::Variant(Arc::new(VariantData::new(i, vec![variant.clone()])));
765 }
766
767 let start = std::time::Instant::now();
769 for _ in 0..1000 {
770 let _copy = variant.clone();
771 }
772 let elapsed = start.elapsed();
773
774 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 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 let outer_clone = outer.clone();
791
792 match (&outer, &outer_clone) {
794 (Value::Variant(a), Value::Variant(b)) => {
795 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 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 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 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}