scryer_prolog/
macros.rs

1/* A simple macro to count the arguments in a variadic list
2 * of token trees.
3*/
4
5macro_rules! char_as_cell {
6    ($c: expr) => {
7        HeapCellValue::from_bytes(AtomCell::new_char_inlined($c).into_bytes())
8    };
9}
10
11macro_rules! fixnum_as_cell {
12    ($n: expr) => {
13        HeapCellValue::from_bytes($n.into_bytes())
14    };
15}
16
17macro_rules! integer_as_cell {
18    ($n: expr) => {{
19        match $n {
20            Number::Float(_) => unreachable!(),
21            Number::Fixnum(n) => fixnum_as_cell!(n),
22            Number::Rational(r) => typed_arena_ptr_as_cell!(r),
23            Number::Integer(n) => typed_arena_ptr_as_cell!(n),
24        }
25    }};
26}
27
28macro_rules! empty_list_as_cell {
29    () => {
30        // the empty list atom has the fixed index of 8 (8 >> 3 == 1 in the condensed atom representation).
31        atom_as_cell!(atom!("[]"))
32    };
33}
34
35macro_rules! atom_as_cell {
36    ($atom:expr) => {
37        HeapCellValue::from_bytes(AtomCell::build_with($atom.index, 0).into_bytes())
38    };
39    ($atom:expr, $arity:expr) => {
40        HeapCellValue::from_bytes(AtomCell::build_with($atom.index, $arity as u8).into_bytes())
41    };
42}
43
44macro_rules! cell_as_atom {
45    ($cell:expr) => {
46        AtomCell::from_bytes($cell.into_bytes()).get_name()
47    };
48}
49
50macro_rules! cell_as_atom_cell {
51    ($cell:expr) => {
52        AtomCell::from_bytes($cell.into_bytes())
53    };
54}
55
56macro_rules! cell_as_f64_offset {
57    ($cell:expr) => {{
58        let offset = $cell.get_value() as usize;
59        F64Offset::from(offset)
60    }};
61}
62
63macro_rules! cell_as_code_index_offset {
64    ($cell:expr) => {{
65        let offset = $cell.get_value() as usize;
66        CodeIndexOffset::from(offset)
67    }};
68}
69
70macro_rules! cell_as_untyped_arena_ptr {
71    ($cell:expr) => {
72        UntypedArenaPtr::from_bytes($cell.to_untyped_arena_ptr_bytes())
73    };
74}
75
76macro_rules! pstr_loc_as_cell {
77    ($h:expr) => {
78        HeapCellValue::build_with(HeapCellValueTag::PStrLoc, $h as u64)
79    };
80}
81
82macro_rules! list_loc_as_cell {
83    ($h:expr) => {
84        HeapCellValue::build_with(HeapCellValueTag::Lis, $h as u64)
85    };
86}
87
88macro_rules! str_loc_as_cell {
89    ($h:expr) => {
90        HeapCellValue::build_with(HeapCellValueTag::Str, $h as u64)
91    };
92}
93
94macro_rules! stack_loc {
95    (OrFrame, $b:expr, $idx:expr) => ({
96        $b + prelude_size::<OrFrame>() + $idx * std::mem::size_of::<HeapCellValue>()
97    });
98    (AndFrame, $e:expr, $idx:expr) => ({
99        $e + prelude_size::<AndFrame>() + ($idx  - 1) * std::mem::size_of::<HeapCellValue>()
100    });
101}
102
103macro_rules! stack_loc_as_cell {
104    (OrFrame, $b:expr, $idx:expr) => {
105        stack_loc_as_cell!(stack_loc!(OrFrame, $b, $idx))
106    };
107    (AndFrame, $b:expr, $idx:expr) => {
108        stack_loc_as_cell!(stack_loc!(AndFrame, $b, $idx))
109    };
110    ($h:expr) => {
111        HeapCellValue::build_with(HeapCellValueTag::StackVar, $h as u64)
112    };
113}
114
115macro_rules! heap_loc_as_cell {
116    ($h:expr) => {
117        HeapCellValue::build_with(HeapCellValueTag::Var, $h as u64)
118    };
119}
120
121macro_rules! attr_var_as_cell {
122    ($h:expr) => {
123        HeapCellValue::build_with(HeapCellValueTag::AttrVar, $h as u64)
124    };
125}
126
127#[allow(unused)]
128macro_rules! attr_var_loc_as_cell {
129    ($h:expr) => {
130        HeapCellValue::build_with(HeapCellValueTag::AttrVar, $h as u64)
131    };
132}
133
134macro_rules! typed_arena_ptr_as_cell {
135    ($ptr:expr) => {
136        raw_ptr_as_cell!($ptr.header_ptr())
137    };
138}
139
140macro_rules! raw_ptr_as_cell {
141    ($ptr:expr) => {{
142        // Cell is 64-bit, but raw ptr is 32-bit in 32-bit systems
143        let ptr: *const _ = $ptr;
144        // This needs to expose provenance because it needs to be turned back into a pointer
145        // in contexts where there is no available provenance locally. For example, in
146        // `ConsPtr::as_ptr`.
147        HeapCellValue::from_ptr_addr(ptr.expose_provenance())
148    }};
149}
150
151macro_rules! untyped_arena_ptr_as_cell {
152    ($ptr:expr) => {
153        HeapCellValue::from_bytes(UntypedArenaPtr::into_bytes($ptr))
154    };
155}
156
157macro_rules! stream_as_cell {
158    ($ptr:expr) => {
159        raw_ptr_as_cell!($ptr.as_ptr())
160    };
161}
162
163macro_rules! cell_as_stream {
164    ($cell:expr) => {{
165        let ptr = cell_as_untyped_arena_ptr!($cell);
166        Stream::from_tag(ptr.get_tag(), ptr)
167    }};
168}
169
170macro_rules! cell_as_load_state_payload {
171    ($cell:expr) => {{
172        let ptr = cell_as_untyped_arena_ptr!($cell);
173        unsafe { ptr.as_typed_ptr::<LiveLoadState>() }
174    }};
175}
176
177macro_rules! match_untyped_arena_ptr_pat_body {
178    ($ptr:ident, Integer, $n:ident, $code:expr) => {{
179        let $n = unsafe { $ptr.as_typed_ptr::<Integer>() };
180        #[allow(unused_braces)]
181        $code
182    }};
183    ($ptr:ident, Rational, $n:ident, $code:expr) => {{
184        let $n = unsafe { $ptr.as_typed_ptr::<Rational>() };
185        #[allow(unused_braces)]
186        $code
187    }};
188    ($ptr:ident, OssifiedOpDir, $n:ident, $code:expr) => {{
189        let $n = unsafe { $ptr.as_typed_ptr::<OssifiedOpDir>() };
190        #[allow(unused_braces)]
191        $code
192    }};
193    ($ptr:ident, LiveLoadState, $n:ident, $code:expr) => {{
194        let $n = unsafe { $ptr.as_typed_ptr::<LiveLoadState>() };
195        #[allow(unused_braces)]
196        $code
197    }};
198    ($ptr:ident, Stream, $s:ident, $code:expr) => {{
199        let $s = Stream::from_tag($ptr.get_tag(), $ptr);
200        #[allow(unused_braces)]
201        $code
202    }};
203    ($ptr:ident, TcpListener, $listener:ident, $code:expr) => {{
204        #[allow(unused_mut)]
205        let mut $listener = unsafe { $ptr.as_typed_ptr::<TcpListener>() };
206        #[allow(unused_braces)]
207        $code
208    }};
209    ($ptr:ident, HttpListener, $listener:ident, $code:expr) => {{
210        #[allow(unused_mut)]
211        let mut $listener = unsafe { $ptr.as_typed_ptr::<HttpListener>() };
212        #[allow(unused_braces)]
213        $code
214    }};
215    ($ptr:ident, HttpResponse, $listener:ident, $code:expr) => {{
216        #[allow(unused_mut)]
217        let mut $listener = unsafe { $ptr.as_typed_ptr::<HttpResponse>() };
218        #[allow(unused_braces)]
219        $code
220    }};
221    ($ptr:ident, PipeReader, $listener:ident, $code:expr) => {{
222        #[allow(unused_mut)]
223        let mut $listener = unsafe { $ptr.as_typed_ptr::<PipeReader>() };
224        #[allow(unused_braces)]
225        $code
226    }};
227    ($ptr:ident, PipeWriter, $listener:ident, $code:expr) => {{
228        #[allow(unused_mut)]
229        let mut $listener = unsafe { $ptr.as_typed_ptr::<PipeWriter>() };
230        #[allow(unused_braces)]
231        $code
232    }};
233    ($ptr:ident, ChildProcess, $listener:ident, $code:expr) => {{
234        #[allow(unused_mut)]
235        let mut $listener = unsafe { $ptr.as_typed_ptr::<std::process::Child>() };
236        #[allow(unused_braces)]
237        $code
238    }};
239    ($ptr:ident, $($tags:tt)|+, $s:ident, $code:expr) => {{
240        let $s = Stream::from_tag($ptr.get_tag(), $ptr);
241        #[allow(unused_braces)]
242        $code
243    }};
244}
245
246macro_rules! match_untyped_arena_ptr_pat {
247    (Stream) => {
248        ArenaHeaderTag::InputFileStream
249            | ArenaHeaderTag::OutputFileStream
250            | ArenaHeaderTag::NamedTcpStream
251            | ArenaHeaderTag::NamedTlsStream
252            | ArenaHeaderTag::HttpReadStream
253            | ArenaHeaderTag::HttpWriteStream
254            | ArenaHeaderTag::ReadlineStream
255            | ArenaHeaderTag::StaticStringStream
256            | ArenaHeaderTag::ByteStream
257            | ArenaHeaderTag::CallbackStream
258            | ArenaHeaderTag::InputChannelStream
259            | ArenaHeaderTag::StandardOutputStream
260            | ArenaHeaderTag::StandardErrorStream
261            | ArenaHeaderTag::PipeReader
262            | ArenaHeaderTag::PipeWriter
263    };
264    ($tag:ident) => {
265        ArenaHeaderTag::$tag
266    };
267}
268
269macro_rules! match_untyped_arena_ptr {
270    ($ptr:expr, $( ($(ArenaHeaderTag::$tag:tt)|+, $n:ident) => $code:block $(,)?)+ $(_ => $misc_code:expr $(,)?)?) => ({
271        let ptr_id = $ptr;
272
273        #[allow(clippy::toplevel_ref_arg)]
274        match ptr_id.get_tag() {
275            $($(match_untyped_arena_ptr_pat!($tag) => {
276                match_untyped_arena_ptr_pat_body!(ptr_id, $tag, $n, $code)
277            })+)+
278            $(_ => $misc_code)?
279        }
280    });
281}
282
283macro_rules! read_heap_cell_pat_body {
284    ($cell:ident, Cons, $n:ident, $code:expr) => {{
285        let $n = cell_as_untyped_arena_ptr!($cell);
286        #[allow(unused_braces)]
287        $code
288    }};
289    ($cell:ident, F64Offset, $n:ident, $code:expr) => {{
290        let $n = cell_as_f64_offset!($cell);
291        #[allow(unused_braces)]
292        $code
293    }};
294    ($cell:ident, CodeIndexOffset, $n:ident, $code:expr) => {{
295        let $n = cell_as_code_index_offset!($cell);
296        #[allow(unused_braces)]
297        $code
298    }};
299    ($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => {{
300        let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity();
301        #[allow(unused_braces)]
302        $code
303    }};
304    ($cell:ident, Fixnum, $value:ident, $code:expr) => {{
305        let $value = Fixnum::from_bytes($cell.into_bytes());
306        #[allow(unused_braces)]
307        $code
308    }};
309    ($cell:ident, CutPoint, $value:ident, $code:expr) => {{
310        let $value = Fixnum::from_bytes($cell.into_bytes());
311        #[allow(unused_braces)]
312        $code
313    }};
314    ($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => {{
315        let $value = Fixnum::from_bytes($cell.into_bytes());
316        #[allow(unused_braces)]
317        $code
318    }};
319    ($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => {{
320        let $value = Fixnum::from_bytes($cell.into_bytes());
321        #[allow(unused_braces)]
322        $code
323    }};
324    ($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => {{
325        let $value = $cell.get_value() as usize;
326        #[allow(unused_braces)]
327        $code
328    }};
329}
330
331macro_rules! read_heap_cell_pat {
332    (($(HeapCellValueTag::$tag:tt)|+, $n:tt)) => {
333        $(HeapCellValueTag::$tag)|+
334    };
335    (($(HeapCellValueTag::$tag:tt)|+)) => {
336        $(HeapCellValueTag::$tag)|+
337    };
338    (_) => { _ };
339}
340
341macro_rules! read_heap_cell_pat_expander {
342    ($cell_id:ident, ($(HeapCellValueTag::$tag:tt)|+, $n:tt), $code:block) => ({
343        read_heap_cell_pat_body!($cell_id, $($tag)|+, $n, $code)
344    });
345    ($cell_id:ident, ($(HeapCellValueTag::$tag:tt)|+), $code:block) => ({
346        $code
347    });
348    ($cell_id:ident, _, $code:block) => ({
349        $code
350    });
351}
352
353macro_rules! read_heap_cell {
354    ($cell:expr, $($pat:tt $(if $guard_expr:expr)? => $code:block $(,)?)+) => ({
355        let cell_id = $cell;
356
357        match cell_id.get_tag() {
358            $(read_heap_cell_pat!($pat) $(if $guard_expr)? => {
359                read_heap_cell_pat_expander!(cell_id, $pat, $code)
360            })+
361        }
362    });
363}
364
365macro_rules! compare_number_instr {
366    ($cmp: expr, $at_1: expr, $at_2: expr) => {{
367        $cmp.set_terms($at_1, $at_2);
368        ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)).to_instr()
369    }};
370}
371
372macro_rules! interm {
373    ($n: expr) => {
374        ArithmeticTerm::Interm($n)
375    };
376}
377
378macro_rules! ar_reg {
379    ($r: expr) => {
380        ArithmeticTerm::Reg($r)
381    };
382}
383
384macro_rules! unmark_cell_bits {
385    ($e:expr) => {{
386        let mut result = $e;
387
388        result.set_mark_bit(false);
389        result.set_forwarding_bit(false);
390
391        result
392    }};
393}
394
395macro_rules! index_store {
396    ($code_dir:expr, $op_dir:expr, $modules:expr) => {
397        IndexStore {
398            code_dir: $code_dir,
399            extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
400            local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
401                FxBuildHasher::default(),
402            ),
403            global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()),
404            goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()),
405            meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
406            modules: $modules,
407            op_dir: $op_dir,
408            streams: StreamDir::new(),
409            stream_aliases: StreamAliasDir::with_hasher(FxBuildHasher::default()),
410        }
411    };
412}
413
414macro_rules! unify {
415    ($machine_st:expr, $($value:expr),*) => {{
416        $($machine_st.pdl.push($value);)*
417        $machine_st.unify()
418    }};
419}
420
421macro_rules! unify_fn {
422    ($machine_st:expr, $($value:expr),*) => {{
423        $($machine_st.pdl.push($value);)*
424        ($machine_st.unify_fn)(&mut $machine_st)
425    }};
426}
427
428macro_rules! unify_with_occurs_check {
429    ($machine_st:expr, $($value:expr),*) => {{
430        $($machine_st.pdl.push($value);)*
431        $machine_st.unify_with_occurs_check()
432    }};
433}
434
435macro_rules! compare_term_test {
436    ($machine_st:expr, $e1:expr, $e2:expr) => {{
437        $machine_st.pdl.push($e2);
438        $machine_st.pdl.push($e1);
439
440        $machine_st.compare_term_test(VarComparison::Distinct)
441    }};
442    ($machine_st:expr, $e1:expr, $e2:expr, $var_comparison:expr) => {{
443        $machine_st.pdl.push($e2);
444        $machine_st.pdl.push($e1);
445
446        $machine_st.compare_term_test($var_comparison)
447    }};
448}
449
450macro_rules! step_or_resource_error {
451    ($machine_st:expr, $val:expr) => {{
452        match $val {
453            Ok(r) => r,
454            Err(err_loc) => {
455                $machine_st.throw_resource_error(err_loc);
456                return;
457            }
458        }
459    }};
460    ($machine_st:expr, $val:expr, $fail:block) => {{
461        match $val {
462            Ok(r) => r,
463            Err(err_loc) => {
464                $machine_st.throw_resource_error(err_loc);
465                $fail
466            }
467        }
468    }};
469}
470
471macro_rules! resource_error_call_result {
472    ($machine_st:expr, $val:expr) => {
473        step_or_resource_error!($machine_st, $val, {
474            return Err(vec![]);
475        })
476    };
477}
478
479macro_rules! heap_index {
480    ($idx:expr) => {
481        ($idx) * std::mem::size_of::<HeapCellValue>()
482    };
483}
484
485macro_rules! cell_index {
486    ($idx:expr) => {
487        (($idx) / std::mem::size_of::<HeapCellValue>())
488    };
489}