1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#[macro_export]
macro_rules! caml_ffi {
    ($code:tt) => {
        let mut caml_frame = $crate::core::memory::caml_local_roots.clone();
        $code;
        return
    };
    ($code:tt => $result:expr) => {
        let mut caml_frame = $crate::core::memory::caml_local_roots;
        $code;
        return $crate::core::mlvalues::Value::from($result);
    }
}
#[macro_export]
macro_rules! caml_param {
    (@step $idx:expr, $caml_roots:ident,) => {
        $caml_roots.ntables = $idx;
    };
    (@step $idx:expr, $caml_roots:ident, $param:expr, $($tail:expr,)*) => {
        $caml_roots.tables[$idx] = &mut $param;
        caml_param!(@step $idx + 1usize, $caml_roots, $($tail,)*);
    };
    ($($n:expr),*) => {
        let mut caml_roots: $crate::core::memory::CamlRootsBlock = ::std::default::Default::default();
        caml_roots.next = $crate::core::memory::caml_local_roots;
        $crate::core::memory::caml_local_roots = (&mut caml_roots) as *mut $crate::core::memory::CamlRootsBlock;
        caml_roots.nitems = 1; 
        caml_param!(@step 0usize, caml_roots, $($n,)*);
    }
}
#[macro_export]
macro_rules! caml_local {
    ($($local:ident),*) => {
        $(let mut $local = $crate::value::Value::new($crate::core::mlvalues::UNIT);)*
        caml_param!($($local.0),*);
    }
}
#[macro_export]
macro_rules! caml_body {
    (||, <$($local:ident),*>, $code:block) => {
        let caml_frame = $crate::core::memory::caml_local_roots;
        caml_local!($($local),*);
        {
            $(let mut $param = $crate::value::Value::new($param);
            {
                let _ = $param;
            })*
            $code;
        }
        $crate::core::memory::caml_local_roots = caml_frame;
    };
    (|$($param:ident),*|, @code $code:block) => {
        let caml_frame = $crate::core::memory::caml_local_roots;
        caml_param!($($param),*);
        {
            $(let mut $param = $crate::value::Value::new($param);
            {
                let _ = $param;
            })*
            $code;
        }
        $crate::core::memory::caml_local_roots = caml_frame;
    };
    (|$($param:ident),*|, <$($local:ident),*>, $code:block) => {
        let caml_frame = $crate::core::memory::caml_local_roots;
        caml_param!($($param),*);
        caml_local!($($local),*);
        {
            $(let mut $param = $crate::value::Value::new($param);
            {
                let _ = $param;
            })*
            $code;
        }
        $crate::core::memory::caml_local_roots = caml_frame;
    }
}
#[macro_export]
macro_rules! caml {
    ($name:ident, |$($param:ident),*|, <$($local:ident),*>, $code:block -> $retval:ident) => {
        #[allow(unused_mut)]
        #[no_mangle]
        pub unsafe extern fn $name ($(mut $param: $crate::core::mlvalues::Value,)*) -> $crate::core::mlvalues::Value {
            caml_body!(|$($param),*|, <$($local),*>, $code);
            return $crate::core::mlvalues::Value::from($retval)
        }
    };
    ($name:ident, |$($param:ident),*|, $code:block) => {
        #[allow(unused_mut)]
        #[no_mangle]
        pub unsafe extern fn $name ($(mut $param: $crate::core::mlvalues::Value,)*) {
            caml_body!(|$($param),*|, @code $code);
            return;
        }
    };
    ($name:ident, |$($param:ident),*|, $code:block -> $retval:ident) => {
        #[allow(unused_mut)]
        #[no_mangle]
        pub unsafe extern fn $name ($(mut $param: $crate::core::mlvalues::Value,)*) -> $crate::core::mlvalues::Value {
            caml_body!(|$($param),*|, @code $code);
            return $crate::core::mlvalues::Value::from($retval);
        }
    };
}
#[macro_export]
macro_rules! tuple {
    ($($x:expr),*) => {
        $crate::Tuple::from(&[$($x.to_value(),)*]).into()
    }
}
#[macro_export]
macro_rules! array {
    ($($x:expr),*) => {
        $crate::Array::from(&[$($x.to_value(),)*]).into()
    }
}
#[macro_export]
macro_rules! list {
    ($($x:expr),*) => {
        $crate::List::from(&[$($x.to_value(),)*]).into()
    }
}