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)]
178pub unsafe extern "C" fn patch_seq_variant_append(stack: Stack) -> Stack {
179 use crate::value::VariantData;
180
181 unsafe {
182 let (stack, value) = pop(stack);
184
185 let (stack, variant_val) = pop(stack);
187
188 match variant_val {
189 Value::Variant(variant_data) => {
190 let mut new_fields = variant_data.fields.to_vec();
192 new_fields.push(value);
193
194 let new_variant =
196 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
197
198 push(stack, new_variant)
199 }
200 _ => panic!("variant-append: expected Variant, got {:?}", variant_val),
201 }
202 }
203}
204
205#[unsafe(no_mangle)]
215pub unsafe extern "C" fn patch_seq_variant_last(stack: Stack) -> Stack {
216 unsafe {
217 let (stack, variant_val) = pop(stack);
218
219 match variant_val {
220 Value::Variant(variant_data) => {
221 if variant_data.fields.is_empty() {
222 panic!("variant-last: variant has no fields");
223 }
224
225 let last = variant_data.fields.last().unwrap().clone();
226 push(stack, last)
227 }
228 _ => panic!("variant-last: expected Variant, got {:?}", variant_val),
229 }
230 }
231}
232
233#[unsafe(no_mangle)]
244pub unsafe extern "C" fn patch_seq_variant_init(stack: Stack) -> Stack {
245 use crate::value::VariantData;
246
247 unsafe {
248 let (stack, variant_val) = pop(stack);
249
250 match variant_val {
251 Value::Variant(variant_data) => {
252 if variant_data.fields.is_empty() {
253 panic!("variant-init: variant has no fields");
254 }
255
256 let new_fields: Vec<Value> =
258 variant_data.fields[..variant_data.fields.len() - 1].to_vec();
259
260 let new_variant =
261 Value::Variant(Box::new(VariantData::new(variant_data.tag, new_fields)));
262
263 push(stack, new_variant)
264 }
265 _ => panic!("variant-init: expected Variant, got {:?}", variant_val),
266 }
267 }
268}
269
270pub use patch_seq_make_variant as make_variant;
272pub use patch_seq_variant_append as variant_append;
273pub use patch_seq_variant_field_at as variant_field_at;
274pub use patch_seq_variant_field_count as variant_field_count;
275pub use patch_seq_variant_init as variant_init;
276pub use patch_seq_variant_last as variant_last;
277pub use patch_seq_variant_tag as variant_tag;
278
279#[cfg(test)]
280mod tests {
281 use super::*;
282 use crate::seqstring::global_string;
283 use crate::value::VariantData;
284
285 #[test]
286 fn test_variant_field_count() {
287 unsafe {
288 let variant = Value::Variant(Box::new(VariantData::new(
290 0,
291 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
292 )));
293
294 let stack = std::ptr::null_mut();
295 let stack = push(stack, variant);
296 let stack = variant_field_count(stack);
297
298 let (stack, result) = pop(stack);
299 assert_eq!(result, Value::Int(3));
300 assert!(stack.is_null());
301 }
302 }
303
304 #[test]
305 fn test_variant_tag() {
306 unsafe {
307 let variant = Value::Variant(Box::new(VariantData::new(42, vec![Value::Int(10)])));
309
310 let stack = std::ptr::null_mut();
311 let stack = push(stack, variant);
312 let stack = variant_tag(stack);
313
314 let (stack, result) = pop(stack);
315 assert_eq!(result, Value::Int(42));
316 assert!(stack.is_null());
317 }
318 }
319
320 #[test]
321 fn test_variant_field_at() {
322 unsafe {
323 let str1 = global_string("hello".to_string());
324 let str2 = global_string("world".to_string());
325
326 let variant = Value::Variant(Box::new(VariantData::new(
328 0,
329 vec![
330 Value::String(str1.clone()),
331 Value::Int(42),
332 Value::String(str2.clone()),
333 ],
334 )));
335
336 let stack = std::ptr::null_mut();
338 let stack = push(stack, variant.clone());
339 let stack = push(stack, Value::Int(0));
340 let stack = variant_field_at(stack);
341
342 let (stack, result) = pop(stack);
343 assert_eq!(result, Value::String(str1.clone()));
344 assert!(stack.is_null());
345
346 let stack = push(stack, variant.clone());
348 let stack = push(stack, Value::Int(1));
349 let stack = variant_field_at(stack);
350
351 let (stack, result) = pop(stack);
352 assert_eq!(result, Value::Int(42));
353 assert!(stack.is_null());
354
355 let stack = push(stack, variant.clone());
357 let stack = push(stack, Value::Int(2));
358 let stack = variant_field_at(stack);
359
360 let (stack, result) = pop(stack);
361 assert_eq!(result, Value::String(str2));
362 assert!(stack.is_null());
363 }
364 }
365
366 #[test]
367 fn test_variant_field_count_empty() {
368 unsafe {
369 let variant = Value::Variant(Box::new(VariantData::new(0, vec![])));
371
372 let stack = std::ptr::null_mut();
373 let stack = push(stack, variant);
374 let stack = variant_field_count(stack);
375
376 let (stack, result) = pop(stack);
377 assert_eq!(result, Value::Int(0));
378 assert!(stack.is_null());
379 }
380 }
381
382 #[test]
383 fn test_make_variant_with_fields() {
384 unsafe {
385 let stack = std::ptr::null_mut();
388 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);
395
396 let (stack, result) = pop(stack);
397
398 match result {
399 Value::Variant(v) => {
400 assert_eq!(v.tag, 42);
401 assert_eq!(v.fields.len(), 3);
402 assert_eq!(v.fields[0], Value::Int(10));
403 assert_eq!(v.fields[1], Value::Int(20));
404 assert_eq!(v.fields[2], Value::Int(30));
405 }
406 _ => panic!("Expected Variant"),
407 }
408 assert!(stack.is_null());
409 }
410 }
411
412 #[test]
413 fn test_make_variant_empty() {
414 unsafe {
415 let stack = std::ptr::null_mut();
418 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(0)); let stack = make_variant(stack);
422
423 let (stack, result) = pop(stack);
424
425 match result {
426 Value::Variant(v) => {
427 assert_eq!(v.tag, 0);
428 assert_eq!(v.fields.len(), 0);
429 }
430 _ => panic!("Expected Variant"),
431 }
432 assert!(stack.is_null());
433 }
434 }
435
436 #[test]
437 fn test_make_variant_with_mixed_types() {
438 unsafe {
439 let s = global_string("hello".to_string());
440
441 let stack = std::ptr::null_mut();
443 let stack = push(stack, Value::Int(42));
444 let stack = push(stack, Value::String(s.clone()));
445 let stack = push(stack, Value::Float(3.5));
446 let stack = push(stack, Value::Int(3)); let stack = push(stack, Value::Int(1)); let stack = make_variant(stack);
450
451 let (stack, result) = pop(stack);
452
453 match result {
454 Value::Variant(v) => {
455 assert_eq!(v.tag, 1);
456 assert_eq!(v.fields.len(), 3);
457 assert_eq!(v.fields[0], Value::Int(42));
458 assert_eq!(v.fields[1], Value::String(s));
459 assert_eq!(v.fields[2], Value::Float(3.5));
460 }
461 _ => panic!("Expected Variant"),
462 }
463 assert!(stack.is_null());
464 }
465 }
466
467 #[test]
468 fn test_variant_append() {
469 unsafe {
470 let stack = std::ptr::null_mut();
472 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(4)); let stack = make_variant(stack);
475
476 let stack = push(stack, Value::Int(42));
478 let stack = variant_append(stack);
479
480 let (stack, result) = pop(stack);
482 match result {
483 Value::Variant(v) => {
484 assert_eq!(v.tag, 4);
485 assert_eq!(v.fields.len(), 1);
486 assert_eq!(v.fields[0], Value::Int(42));
487 }
488 _ => panic!("Expected Variant"),
489 }
490 assert!(stack.is_null());
491 }
492 }
493
494 #[test]
495 fn test_variant_append_multiple() {
496 unsafe {
497 let stack = std::ptr::null_mut();
499 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(5)); let stack = make_variant(stack);
502
503 let key = global_string("name".to_string());
505 let stack = push(stack, Value::String(key.clone()));
506 let stack = variant_append(stack);
507
508 let val = global_string("John".to_string());
510 let stack = push(stack, Value::String(val.clone()));
511 let stack = variant_append(stack);
512
513 let (stack, result) = pop(stack);
515 match result {
516 Value::Variant(v) => {
517 assert_eq!(v.tag, 5);
518 assert_eq!(v.fields.len(), 2);
519 assert_eq!(v.fields[0], Value::String(key));
520 assert_eq!(v.fields[1], Value::String(val));
521 }
522 _ => panic!("Expected Variant"),
523 }
524 assert!(stack.is_null());
525 }
526 }
527
528 #[test]
529 fn test_variant_last() {
530 unsafe {
531 let variant = Value::Variant(Box::new(VariantData::new(
533 0,
534 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
535 )));
536
537 let stack = std::ptr::null_mut();
538 let stack = push(stack, variant);
539 let stack = variant_last(stack);
540
541 let (stack, result) = pop(stack);
542 assert_eq!(result, Value::Int(30));
543 assert!(stack.is_null());
544 }
545 }
546
547 #[test]
548 fn test_variant_init() {
549 unsafe {
550 let variant = Value::Variant(Box::new(VariantData::new(
552 42,
553 vec![Value::Int(10), Value::Int(20), Value::Int(30)],
554 )));
555
556 let stack = std::ptr::null_mut();
557 let stack = push(stack, variant);
558 let stack = variant_init(stack);
559
560 let (stack, result) = pop(stack);
561 match result {
562 Value::Variant(v) => {
563 assert_eq!(v.tag, 42); assert_eq!(v.fields.len(), 2);
565 assert_eq!(v.fields[0], Value::Int(10));
566 assert_eq!(v.fields[1], Value::Int(20));
567 }
568 _ => panic!("Expected Variant"),
569 }
570 assert!(stack.is_null());
571 }
572 }
573
574 #[test]
575 fn test_variant_stack_operations() {
576 unsafe {
578 let stack = std::ptr::null_mut();
580 let stack = push(stack, Value::Int(0)); let stack = push(stack, Value::Int(99)); let stack = make_variant(stack);
583
584 let stack = push(stack, Value::Int(10));
586 let stack = variant_append(stack);
587
588 let stack = push(stack, Value::Int(20));
590 let stack = variant_append(stack);
591
592 let (stack, variant) = pop(stack);
595 let stack = push(stack, variant.clone());
596 let stack = push(stack, variant);
597 let stack = variant_last(stack);
598 let (stack, top) = pop(stack);
599 assert_eq!(top, Value::Int(20));
600
601 let stack = variant_init(stack);
603
604 let (stack, variant) = pop(stack);
606 let stack = push(stack, variant.clone());
607 let stack = push(stack, variant);
608 let stack = variant_last(stack);
609 let (stack, top) = pop(stack);
610 assert_eq!(top, Value::Int(10));
611
612 let (stack, result) = pop(stack);
614 match result {
615 Value::Variant(v) => {
616 assert_eq!(v.fields.len(), 1);
617 assert_eq!(v.fields[0], Value::Int(10));
618 }
619 _ => panic!("Expected Variant"),
620 }
621 assert!(stack.is_null());
622 }
623 }
624}