ocaml_sys/
mlvalues.rs

1//! Contains OCaml types and conversion functions from runtime representations.
2use crate::tag::Tag;
3
4/// OCaml `value` type
5pub type Value = isize;
6
7/// OCaml's integer type
8pub type Intnat = isize;
9
10/// OCaml's unsigned integer type
11pub type Uintnat = usize;
12
13/// OCaml's size type
14pub type Size = Uintnat;
15pub type Color = Uintnat;
16pub type Mark = Uintnat;
17
18/// An OCaml heap-allocated block header. **NB**: this is currently unimplemented.
19///
20/// Structure of the header:
21///
22/// For 16-bit and 32-bit architectures:
23///
24///```text
25///      +--------+-------+-----+
26///      | wosize | color | tag |
27///      +--------+-------+-----+
28/// bits  31    10 9     8 7   0
29///```
30///
31/// For 64-bit architectures:
32///
33///```text
34///      +--------+-------+-----+
35///      | wosize | color | tag |
36///      +--------+-------+-----+
37/// bits  63    10 9     8 7   0
38///```
39///
40pub type Header = Uintnat;
41
42/// #ifdef ARCH_BIG_ENDIAN
43/// #define Tag_val(val) (((unsigned char *) (val)) [-1])
44/// #else
45/// #define Tag_val(val) (((unsigned char *) (val)) [-sizeof(value)])
46/// #endif
47#[cfg(target_endian = "big")]
48#[inline]
49pub const unsafe fn tag_val(val: Value) -> Tag {
50    *(val as *const u8).offset(-1)
51}
52
53#[cfg(target_endian = "little")]
54#[inline]
55pub unsafe fn tag_val(val: Value) -> Tag {
56    *(val as *const u8).offset(-(core::mem::size_of::<Value>() as isize))
57}
58
59#[inline]
60pub unsafe fn hd_val(val: Value) -> Header {
61    *(val as *const Header).offset(-1)
62}
63
64#[inline]
65pub unsafe fn wosize_val(val: Value) -> Size {
66    hd_val(val) >> 10
67}
68
69/// `(((intnat)(x) << 1) + 1)`
70pub const unsafe fn val_int(i: isize) -> Value {
71    (i << 1) + 1
72}
73
74pub const unsafe fn int_val(val: Value) -> isize {
75    val >> 1
76}
77
78pub fn is_block(v: Value) -> bool {
79    (v & 1) == 0
80}
81
82pub const fn is_long(v: Value) -> bool {
83    (v & 1) != 0
84}
85
86// #define Max_long (((intnat)1 << (8 * sizeof(value) - 2)) - 1)
87// #define Min_long (-((intnat)1 << (8 * sizeof(value) - 2)))
88
89/// Maximum possible value for an OCaml fixnum.
90pub const MAX_FIXNUM: Intnat = (1 << (8 * core::mem::size_of::<Intnat>() - 2)) - 1;
91
92/// Minimum possible value for an OCaml fixnum.
93pub const MIN_FIXNUM: Intnat = -(1 << (8 * core::mem::size_of::<Intnat>() - 2));
94
95/// Extract a field from an OCaml value
96///
97/// # Safety
98///
99/// This function does no bounds checking or validation of the OCaml values
100pub unsafe fn field(block: Value, index: usize) -> *mut Value {
101    (block as *mut Value).add(index)
102}
103
104/// The OCaml `()` (`unit`) value
105pub const UNIT: Value = unsafe { val_int(0) };
106
107/// The OCaml `None` value
108pub const NONE: Value = unsafe { val_int(0) };
109
110/// Empty list value
111pub const EMPTY_LIST: Value = unsafe { val_int(0) };
112
113/// The OCaml `true` value
114pub const TRUE: Value = unsafe { val_int(1) };
115
116/// OCaml `false` value
117pub const FALSE: Value = unsafe { val_int(0) };
118
119/// Tag used for OCaml conses
120pub const TAG_CONS: Tag = 0;
121
122/// Tag used for OCaml `Some x` values
123pub const TAG_SOME: Tag = 0;
124
125/// Pointer to the first byte
126#[inline]
127pub const unsafe fn bp_val(val: Value) -> *const u8 {
128    val as *const u8
129}
130
131/// Extracts a machine `ptr` to the bytes making up an OCaml `string`
132#[inline]
133pub const unsafe fn string_val(val: Value) -> *mut u8 {
134    val as *mut u8
135}
136
137extern "C" {
138    /// Returns size of the string in `value` in bytes
139    pub fn caml_string_length(value: Value) -> Size;
140    pub fn caml_array_length(value: Value) -> Size;
141    pub fn caml_hash_variant(tag: *const u8) -> Value;
142    pub fn caml_get_public_method(obj: Value, tag: Value) -> Value;
143    pub fn caml_sys_store_double_val(x: Value, f: f64);
144    pub fn caml_sys_double_val(x: Value) -> f64;
145    pub fn caml_sys_double_field(x: Value, i: Size) -> f64;
146    pub fn caml_sys_store_double_field(x: Value, index: Size, d: f64);
147}