1use crate::seqstring::global_string;
36use crate::stack::{Stack, heap_value_mut, 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)]
62pub unsafe extern "C" fn patch_seq_map_get(stack: Stack) -> Stack {
63 unsafe {
64 let (stack, key_val) = pop(stack);
66 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
67 panic!(
68 "map-get: key must be Int, String, or Bool, got {:?}",
69 key_val
70 )
71 });
72
73 let (stack, map_val) = pop(stack);
75 let map = match map_val {
76 Value::Map(m) => m,
77 _ => panic!("map-get: expected Map, got {:?}", map_val),
78 };
79
80 match map.get(&key) {
82 Some(value) => {
83 let stack = push(stack, value.clone());
84 push(stack, Value::Bool(true))
85 }
86 None => {
87 let stack = push(stack, Value::Int(0)); push(stack, Value::Bool(false)) }
90 }
91 }
92}
93
94#[unsafe(no_mangle)]
105pub unsafe extern "C" fn patch_seq_map_set(stack: Stack) -> Stack {
106 unsafe {
107 if let Some(Value::Map(map)) = heap_value_mut(stack.sub(3)) {
111 let (stack, value) = pop(stack);
113 let (stack, key_val) = pop(stack);
114 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
115 panic!(
116 "map-set: key must be Int, String, or Bool, got {:?}",
117 key_val
118 )
119 });
120 map.insert(key, value);
123 return stack; }
125
126 let (stack, value) = pop(stack);
128 let (stack, key_val) = pop(stack);
129 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
130 panic!(
131 "map-set: key must be Int, String, or Bool, got {:?}",
132 key_val
133 )
134 });
135 let (stack, map_val) = pop(stack);
136 let mut map = match map_val {
137 Value::Map(m) => *m,
138 _ => panic!("map-set: expected Map, got {:?}", map_val),
139 };
140 map.insert(key, value);
141 push(stack, Value::Map(Box::new(map)))
142 }
143}
144
145#[unsafe(no_mangle)]
155pub unsafe extern "C" fn patch_seq_map_has(stack: Stack) -> Stack {
156 unsafe {
157 let (stack, key_val) = pop(stack);
159 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
160 panic!(
161 "map-has?: key must be Int, String, or Bool, got {:?}",
162 key_val
163 )
164 });
165
166 let (stack, map_val) = pop(stack);
168 let map = match map_val {
169 Value::Map(m) => m,
170 _ => panic!("map-has?: expected Map, got {:?}", map_val),
171 };
172
173 let has_key = map.contains_key(&key);
174 push(stack, Value::Bool(has_key))
175 }
176}
177
178#[unsafe(no_mangle)]
189pub unsafe extern "C" fn patch_seq_map_remove(stack: Stack) -> Stack {
190 unsafe {
191 if let Some(Value::Map(map)) = heap_value_mut(stack.sub(2)) {
195 let (stack, key_val) = pop(stack);
196 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
197 panic!(
198 "map-remove: key must be Int, String, or Bool, got {:?}",
199 key_val
200 )
201 });
202 map.remove(&key);
205 return stack; }
207
208 let (stack, key_val) = pop(stack);
210 let key = MapKey::from_value(&key_val).unwrap_or_else(|| {
211 panic!(
212 "map-remove: key must be Int, String, or Bool, got {:?}",
213 key_val
214 )
215 });
216 let (stack, map_val) = pop(stack);
217 let mut map = match map_val {
218 Value::Map(m) => *m,
219 _ => panic!("map-remove: expected Map, got {:?}", map_val),
220 };
221 map.remove(&key);
222 push(stack, Value::Map(Box::new(map)))
223 }
224}
225
226#[unsafe(no_mangle)]
236pub unsafe extern "C" fn patch_seq_map_keys(stack: Stack) -> Stack {
237 unsafe {
238 let (stack, map_val) = pop(stack);
239 let map = match map_val {
240 Value::Map(m) => m,
241 _ => panic!("map-keys: expected Map, got {:?}", map_val),
242 };
243
244 let keys: Vec<Value> = map.keys().map(|k| k.to_value()).collect();
245 let variant = Value::Variant(Arc::new(VariantData::new(
246 global_string("List".to_string()),
247 keys,
248 )));
249 push(stack, variant)
250 }
251}
252
253#[unsafe(no_mangle)]
263pub unsafe extern "C" fn patch_seq_map_values(stack: Stack) -> Stack {
264 unsafe {
265 let (stack, map_val) = pop(stack);
266 let map = match map_val {
267 Value::Map(m) => m,
268 _ => panic!("map-values: expected Map, got {:?}", map_val),
269 };
270
271 let values: Vec<Value> = map.values().cloned().collect();
272 let variant = Value::Variant(Arc::new(VariantData::new(
273 global_string("List".to_string()),
274 values,
275 )));
276 push(stack, variant)
277 }
278}
279
280#[unsafe(no_mangle)]
287pub unsafe extern "C" fn patch_seq_map_size(stack: Stack) -> Stack {
288 unsafe {
289 let (stack, map_val) = pop(stack);
290 let map = match map_val {
291 Value::Map(m) => m,
292 _ => panic!("map-size: expected Map, got {:?}", map_val),
293 };
294
295 push(stack, Value::Int(map.len() as i64))
296 }
297}
298
299#[unsafe(no_mangle)]
308pub unsafe extern "C" fn patch_seq_map_empty(stack: Stack) -> Stack {
309 unsafe {
310 let (stack, map_val) = pop(stack);
311 let map = match map_val {
312 Value::Map(m) => m,
313 _ => panic!("map-empty?: expected Map, got {:?}", map_val),
314 };
315
316 let is_empty = map.is_empty();
317 push(stack, Value::Bool(is_empty))
318 }
319}
320
321pub use patch_seq_make_map as make_map;
323pub use patch_seq_map_empty as map_empty;
324pub use patch_seq_map_get as map_get;
325pub use patch_seq_map_has as map_has;
326pub use patch_seq_map_keys as map_keys;
327pub use patch_seq_map_remove as map_remove;
328pub use patch_seq_map_set as map_set;
329pub use patch_seq_map_size as map_size;
330pub use patch_seq_map_values as map_values;
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335
336 #[test]
337 fn test_make_map() {
338 unsafe {
339 let stack = crate::stack::alloc_test_stack();
340 let stack = make_map(stack);
341
342 let (_stack, result) = pop(stack);
343 match result {
344 Value::Map(m) => assert!(m.is_empty()),
345 _ => panic!("Expected Map"),
346 }
347 }
348 }
349
350 #[test]
351 fn test_map_set_and_get() {
352 unsafe {
353 let stack = crate::stack::alloc_test_stack();
354 let stack = make_map(stack);
355 let stack = push(stack, Value::String("name".into()));
356 let stack = push(stack, Value::String("Alice".into()));
357 let stack = map_set(stack);
358
359 let stack = push(stack, Value::String("name".into()));
361 let stack = map_get(stack);
362
363 let (stack, flag) = pop(stack);
365 assert_eq!(flag, Value::Bool(true));
366 let (_stack, result) = pop(stack);
367 match result {
368 Value::String(s) => assert_eq!(s.as_str(), "Alice"),
369 _ => panic!("Expected String"),
370 }
371 }
372 }
373
374 #[test]
375 fn test_map_set_with_int_key() {
376 unsafe {
377 let stack = crate::stack::alloc_test_stack();
378 let stack = make_map(stack);
379 let stack = push(stack, Value::Int(42));
380 let stack = push(stack, Value::String("answer".into()));
381 let stack = map_set(stack);
382
383 let stack = push(stack, Value::Int(42));
384 let stack = map_get(stack);
385
386 let (stack, flag) = pop(stack);
388 assert_eq!(flag, Value::Bool(true));
389 let (_stack, result) = pop(stack);
390 match result {
391 Value::String(s) => assert_eq!(s.as_str(), "answer"),
392 _ => panic!("Expected String"),
393 }
394 }
395 }
396
397 #[test]
398 fn test_map_has() {
399 unsafe {
400 let stack = crate::stack::alloc_test_stack();
401 let stack = make_map(stack);
402 let stack = push(stack, Value::String("key".into()));
403 let stack = push(stack, Value::Int(100));
404 let stack = map_set(stack);
405
406 let stack = crate::stack::dup(stack);
408 let stack = push(stack, Value::String("key".into()));
409 let stack = map_has(stack);
410 let (stack, result) = pop(stack);
411 assert_eq!(result, Value::Bool(true));
412
413 let stack = push(stack, Value::String("missing".into()));
415 let stack = map_has(stack);
416 let (_stack, result) = pop(stack);
417 assert_eq!(result, Value::Bool(false));
418 }
419 }
420
421 #[test]
422 fn test_map_remove() {
423 unsafe {
424 let stack = crate::stack::alloc_test_stack();
425 let stack = make_map(stack);
426 let stack = push(stack, Value::String("a".into()));
427 let stack = push(stack, Value::Int(1));
428 let stack = map_set(stack);
429 let stack = push(stack, Value::String("b".into()));
430 let stack = push(stack, Value::Int(2));
431 let stack = map_set(stack);
432
433 let stack = push(stack, Value::String("a".into()));
435 let stack = map_remove(stack);
436
437 let stack = crate::stack::dup(stack);
439 let stack = push(stack, Value::String("a".into()));
440 let stack = map_has(stack);
441 let (stack, result) = pop(stack);
442 assert_eq!(result, Value::Bool(false));
443
444 let stack = push(stack, Value::String("b".into()));
446 let stack = map_has(stack);
447 let (_stack, result) = pop(stack);
448 assert_eq!(result, Value::Bool(true));
449 }
450 }
451
452 #[test]
453 fn test_map_size() {
454 unsafe {
455 let stack = crate::stack::alloc_test_stack();
456 let stack = make_map(stack);
457
458 let stack = map_size(stack);
460 let (stack, result) = pop(stack);
461 assert_eq!(result, Value::Int(0));
462
463 let stack = make_map(stack);
465 let stack = push(stack, Value::String("a".into()));
466 let stack = push(stack, Value::Int(1));
467 let stack = map_set(stack);
468 let stack = push(stack, Value::String("b".into()));
469 let stack = push(stack, Value::Int(2));
470 let stack = map_set(stack);
471
472 let stack = map_size(stack);
473 let (_stack, result) = pop(stack);
474 assert_eq!(result, Value::Int(2));
475 }
476 }
477
478 #[test]
479 fn test_map_empty() {
480 unsafe {
481 let stack = crate::stack::alloc_test_stack();
482 let stack = make_map(stack);
483
484 let stack = map_empty(stack);
485 let (stack, result) = pop(stack);
486 assert_eq!(result, Value::Bool(true));
487
488 let stack = make_map(stack);
490 let stack = push(stack, Value::String("key".into()));
491 let stack = push(stack, Value::Int(1));
492 let stack = map_set(stack);
493
494 let stack = map_empty(stack);
495 let (_stack, result) = pop(stack);
496 assert_eq!(result, Value::Bool(false));
497 }
498 }
499
500 #[test]
501 fn test_map_keys_and_values() {
502 unsafe {
503 let stack = crate::stack::alloc_test_stack();
504 let stack = make_map(stack);
505 let stack = push(stack, Value::String("x".into()));
506 let stack = push(stack, Value::Int(10));
507 let stack = map_set(stack);
508 let stack = push(stack, Value::String("y".into()));
509 let stack = push(stack, Value::Int(20));
510 let stack = map_set(stack);
511
512 let stack = crate::stack::dup(stack); let stack = map_keys(stack);
515 let (stack, keys_result) = pop(stack);
516 match keys_result {
517 Value::Variant(v) => {
518 assert_eq!(v.fields.len(), 2);
519 }
521 _ => panic!("Expected Variant"),
522 }
523
524 let stack = map_values(stack);
526 let (_stack, values_result) = pop(stack);
527 match values_result {
528 Value::Variant(v) => {
529 assert_eq!(v.fields.len(), 2);
530 }
532 _ => panic!("Expected Variant"),
533 }
534 }
535 }
536
537 #[test]
538 fn test_map_get_found() {
539 unsafe {
540 let stack = crate::stack::alloc_test_stack();
541 let stack = make_map(stack);
542 let stack = push(stack, Value::String("key".into()));
543 let stack = push(stack, Value::Int(42));
544 let stack = map_set(stack);
545
546 let stack = push(stack, Value::String("key".into()));
547 let stack = map_get(stack);
548
549 let (stack, flag) = pop(stack);
550 let (_stack, value) = pop(stack);
551 assert_eq!(flag, Value::Bool(true));
552 assert_eq!(value, Value::Int(42));
553 }
554 }
555
556 #[test]
557 fn test_map_get_not_found() {
558 unsafe {
559 let stack = crate::stack::alloc_test_stack();
560 let stack = make_map(stack);
561
562 let stack = push(stack, Value::String("missing".into()));
563 let stack = map_get(stack);
564
565 let (stack, flag) = pop(stack);
566 let (_stack, _value) = pop(stack); assert_eq!(flag, Value::Bool(false));
568 }
569 }
570
571 #[test]
572 fn test_map_with_bool_key() {
573 unsafe {
574 let stack = crate::stack::alloc_test_stack();
575 let stack = make_map(stack);
576 let stack = push(stack, Value::Bool(true));
577 let stack = push(stack, Value::String("yes".into()));
578 let stack = map_set(stack);
579 let stack = push(stack, Value::Bool(false));
580 let stack = push(stack, Value::String("no".into()));
581 let stack = map_set(stack);
582
583 let stack = push(stack, Value::Bool(true));
584 let stack = map_get(stack);
585 let (stack, flag) = pop(stack);
587 assert_eq!(flag, Value::Bool(true));
588 let (_stack, result) = pop(stack);
589 match result {
590 Value::String(s) => assert_eq!(s.as_str(), "yes"),
591 _ => panic!("Expected String"),
592 }
593 }
594 }
595
596 #[test]
597 fn test_map_key_overwrite() {
598 unsafe {
600 let stack = crate::stack::alloc_test_stack();
601 let stack = make_map(stack);
602
603 let stack = push(stack, Value::String("key".into()));
605 let stack = push(stack, Value::Int(100));
606 let stack = map_set(stack);
607
608 let stack = push(stack, Value::String("key".into()));
610 let stack = push(stack, Value::Int(200));
611 let stack = map_set(stack);
612
613 let stack = crate::stack::dup(stack);
615 let stack = map_size(stack);
616 let (stack, size) = pop(stack);
617 assert_eq!(size, Value::Int(1));
618
619 let stack = push(stack, Value::String("key".into()));
621 let stack = map_get(stack);
622 let (stack, flag) = pop(stack);
624 assert_eq!(flag, Value::Bool(true));
625 let (_stack, result) = pop(stack);
626 assert_eq!(result, Value::Int(200));
627 }
628 }
629
630 #[test]
631 fn test_map_mixed_key_types() {
632 unsafe {
634 let stack = crate::stack::alloc_test_stack();
635 let stack = make_map(stack);
636
637 let stack = push(stack, Value::String("name".into()));
639 let stack = push(stack, Value::String("Alice".into()));
640 let stack = map_set(stack);
641
642 let stack = push(stack, Value::Int(42));
644 let stack = push(stack, Value::String("answer".into()));
645 let stack = map_set(stack);
646
647 let stack = push(stack, Value::Bool(true));
649 let stack = push(stack, Value::String("yes".into()));
650 let stack = map_set(stack);
651
652 let stack = crate::stack::dup(stack);
654 let stack = map_size(stack);
655 let (stack, size) = pop(stack);
656 assert_eq!(size, Value::Int(3));
657
658 let stack = crate::stack::dup(stack);
661 let stack = push(stack, Value::String("name".into()));
662 let stack = map_get(stack);
663 let (stack, flag) = pop(stack);
664 assert_eq!(flag, Value::Bool(true));
665 let (stack, result) = pop(stack);
666 match result {
667 Value::String(s) => assert_eq!(s.as_str(), "Alice"),
668 _ => panic!("Expected String for name key"),
669 }
670
671 let stack = crate::stack::dup(stack);
672 let stack = push(stack, Value::Int(42));
673 let stack = map_get(stack);
674 let (stack, flag) = pop(stack);
675 assert_eq!(flag, Value::Bool(true));
676 let (stack, result) = pop(stack);
677 match result {
678 Value::String(s) => assert_eq!(s.as_str(), "answer"),
679 _ => panic!("Expected String for int key"),
680 }
681
682 let stack = push(stack, Value::Bool(true));
683 let stack = map_get(stack);
684 let (stack, flag) = pop(stack);
685 assert_eq!(flag, Value::Bool(true));
686 let (_stack, result) = pop(stack);
687 match result {
688 Value::String(s) => assert_eq!(s.as_str(), "yes"),
689 _ => panic!("Expected String for bool key"),
690 }
691 }
692 }
693}