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)]
109pub unsafe extern "C" fn patch_seq_make_variant_0(stack: Stack) -> Stack {
110 use crate::value::VariantData;
111
112 unsafe {
113 let (stack, tag_val) = pop(stack);
114 let tag = match tag_val {
115 Value::Int(t) => {
116 if t < 0 {
117 panic!("make-variant-0: tag cannot be negative: {}", t);
118 }
119 t as u32
120 }
121 _ => panic!("make-variant-0: expected Int (tag), got {:?}", tag_val),
122 };
123
124 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![])));
125 push(stack, variant)
126 }
127}
128
129#[unsafe(no_mangle)]
136pub unsafe extern "C" fn patch_seq_make_variant_1(stack: Stack) -> Stack {
137 use crate::value::VariantData;
138
139 unsafe {
140 let (stack, tag_val) = pop(stack);
141 let tag = match tag_val {
142 Value::Int(t) => {
143 if t < 0 {
144 panic!("make-variant-1: tag cannot be negative: {}", t);
145 }
146 t as u32
147 }
148 _ => panic!("make-variant-1: expected Int (tag), got {:?}", tag_val),
149 };
150
151 let (stack, field1) = pop(stack);
152 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![field1])));
153 push(stack, variant)
154 }
155}
156
157#[unsafe(no_mangle)]
164pub unsafe extern "C" fn patch_seq_make_variant_2(stack: Stack) -> Stack {
165 use crate::value::VariantData;
166
167 unsafe {
168 let (stack, tag_val) = pop(stack);
169 let tag = match tag_val {
170 Value::Int(t) => {
171 if t < 0 {
172 panic!("make-variant-2: tag cannot be negative: {}", t);
173 }
174 t as u32
175 }
176 _ => panic!("make-variant-2: expected Int (tag), got {:?}", tag_val),
177 };
178
179 let (stack, field2) = pop(stack);
180 let (stack, field1) = pop(stack);
181 let variant = Value::Variant(Box::new(VariantData::new(tag, vec![field1, field2])));
182 push(stack, variant)
183 }
184}
185
186#[unsafe(no_mangle)]
193pub unsafe extern "C" fn patch_seq_make_variant_3(stack: Stack) -> Stack {
194 use crate::value::VariantData;
195
196 unsafe {
197 let (stack, tag_val) = pop(stack);
198 let tag = match tag_val {
199 Value::Int(t) => {
200 if t < 0 {
201 panic!("make-variant-3: tag cannot be negative: {}", t);
202 }
203 t as u32
204 }
205 _ => panic!("make-variant-3: expected Int (tag), got {:?}", tag_val),
206 };
207
208 let (stack, field3) = pop(stack);
209 let (stack, field2) = pop(stack);
210 let (stack, field1) = pop(stack);
211 let variant = Value::Variant(Box::new(VariantData::new(
212 tag,
213 vec![field1, field2, field3],
214 )));
215 push(stack, variant)
216 }
217}
218
219#[unsafe(no_mangle)]
226pub unsafe extern "C" fn patch_seq_make_variant_4(stack: Stack) -> Stack {
227 use crate::value::VariantData;
228
229 unsafe {
230 let (stack, tag_val) = pop(stack);
231 let tag = match tag_val {
232 Value::Int(t) => {
233 if t < 0 {
234 panic!("make-variant-4: tag cannot be negative: {}", t);
235 }
236 t as u32
237 }
238 _ => panic!("make-variant-4: expected Int (tag), got {:?}", tag_val),
239 };
240
241 let (stack, field4) = pop(stack);
242 let (stack, field3) = pop(stack);
243 let (stack, field2) = pop(stack);
244 let (stack, field1) = pop(stack);
245 let variant = Value::Variant(Box::new(VariantData::new(
246 tag,
247 vec![field1, field2, field3, field4],
248 )));
249 push(stack, variant)
250 }
251}
252
253pub use patch_seq_make_variant_0 as make_variant_0;
255pub use patch_seq_make_variant_1 as make_variant_1;
256pub use patch_seq_make_variant_2 as make_variant_2;
257pub use patch_seq_make_variant_3 as make_variant_3;
258pub use patch_seq_make_variant_4 as make_variant_4;
259
260#[unsafe(no_mangle)]
274pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
275 use crate::value::VariantData;
276
277 unsafe {
278 let (stack, value) = pop(stack);
280
281 let (stack, variant_val) = pop(stack);
283
284 match variant_val {
285 Value::Variant(variant_data) => {
286 let mut new_fields = variant_data.fields.to_vec();
288 new_fields.push(value);
289
290 let new_variant =
292 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
293
294 push(stack, new_variant)
295 }
296 _ => panic!("variant-append: expected Variant, got {:?}", variant_val),
297 }
298 }
299}
300
301#[unsafe(no_mangle)]
311pub unsafe extern "C" fn patch_seq_variant_last(stack: Stack) -> Stack {
312 unsafe {
313 let (stack, variant_val) = pop(stack);
314
315 match variant_val {
316 Value::Variant(variant_data) => {
317 if variant_data.fields.is_empty() {
318 panic!("variant-last: variant has no fields");
319 }
320
321 let last = variant_data.fields.last().unwrap().clone();
322 push(stack, last)
323 }
324 _ => panic!("variant-last: expected Variant, got {:?}", variant_val),
325 }
326 }
327}
328
329#[unsafe(no_mangle)]
340pub unsafe extern "C" fn patch_seq_variant_init(stack: Stack) -> Stack {
341 use crate::value::VariantData;
342
343 unsafe {
344 let (stack, variant_val) = pop(stack);
345
346 match variant_val {
347 Value::Variant(variant_data) => {
348 if variant_data.fields.is_empty() {
349 panic!("variant-init: variant has no fields");
350 }
351
352 let new_fields: Vec<Value> =
354 variant_data.fields[..variant_data.fields.len() - 1].to_vec();
355
356 let new_variant =
357 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
358
359 push(stack, new_variant)
360 }
361 _ => panic!("variant-init: expected Variant, got {:?}", variant_val),
362 }
363 }
364}
365
366#[unsafe(no_mangle)]
379pub unsafe extern "C" fn patch_seq_unpack_variant(stack: Stack, field_count: i64) -> Stack {
380 unsafe {
381 let (mut stack, variant_val) = pop(stack);
382
383 match variant_val {
384 Value::Variant(variant_data) => {
385 let count = field_count as usize;
386 if count > variant_data.fields.len() {
387 panic!(
388 "unpack-variant: requested {} fields but variant only has {}",
389 count,
390 variant_data.fields.len()
391 );
392 }
393
394 for i in 0..count {
396 stack = push(stack, variant_data.fields[i].clone());
397 }
398
399 stack
400 }
401 _ => panic!("unpack-variant: expected Variant, got {:?}", variant_val),
402 }
403 }
404}
405
406pub use patch_seq_unpack_variant as unpack_variant;
408pub use patch_seq_variant_append as variant_append;
409pub use patch_seq_variant_field_at as variant_field_at;
410pub use patch_seq_variant_field_count as variant_field_count;
411pub use patch_seq_variant_init as variant_init;
412pub use patch_seq_variant_last as variant_last;
413pub use patch_seq_variant_tag as variant_tag;
414
415#[cfg(test)]
416mod tests {
417 use super::*;
418 use crate::seqstring::global_string;
419 use crate::value::VariantData;
420
421 #[test]
422 fn test_variant_field_count() {
423 unsafe {
424 let variant = Value::Variant(Box::new(VariantData::new(
426 0,
427 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
428 )));
429
430 let stack = std::ptr::null_mut();
431 let stack = push(stack, variant);
432 let stack = variant_field_count(stack);
433
434 let (stack, result) = pop(stack);
435 assert_eq!(result, Value::Int(3));
436 assert!(stack.is_null());
437 }
438 }
439
440 #[test]
441 fn test_variant_tag() {
442 unsafe {
443 let variant = Value::Variant(Box::new(VariantData::new(42, vec![Value::Int(10)])));
445
446 let stack = std::ptr::null_mut();
447 let stack = push(stack, variant);
448 let stack = variant_tag(stack);
449
450 let (stack, result) = pop(stack);
451 assert_eq!(result, Value::Int(42));
452 assert!(stack.is_null());
453 }
454 }
455
456 #[test]
457 fn test_variant_field_at() {
458 unsafe {
459 let str1 = global_string("hello".to_string());
460 let str2 = global_string("world".to_string());
461
462 let variant = Value::Variant(Box::new(VariantData::new(
464 0,
465 vec![
466 Value::String(str1.clone()),
467 Value::Int(42),
468 Value::String(str2.clone()),
469 ],
470 )));
471
472 let stack = std::ptr::null_mut();
474 let stack = push(stack, variant.clone());
475 let stack = push(stack, Value::Int(0));
476 let stack = variant_field_at(stack);
477
478 let (stack, result) = pop(stack);
479 assert_eq!(result, Value::String(str1.clone()));
480 assert!(stack.is_null());
481
482 let stack = push(stack, variant.clone());
484 let stack = push(stack, Value::Int(1));
485 let stack = variant_field_at(stack);
486
487 let (stack, result) = pop(stack);
488 assert_eq!(result, Value::Int(42));
489 assert!(stack.is_null());
490
491 let stack = push(stack, variant.clone());
493 let stack = push(stack, Value::Int(2));
494 let stack = variant_field_at(stack);
495
496 let (stack, result) = pop(stack);
497 assert_eq!(result, Value::String(str2));
498 assert!(stack.is_null());
499 }
500 }
501
502 #[test]
503 fn test_variant_field_count_empty() {
504 unsafe {
505 let variant = Value::Variant(Box::new(VariantData::new(0, vec![])));
507
508 let stack = std::ptr::null_mut();
509 let stack = push(stack, variant);
510 let stack = variant_field_count(stack);
511
512 let (stack, result) = pop(stack);
513 assert_eq!(result, Value::Int(0));
514 assert!(stack.is_null());
515 }
516 }
517
518 #[test]
519 fn test_make_variant_with_fields() {
520 unsafe {
521 let stack = std::ptr::null_mut();
524 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);
530
531 let (stack, result) = pop(stack);
532
533 match result {
534 Value::Variant(v) => {
535 assert_eq!(v.tag, 42);
536 assert_eq!(v.fields.len(), 3);
537 assert_eq!(v.fields[0], Value::Int(10));
538 assert_eq!(v.fields[1], Value::Int(20));
539 assert_eq!(v.fields[2], Value::Int(30));
540 }
541 _ => panic!("Expected Variant"),
542 }
543 assert!(stack.is_null());
544 }
545 }
546
547 #[test]
548 fn test_make_variant_empty() {
549 unsafe {
550 let stack = std::ptr::null_mut();
553 let stack = push(stack, Value::Int(0)); let stack = make_variant_0(stack);
556
557 let (stack, result) = pop(stack);
558
559 match result {
560 Value::Variant(v) => {
561 assert_eq!(v.tag, 0);
562 assert_eq!(v.fields.len(), 0);
563 }
564 _ => panic!("Expected Variant"),
565 }
566 assert!(stack.is_null());
567 }
568 }
569
570 #[test]
571 fn test_make_variant_with_mixed_types() {
572 unsafe {
573 let s = global_string("hello".to_string());
574
575 let stack = std::ptr::null_mut();
577 let stack = push(stack, Value::Int(42));
578 let stack = push(stack, Value::String(s.clone()));
579 let stack = push(stack, Value::Float(3.5));
580 let stack = push(stack, Value::Int(1)); let stack = make_variant_3(stack);
583
584 let (stack, result) = pop(stack);
585
586 match result {
587 Value::Variant(v) => {
588 assert_eq!(v.tag, 1);
589 assert_eq!(v.fields.len(), 3);
590 assert_eq!(v.fields[0], Value::Int(42));
591 assert_eq!(v.fields[1], Value::String(s));
592 assert_eq!(v.fields[2], Value::Float(3.5));
593 }
594 _ => panic!("Expected Variant"),
595 }
596 assert!(stack.is_null());
597 }
598 }
599
600 #[test]
601 fn test_variant_append() {
602 unsafe {
603 let stack = std::ptr::null_mut();
605 let stack = push(stack, Value::Int(4)); let stack = make_variant_0(stack);
607
608 let stack = push(stack, Value::Int(42));
610 let stack = variant_append(stack);
611
612 let (stack, result) = pop(stack);
614 match result {
615 Value::Variant(v) => {
616 assert_eq!(v.tag, 4);
617 assert_eq!(v.fields.len(), 1);
618 assert_eq!(v.fields[0], Value::Int(42));
619 }
620 _ => panic!("Expected Variant"),
621 }
622 assert!(stack.is_null());
623 }
624 }
625
626 #[test]
627 fn test_variant_append_multiple() {
628 unsafe {
629 let stack = std::ptr::null_mut();
631 let stack = push(stack, Value::Int(5)); let stack = make_variant_0(stack);
633
634 let key = global_string("name".to_string());
636 let stack = push(stack, Value::String(key.clone()));
637 let stack = variant_append(stack);
638
639 let val = global_string("John".to_string());
641 let stack = push(stack, Value::String(val.clone()));
642 let stack = variant_append(stack);
643
644 let (stack, result) = pop(stack);
646 match result {
647 Value::Variant(v) => {
648 assert_eq!(v.tag, 5);
649 assert_eq!(v.fields.len(), 2);
650 assert_eq!(v.fields[0], Value::String(key));
651 assert_eq!(v.fields[1], Value::String(val));
652 }
653 _ => panic!("Expected Variant"),
654 }
655 assert!(stack.is_null());
656 }
657 }
658
659 #[test]
660 fn test_variant_last() {
661 unsafe {
662 let variant = Value::Variant(Box::new(VariantData::new(
664 0,
665 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
666 )));
667
668 let stack = std::ptr::null_mut();
669 let stack = push(stack, variant);
670 let stack = variant_last(stack);
671
672 let (stack, result) = pop(stack);
673 assert_eq!(result, Value::Int(30));
674 assert!(stack.is_null());
675 }
676 }
677
678 #[test]
679 fn test_variant_init() {
680 unsafe {
681 let variant = Value::Variant(Box::new(VariantData::new(
683 42,
684 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
685 )));
686
687 let stack = std::ptr::null_mut();
688 let stack = push(stack, variant);
689 let stack = variant_init(stack);
690
691 let (stack, result) = pop(stack);
692 match result {
693 Value::Variant(v) => {
694 assert_eq!(v.tag, 42); assert_eq!(v.fields.len(), 2);
696 assert_eq!(v.fields[0], Value::Int(10));
697 assert_eq!(v.fields[1], Value::Int(20));
698 }
699 _ => panic!("Expected Variant"),
700 }
701 assert!(stack.is_null());
702 }
703 }
704
705 #[test]
706 fn test_variant_stack_operations() {
707 unsafe {
709 let stack = std::ptr::null_mut();
711 let stack = push(stack, Value::Int(99)); let stack = make_variant_0(stack);
713
714 let stack = push(stack, Value::Int(10));
716 let stack = variant_append(stack);
717
718 let stack = push(stack, Value::Int(20));
720 let stack = variant_append(stack);
721
722 let (stack, variant) = pop(stack);
725 let stack = push(stack, variant.clone());
726 let stack = push(stack, variant);
727 let stack = variant_last(stack);
728 let (stack, top) = pop(stack);
729 assert_eq!(top, Value::Int(20));
730
731 let stack = variant_init(stack);
733
734 let (stack, variant) = pop(stack);
736 let stack = push(stack, variant.clone());
737 let stack = push(stack, variant);
738 let stack = variant_last(stack);
739 let (stack, top) = pop(stack);
740 assert_eq!(top, Value::Int(10));
741
742 let (stack, result) = pop(stack);
744 match result {
745 Value::Variant(v) => {
746 assert_eq!(v.fields.len(), 1);
747 assert_eq!(v.fields[0], Value::Int(10));
748 }
749 _ => panic!("Expected Variant"),
750 }
751 assert!(stack.is_null());
752 }
753 }
754}