use core;
use tag::Tag;
use error::Error;
pub type Size = core::mlvalues::Size;
#[derive(Debug, Clone)]
pub struct Value(pub core::mlvalues::Value);
impl From<Value> for core::mlvalues::Value {
fn from(v: Value) -> core::mlvalues::Value {
v.0
}
}
pub trait ToValue {
fn to_value(&self) -> Value;
}
pub trait FromValue {
fn from_value(v: Value) -> Self;
}
impl ToValue for Value {
fn to_value(&self) -> Value {
self.clone()
}
}
impl FromValue for Value {
fn from_value(v: Value) -> Value {
v
}
}
impl Value {
pub fn alloc(n: usize, tag: Tag) -> Value {
let x = unsafe {
core::alloc::caml_alloc(n, tag.into())
};
Value::new(x)
}
pub fn alloc_small(n: usize, tag: Tag) -> Value {
let x = unsafe {
core::alloc::caml_alloc_small(n, tag.into())
};
Value::new(x)
}
pub fn new(v: core::mlvalues::Value) -> Value {
Value(v)
}
pub fn value(&self) -> core::mlvalues::Value {
self.0
}
pub fn tag(&self) -> Tag {
unsafe {
Tag::new(tag_val!(self.0))
}
}
pub fn ptr<T>(p: *const T) -> Value {
Value(p as core::mlvalues::Value)
}
pub fn int(i: i32) -> Value {
Value(val_int!(i))
}
pub fn long(i: i64) -> Value {
Value(val_long!(i))
}
pub fn double(d: f64) -> Value {
unsafe {
Value(core::alloc::caml_copy_double(d))
}
}
pub fn is_block(&self) -> bool {
core::mlvalues::is_block(self.0)
}
pub fn is_long(&self) -> bool {
core::mlvalues::is_long(self.0)
}
pub fn field(&self, i: Size) -> Value {
unsafe {
Value::new(*core::mlvalues::field(self.0, i))
}
}
pub fn store_field<V: ToValue>(&mut self, i: Size, val: V) {
unsafe {
core::memory::store_field(self.0, i, val.to_value().0)
}
}
pub fn int_val(&self) -> i32 {
int_val!(self.0) as i32
}
pub fn long_val(&self) -> i64 {
long_val!(self.0) as i64
}
pub fn double_val(&self) -> f64 {
unsafe {
*self.ptr_val::<f64>()
}
}
pub fn ptr_val<T>(&self) -> *const T {
self.0 as *mut T
}
pub fn call<A: ToValue>(&self, arg: A) -> Result<Value, Error> {
if self.tag() != Tag::Closure {
return Err(Error::NotCallable)
}
unsafe {
Ok(Value::new(core::callback::caml_callback(self.0, arg.to_value().0)))
}
}
pub fn call2<A: ToValue, B: ToValue>(&self, arg1: A, arg2: B) -> Result<Value, Error> {
if self.tag() != Tag::Closure {
return Err(Error::NotCallable)
}
unsafe {
Ok(Value::new(core::callback::caml_callback2(self.0, arg1.to_value().0, arg2.to_value().0)))
}
}
pub fn call3<A: ToValue, B: ToValue, C: ToValue>(&self, arg1: A, arg2: B, arg3: C) -> Result<Value, Error> {
if self.tag() != Tag::Closure {
return Err(Error::NotCallable)
}
unsafe {
Ok(Value::new(core::callback::caml_callback3(self.0, arg1.to_value().0, arg2.to_value().0, arg3.to_value().0)))
}
}
pub fn call_n<A: AsRef<[Value]>>(&self, args: A) -> Result<Value, Error> {
if self.tag() != Tag::Closure {
return Err(Error::NotCallable)
}
let n = args.as_ref().len();
let x: Vec<core::mlvalues::Value> = args.as_ref().iter().map(|x| x.0).collect();
unsafe {
Ok(Value::new(core::callback::caml_callbackN(self.0, n, x.as_ptr() as *mut core::mlvalues::Value)))
}
}
pub fn modify<V: ToValue>(&mut self, v: V) {
unsafe {
core::memory::caml_modify(&mut self.0, v.to_value().0)
}
}
}