1use crate::cell::*;
16use crate::machine::Machine;
17use plg_shared::atom::ATOM_NIL;
18
19#[inline]
20fn mref<'a>(m: *mut Machine) -> &'a mut Machine {
21 unsafe { &mut *m }
22}
23
24#[unsafe(no_mangle)]
26pub extern "C" fn plg_rt_b_var_1(m: *mut Machine, a: u64) -> i32 {
27 let m = mref(m);
28 (tag_of(m.deref(a)) == TAG_REF) as i32
29}
30
31#[unsafe(no_mangle)]
33pub extern "C" fn plg_rt_b_nonvar_1(m: *mut Machine, a: u64) -> i32 {
34 let m = mref(m);
35 (tag_of(m.deref(a)) != TAG_REF) as i32
36}
37
38#[unsafe(no_mangle)]
40pub extern "C" fn plg_rt_b_atom_1(m: *mut Machine, a: u64) -> i32 {
41 let m = mref(m);
42 (tag_of(m.deref(a)) == TAG_ATOM) as i32
43}
44
45#[unsafe(no_mangle)]
47pub extern "C" fn plg_rt_b_number_1(m: *mut Machine, a: u64) -> i32 {
48 let m = mref(m);
49 matches!(tag_of(m.deref(a)), TAG_INT | TAG_BIG | TAG_FLT) as i32
50}
51
52#[unsafe(no_mangle)]
54pub extern "C" fn plg_rt_b_integer_1(m: *mut Machine, a: u64) -> i32 {
55 let m = mref(m);
56 matches!(tag_of(m.deref(a)), TAG_INT | TAG_BIG) as i32
57}
58
59#[unsafe(no_mangle)]
61pub extern "C" fn plg_rt_b_float_1(m: *mut Machine, a: u64) -> i32 {
62 let m = mref(m);
63 (tag_of(m.deref(a)) == TAG_FLT) as i32
64}
65
66#[unsafe(no_mangle)]
68pub extern "C" fn plg_rt_b_compound_1(m: *mut Machine, a: u64) -> i32 {
69 let m = mref(m);
70 matches!(tag_of(m.deref(a)), TAG_STR | TAG_LST) as i32
71}
72
73#[unsafe(no_mangle)]
76pub extern "C" fn plg_rt_b_is_list_1(m: *mut Machine, a: u64) -> i32 {
77 let m = mref(m);
78 let mut cur = m.deref(a);
79 loop {
80 match tag_of(cur) {
81 TAG_ATOM if atom_id(cur) == ATOM_NIL => return 1,
82 TAG_LST => {
83 let idx = payload(cur) as usize;
84 cur = m.deref(m.heap[idx + 1]); }
86 _ => return 0, }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use plg_shared::StringInterner;
95
96 fn machine() -> Box<Machine> {
97 Machine::new(StringInterner::new(), Vec::new())
98 }
99
100 fn big(m: &mut Machine, n: i64) -> Word {
101 let idx = m.heap.len();
102 m.heap.push(n as u64);
103 make(TAG_BIG, idx as u64)
104 }
105
106 fn flt(m: &mut Machine, f: f64) -> Word {
107 let idx = m.heap.len();
108 m.heap.push(f.to_bits());
109 make(TAG_FLT, idx as u64)
110 }
111
112 fn str_term(m: &mut Machine, name: &str, args: &[Word]) -> Word {
113 let f = m.atoms.intern(name);
114 let idx = m.heap.len();
115 m.heap.push(pack_functor(f, args.len() as u32));
116 m.heap.extend_from_slice(args);
117 make(TAG_STR, idx as u64)
118 }
119
120 fn list(m: &mut Machine, head: Word, tail: Word) -> Word {
121 let idx = m.heap.len();
122 m.heap.push(head);
123 m.heap.push(tail);
124 make(TAG_LST, idx as u64)
125 }
126
127 #[test]
128 fn var_nonvar() {
129 let mut m = machine();
130 let v = m.new_var();
131 let mp = &mut *m as *mut Machine;
132 assert_eq!(plg_rt_b_var_1(mp, v), 1);
133 assert_eq!(plg_rt_b_nonvar_1(mp, v), 0);
134 assert_eq!(plg_rt_b_var_1(mp, make_int(3)), 0);
135 assert_eq!(plg_rt_b_nonvar_1(mp, make_int(3)), 1);
136 m.bind(payload(v) as usize, make_atom(7));
138 let mp = &mut *m as *mut Machine;
139 assert_eq!(plg_rt_b_var_1(mp, v), 0);
140 assert_eq!(plg_rt_b_nonvar_1(mp, v), 1);
141 }
142
143 #[test]
144 fn atom_number_integer_float() {
145 let mut m = machine();
146 let a = make_atom(m.atoms.intern("a"));
147 let b = big(&mut m, 1 << 62);
148 let f = flt(&mut m, 1.5);
149 let mp = &mut *m as *mut Machine;
150 assert_eq!(plg_rt_b_atom_1(mp, a), 1);
151 assert_eq!(plg_rt_b_atom_1(mp, make_int(1)), 0);
152
153 assert_eq!(plg_rt_b_number_1(mp, make_int(1)), 1);
154 assert_eq!(plg_rt_b_number_1(mp, b), 1);
155 assert_eq!(plg_rt_b_number_1(mp, f), 1);
156 assert_eq!(plg_rt_b_number_1(mp, a), 0);
157
158 assert_eq!(plg_rt_b_integer_1(mp, make_int(1)), 1);
159 assert_eq!(plg_rt_b_integer_1(mp, b), 1); assert_eq!(plg_rt_b_integer_1(mp, f), 0);
161
162 assert_eq!(plg_rt_b_float_1(mp, f), 1);
163 assert_eq!(plg_rt_b_float_1(mp, make_int(1)), 0);
164 assert_eq!(plg_rt_b_float_1(mp, b), 0);
165 }
166
167 #[test]
168 fn compound_includes_lists() {
169 let mut m = machine();
170 let nil = make_atom(ATOM_NIL);
171 let s = str_term(&mut m, "foo", &[make_int(1)]);
172 let l = list(&mut m, make_int(1), nil);
173 let a = make_atom(m.atoms.intern("a"));
174 let mp = &mut *m as *mut Machine;
175 assert_eq!(plg_rt_b_compound_1(mp, s), 1); assert_eq!(plg_rt_b_compound_1(mp, l), 1); assert_eq!(plg_rt_b_compound_1(mp, a), 0);
178 assert_eq!(plg_rt_b_compound_1(mp, make_int(1)), 0);
179 }
180
181 #[test]
182 fn is_list_proper_partial_improper() {
183 let mut m = machine();
184 let nil = make_atom(ATOM_NIL);
185 let proper = {
187 let inner = list(&mut m, make_atom(2), nil);
188 list(&mut m, make_atom(1), inner)
189 };
190 let improper = list(&mut m, make_atom(1), make_atom(2));
192 let v = m.new_var();
194 let partial = list(&mut m, make_atom(1), v);
195 let mp = &mut *m as *mut Machine;
196 assert_eq!(plg_rt_b_is_list_1(mp, proper), 1);
197 assert_eq!(plg_rt_b_is_list_1(mp, nil), 1); assert_eq!(plg_rt_b_is_list_1(mp, improper), 0);
199 assert_eq!(plg_rt_b_is_list_1(mp, partial), 0);
200 assert_eq!(plg_rt_b_is_list_1(mp, make_int(1)), 0);
201 }
202}