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
366pub use patch_seq_variant_append as variant_append;
368pub use patch_seq_variant_field_at as variant_field_at;
369pub use patch_seq_variant_field_count as variant_field_count;
370pub use patch_seq_variant_init as variant_init;
371pub use patch_seq_variant_last as variant_last;
372pub use patch_seq_variant_tag as variant_tag;
373
374#[cfg(test)]
375mod tests {
376 use super::*;
377 use crate::seqstring::global_string;
378 use crate::value::VariantData;
379
380 #[test]
381 fn test_variant_field_count() {
382 unsafe {
383 let variant = Value::Variant(Box::new(VariantData::new(
385 0,
386 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
387 )));
388
389 let stack = std::ptr::null_mut();
390 let stack = push(stack, variant);
391 let stack = variant_field_count(stack);
392
393 let (stack, result) = pop(stack);
394 assert_eq!(result, Value::Int(3));
395 assert!(stack.is_null());
396 }
397 }
398
399 #[test]
400 fn test_variant_tag() {
401 unsafe {
402 let variant = Value::Variant(Box::new(VariantData::new(42, vec![Value::Int(10)])));
404
405 let stack = std::ptr::null_mut();
406 let stack = push(stack, variant);
407 let stack = variant_tag(stack);
408
409 let (stack, result) = pop(stack);
410 assert_eq!(result, Value::Int(42));
411 assert!(stack.is_null());
412 }
413 }
414
415 #[test]
416 fn test_variant_field_at() {
417 unsafe {
418 let str1 = global_string("hello".to_string());
419 let str2 = global_string("world".to_string());
420
421 let variant = Value::Variant(Box::new(VariantData::new(
423 0,
424 vec![
425 Value::String(str1.clone()),
426 Value::Int(42),
427 Value::String(str2.clone()),
428 ],
429 )));
430
431 let stack = std::ptr::null_mut();
433 let stack = push(stack, variant.clone());
434 let stack = push(stack, Value::Int(0));
435 let stack = variant_field_at(stack);
436
437 let (stack, result) = pop(stack);
438 assert_eq!(result, Value::String(str1.clone()));
439 assert!(stack.is_null());
440
441 let stack = push(stack, variant.clone());
443 let stack = push(stack, Value::Int(1));
444 let stack = variant_field_at(stack);
445
446 let (stack, result) = pop(stack);
447 assert_eq!(result, Value::Int(42));
448 assert!(stack.is_null());
449
450 let stack = push(stack, variant.clone());
452 let stack = push(stack, Value::Int(2));
453 let stack = variant_field_at(stack);
454
455 let (stack, result) = pop(stack);
456 assert_eq!(result, Value::String(str2));
457 assert!(stack.is_null());
458 }
459 }
460
461 #[test]
462 fn test_variant_field_count_empty() {
463 unsafe {
464 let variant = Value::Variant(Box::new(VariantData::new(0, vec![])));
466
467 let stack = std::ptr::null_mut();
468 let stack = push(stack, variant);
469 let stack = variant_field_count(stack);
470
471 let (stack, result) = pop(stack);
472 assert_eq!(result, Value::Int(0));
473 assert!(stack.is_null());
474 }
475 }
476
477 #[test]
478 fn test_make_variant_with_fields() {
479 unsafe {
480 let stack = std::ptr::null_mut();
483 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);
489
490 let (stack, result) = pop(stack);
491
492 match result {
493 Value::Variant(v) => {
494 assert_eq!(v.tag, 42);
495 assert_eq!(v.fields.len(), 3);
496 assert_eq!(v.fields[0], Value::Int(10));
497 assert_eq!(v.fields[1], Value::Int(20));
498 assert_eq!(v.fields[2], Value::Int(30));
499 }
500 _ => panic!("Expected Variant"),
501 }
502 assert!(stack.is_null());
503 }
504 }
505
506 #[test]
507 fn test_make_variant_empty() {
508 unsafe {
509 let stack = std::ptr::null_mut();
512 let stack = push(stack, Value::Int(0)); let stack = make_variant_0(stack);
515
516 let (stack, result) = pop(stack);
517
518 match result {
519 Value::Variant(v) => {
520 assert_eq!(v.tag, 0);
521 assert_eq!(v.fields.len(), 0);
522 }
523 _ => panic!("Expected Variant"),
524 }
525 assert!(stack.is_null());
526 }
527 }
528
529 #[test]
530 fn test_make_variant_with_mixed_types() {
531 unsafe {
532 let s = global_string("hello".to_string());
533
534 let stack = std::ptr::null_mut();
536 let stack = push(stack, Value::Int(42));
537 let stack = push(stack, Value::String(s.clone()));
538 let stack = push(stack, Value::Float(3.5));
539 let stack = push(stack, Value::Int(1)); let stack = make_variant_3(stack);
542
543 let (stack, result) = pop(stack);
544
545 match result {
546 Value::Variant(v) => {
547 assert_eq!(v.tag, 1);
548 assert_eq!(v.fields.len(), 3);
549 assert_eq!(v.fields[0], Value::Int(42));
550 assert_eq!(v.fields[1], Value::String(s));
551 assert_eq!(v.fields[2], Value::Float(3.5));
552 }
553 _ => panic!("Expected Variant"),
554 }
555 assert!(stack.is_null());
556 }
557 }
558
559 #[test]
560 fn test_variant_append() {
561 unsafe {
562 let stack = std::ptr::null_mut();
564 let stack = push(stack, Value::Int(4)); let stack = make_variant_0(stack);
566
567 let stack = push(stack, Value::Int(42));
569 let stack = variant_append(stack);
570
571 let (stack, result) = pop(stack);
573 match result {
574 Value::Variant(v) => {
575 assert_eq!(v.tag, 4);
576 assert_eq!(v.fields.len(), 1);
577 assert_eq!(v.fields[0], Value::Int(42));
578 }
579 _ => panic!("Expected Variant"),
580 }
581 assert!(stack.is_null());
582 }
583 }
584
585 #[test]
586 fn test_variant_append_multiple() {
587 unsafe {
588 let stack = std::ptr::null_mut();
590 let stack = push(stack, Value::Int(5)); let stack = make_variant_0(stack);
592
593 let key = global_string("name".to_string());
595 let stack = push(stack, Value::String(key.clone()));
596 let stack = variant_append(stack);
597
598 let val = global_string("John".to_string());
600 let stack = push(stack, Value::String(val.clone()));
601 let stack = variant_append(stack);
602
603 let (stack, result) = pop(stack);
605 match result {
606 Value::Variant(v) => {
607 assert_eq!(v.tag, 5);
608 assert_eq!(v.fields.len(), 2);
609 assert_eq!(v.fields[0], Value::String(key));
610 assert_eq!(v.fields[1], Value::String(val));
611 }
612 _ => panic!("Expected Variant"),
613 }
614 assert!(stack.is_null());
615 }
616 }
617
618 #[test]
619 fn test_variant_last() {
620 unsafe {
621 let variant = Value::Variant(Box::new(VariantData::new(
623 0,
624 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
625 )));
626
627 let stack = std::ptr::null_mut();
628 let stack = push(stack, variant);
629 let stack = variant_last(stack);
630
631 let (stack, result) = pop(stack);
632 assert_eq!(result, Value::Int(30));
633 assert!(stack.is_null());
634 }
635 }
636
637 #[test]
638 fn test_variant_init() {
639 unsafe {
640 let variant = Value::Variant(Box::new(VariantData::new(
642 42,
643 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
644 )));
645
646 let stack = std::ptr::null_mut();
647 let stack = push(stack, variant);
648 let stack = variant_init(stack);
649
650 let (stack, result) = pop(stack);
651 match result {
652 Value::Variant(v) => {
653 assert_eq!(v.tag, 42); assert_eq!(v.fields.len(), 2);
655 assert_eq!(v.fields[0], Value::Int(10));
656 assert_eq!(v.fields[1], Value::Int(20));
657 }
658 _ => panic!("Expected Variant"),
659 }
660 assert!(stack.is_null());
661 }
662 }
663
664 #[test]
665 fn test_variant_stack_operations() {
666 unsafe {
668 let stack = std::ptr::null_mut();
670 let stack = push(stack, Value::Int(99)); let stack = make_variant_0(stack);
672
673 let stack = push(stack, Value::Int(10));
675 let stack = variant_append(stack);
676
677 let stack = push(stack, Value::Int(20));
679 let stack = variant_append(stack);
680
681 let (stack, variant) = pop(stack);
684 let stack = push(stack, variant.clone());
685 let stack = push(stack, variant);
686 let stack = variant_last(stack);
687 let (stack, top) = pop(stack);
688 assert_eq!(top, Value::Int(20));
689
690 let stack = variant_init(stack);
692
693 let (stack, variant) = pop(stack);
695 let stack = push(stack, variant.clone());
696 let stack = push(stack, variant);
697 let stack = variant_last(stack);
698 let (stack, top) = pop(stack);
699 assert_eq!(top, Value::Int(10));
700
701 let (stack, result) = pop(stack);
703 match result {
704 Value::Variant(v) => {
705 assert_eq!(v.fields.len(), 1);
706 assert_eq!(v.fields[0], Value::Int(10));
707 }
708 _ => panic!("Expected Variant"),
709 }
710 assert!(stack.is_null());
711 }
712 }
713}