use crate::stack::{Stack, peek_heap_mut_second, pop, push};
use crate::value::{Value, VariantData};
use std::sync::Arc;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_list_length(stack: Stack) -> Stack {
unsafe { crate::variant_ops::patch_seq_variant_field_count(stack) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_list_empty(stack: Stack) -> Stack {
unsafe {
let (stack, list_val) = pop(stack);
let is_empty = match list_val {
Value::Variant(v) => v.fields.is_empty(),
_ => panic!("list-empty?: expected Variant (list), got {:?}", list_val),
};
push(stack, Value::Bool(is_empty))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_list_make(stack: Stack) -> Stack {
unsafe {
let list = Value::Variant(Arc::new(VariantData::new(
crate::seqstring::global_string("List".to_string()),
vec![],
)));
push(stack, list)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_list_push(stack: Stack) -> Stack {
unsafe {
if let Some(Value::Variant(variant_arc)) = peek_heap_mut_second(stack)
&& let Some(data) = Arc::get_mut(variant_arc)
{
let (stack, value) = pop(stack);
data.fields.push(value);
return stack; }
let (stack, value) = pop(stack);
let (stack, list_val) = pop(stack);
let variant_arc = match list_val {
Value::Variant(v) => v,
_ => panic!("list.push: expected Variant (list), got {:?}", list_val),
};
push_to_variant(stack, variant_arc, value)
}
}
unsafe fn push_to_variant(stack: Stack, mut variant_arc: Arc<VariantData>, value: Value) -> Stack {
unsafe {
if let Some(data) = Arc::get_mut(&mut variant_arc) {
data.fields.push(value);
push(stack, Value::Variant(variant_arc))
} else {
let mut new_fields = Vec::with_capacity(variant_arc.fields.len() + 1);
new_fields.extend(variant_arc.fields.iter().cloned());
new_fields.push(value);
let new_list = Value::Variant(Arc::new(VariantData::new(
variant_arc.tag.clone(),
new_fields,
)));
push(stack, new_list)
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_list_reverse(stack: Stack) -> Stack {
unsafe {
let (stack, list_val) = pop(stack);
let variant_data = match list_val {
Value::Variant(v) => v,
_ => panic!("list.reverse: expected Variant (list), got {:?}", list_val),
};
let mut reversed: Vec<Value> = variant_data.fields.to_vec();
reversed.reverse();
let new_variant = Value::Variant(Arc::new(VariantData::new(
variant_data.tag.clone(),
reversed,
)));
push(stack, new_variant)
}
}