1use crate::stack::{Stack, pop, push};
7use crate::value::Value;
8
9#[unsafe(no_mangle)]
16pub unsafe extern "C" fn patch_seq_variant_field_count(stack: Stack) -> Stack {
17 unsafe {
18 let (stack, value) = pop(stack);
19
20 match value {
21 Value::Variant(variant_data) => {
22 let count = variant_data.fields.len() as i64;
23 push(stack, Value::Int(count))
24 }
25 _ => panic!("variant-field-count: expected Variant, got {:?}", value),
26 }
27 }
28}
29
30#[unsafe(no_mangle)]
37pub unsafe extern "C" fn patch_seq_variant_tag(stack: Stack) -> Stack {
38 unsafe {
39 let (stack, value) = pop(stack);
40
41 match value {
42 Value::Variant(variant_data) => {
43 let tag = variant_data.tag as i64;
44 push(stack, Value::Int(tag))
45 }
46 _ => panic!("variant-tag: expected Variant, got {:?}", value),
47 }
48 }
49}
50
51#[unsafe(no_mangle)]
61pub unsafe extern "C" fn patch_seq_variant_field_at(stack: Stack) -> Stack {
62 unsafe {
63 let (stack, index_val) = pop(stack);
64 let index = match index_val {
65 Value::Int(i) => i,
66 _ => panic!(
67 "variant-field-at: expected Int (index), got {:?}",
68 index_val
69 ),
70 };
71
72 if index < 0 {
73 panic!("variant-field-at: index cannot be negative: {}", index);
74 }
75
76 let (stack, variant_val) = pop(stack);
77
78 match variant_val {
79 Value::Variant(variant_data) => {
80 let idx = index as usize;
81 if idx >= variant_data.fields.len() {
82 panic!(
83 "variant-field-at: index {} out of bounds (variant has {} fields)",
84 index,
85 variant_data.fields.len()
86 );
87 }
88
89 let field = variant_data.fields[idx].clone();
91 push(stack, field)
92 }
93 _ => panic!("variant-field-at: expected Variant, got {:?}", variant_val),
94 }
95 }
96}
97
98#[unsafe(no_mangle)]
111pub unsafe extern "C" fn patch_seq_make_variant(stack: Stack) -> Stack {
112 use crate::value::VariantData;
113
114 unsafe {
115 let (stack, tag_val) = pop(stack);
117 let tag = match tag_val {
118 Value::Int(t) => {
119 if t < 0 {
120 panic!("make-variant: tag cannot be negative: {}", t);
121 }
122 t as u32
123 }
124 _ => panic!("make-variant: expected Int (tag), got {:?}", tag_val),
125 };
126
127 let (stack, count_val) = pop(stack);
129 let count = match count_val {
130 Value::Int(c) => {
131 if c < 0 {
132 panic!("make-variant: count cannot be negative: {}", c);
133 }
134 c as usize
135 }
136 _ => panic!("make-variant: expected Int (count), got {:?}", count_val),
137 };
138
139 let mut fields = Vec::with_capacity(count);
141 let mut current_stack = stack;
142
143 for i in 0..count {
144 if current_stack.is_null() {
145 panic!(
146 "make-variant: stack underflow, expected {} fields but only got {}",
147 count, i
148 );
149 }
150 let (new_stack, value) = pop(current_stack);
151 fields.push(value);
152 current_stack = new_stack;
153 }
154
155 fields.reverse();
157
158 let variant = Value::Variant(Box::new(VariantData::new(tag, fields)));
160 push(current_stack, variant)
161 }
162}
163
164#[unsafe(no_mangle)]
175pub unsafe extern "C" fn patch_seq_make_variant_0(stack: Stack) -> Stack {
176 use crate::value::VariantData;
177
178 unsafe {
179 let (stack, tag_val) = pop(stack);
180 let tag = match tag_val {
181 Value::Int(t) => {
182 if t < 0 {
183 panic!("make-variant-0: tag cannot be negative: {}", t);
184 }
185 t as u32
186 }
187 _ => panic!("make-variant-0: expected Int (tag), got {:?}", tag_val),
188 };
189
190 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![])));
191 push(stack, variant)
192 }
193}
194
195#[unsafe(no_mangle)]
202pub unsafe extern "C" fn patch_seq_make_variant_1(stack: Stack) -> Stack {
203 use crate::value::VariantData;
204
205 unsafe {
206 let (stack, tag_val) = pop(stack);
207 let tag = match tag_val {
208 Value::Int(t) => {
209 if t < 0 {
210 panic!("make-variant-1: tag cannot be negative: {}", t);
211 }
212 t as u32
213 }
214 _ => panic!("make-variant-1: expected Int (tag), got {:?}", tag_val),
215 };
216
217 let (stack, field1) = pop(stack);
218 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![field1])));
219 push(stack, variant)
220 }
221}
222
223#[unsafe(no_mangle)]
230pub unsafe extern "C" fn patch_seq_make_variant_2(stack: Stack) -> Stack {
231 use crate::value::VariantData;
232
233 unsafe {
234 let (stack, tag_val) = pop(stack);
235 let tag = match tag_val {
236 Value::Int(t) => {
237 if t < 0 {
238 panic!("make-variant-2: tag cannot be negative: {}", t);
239 }
240 t as u32
241 }
242 _ => panic!("make-variant-2: expected Int (tag), got {:?}", tag_val),
243 };
244
245 let (stack, field2) = pop(stack);
246 let (stack, field1) = pop(stack);
247 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![field1, field2])));
248 push(stack, variant)
249 }
250}
251
252#[unsafe(no_mangle)]
259pub unsafe extern "C" fn patch_seq_make_variant_3(stack: Stack) -> Stack {
260 use crate::value::VariantData;
261
262 unsafe {
263 let (stack, tag_val) = pop(stack);
264 let tag = match tag_val {
265 Value::Int(t) => {
266 if t < 0 {
267 panic!("make-variant-3: tag cannot be negative: {}", t);
268 }
269 t as u32
270 }
271 _ => panic!("make-variant-3: expected Int (tag), got {:?}", tag_val),
272 };
273
274 let (stack, field3) = pop(stack);
275 let (stack, field2) = pop(stack);
276 let (stack, field1) = pop(stack);
277 let variant = Value::Variant(Box::new(VariantData::new(
278 tag,
279 vec![field1, field2, field3],
280 )));
281 push(stack, variant)
282 }
283}
284
285#[unsafe(no_mangle)]
292pub unsafe extern "C" fn patch_seq_make_variant_4(stack: Stack) -> Stack {
293 use crate::value::VariantData;
294
295 unsafe {
296 let (stack, tag_val) = pop(stack);
297 let tag = match tag_val {
298 Value::Int(t) => {
299 if t < 0 {
300 panic!("make-variant-4: tag cannot be negative: {}", t);
301 }
302 t as u32
303 }
304 _ => panic!("make-variant-4: expected Int (tag), got {:?}", tag_val),
305 };
306
307 let (stack, field4) = pop(stack);
308 let (stack, field3) = pop(stack);
309 let (stack, field2) = pop(stack);
310 let (stack, field1) = pop(stack);
311 let variant = Value::Variant(Box::new(VariantData::new(
312 tag,
313 vec![field1, field2, field3, field4],
314 )));
315 push(stack, variant)
316 }
317}
318
319pub use patch_seq_make_variant_0 as make_variant_0;
321pub use patch_seq_make_variant_1 as make_variant_1;
322pub use patch_seq_make_variant_2 as make_variant_2;
323pub use patch_seq_make_variant_3 as make_variant_3;
324pub use patch_seq_make_variant_4 as make_variant_4;
325
326#[unsafe(no_mangle)]
340pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
341 use crate::value::VariantData;
342
343 unsafe {
344 let (stack, value) = pop(stack);
346
347 let (stack, variant_val) = pop(stack);
349
350 match variant_val {
351 Value::Variant(variant_data) => {
352 let mut new_fields = variant_data.fields.to_vec();
354 new_fields.push(value);
355
356 let new_variant =
358 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
359
360 push(stack, new_variant)
361 }
362 _ => panic!("variant-append: expected Variant, got {:?}", variant_val),
363 }
364 }
365}
366
367#[unsafe(no_mangle)]
377pub unsafe extern "C" fn patch_seq_variant_last(stack: Stack) -> Stack {
378 unsafe {
379 let (stack, variant_val) = pop(stack);
380
381 match variant_val {
382 Value::Variant(variant_data) => {
383 if variant_data.fields.is_empty() {
384 panic!("variant-last: variant has no fields");
385 }
386
387 let last = variant_data.fields.last().unwrap().clone();
388 push(stack, last)
389 }
390 _ => panic!("variant-last: expected Variant, got {:?}", variant_val),
391 }
392 }
393}
394
395#[unsafe(no_mangle)]
406pub unsafe extern "C" fn patch_seq_variant_init(stack: Stack) -> Stack {
407 use crate::value::VariantData;
408
409 unsafe {
410 let (stack, variant_val) = pop(stack);
411
412 match variant_val {
413 Value::Variant(variant_data) => {
414 if variant_data.fields.is_empty() {
415 panic!("variant-init: variant has no fields");
416 }
417
418 let new_fields: Vec<Value> =
420 variant_data.fields[..variant_data.fields.len() - 1].to_vec();
421
422 let new_variant =
423 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
424
425 push(stack, new_variant)
426 }
427 _ => panic!("variant-init: expected Variant, got {:?}", variant_val),
428 }
429 }
430}
431
432pub use patch_seq_make_variant as make_variant;
434pub use patch_seq_variant_append as variant_append;
435pub use patch_seq_variant_field_at as variant_field_at;
436pub use patch_seq_variant_field_count as variant_field_count;
437pub use patch_seq_variant_init as variant_init;
438pub use patch_seq_variant_last as variant_last;
439pub use patch_seq_variant_tag as variant_tag;
440
441#[cfg(test)]
442mod tests {
443 use super::*;
444 use crate::seqstring::global_string;
445 use crate::value::VariantData;
446
447 #[test]
448 fn test_variant_field_count() {
449 unsafe {
450 let variant = Value::Variant(Box::new(VariantData::new(
452 0,
453 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
454 )));
455
456 let stack = std::ptr::null_mut();
457 let stack = push(stack, variant);
458 let stack = variant_field_count(stack);
459
460 let (stack, result) = pop(stack);
461 assert_eq!(result, Value::Int(3));
462 assert!(stack.is_null());
463 }
464 }
465
466 #[test]
467 fn test_variant_tag() {
468 unsafe {
469 let variant = Value::Variant(Box::new(VariantData::new(42, vec![Value::Int(10)])));
471
472 let stack = std::ptr::null_mut();
473 let stack = push(stack, variant);
474 let stack = variant_tag(stack);
475
476 let (stack, result) = pop(stack);
477 assert_eq!(result, Value::Int(42));
478 assert!(stack.is_null());
479 }
480 }
481
482 #[test]
483 fn test_variant_field_at() {
484 unsafe {
485 let str1 = global_string("hello".to_string());
486 let str2 = global_string("world".to_string());
487
488 let variant = Value::Variant(Box::new(VariantData::new(
490 0,
491 vec![
492 Value::String(str1.clone()),
493 Value::Int(42),
494 Value::String(str2.clone()),
495 ],
496 )));
497
498 let stack = std::ptr::null_mut();
500 let stack = push(stack, variant.clone());
501 let stack = push(stack, Value::Int(0));
502 let stack = variant_field_at(stack);
503
504 let (stack, result) = pop(stack);
505 assert_eq!(result, Value::String(str1.clone()));
506 assert!(stack.is_null());
507
508 let stack = push(stack, variant.clone());
510 let stack = push(stack, Value::Int(1));
511 let stack = variant_field_at(stack);
512
513 let (stack, result) = pop(stack);
514 assert_eq!(result, Value::Int(42));
515 assert!(stack.is_null());
516
517 let stack = push(stack, variant.clone());
519 let stack = push(stack, Value::Int(2));
520 let stack = variant_field_at(stack);
521
522 let (stack, result) = pop(stack);
523 assert_eq!(result, Value::String(str2));
524 assert!(stack.is_null());
525 }
526 }
527
528 #[test]
529 fn test_variant_field_count_empty() {
530 unsafe {
531 let variant = Value::Variant(Box::new(VariantData::new(0, vec![])));
533
534 let stack = std::ptr::null_mut();
535 let stack = push(stack, variant);
536 let stack = variant_field_count(stack);
537
538 let (stack, result) = pop(stack);
539 assert_eq!(result, Value::Int(0));
540 assert!(stack.is_null());
541 }
542 }
543
544 #[test]
545 fn test_make_variant_with_fields() {
546 unsafe {
547 let stack = std::ptr::null_mut();
550 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(3)); let stack = push(stack, Value::Int(42)); let stack = make_variant(stack);
557
558 let (stack, result) = pop(stack);
559
560 match result {
561 Value::Variant(v) => {
562 assert_eq!(v.tag, 42);
563 assert_eq!(v.fields.len(), 3);
564 assert_eq!(v.fields[0], Value::Int(10));
565 assert_eq!(v.fields[1], Value::Int(20));
566 assert_eq!(v.fields[2], Value::Int(30));
567 }
568 _ => panic!("Expected Variant"),
569 }
570 assert!(stack.is_null());
571 }
572 }
573
574 #[test]
575 fn test_make_variant_empty() {
576 unsafe {
577 let stack = std::ptr::null_mut();
580 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(0)); let stack = make_variant(stack);
584
585 let (stack, result) = pop(stack);
586
587 match result {
588 Value::Variant(v) => {
589 assert_eq!(v.tag, 0);
590 assert_eq!(v.fields.len(), 0);
591 }
592 _ => panic!("Expected Variant"),
593 }
594 assert!(stack.is_null());
595 }
596 }
597
598 #[test]
599 fn test_make_variant_with_mixed_types() {
600 unsafe {
601 let s = global_string("hello".to_string());
602
603 let stack = std::ptr::null_mut();
605 let stack = push(stack, Value::Int(42));
606 let stack = push(stack, Value::String(s.clone()));
607 let stack = push(stack, Value::Float(3.5));
608 let stack = push(stack, Value::Int(3)); let stack = push(stack, Value::Int(1)); let stack = make_variant(stack);
612
613 let (stack, result) = pop(stack);
614
615 match result {
616 Value::Variant(v) => {
617 assert_eq!(v.tag, 1);
618 assert_eq!(v.fields.len(), 3);
619 assert_eq!(v.fields[0], Value::Int(42));
620 assert_eq!(v.fields[1], Value::String(s));
621 assert_eq!(v.fields[2], Value::Float(3.5));
622 }
623 _ => panic!("Expected Variant"),
624 }
625 assert!(stack.is_null());
626 }
627 }
628
629 #[test]
630 fn test_variant_append() {
631 unsafe {
632 let stack = std::ptr::null_mut();
634 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(4)); let stack = make_variant(stack);
637
638 let stack = push(stack, Value::Int(42));
640 let stack = variant_append(stack);
641
642 let (stack, result) = pop(stack);
644 match result {
645 Value::Variant(v) => {
646 assert_eq!(v.tag, 4);
647 assert_eq!(v.fields.len(), 1);
648 assert_eq!(v.fields[0], Value::Int(42));
649 }
650 _ => panic!("Expected Variant"),
651 }
652 assert!(stack.is_null());
653 }
654 }
655
656 #[test]
657 fn test_variant_append_multiple() {
658 unsafe {
659 let stack = std::ptr::null_mut();
661 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(5)); let stack = make_variant(stack);
664
665 let key = global_string("name".to_string());
667 let stack = push(stack, Value::String(key.clone()));
668 let stack = variant_append(stack);
669
670 let val = global_string("John".to_string());
672 let stack = push(stack, Value::String(val.clone()));
673 let stack = variant_append(stack);
674
675 let (stack, result) = pop(stack);
677 match result {
678 Value::Variant(v) => {
679 assert_eq!(v.tag, 5);
680 assert_eq!(v.fields.len(), 2);
681 assert_eq!(v.fields[0], Value::String(key));
682 assert_eq!(v.fields[1], Value::String(val));
683 }
684 _ => panic!("Expected Variant"),
685 }
686 assert!(stack.is_null());
687 }
688 }
689
690 #[test]
691 fn test_variant_last() {
692 unsafe {
693 let variant = Value::Variant(Box::new(VariantData::new(
695 0,
696 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
697 )));
698
699 let stack = std::ptr::null_mut();
700 let stack = push(stack, variant);
701 let stack = variant_last(stack);
702
703 let (stack, result) = pop(stack);
704 assert_eq!(result, Value::Int(30));
705 assert!(stack.is_null());
706 }
707 }
708
709 #[test]
710 fn test_variant_init() {
711 unsafe {
712 let variant = Value::Variant(Box::new(VariantData::new(
714 42,
715 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
716 )));
717
718 let stack = std::ptr::null_mut();
719 let stack = push(stack, variant);
720 let stack = variant_init(stack);
721
722 let (stack, result) = pop(stack);
723 match result {
724 Value::Variant(v) => {
725 assert_eq!(v.tag, 42); assert_eq!(v.fields.len(), 2);
727 assert_eq!(v.fields[0], Value::Int(10));
728 assert_eq!(v.fields[1], Value::Int(20));
729 }
730 _ => panic!("Expected Variant"),
731 }
732 assert!(stack.is_null());
733 }
734 }
735
736 #[test]
737 fn test_variant_stack_operations() {
738 unsafe {
740 let stack = std::ptr::null_mut();
742 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(99)); let stack = make_variant(stack);
745
746 let stack = push(stack, Value::Int(10));
748 let stack = variant_append(stack);
749
750 let stack = push(stack, Value::Int(20));
752 let stack = variant_append(stack);
753
754 let (stack, variant) = pop(stack);
757 let stack = push(stack, variant.clone());
758 let stack = push(stack, variant);
759 let stack = variant_last(stack);
760 let (stack, top) = pop(stack);
761 assert_eq!(top, Value::Int(20));
762
763 let stack = variant_init(stack);
765
766 let (stack, variant) = pop(stack);
768 let stack = push(stack, variant.clone());
769 let stack = push(stack, variant);
770 let stack = variant_last(stack);
771 let (stack, top) = pop(stack);
772 assert_eq!(top, Value::Int(10));
773
774 let (stack, result) = pop(stack);
776 match result {
777 Value::Variant(v) => {
778 assert_eq!(v.fields.len(), 1);
779 assert_eq!(v.fields[0], Value::Int(10));
780 }
781 _ => panic!("Expected Variant"),
782 }
783 assert!(stack.is_null());
784 }
785 }
786}