use super::jit_kinds::*;
use super::value_ffi::*;
use shape_value::heap_value::{OptionData, ResultData};
use shape_value::kinded_slot::KindedSlot;
use std::sync::Arc;
pub extern "C" fn jit_make_ok(inner_bits: u64) -> u64 {
if tracing::enabled!(target: "shape_jit", tracing::Level::TRACE) {
let kind = super::value_ffi::heap_kind(inner_bits);
tracing::trace!(
target: "shape_jit",
inner = inner_bits,
inner_kind = ?kind,
"make_ok",
);
}
box_ok(inner_bits)
}
pub extern "C" fn jit_make_err(inner_bits: u64) -> u64 {
box_err(inner_bits)
}
pub extern "C" fn jit_is_ok(bits: u64) -> u64 {
if is_ok_tag(bits) { TAG_BOOL_TRUE } else { TAG_BOOL_FALSE }
}
pub extern "C" fn jit_is_err(bits: u64) -> u64 {
if is_err_tag(bits) {
TAG_BOOL_TRUE
} else {
TAG_BOOL_FALSE
}
}
pub extern "C" fn jit_is_result(bits: u64) -> u64 {
if is_result_tag(bits) {
TAG_BOOL_TRUE
} else {
TAG_BOOL_FALSE
}
}
pub extern "C" fn jit_unwrap_ok(bits: u64) -> u64 {
if is_ok_tag(bits) {
let inner = unsafe { unbox_result_inner(bits) };
let ptr = unbox_heap_pointer(bits);
if !ptr.is_null() {
unsafe {
UnifiedValue::<u64>::heap_drop(ptr as u64);
}
}
inner
} else {
TAG_NULL
}
}
pub extern "C" fn jit_unwrap_err(bits: u64) -> u64 {
if is_err_tag(bits) {
let inner = unsafe { unbox_result_inner(bits) };
let ptr = unbox_heap_pointer(bits);
if !ptr.is_null() {
unsafe {
UnifiedValue::<u64>::heap_drop(ptr as u64);
}
}
inner
} else {
TAG_NULL
}
}
pub extern "C" fn jit_unwrap_or(bits: u64, default_bits: u64) -> u64 {
if is_ok_tag(bits) {
unsafe { unbox_result_inner(bits) }
} else {
default_bits
}
}
pub extern "C" fn jit_result_inner(bits: u64) -> u64 {
if is_ok_tag(bits) || is_err_tag(bits) {
unsafe { unbox_result_inner(bits) }
} else {
bits
}
}
pub extern "C" fn jit_make_some(inner_bits: u64) -> u64 {
box_some(inner_bits)
}
pub extern "C" fn jit_is_some(bits: u64) -> u64 {
if is_some_tag(bits) {
TAG_BOOL_TRUE
} else {
TAG_BOOL_FALSE
}
}
pub extern "C" fn jit_is_none(bits: u64) -> u64 {
if is_none_tag(bits) {
TAG_BOOL_TRUE
} else {
TAG_BOOL_FALSE
}
}
pub extern "C" fn jit_unwrap_some(bits: u64) -> u64 {
if is_some_tag(bits) {
let inner = unsafe { unbox_some_inner(bits) };
let ptr = unbox_heap_pointer(bits);
if !ptr.is_null() {
unsafe {
UnifiedValue::<u64>::heap_drop(ptr as u64);
}
}
inner
} else {
TAG_NULL
}
}
#[inline]
fn decode_payload_kind_or_surface(
code: u8,
func_name: &str,
) -> shape_value::NativeKind {
match super::stack_kind_code::decode(code) {
Some(k) => k,
None => {
tracing::debug!(
target: "shape_jit",
func_name,
code,
"SURFACE: payload kind code is sentinel/unknown. \
ADR-006 \u{a7}2.7.7 #9 \u{2014} producer-site MIR kind \
classification gap. Falling back to Bool placeholder; \
downstream consumer will surface on slot-kind mismatch.",
);
shape_value::NativeKind::Bool
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_v2_make_result_ok(payload_bits: u64, payload_kind_code: u8) -> u64 {
let kind = decode_payload_kind_or_surface(payload_kind_code, "jit_v2_make_result_ok");
let payload_slot = shape_value::ValueSlot::from_raw(payload_bits);
let payload = KindedSlot::new(payload_slot, kind);
let arc = Arc::new(ResultData::ok(payload));
Arc::into_raw(arc) as u64
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_v2_make_result_err(payload_bits: u64, payload_kind_code: u8) -> u64 {
let kind = decode_payload_kind_or_surface(payload_kind_code, "jit_v2_make_result_err");
let payload_slot = shape_value::ValueSlot::from_raw(payload_bits);
let payload = KindedSlot::new(payload_slot, kind);
let arc = Arc::new(ResultData::err(payload));
Arc::into_raw(arc) as u64
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_v2_make_option_some(payload_bits: u64, payload_kind_code: u8) -> u64 {
let kind = decode_payload_kind_or_surface(payload_kind_code, "jit_v2_make_option_some");
let payload_slot = shape_value::ValueSlot::from_raw(payload_bits);
let payload = KindedSlot::new(payload_slot, kind);
let arc = Arc::new(OptionData::some(payload));
Arc::into_raw(arc) as u64
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_v2_make_option_none() -> u64 {
let arc = Arc::new(OptionData::none());
Arc::into_raw(arc) as u64
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_result_is_ok(bits: u64) -> u8 {
if bits == 0 {
return 0;
}
let r: &ResultData = unsafe { &*(bits as *const ResultData) };
if r.is_ok { 1 } else { 0 }
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_result_is_err(bits: u64) -> u8 {
if bits == 0 {
return 0;
}
let r: &ResultData = unsafe { &*(bits as *const ResultData) };
if r.is_ok { 0 } else { 1 }
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_result_payload(bits: u64) -> u64 {
if bits == 0 {
return 0;
}
let r: &ResultData = unsafe { &*(bits as *const ResultData) };
let payload_clone = r.payload.clone();
let raw = payload_clone.slot.raw();
std::mem::forget(payload_clone);
raw
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_option_is_some(bits: u64) -> u8 {
if bits == 0 {
return 0;
}
let o: &OptionData = unsafe { &*(bits as *const OptionData) };
if o.is_some { 1 } else { 0 }
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_option_is_none(bits: u64) -> u8 {
if bits == 0 {
return 0;
}
let o: &OptionData = unsafe { &*(bits as *const OptionData) };
if o.is_some { 0 } else { 1 }
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_option_payload(bits: u64) -> u64 {
if bits == 0 {
return 0;
}
let o: &OptionData = unsafe { &*(bits as *const OptionData) };
let payload_clone = o.payload.clone();
let raw = payload_clone.slot.raw();
std::mem::forget(payload_clone);
raw
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_result_retain(bits: u64) {
if bits == 0 {
return;
}
unsafe {
Arc::increment_strong_count(bits as *const ResultData);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_result_release(bits: u64) {
if bits == 0 {
return;
}
unsafe {
Arc::decrement_strong_count(bits as *const ResultData);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_option_retain(bits: u64) {
if bits == 0 {
return;
}
unsafe {
Arc::increment_strong_count(bits as *const OptionData);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn jit_arc_option_release(bits: u64) {
if bits == 0 {
return;
}
unsafe {
Arc::decrement_strong_count(bits as *const OptionData);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unwrap_or_with_err() {
let err_result = jit_make_err(box_number(-1.0));
let default = box_number(999.0);
let result = jit_unwrap_or(err_result, default);
assert_eq!(unbox_number(result), 999.0);
}
#[test]
fn test_option_none() {
assert_eq!(jit_is_none(TAG_NULL), TAG_BOOL_TRUE);
assert_eq!(jit_is_some(TAG_NULL), TAG_BOOL_FALSE);
}
#[test]
fn test_non_result_values() {
let num = box_number(42.0);
assert_eq!(jit_is_result(num), TAG_BOOL_FALSE);
assert_eq!(jit_is_ok(num), TAG_BOOL_FALSE);
assert_eq!(jit_is_err(num), TAG_BOOL_FALSE);
}
use super::super::stack_kind_code;
use shape_value::heap_value::HeapKind;
use shape_value::ValueSlot;
unsafe fn drop_arc_result(bits: u64) {
if bits != 0 {
let _ = Arc::<ResultData>::from_raw(bits as *const ResultData);
}
}
unsafe fn drop_arc_option(bits: u64) {
if bits != 0 {
let _ = Arc::<OptionData>::from_raw(bits as *const OptionData);
}
}
#[test]
fn arc_result_ok_roundtrip_int_payload() {
let inner_bits = ValueSlot::from_int(42).raw();
let arc_bits = jit_v2_make_result_ok(inner_bits, stack_kind_code::C_INT64);
assert_ne!(arc_bits, 0);
assert_eq!(jit_arc_result_is_ok(arc_bits), 1);
assert_eq!(jit_arc_result_is_err(arc_bits), 0);
let payload_bits = jit_arc_result_payload(arc_bits);
assert_eq!(payload_bits, inner_bits);
assert_eq!(ValueSlot::from_raw(payload_bits).as_i64(), 42);
unsafe { drop_arc_result(arc_bits) };
}
#[test]
fn arc_result_err_roundtrip_int_payload() {
let inner_bits = ValueSlot::from_int(-1).raw();
let arc_bits = jit_v2_make_result_err(inner_bits, stack_kind_code::C_INT64);
assert_ne!(arc_bits, 0);
assert_eq!(jit_arc_result_is_ok(arc_bits), 0);
assert_eq!(jit_arc_result_is_err(arc_bits), 1);
let payload_bits = jit_arc_result_payload(arc_bits);
assert_eq!(payload_bits, inner_bits);
unsafe { drop_arc_result(arc_bits) };
}
#[test]
fn arc_option_some_roundtrip_int_payload() {
let inner_bits = ValueSlot::from_int(7).raw();
let arc_bits = jit_v2_make_option_some(inner_bits, stack_kind_code::C_INT64);
assert_ne!(arc_bits, 0);
assert_eq!(jit_arc_option_is_some(arc_bits), 1);
assert_eq!(jit_arc_option_is_none(arc_bits), 0);
let payload_bits = jit_arc_option_payload(arc_bits);
assert_eq!(payload_bits, inner_bits);
unsafe { drop_arc_option(arc_bits) };
}
#[test]
fn arc_option_none_roundtrip() {
let arc_bits = jit_v2_make_option_none();
assert_ne!(arc_bits, 0);
assert_eq!(jit_arc_option_is_some(arc_bits), 0);
assert_eq!(jit_arc_option_is_none(arc_bits), 1);
unsafe { drop_arc_option(arc_bits) };
}
#[test]
fn arc_result_null_bits_safe() {
assert_eq!(jit_arc_result_is_ok(0), 0);
assert_eq!(jit_arc_result_is_err(0), 0);
assert_eq!(jit_arc_result_payload(0), 0);
assert_eq!(jit_arc_option_is_some(0), 0);
assert_eq!(jit_arc_option_is_none(0), 0);
assert_eq!(jit_arc_option_payload(0), 0);
}
#[test]
fn arc_carrier_kind_label_matches_producer() {
let result_code = stack_kind_code::encode(
shape_value::NativeKind::Ptr(HeapKind::Result),
);
let option_code = stack_kind_code::encode(
shape_value::NativeKind::Ptr(HeapKind::Option),
);
assert_eq!(
stack_kind_code::decode(result_code),
Some(shape_value::NativeKind::Ptr(HeapKind::Result))
);
assert_eq!(
stack_kind_code::decode(option_code),
Some(shape_value::NativeKind::Ptr(HeapKind::Option))
);
}
}