patch_prolog_shared/
cell.rs1pub type Word = u64;
14
15pub const TAG_REF: u64 = 0; pub const TAG_ATOM: u64 = 1; pub const TAG_INT: u64 = 2; pub const TAG_STR: u64 = 3; pub const TAG_LST: u64 = 4; pub const TAG_FLT: u64 = 5; pub const TAG_BIG: u64 = 6; pub const INT_MAX: i64 = (1 << 60) - 1;
26pub const INT_MIN: i64 = -(1 << 60);
27
28#[inline]
29pub fn make(tag: u64, payload: u64) -> Word {
30 (payload << 3) | tag
31}
32
33#[inline]
34pub fn tag_of(w: Word) -> u64 {
35 w & 7
36}
37
38#[inline]
39pub fn payload(w: Word) -> u64 {
40 w >> 3
41}
42
43#[inline]
44pub fn make_atom(id: u32) -> Word {
45 make(TAG_ATOM, id as u64)
46}
47
48#[inline]
49pub fn make_int(n: i64) -> Word {
50 debug_assert!((INT_MIN..=INT_MAX).contains(&n));
51 ((n as u64) << 3) | TAG_INT
52}
53
54#[inline]
56pub fn int_value(w: Word) -> i64 {
57 (w as i64) >> 3
58}
59
60#[inline]
61pub fn make_ref(idx: usize) -> Word {
62 make(TAG_REF, idx as u64)
63}
64
65#[inline]
66pub fn atom_id(w: Word) -> u32 {
67 payload(w) as u32
68}
69
70#[inline]
72pub fn pack_functor(functor: u32, arity: u32) -> u64 {
73 ((functor as u64) << 32) | arity as u64
74}
75
76#[inline]
77pub fn unpack_functor(cell: u64) -> (u32, u32) {
78 ((cell >> 32) as u32, cell as u32)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn int_roundtrip_preserves_sign() {
87 for n in [0i64, 1, -1, 42, -42, INT_MAX, INT_MIN] {
88 assert_eq!(int_value(make_int(n)), n, "roundtrip {n}");
89 assert_eq!(tag_of(make_int(n)), TAG_INT);
90 }
91 }
92
93 #[test]
94 fn functor_packing() {
95 let cell = pack_functor(7, 3);
96 assert_eq!(unpack_functor(cell), (7, 3));
97 }
98
99 #[test]
100 fn tags_distinct() {
101 assert_eq!(tag_of(make_atom(5)), TAG_ATOM);
102 assert_eq!(tag_of(make_ref(9)), TAG_REF);
103 assert_eq!(atom_id(make_atom(5)), 5);
104 }
105}