use crate::stack::{Stack, pop, push};
use crate::value::Value;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_variant_field_count(stack: Stack) -> Stack {
unsafe {
let (stack, value) = pop(stack);
match value {
Value::Variant(variant_data) => {
let count = variant_data.fields.len() as i64;
push(stack, Value::Int(count))
}
_ => panic!("variant-field-count: expected Variant, got {:?}", value),
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_variant_tag(stack: Stack) -> Stack {
unsafe {
let (stack, value) = pop(stack);
match value {
Value::Variant(variant_data) => {
push(stack, Value::Symbol(variant_data.tag.clone()))
}
_ => panic!("variant-tag: expected Variant, got {:?}", value),
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_symbol_eq_cstr(stack: Stack, c_str: *const i8) -> Stack {
use std::ffi::CStr;
unsafe {
let (stack, value) = pop(stack);
let symbol_str = match value {
Value::Symbol(s) => s,
_ => panic!("symbol_eq_cstr: expected Symbol, got {:?}", value),
};
let expected = CStr::from_ptr(c_str)
.to_str()
.expect("Invalid UTF-8 in variant name");
let is_equal = symbol_str.as_str() == expected;
push(stack, Value::Bool(is_equal))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_variant_field_at(stack: Stack) -> Stack {
unsafe {
let (stack, index_val) = pop(stack);
let index = match index_val {
Value::Int(i) => i,
_ => panic!(
"variant-field-at: expected Int (index), got {:?}",
index_val
),
};
if index < 0 {
panic!("variant-field-at: index cannot be negative: {}", index);
}
let (stack, variant_val) = pop(stack);
match variant_val {
Value::Variant(variant_data) => {
let idx = index as usize;
if idx >= variant_data.fields.len() {
panic!(
"variant-field-at: index {} out of bounds (variant has {} fields)",
index,
variant_data.fields.len()
);
}
let field = variant_data.fields[idx].clone();
push(stack, field)
}
_ => panic!("variant-field-at: expected Variant, got {:?}", variant_val),
}
}
}