/* A simple macro to count the arguments in a variadic list * of token trees. */ macro_rules! char_as_cell { ($c: expr) => { HeapCellValue::from_bytes(AtomCell::new_char_inlined($c).into_bytes()) }; } macro_rules! fixnum_as_cell { ($n: expr) => { HeapCellValue::from_bytes($n.into_bytes()) }; } macro_rules! integer_as_cell { ($n: expr) => {{ match $n { Number::Float(_) => unreachable!(), Number::Fixnum(n) => fixnum_as_cell!(n), Number::Rational(r) => typed_arena_ptr_as_cell!(r), Number::Integer(n) => typed_arena_ptr_as_cell!(n), } }}; } macro_rules! empty_list_as_cell { () => { // the empty list atom has the fixed index of 8 (8 >> 3 == 1 in the condensed atom representation). atom_as_cell!(atom!("[]")) }; } macro_rules! atom_as_cell { ($atom:expr) => { HeapCellValue::from_bytes(AtomCell::build_with($atom.index, 0).into_bytes()) }; ($atom:expr, $arity:expr) => { HeapCellValue::from_bytes(AtomCell::build_with($atom.index, $arity as u8).into_bytes()) }; } macro_rules! cell_as_atom { ($cell:expr) => { AtomCell::from_bytes($cell.into_bytes()).get_name() }; } macro_rules! cell_as_atom_cell { ($cell:expr) => { AtomCell::from_bytes($cell.into_bytes()) }; } macro_rules! cell_as_f64_offset { ($cell:expr) => {{ let offset = $cell.get_value() as usize; F64Offset::from(offset) }}; } macro_rules! cell_as_code_index_offset { ($cell:expr) => {{ let offset = $cell.get_value() as usize; CodeIndexOffset::from(offset) }}; } macro_rules! cell_as_untyped_arena_ptr { ($cell:expr) => { UntypedArenaPtr::from_bytes($cell.to_untyped_arena_ptr_bytes()) }; } macro_rules! pstr_loc_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::PStrLoc, $h as u64) }; } macro_rules! list_loc_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::Lis, $h as u64) }; } macro_rules! str_loc_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::Str, $h as u64) }; } macro_rules! stack_loc { (OrFrame, $b:expr, $idx:expr) => ({ $b + prelude_size::() + $idx * std::mem::size_of::() }); (AndFrame, $e:expr, $idx:expr) => ({ $e + prelude_size::() + ($idx - 1) * std::mem::size_of::() }); } macro_rules! stack_loc_as_cell { (OrFrame, $b:expr, $idx:expr) => { stack_loc_as_cell!(stack_loc!(OrFrame, $b, $idx)) }; (AndFrame, $b:expr, $idx:expr) => { stack_loc_as_cell!(stack_loc!(AndFrame, $b, $idx)) }; ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::StackVar, $h as u64) }; } macro_rules! heap_loc_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::Var, $h as u64) }; } macro_rules! attr_var_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::AttrVar, $h as u64) }; } #[allow(unused)] macro_rules! attr_var_loc_as_cell { ($h:expr) => { HeapCellValue::build_with(HeapCellValueTag::AttrVar, $h as u64) }; } macro_rules! typed_arena_ptr_as_cell { ($ptr:expr) => { raw_ptr_as_cell!($ptr.header_ptr()) }; } macro_rules! raw_ptr_as_cell { ($ptr:expr) => {{ // Cell is 64-bit, but raw ptr is 32-bit in 32-bit systems let ptr: *const _ = $ptr; // This needs to expose provenance because it needs to be turned back into a pointer // in contexts where there is no available provenance locally. For example, in // `ConsPtr::as_ptr`. HeapCellValue::from_ptr_addr(ptr.expose_provenance()) }}; } macro_rules! untyped_arena_ptr_as_cell { ($ptr:expr) => { HeapCellValue::from_bytes(UntypedArenaPtr::into_bytes($ptr)) }; } macro_rules! stream_as_cell { ($ptr:expr) => { raw_ptr_as_cell!($ptr.as_ptr()) }; } macro_rules! cell_as_stream { ($cell:expr) => {{ let ptr = cell_as_untyped_arena_ptr!($cell); Stream::from_tag(ptr.get_tag(), ptr) }}; } macro_rules! cell_as_load_state_payload { ($cell:expr) => {{ let ptr = cell_as_untyped_arena_ptr!($cell); unsafe { ptr.as_typed_ptr::() } }}; } macro_rules! match_untyped_arena_ptr_pat_body { ($ptr:ident, Integer, $n:ident, $code:expr) => {{ let $n = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, Rational, $n:ident, $code:expr) => {{ let $n = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, OssifiedOpDir, $n:ident, $code:expr) => {{ let $n = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, LiveLoadState, $n:ident, $code:expr) => {{ let $n = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, Stream, $s:ident, $code:expr) => {{ let $s = Stream::from_tag($ptr.get_tag(), $ptr); #[allow(unused_braces)] $code }}; ($ptr:ident, TcpListener, $listener:ident, $code:expr) => {{ #[allow(unused_mut)] let mut $listener = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, HttpListener, $listener:ident, $code:expr) => {{ #[allow(unused_mut)] let mut $listener = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, HttpResponse, $listener:ident, $code:expr) => {{ #[allow(unused_mut)] let mut $listener = unsafe { $ptr.as_typed_ptr::() }; #[allow(unused_braces)] $code }}; ($ptr:ident, $($tags:tt)|+, $s:ident, $code:expr) => {{ let $s = Stream::from_tag($ptr.get_tag(), $ptr); #[allow(unused_braces)] $code }}; } macro_rules! match_untyped_arena_ptr_pat { (Stream) => { ArenaHeaderTag::InputFileStream | ArenaHeaderTag::OutputFileStream | ArenaHeaderTag::NamedTcpStream | ArenaHeaderTag::NamedTlsStream | ArenaHeaderTag::HttpReadStream | ArenaHeaderTag::HttpWriteStream | ArenaHeaderTag::ReadlineStream | ArenaHeaderTag::StaticStringStream | ArenaHeaderTag::ByteStream | ArenaHeaderTag::CallbackStream | ArenaHeaderTag::InputChannelStream | ArenaHeaderTag::StandardOutputStream | ArenaHeaderTag::StandardErrorStream }; ($tag:ident) => { ArenaHeaderTag::$tag }; } macro_rules! match_untyped_arena_ptr { ($ptr:expr, $( ($(ArenaHeaderTag::$tag:tt)|+, $n:ident) => $code:block $(,)?)+ $(_ => $misc_code:expr $(,)?)?) => ({ let ptr_id = $ptr; #[allow(clippy::toplevel_ref_arg)] match ptr_id.get_tag() { $($(match_untyped_arena_ptr_pat!($tag) => { match_untyped_arena_ptr_pat_body!(ptr_id, $tag, $n, $code) })+)+ $(_ => $misc_code)? } }); } macro_rules! read_heap_cell_pat_body { ($cell:ident, Cons, $n:ident, $code:expr) => {{ let $n = cell_as_untyped_arena_ptr!($cell); #[allow(unused_braces)] $code }}; ($cell:ident, F64Offset, $n:ident, $code:expr) => {{ let $n = cell_as_f64_offset!($cell); #[allow(unused_braces)] $code }}; ($cell:ident, CodeIndexOffset, $n:ident, $code:expr) => {{ let $n = cell_as_code_index_offset!($cell); #[allow(unused_braces)] $code }}; ($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => {{ let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity(); #[allow(unused_braces)] $code }}; ($cell:ident, Fixnum, $value:ident, $code:expr) => {{ let $value = Fixnum::from_bytes($cell.into_bytes()); #[allow(unused_braces)] $code }}; ($cell:ident, CutPoint, $value:ident, $code:expr) => {{ let $value = Fixnum::from_bytes($cell.into_bytes()); #[allow(unused_braces)] $code }}; ($cell:ident, Fixnum | CutPoint, $value:ident, $code:expr) => {{ let $value = Fixnum::from_bytes($cell.into_bytes()); #[allow(unused_braces)] $code }}; ($cell:ident, CutPoint | Fixnum, $value:ident, $code:expr) => {{ let $value = Fixnum::from_bytes($cell.into_bytes()); #[allow(unused_braces)] $code }}; ($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => {{ let $value = $cell.get_value() as usize; #[allow(unused_braces)] $code }}; } macro_rules! read_heap_cell_pat { (($(HeapCellValueTag::$tag:tt)|+, $n:tt)) => { $(HeapCellValueTag::$tag)|+ }; (($(HeapCellValueTag::$tag:tt)|+)) => { $(HeapCellValueTag::$tag)|+ }; (_) => { _ }; } macro_rules! read_heap_cell_pat_expander { ($cell_id:ident, ($(HeapCellValueTag::$tag:tt)|+, $n:tt), $code:block) => ({ read_heap_cell_pat_body!($cell_id, $($tag)|+, $n, $code) }); ($cell_id:ident, ($(HeapCellValueTag::$tag:tt)|+), $code:block) => ({ $code }); ($cell_id:ident, _, $code:block) => ({ $code }); } macro_rules! read_heap_cell { ($cell:expr, $($pat:tt $(if $guard_expr:expr)? => $code:block $(,)?)+) => ({ let cell_id = $cell; match cell_id.get_tag() { $(read_heap_cell_pat!($pat) $(if $guard_expr)? => { read_heap_cell_pat_expander!(cell_id, $pat, $code) })+ } }); } macro_rules! compare_number_instr { ($cmp: expr, $at_1: expr, $at_2: expr) => {{ $cmp.set_terms($at_1, $at_2); ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)).to_instr() }}; } macro_rules! interm { ($n: expr) => { ArithmeticTerm::Interm($n) }; } macro_rules! ar_reg { ($r: expr) => { ArithmeticTerm::Reg($r) }; } macro_rules! unmark_cell_bits { ($e:expr) => {{ let mut result = $e; result.set_mark_bit(false); result.set_forwarding_bit(false); result }}; } macro_rules! index_store { ($code_dir:expr, $op_dir:expr, $modules:expr) => { IndexStore { code_dir: $code_dir, extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()), local_extensible_predicates: LocalExtensiblePredicates::with_hasher( FxBuildHasher::default(), ), global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()), goal_expansion_indices: GoalExpansionIndices::with_hasher(FxBuildHasher::default()), meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()), modules: $modules, op_dir: $op_dir, streams: StreamDir::new(), stream_aliases: StreamAliasDir::with_hasher(FxBuildHasher::default()), } }; } macro_rules! unify { ($machine_st:expr, $($value:expr),*) => {{ $($machine_st.pdl.push($value);)* $machine_st.unify() }}; } macro_rules! unify_fn { ($machine_st:expr, $($value:expr),*) => {{ $($machine_st.pdl.push($value);)* ($machine_st.unify_fn)(&mut $machine_st) }}; } macro_rules! unify_with_occurs_check { ($machine_st:expr, $($value:expr),*) => {{ $($machine_st.pdl.push($value);)* $machine_st.unify_with_occurs_check() }}; } macro_rules! compare_term_test { ($machine_st:expr, $e1:expr, $e2:expr) => {{ $machine_st.pdl.push($e2); $machine_st.pdl.push($e1); $machine_st.compare_term_test(VarComparison::Distinct) }}; ($machine_st:expr, $e1:expr, $e2:expr, $var_comparison:expr) => {{ $machine_st.pdl.push($e2); $machine_st.pdl.push($e1); $machine_st.compare_term_test($var_comparison) }}; } macro_rules! step_or_resource_error { ($machine_st:expr, $val:expr) => {{ match $val { Ok(r) => r, Err(err_loc) => { $machine_st.throw_resource_error(err_loc); return; } } }}; ($machine_st:expr, $val:expr, $fail:block) => {{ match $val { Ok(r) => r, Err(err_loc) => { $machine_st.throw_resource_error(err_loc); $fail } } }}; } macro_rules! resource_error_call_result { ($machine_st:expr, $val:expr) => { step_or_resource_error!($machine_st, $val, { return Err(vec![]); }) }; } macro_rules! heap_index { ($idx:expr) => { ($idx) * std::mem::size_of::() }; } macro_rules! cell_index { ($idx:expr) => { (($idx) / std::mem::size_of::()) }; }