1use crate::stack::{Stack, pop, push};
37use crate::value::{MapKey, Value, VariantData};
38use std::sync::Arc;
39
40#[unsafe(no_mangle)]
47pub unsafe extern "C" fn patch_seq_make_map(stack: Stack) -> Stack {
48 unsafe { push(stack, Value::Map(Box::default())) }
49}
50
51#[unsafe(no_mangle)]
60pub unsafe extern "C" fn patch_seq_map_get(stack: Stack) -> Stack {
61 unsafe {
62 let (stack, key_val) = pop(stack);
64 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
65 panic!(
66 "map-get: key must be Int, String, or Bool, got {:?}",
67 key_val
68 )
69 });
70
71 let (stack, map_val) = pop(stack);
73 let map = match map_val {
74 Value::Map(m) => m,
75 _ => panic!("map-get: expected Map, got {:?}", map_val),
76 };
77
78 let value = map
80 .get(&key)
81 .unwrap_or_else(|| panic!("map-get: key {:?} not found", key))
82 .clone();
83
84 push(stack, value)
85 }
86}
87
88#[unsafe(no_mangle)]
98pub unsafe extern "C" fn patch_seq_map_get_safe(stack: Stack) -> Stack {
99 unsafe {
100 let (stack, key_val) = pop(stack);
102 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
103 panic!(
104 "map-get-safe: key must be Int, String, or Bool, got {:?}",
105 key_val
106 )
107 });
108
109 let (stack, map_val) = pop(stack);
111 let map = match map_val {
112 Value::Map(m) => m,
113 _ => panic!("map-get-safe: expected Map, got {:?}", map_val),
114 };
115
116 match map.get(&key) {
118 Some(value) => {
119 let stack = push(stack, value.clone());
120 push(stack, Value::Int(1))
121 }
122 None => {
123 let stack = push(stack, Value::Int(0)); push(stack, Value::Int(0)) }
126 }
127 }
128}
129
130#[unsafe(no_mangle)]
140pub unsafe extern "C" fn patch_seq_map_set(stack: Stack) -> Stack {
141 unsafe {
142 let (stack, value) = pop(stack);
144
145 let (stack, key_val) = pop(stack);
147 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
148 panic!(
149 "map-set: key must be Int, String, or Bool, got {:?}",
150 key_val
151 )
152 });
153
154 let (stack, map_val) = pop(stack);
156 let mut map = match map_val {
157 Value::Map(m) => *m,
158 _ => panic!("map-set: expected Map, got {:?}", map_val),
159 };
160
161 map.insert(key, value);
163
164 push(stack, Value::Map(Box::new(map)))
165 }
166}
167
168#[unsafe(no_mangle)]
178pub unsafe extern "C" fn patch_seq_map_has(stack: Stack) -> Stack {
179 unsafe {
180 let (stack, key_val) = pop(stack);
182 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
183 panic!(
184 "map-has?: key must be Int, String, or Bool, got {:?}",
185 key_val
186 )
187 });
188
189 let (stack, map_val) = pop(stack);
191 let map = match map_val {
192 Value::Map(m) => m,
193 _ => panic!("map-has?: expected Map, got {:?}", map_val),
194 };
195
196 let has_key = if map.contains_key(&key) { 1i64 } else { 0i64 };
197 push(stack, Value::Int(has_key))
198 }
199}
200
201#[unsafe(no_mangle)]
212pub unsafe extern "C" fn patch_seq_map_remove(stack: Stack) -> Stack {
213 unsafe {
214 let (stack, key_val) = pop(stack);
216 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
217 panic!(
218 "map-remove: key must be Int, String, or Bool, got {:?}",
219 key_val
220 )
221 });
222
223 let (stack, map_val) = pop(stack);
225 let mut map = match map_val {
226 Value::Map(m) => *m,
227 _ => panic!("map-remove: expected Map, got {:?}", map_val),
228 };
229
230 map.remove(&key);
232
233 push(stack, Value::Map(Box::new(map)))
234 }
235}
236
237#[unsafe(no_mangle)]
247pub unsafe extern "C" fn patch_seq_map_keys(stack: Stack) -> Stack {
248 unsafe {
249 let (stack, map_val) = pop(stack);
250 let map = match map_val {
251 Value::Map(m) => m,
252 _ => panic!("map-keys: expected Map, got {:?}", map_val),
253 };
254
255 let keys: Vec<Value> = map.keys().map(|k| k.to_value()).collect();
256 let variant = Value::Variant(Arc::new(VariantData::new(0, keys)));
257 push(stack, variant)
258 }
259}
260
261#[unsafe(no_mangle)]
271pub unsafe extern "C" fn patch_seq_map_values(stack: Stack) -> Stack {
272 unsafe {
273 let (stack, map_val) = pop(stack);
274 let map = match map_val {
275 Value::Map(m) => m,
276 _ => panic!("map-values: expected Map, got {:?}", map_val),
277 };
278
279 let values: Vec<Value> = map.values().cloned().collect();
280 let variant = Value::Variant(Arc::new(VariantData::new(0, values)));
281 push(stack, variant)
282 }
283}
284
285#[unsafe(no_mangle)]
292pub unsafe extern "C" fn patch_seq_map_size(stack: Stack) -> Stack {
293 unsafe {
294 let (stack, map_val) = pop(stack);
295 let map = match map_val {
296 Value::Map(m) => m,
297 _ => panic!("map-size: expected Map, got {:?}", map_val),
298 };
299
300 push(stack, Value::Int(map.len() as i64))
301 }
302}
303
304#[unsafe(no_mangle)]
313pub unsafe extern "C" fn patch_seq_map_empty(stack: Stack) -> Stack {
314 unsafe {
315 let (stack, map_val) = pop(stack);
316 let map = match map_val {
317 Value::Map(m) => m,
318 _ => panic!("map-empty?: expected Map, got {:?}", map_val),
319 };
320
321 let is_empty = if map.is_empty() { 1i64 } else { 0i64 };
322 push(stack, Value::Int(is_empty))
323 }
324}
325
326pub use patch_seq_make_map as make_map;
328pub use patch_seq_map_empty as map_empty;
329pub use patch_seq_map_get as map_get;
330pub use patch_seq_map_get_safe as map_get_safe;
331pub use patch_seq_map_has as map_has;
332pub use patch_seq_map_keys as map_keys;
333pub use patch_seq_map_remove as map_remove;
334pub use patch_seq_map_set as map_set;
335pub use patch_seq_map_size as map_size;
336pub use patch_seq_map_values as map_values;
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341
342 #[test]
343 fn test_make_map() {
344 unsafe {
345 let stack = std::ptr::null_mut();
346 let stack = make_map(stack);
347
348 let (stack, result) = pop(stack);
349 match result {
350 Value::Map(m) => assert!(m.is_empty()),
351 _ => panic!("Expected Map"),
352 }
353 assert!(stack.is_null());
354 }
355 }
356
357 #[test]
358 fn test_map_set_and_get() {
359 unsafe {
360 let stack = std::ptr::null_mut();
361 let stack = make_map(stack);
362 let stack = push(stack, Value::String("name".into()));
363 let stack = push(stack, Value::String("Alice".into()));
364 let stack = map_set(stack);
365
366 let stack = push(stack, Value::String("name".into()));
368 let stack = map_get(stack);
369
370 let (stack, result) = pop(stack);
371 match result {
372 Value::String(s) => assert_eq!(s.as_str(), "Alice"),
373 _ => panic!("Expected String"),
374 }
375 assert!(stack.is_null());
376 }
377 }
378
379 #[test]
380 fn test_map_set_with_int_key() {
381 unsafe {
382 let stack = std::ptr::null_mut();
383 let stack = make_map(stack);
384 let stack = push(stack, Value::Int(42));
385 let stack = push(stack, Value::String("answer".into()));
386 let stack = map_set(stack);
387
388 let stack = push(stack, Value::Int(42));
389 let stack = map_get(stack);
390
391 let (stack, result) = pop(stack);
392 match result {
393 Value::String(s) => assert_eq!(s.as_str(), "answer"),
394 _ => panic!("Expected String"),
395 }
396 assert!(stack.is_null());
397 }
398 }
399
400 #[test]
401 fn test_map_has() {
402 unsafe {
403 let stack = std::ptr::null_mut();
404 let stack = make_map(stack);
405 let stack = push(stack, Value::String("key".into()));
406 let stack = push(stack, Value::Int(100));
407 let stack = map_set(stack);
408
409 let stack = crate::stack::dup(stack);
411 let stack = push(stack, Value::String("key".into()));
412 let stack = map_has(stack);
413 let (stack, result) = pop(stack);
414 assert_eq!(result, Value::Int(1));
415
416 let stack = push(stack, Value::String("missing".into()));
418 let stack = map_has(stack);
419 let (stack, result) = pop(stack);
420 assert_eq!(result, Value::Int(0));
421 assert!(stack.is_null());
422 }
423 }
424
425 #[test]
426 fn test_map_remove() {
427 unsafe {
428 let stack = std::ptr::null_mut();
429 let stack = make_map(stack);
430 let stack = push(stack, Value::String("a".into()));
431 let stack = push(stack, Value::Int(1));
432 let stack = map_set(stack);
433 let stack = push(stack, Value::String("b".into()));
434 let stack = push(stack, Value::Int(2));
435 let stack = map_set(stack);
436
437 let stack = push(stack, Value::String("a".into()));
439 let stack = map_remove(stack);
440
441 let stack = crate::stack::dup(stack);
443 let stack = push(stack, Value::String("a".into()));
444 let stack = map_has(stack);
445 let (stack, result) = pop(stack);
446 assert_eq!(result, Value::Int(0));
447
448 let stack = push(stack, Value::String("b".into()));
450 let stack = map_has(stack);
451 let (stack, result) = pop(stack);
452 assert_eq!(result, Value::Int(1));
453 assert!(stack.is_null());
454 }
455 }
456
457 #[test]
458 fn test_map_size() {
459 unsafe {
460 let stack = std::ptr::null_mut();
461 let stack = make_map(stack);
462
463 let stack = map_size(stack);
465 let (stack, result) = pop(stack);
466 assert_eq!(result, Value::Int(0));
467
468 let stack = make_map(stack);
470 let stack = push(stack, Value::String("a".into()));
471 let stack = push(stack, Value::Int(1));
472 let stack = map_set(stack);
473 let stack = push(stack, Value::String("b".into()));
474 let stack = push(stack, Value::Int(2));
475 let stack = map_set(stack);
476
477 let stack = map_size(stack);
478 let (stack, result) = pop(stack);
479 assert_eq!(result, Value::Int(2));
480 assert!(stack.is_null());
481 }
482 }
483
484 #[test]
485 fn test_map_empty() {
486 unsafe {
487 let stack = std::ptr::null_mut();
488 let stack = make_map(stack);
489
490 let stack = map_empty(stack);
491 let (stack, result) = pop(stack);
492 assert_eq!(result, Value::Int(1));
493
494 let stack = make_map(stack);
496 let stack = push(stack, Value::String("key".into()));
497 let stack = push(stack, Value::Int(1));
498 let stack = map_set(stack);
499
500 let stack = map_empty(stack);
501 let (stack, result) = pop(stack);
502 assert_eq!(result, Value::Int(0));
503 assert!(stack.is_null());
504 }
505 }
506
507 #[test]
508 fn test_map_keys_and_values() {
509 unsafe {
510 let stack = std::ptr::null_mut();
511 let stack = make_map(stack);
512 let stack = push(stack, Value::String("x".into()));
513 let stack = push(stack, Value::Int(10));
514 let stack = map_set(stack);
515 let stack = push(stack, Value::String("y".into()));
516 let stack = push(stack, Value::Int(20));
517 let stack = map_set(stack);
518
519 let stack = crate::stack::dup(stack); let stack = map_keys(stack);
522 let (stack, keys_result) = pop(stack);
523 match keys_result {
524 Value::Variant(v) => {
525 assert_eq!(v.fields.len(), 2);
526 }
528 _ => panic!("Expected Variant"),
529 }
530
531 let stack = map_values(stack);
533 let (stack, values_result) = pop(stack);
534 match values_result {
535 Value::Variant(v) => {
536 assert_eq!(v.fields.len(), 2);
537 }
539 _ => panic!("Expected Variant"),
540 }
541 assert!(stack.is_null());
542 }
543 }
544
545 #[test]
546 fn test_map_get_safe_found() {
547 unsafe {
548 let stack = std::ptr::null_mut();
549 let stack = make_map(stack);
550 let stack = push(stack, Value::String("key".into()));
551 let stack = push(stack, Value::Int(42));
552 let stack = map_set(stack);
553
554 let stack = push(stack, Value::String("key".into()));
555 let stack = map_get_safe(stack);
556
557 let (stack, flag) = pop(stack);
558 let (stack, value) = pop(stack);
559 assert_eq!(flag, Value::Int(1));
560 assert_eq!(value, Value::Int(42));
561 assert!(stack.is_null());
562 }
563 }
564
565 #[test]
566 fn test_map_get_safe_not_found() {
567 unsafe {
568 let stack = std::ptr::null_mut();
569 let stack = make_map(stack);
570
571 let stack = push(stack, Value::String("missing".into()));
572 let stack = map_get_safe(stack);
573
574 let (stack, flag) = pop(stack);
575 let (stack, _value) = pop(stack); assert_eq!(flag, Value::Int(0));
577 assert!(stack.is_null());
578 }
579 }
580
581 #[test]
582 fn test_map_with_bool_key() {
583 unsafe {
584 let stack = std::ptr::null_mut();
585 let stack = make_map(stack);
586 let stack = push(stack, Value::Bool(true));
587 let stack = push(stack, Value::String("yes".into()));
588 let stack = map_set(stack);
589 let stack = push(stack, Value::Bool(false));
590 let stack = push(stack, Value::String("no".into()));
591 let stack = map_set(stack);
592
593 let stack = push(stack, Value::Bool(true));
594 let stack = map_get(stack);
595 let (stack, result) = pop(stack);
596 match result {
597 Value::String(s) => assert_eq!(s.as_str(), "yes"),
598 _ => panic!("Expected String"),
599 }
600 assert!(stack.is_null());
601 }
602 }
603
604 #[test]
605 fn test_map_key_overwrite() {
606 unsafe {
608 let stack = std::ptr::null_mut();
609 let stack = make_map(stack);
610
611 let stack = push(stack, Value::String("key".into()));
613 let stack = push(stack, Value::Int(100));
614 let stack = map_set(stack);
615
616 let stack = push(stack, Value::String("key".into()));
618 let stack = push(stack, Value::Int(200));
619 let stack = map_set(stack);
620
621 let stack = crate::stack::dup(stack);
623 let stack = map_size(stack);
624 let (stack, size) = pop(stack);
625 assert_eq!(size, Value::Int(1));
626
627 let stack = push(stack, Value::String("key".into()));
629 let stack = map_get(stack);
630 let (stack, result) = pop(stack);
631 assert_eq!(result, Value::Int(200));
632 assert!(stack.is_null());
633 }
634 }
635
636 #[test]
637 fn test_map_mixed_key_types() {
638 unsafe {
640 let stack = std::ptr::null_mut();
641 let stack = make_map(stack);
642
643 let stack = push(stack, Value::String("name".into()));
645 let stack = push(stack, Value::String("Alice".into()));
646 let stack = map_set(stack);
647
648 let stack = push(stack, Value::Int(42));
650 let stack = push(stack, Value::String("answer".into()));
651 let stack = map_set(stack);
652
653 let stack = push(stack, Value::Bool(true));
655 let stack = push(stack, Value::String("yes".into()));
656 let stack = map_set(stack);
657
658 let stack = crate::stack::dup(stack);
660 let stack = map_size(stack);
661 let (stack, size) = pop(stack);
662 assert_eq!(size, Value::Int(3));
663
664 let stack = crate::stack::dup(stack);
666 let stack = push(stack, Value::String("name".into()));
667 let stack = map_get(stack);
668 let (stack, result) = pop(stack);
669 match result {
670 Value::String(s) => assert_eq!(s.as_str(), "Alice"),
671 _ => panic!("Expected String for name key"),
672 }
673
674 let stack = crate::stack::dup(stack);
675 let stack = push(stack, Value::Int(42));
676 let stack = map_get(stack);
677 let (stack, result) = pop(stack);
678 match result {
679 Value::String(s) => assert_eq!(s.as_str(), "answer"),
680 _ => panic!("Expected String for int key"),
681 }
682
683 let stack = push(stack, Value::Bool(true));
684 let stack = map_get(stack);
685 let (stack, result) = pop(stack);
686 match result {
687 Value::String(s) => assert_eq!(s.as_str(), "yes"),
688 _ => panic!("Expected String for bool key"),
689 }
690 assert!(stack.is_null());
691 }
692 }
693}