use crate::executor::VirtualMachine;
use shape_runtime::context::ExecutionContext;
use shape_value::heap_value::{HeapKind, HeapValue, PriorityQueueData};
use shape_value::{KindedSlot, NativeKind, VMError};
use std::sync::Arc;
#[inline]
fn type_error(msg: impl Into<String>) -> VMError {
VMError::RuntimeError(msg.into())
}
#[inline]
fn as_priority_queue(slot: &KindedSlot) -> Result<Arc<PriorityQueueData>, VMError> {
if !matches!(slot.kind, NativeKind::Ptr(HeapKind::PriorityQueue)) {
return Err(type_error(format!(
"PriorityQueue method receiver must be a PriorityQueue \
(got kind {:?})",
slot.kind
)));
}
let bits = slot.slot.raw();
if bits == 0 {
return Err(type_error(
"PriorityQueue method receiver slot bits null",
));
}
let arc =
unsafe { Arc::<PriorityQueueData>::from_raw(bits as *const PriorityQueueData) };
let cloned = Arc::clone(&arc);
let _ = Arc::into_raw(arc);
Ok(cloned)
}
#[inline]
fn as_i64_priority(slot: &KindedSlot) -> Result<i64, VMError> {
slot.as_i64().ok_or_else(|| {
type_error(format!(
"PriorityQueue priority must be an int (got kind {:?})",
slot.kind
))
})
}
pub fn v2_size(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.size() takes no arguments",
));
}
let pq = as_priority_queue(&args[0])?;
Ok(KindedSlot::from_int(pq.len() as i64))
}
pub fn v2_is_empty(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.isEmpty() takes no arguments",
));
}
let pq = as_priority_queue(&args[0])?;
Ok(KindedSlot::from_bool(pq.is_empty()))
}
pub fn v2_peek(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.peek() takes no arguments",
));
}
let pq = as_priority_queue(&args[0])?;
Ok(KindedSlot::from_int(pq.peek().unwrap_or(0)))
}
pub fn v2_to_array(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.toArray() takes no arguments",
));
}
let _pq = as_priority_queue(&args[0])?;
Err(VMError::NotImplemented(
"PriorityQueue.toArray: SURFACE — V3-S5 ckpt-5-prime²a consumer-\
cascade. The deleted typed-array-data I64 `Arc<Buf<i64>>` payload + \
`KindedSlot::from_typed_array` DELETED at V3-S5 ckpt-1..ckpt-4. \
Rebuild = per-T v2-raw `*mut TypedArray<i64>` flat-struct \
construction (cluster-2 / ckpt-6 territory). REFUSED ON SIGHT: \
resurrection under any rename (Refusal #1)."
.to_string(),
))
}
pub fn v2_to_sorted_array(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.toSortedArray() takes no arguments",
));
}
let _pq = as_priority_queue(&args[0])?;
Err(VMError::NotImplemented(
"PriorityQueue.toSortedArray: SURFACE — V3-S5 ckpt-5-prime²a \
consumer-cascade. The deleted typed-array-data I64 `Arc<Buf<i64>>` payload + \
`KindedSlot::from_typed_array` DELETED at V3-S5 ckpt-1..ckpt-4. \
Rebuild = per-T v2-raw `*mut TypedArray<i64>` flat-struct \
construction (cluster-2 / ckpt-6 territory). REFUSED ON SIGHT: \
resurrection under any rename (Refusal #1)."
.to_string(),
))
}
pub fn v2_push(
_vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 2 {
return Err(type_error(
"PriorityQueue.push() requires exactly 1 argument (priority)",
));
}
let pq = as_priority_queue(&args[0])?;
let value = as_i64_priority(&args[1])?;
let mut owned = pq;
Arc::make_mut(&mut owned).push(value);
Ok(KindedSlot::from_priority_queue(owned))
}
pub fn v2_pop(
vm: &mut VirtualMachine,
args: &[KindedSlot],
_ctx: Option<&mut ExecutionContext>,
) -> Result<KindedSlot, VMError> {
if args.len() != 1 {
return Err(type_error(
"PriorityQueue.pop() takes no arguments",
));
}
let pq = as_priority_queue(&args[0])?;
let mut owned = pq;
let min = Arc::make_mut(&mut owned).pop().unwrap_or(0);
let new_self_slot = KindedSlot::from_priority_queue(owned);
vm.push_kinded(new_self_slot.raw(), new_self_slot.kind())?;
std::mem::forget(new_self_slot);
Ok(KindedSlot::from_int(min))
}