1use crate::mlvalues::tag;
5use crate::mlvalues::{tag_val, RawOCaml};
6use crate::value::OCaml;
7use crate::{OCamlRef, OCamlRuntime};
8use ocaml_sys::{
9 caml_callback2_exn, caml_callback3_exn, caml_callbackN_exn, caml_callback_exn, caml_named_value,
10};
11
12#[derive(Copy, Clone)]
13pub struct OCamlClosure(*const RawOCaml);
14
15unsafe impl Sync for OCamlClosure {}
16
17impl OCamlClosure {
18 pub fn named(name: &str) -> Option<OCamlClosure> {
19 let named = unsafe {
20 let s = match std::ffi::CString::new(name) {
21 Ok(s) => s,
22 Err(_) => return None,
23 };
24 caml_named_value(s.as_ptr())
25 };
26 if named.is_null() || unsafe { tag_val(*named) } != tag::CLOSURE {
27 None
28 } else {
29 Some(OCamlClosure(named))
30 }
31 }
32
33 pub fn call<'a, T, R>(&self, cr: &'a mut OCamlRuntime, arg: OCamlRef<T>) -> OCaml<'a, R> {
34 let result = unsafe { caml_callback_exn(*self.0, arg.get_raw()) };
35 self.handle_call_result(cr, result)
36 }
37
38 pub fn call2<'a, T, U, R>(
39 &self,
40 cr: &'a mut OCamlRuntime,
41 arg1: OCamlRef<T>,
42 arg2: OCamlRef<U>,
43 ) -> OCaml<'a, R> {
44 let result = unsafe { caml_callback2_exn(*self.0, arg1.get_raw(), arg2.get_raw()) };
45 self.handle_call_result(cr, result)
46 }
47
48 pub fn call3<'a, T, U, V, R>(
49 &self,
50 cr: &'a mut OCamlRuntime,
51 arg1: OCamlRef<T>,
52 arg2: OCamlRef<U>,
53 arg3: OCamlRef<V>,
54 ) -> OCaml<'a, R> {
55 let result =
56 unsafe { caml_callback3_exn(*self.0, arg1.get_raw(), arg2.get_raw(), arg3.get_raw()) };
57 self.handle_call_result(cr, result)
58 }
59
60 pub fn call_n<'a, R>(&self, cr: &'a mut OCamlRuntime, args: &mut [RawOCaml]) -> OCaml<'a, R> {
61 let len = args.len();
62 let result = unsafe { caml_callbackN_exn(*self.0, len, args.as_mut_ptr()) };
63 self.handle_call_result(cr, result)
64 }
65
66 #[inline]
67 fn handle_call_result<'a, R>(
68 &self,
69 cr: &'a mut OCamlRuntime,
70 result: RawOCaml,
71 ) -> OCaml<'a, R> {
72 match unsafe { OCaml::of_exception_result(cr, result) } {
73 Some(ex) => panic!("OCaml exception, message: {:?}", ex.message()),
74 None => unsafe { OCaml::new(cr, result) },
75 }
76 }
77}
78
79pub type OCamlFn1<'a, A, Ret> = unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>) -> OCaml<'a, Ret>;
81pub type OCamlFn2<'a, A, B, Ret> =
83 unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>, OCamlRef<B>) -> OCaml<'a, Ret>;
84pub type OCamlFn3<'a, A, B, C, Ret> =
86 unsafe fn(&'a mut OCamlRuntime, OCamlRef<A>, OCamlRef<B>, OCamlRef<C>) -> OCaml<'a, Ret>;
87pub type OCamlFn4<'a, A, B, C, D, Ret> = unsafe fn(
89 &'a mut OCamlRuntime,
90 OCamlRef<A>,
91 OCamlRef<B>,
92 OCamlRef<C>,
93 OCamlRef<D>,
94) -> OCaml<'a, Ret>;
95pub type OCamlFn5<'a, A, B, C, D, E, Ret> = unsafe fn(
97 &'a mut OCamlRuntime,
98 OCamlRef<A>,
99 OCamlRef<B>,
100 OCamlRef<C>,
101 OCamlRef<D>,
102 OCamlRef<E>,
103) -> OCaml<'a, Ret>;