use crate::arena::*; use crate::atom_table::*; use crate::instructions::*; use crate::machine::*; use crate::machine::arithmetic_ops::*; use crate::machine::machine_errors::*; use crate::machine::machine_state::*; use crate::types::*; use crate::try_numeric_result; macro_rules! step_or_fail { ($self:expr, $step_e:expr) => { if $self.machine_st.fail { $self.machine_st.backtrack(); } else { $step_e; } }; } macro_rules! try_or_throw { ($s:expr, $e:expr) => {{ match $e { Ok(val) => val, Err(msg) => { $s.throw_exception(msg); $s.backtrack(); continue; } } }}; } macro_rules! try_or_throw_gen { ($s:expr, $e:expr) => {{ match $e { Ok(val) => val, Err(msg_fn) => { let e = msg_fn($s); $s.throw_exception(e); $s.backtrack(); continue; } } }}; } static INSTRUCTIONS_PER_INTERRUPT_POLL: usize = 256; impl MachineState { #[inline(always)] fn compare(&mut self) -> CallResult { let stub_gen = || functor_stub(atom!("compare"), 3); let a1 = self.store(self.deref(self.registers[1])); let a2 = self.registers[2]; let a3 = self.registers[3]; read_heap_cell!(a1, (HeapCellValueTag::Atom, (name, arity)) => { debug_assert_eq!(arity, 0); match name { atom!(">") | atom!("<") | atom!("=") => { } _ => { let err = self.domain_error(DomainErrorType::Order, a1); return Err(self.error_form(err, stub_gen())); } } } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => { } _ => { let err = self.type_error(ValidType::Atom, a1); return Err(self.error_form(err, stub_gen())); } ); let atom = match compare_term_test!(self, a2, a3) { Some(Ordering::Greater) => { atom!(">") } Some(Ordering::Equal) => { atom!("=") } None | Some(Ordering::Less) => { atom!("<") } }; self.unify_atom(atom, a1); Ok(()) } pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) { let old_h = self.heap.len(); let a1 = self.registers[1]; let a2 = self.registers[2]; copy_term(CopyTerm::new(self), a1, attr_var_policy); unify_fn!(*self, heap_loc_as_cell!(old_h), a2); } fn sort(&mut self) -> CallResult { self.check_sort_errors()?; let stub_gen = || functor_stub(atom!("sort"), 2); let mut list = self.try_from_list(self.registers[1], stub_gen)?; list.sort_unstable_by(|v1, v2| { compare_term_test!(self, *v1, *v2).unwrap_or(Ordering::Less) }); list.dedup_by(|v1, v2| { compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal) }); let heap_addr = heap_loc_as_cell!( iter_to_heap_list(&mut self.heap, list.into_iter()) ); let target_addr = self.registers[2]; unify_fn!(*self, target_addr, heap_addr); Ok(()) } fn keysort(&mut self) -> CallResult { self.check_keysort_errors()?; let stub_gen = || functor_stub(atom!("keysort"), 2); let list = self.try_from_list(self.registers[1], stub_gen)?; let mut key_pairs = Vec::with_capacity(list.len()); for val in list { let key = self.project_onto_key(val)?; key_pairs.push((key, val)); } key_pairs.sort_by(|a1, a2| { compare_term_test!(self, a1.0, a2.0).unwrap_or(Ordering::Less) }); let key_pairs = key_pairs.into_iter().map(|kp| kp.1); let heap_addr = heap_loc_as_cell!( iter_to_heap_list(&mut self.heap, key_pairs) ); let target_addr = self.registers[2]; unify_fn!(*self, target_addr, heap_addr); Ok(()) } fn is(&mut self, r: RegType, at: ArithmeticTerm) -> CallResult { let n1 = self.store(self.deref(self[r])); match self.get_number(&at)? { Number::Fixnum(n) => self.unify_fixnum(n, n1), Number::Float(n) => { let n = float_alloc!(n.into_inner(), self.arena); self.unify_f64(n, n1) } Number::Integer(n) => self.unify_big_int(n, n1), Number::Rational(n) => self.unify_rational(n, n1), } Ok(()) } } impl Machine { fn read(&mut self) -> CallResult { let stream = self.machine_st.get_stream_or_alias( self.machine_st.registers[1], &self.indices.stream_aliases, atom!("read"), 2, )?; match self.machine_st.read(stream, &self.indices.op_dir) { Ok(offset) => { let value = self.machine_st.registers[2]; unify_fn!(&mut self.machine_st, value, heap_loc_as_cell!(offset.heap_loc)); } Err(ParserError::UnexpectedEOF) => { let value = self.machine_st.registers[2]; self.machine_st.unify_atom(atom!("end_of_file"), value); } Err(e) => { let stub = functor_stub(atom!("read"), 2); let err = self.machine_st.syntax_error(e); return Err(self.machine_st.error_form(err, stub)); } }; Ok(()) } pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> { loop { match &self.code[p] { &Instruction::DynamicElse( birth, death, NextOrFail::Next(i), ) => { if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death { return Some((p, i)); } else if i > 0 { p += i; } else { return None; } } &Instruction::DynamicElse( birth, death, NextOrFail::Fail(_), ) => { if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death { return Some((p, 0)); } else { return None; } } &Instruction::DynamicInternalElse( birth, death, NextOrFail::Next(i), ) => { if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death { return Some((p, i)); } else if i > 0 { p += i; } else { return None; } } &Instruction::DynamicInternalElse( birth, death, NextOrFail::Fail(_), ) => { if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death { return Some((p, 0)); } else { return None; } } &Instruction::RevJmpBy(i) => { p -= i; } _ => { unreachable!(); } } } } pub(super) fn find_living_dynamic(&self, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> { let p = self.machine_st.p; let indexed_choice_instrs = match &self.code[p] { Instruction::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] { IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => { indexed_choice_instrs } _ => unreachable!(), }, _ => unreachable!(), }; loop { match &indexed_choice_instrs.get(ii as usize) { Some(&offset) => match &self.code[p + offset - 1] { &Instruction::DynamicInternalElse( birth, death, next_or_fail, ) => { if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death { return Some((offset, oi, ii, next_or_fail.is_next())); } else { ii += 1; } } _ => unreachable!(), }, None => return None, } } } #[inline(always)] fn execute_switch_on_term(&mut self) { #[inline(always)] fn dynamic_external_of_clause_is_valid(machine: &mut Machine, p: usize) -> bool { match &machine.code[p] { Instruction::DynamicInternalElse(..) => { machine.machine_st.dynamic_mode = FirstOrNext::First; return true; } _ => {} } match &machine.code[p - 1] { &Instruction::DynamicInternalElse(birth, death, _) => { if birth < machine.machine_st.cc && Death::Finite(machine.machine_st.cc) <= death { return true; } else { return false; } } _ => {} } true } let indexing_lines = self.code[self.machine_st.p].to_indexing_line_mut().unwrap(); let mut index = 0; let addr = match &indexing_lines[0] { &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => { self.machine_st.store(self.machine_st.deref(self.machine_st.registers[arg])) } _ => { unreachable!() } }; loop { match &indexing_lines[index] { &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => { let offset = read_heap_cell!(addr, (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => { v } (HeapCellValueTag::PStrLoc | HeapCellValueTag::Lis | HeapCellValueTag::CStr) => { l } (HeapCellValueTag::Fixnum | HeapCellValueTag::Char | HeapCellValueTag::F64) => { c } (HeapCellValueTag::Atom, (_name, arity)) => { // if arity == 0 { c } else { s } debug_assert!(arity == 0); c } (HeapCellValueTag::Str) => { s } (HeapCellValueTag::Cons, ptr) => { match ptr.get_tag() { ArenaHeaderTag::Rational | ArenaHeaderTag::Integer => { c } _ => { IndexingCodePtr::Fail } } } _ => { unreachable!(); } ); match offset { IndexingCodePtr::Fail => { self.machine_st.fail = true; break; } IndexingCodePtr::DynamicExternal(o) => { // either points directly to a // DynamicInternalElse, or just ahead of // one. Or neither! let p = self.machine_st.p; if !dynamic_external_of_clause_is_valid(self, p + o) { self.machine_st.fail = true; } else { self.machine_st.p += o; } break; } IndexingCodePtr::External(o) => { self.machine_st.p += o; break; } IndexingCodePtr::Internal(o) => { index += o; } } } &IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => { let lit = read_heap_cell!(addr, (HeapCellValueTag::Char, c) => { Literal::Char(c) } (HeapCellValueTag::Fixnum, n) => { Literal::Fixnum(n) } (HeapCellValueTag::F64, f) => { Literal::Float(f) } (HeapCellValueTag::Atom, (atom, arity)) => { debug_assert_eq!(arity, 0); Literal::Atom(atom) } (HeapCellValueTag::Cons, cons_ptr) => { match_untyped_arena_ptr!(cons_ptr, (ArenaHeaderTag::Rational, r) => { Literal::Rational(r) } (ArenaHeaderTag::Integer, n) => { Literal::Integer(n) } _ => { unreachable!() } ) } _ => { unreachable!() } ); let offset = match hm.get(&lit) { Some(offset) => *offset, _ => IndexingCodePtr::Fail, }; match offset { IndexingCodePtr::Fail => { self.machine_st.fail = true; break; } IndexingCodePtr::DynamicExternal(o) => { // either points directly to a // DynamicInternalElse, or just ahead of // one. Or neither! let p = self.machine_st.p; if !dynamic_external_of_clause_is_valid(self, p + o) { self.machine_st.fail = true; } else { self.machine_st.p += o; } break; } IndexingCodePtr::External(o) => { self.machine_st.p += o; break; } IndexingCodePtr::Internal(o) => { index += o; } } } &IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => { let offset = read_heap_cell!(addr, (HeapCellValueTag::Atom, (name, arity)) => { match hm.get(&(name, arity)) { Some(offset) => *offset, None => IndexingCodePtr::Fail, } } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]) .get_name_and_arity(); match hm.get(&(name, arity)) { Some(offset) => *offset, None => IndexingCodePtr::Fail, } } _ => { IndexingCodePtr::Fail } ); match offset { IndexingCodePtr::Fail => { self.machine_st.fail = true; break; } IndexingCodePtr::DynamicExternal(o) => { let p = self.machine_st.p; if !dynamic_external_of_clause_is_valid(self, p + o) { self.machine_st.fail = true; } else { self.machine_st.p += o; } break; } IndexingCodePtr::External(o) => { self.machine_st.p += o; break; } IndexingCodePtr::Internal(o) => { index += o; } } } &IndexingLine::IndexedChoice(_) => { self.machine_st.oip = index as u32; self.machine_st.iip = 0; break; } &IndexingLine::DynamicIndexedChoice(_) => { self.machine_st.dynamic_mode = FirstOrNext::First; self.machine_st.oip = index as u32; self.machine_st.iip = 0; break; } } } } #[inline(always)] pub(super) fn dispatch_loop(&mut self) { 'outer: loop { for _ in 0 .. INSTRUCTIONS_PER_INTERRUPT_POLL { match &self.code[self.machine_st.p] { &Instruction::BreakFromDispatchLoop => { break 'outer; } &Instruction::InstallVerifyAttr => { self.machine_st.p = self.machine_st.attr_var_init.p; if self.code[self.machine_st.p].is_execute() { self.machine_st.p = self.machine_st.attr_var_init.cp; } else { self.machine_st.p += 1; self.machine_st.cp = self.machine_st.attr_var_init.cp; } let mut p = self.machine_st.p; while self.code[p].is_head_instr() { p += 1; } let instr = std::mem::replace( &mut self.code[p], Instruction::VerifyAttrInterrupt, ); self.code[VERIFY_ATTR_INTERRUPT_LOC] = instr; self.machine_st.attr_var_init.cp = p; } &Instruction::VerifyAttrInterrupt => { let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity(); let arity = std::cmp::max(arity, self.machine_st.num_of_args); self.run_verify_attr_interrupt(arity); } &Instruction::Add(ref a1, ref a2, t) => { let stub_gen = || functor_stub(atom!("is"), 2); let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, try_numeric_result!(add(n1, n2, &mut self.machine_st.arena), stub_gen) ); self.machine_st.p += 1; } &Instruction::Sub(ref a1, ref a2, t) => { let stub_gen = || functor_stub(atom!("is"), 2); let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, try_numeric_result!(sub(n1, n2, &mut self.machine_st.arena), stub_gen) ); self.machine_st.p += 1; } &Instruction::Mul(ref a1, ref a2, t) => { let stub_gen = || functor_stub(atom!("is"), 2); let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, try_numeric_result!(mul(n1, n2, &mut self.machine_st.arena), stub_gen) ); self.machine_st.p += 1; } &Instruction::Max(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, max(n1, n2) ); self.machine_st.p += 1; } &Instruction::Min(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, min(n1, n2) ); self.machine_st.p += 1; } &Instruction::IntPow(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, int_pow(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Gcd(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, gcd(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Pow(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, pow(n1, n2, atom!("**")) ); self.machine_st.p += 1; } &Instruction::RDiv(ref a1, ref a2, t) => { let stub_gen = || functor_stub(atom!("(rdiv)"), 2); let r1 = try_or_throw!(self.machine_st, self.machine_st.get_rational(a1, stub_gen)); let r2 = try_or_throw!(self.machine_st, self.machine_st.get_rational(a2, stub_gen)); self.machine_st.interms[t - 1] = Number::Rational(arena_alloc!( try_or_throw_gen!(&mut self.machine_st, rdiv(r1, r2)), self.machine_st.arena )); self.machine_st.p += 1; } &Instruction::IntFloorDiv(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, int_floor_div(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::IDiv(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, idiv(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Abs(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = abs(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } &Instruction::Sign(ref a1, t) => { let n = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = n.sign(); self.machine_st.p += 1; } &Instruction::Neg(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = neg(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } &Instruction::BitwiseComplement(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, bitwise_complement(n1, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Div(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, div(n1, n2) ); self.machine_st.p += 1; } &Instruction::Shr(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, shr(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Shl(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, shl(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Xor(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, xor(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::And(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, and(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Or(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, or(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Mod(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, modulus(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Rem(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = try_or_throw_gen!( &mut self.machine_st, remainder(n1, n2, &mut self.machine_st.arena) ); self.machine_st.p += 1; } &Instruction::Cos(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, cos(n1)) )); self.machine_st.p += 1; } &Instruction::Sin(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, sin(n1)) )); self.machine_st.p += 1; } &Instruction::Tan(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, tan(n1)) )); self.machine_st.p += 1; } &Instruction::Sqrt(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, sqrt(n1)) )); self.machine_st.p += 1; } &Instruction::Log(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, log(n1)) )); self.machine_st.p += 1; } &Instruction::Exp(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, exp(n1)) )); self.machine_st.p += 1; } &Instruction::ACos(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, acos(n1)) )); self.machine_st.p += 1; } &Instruction::ASin(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, asin(n1)) )); self.machine_st.p += 1; } &Instruction::ATan(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, atan(n1)) )); self.machine_st.p += 1; } &Instruction::ATan2(ref a1, ref a2, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, atan2(n1, n2)) )); self.machine_st.p += 1; } &Instruction::Float(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = Number::Float(OrderedFloat( try_or_throw_gen!(&mut self.machine_st, float(n1)) )); self.machine_st.p += 1; } &Instruction::Truncate(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = truncate(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } &Instruction::Round(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = try_or_throw_gen!(&mut self.machine_st, round(n1, &mut self.machine_st.arena)); self.machine_st.p += 1; } &Instruction::Ceiling(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = ceiling(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } &Instruction::Floor(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = floor(n1, &mut self.machine_st.arena); self.machine_st.p += 1; } &Instruction::Plus(ref a1, t) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1)); self.machine_st.interms[t - 1] = n1; self.machine_st.p += 1; } &Instruction::DynamicElse(..) => { if let FirstOrNext::First = self.machine_st.dynamic_mode { self.machine_st.cc = self.machine_st.global_clock; } let p = self.machine_st.p; match self.find_living_dynamic_else(p) { Some((p, next_i)) => { self.machine_st.p = p; self.machine_st.oip = 0; self.machine_st.iip = 0; match self.machine_st.dynamic_mode { FirstOrNext::First if next_i == 0 => { self.machine_st.p += 1; } FirstOrNext::First => { self.machine_st.cc = self.machine_st.global_clock; match self.find_living_dynamic_else(p + next_i) { Some(_) => { self.machine_st.registers[self.machine_st.num_of_args + 1] = fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64)); self.machine_st.num_of_args += 1; self.machine_st.try_me_else(next_i); self.machine_st.num_of_args -= 1; } None => { self.machine_st.p += 1; } } } FirstOrNext::Next => { let n = self.machine_st .stack .index_or_frame(self.machine_st.b) .prelude .univ_prelude .num_cells; self.machine_st.cc = cell_as_fixnum!( self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)] ).get_num() as usize; if next_i > 0 { match self.find_living_dynamic_else(p + next_i) { Some(_) => { self.retry_me_else(next_i); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } None => { self.trust_me(); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } else { self.trust_me(); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } } None => { self.machine_st.fail = true; } } self.machine_st.dynamic_mode = FirstOrNext::Next; if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::DynamicInternalElse(..) => { let p = self.machine_st.p; match self.find_living_dynamic_else(p) { Some((p, next_i)) => { self.machine_st.p = p; self.machine_st.oip = 0; self.machine_st.iip = 0; match self.machine_st.dynamic_mode { FirstOrNext::First if next_i == 0 => { self.machine_st.p += 1; } FirstOrNext::First => { match self.find_living_dynamic_else(p + next_i) { Some(_) => { self.machine_st.registers[self.machine_st.num_of_args + 1] = fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64)); self.machine_st.num_of_args += 1; self.machine_st.try_me_else(next_i); self.machine_st.num_of_args -= 1; } None => { self.machine_st.p += 1; } } } FirstOrNext::Next => { let n = self.machine_st .stack .index_or_frame(self.machine_st.b) .prelude .univ_prelude .num_cells; self.machine_st.cc = cell_as_fixnum!( self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)] ).get_num() as usize; if next_i > 0 { match self.find_living_dynamic_else(p + next_i) { Some(_) => { self.retry_me_else(next_i); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } None => { self.trust_me(); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } else { self.trust_me(); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } } None => { self.machine_st.fail = true; } } self.machine_st.dynamic_mode = FirstOrNext::Next; if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::TryMeElse(offset) => { self.machine_st.try_me_else(offset); } &Instruction::DefaultRetryMeElse(offset) => { self.retry_me_else(offset); } &Instruction::DefaultTrustMe(_) => { self.trust_me(); } &Instruction::RetryMeElse(offset) => { self.retry_me_else(offset); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } &Instruction::TrustMe(_) => { self.trust_me(); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } &Instruction::NeckCut => { let b = self.machine_st.b; let b0 = self.machine_st.b0; if b > b0 { self.machine_st.b = b0; if b > self.machine_st.e { self.machine_st.stack.truncate(b); } } self.machine_st.p += 1; } &Instruction::GetLevel(r) => { let b0 = self.machine_st.b0; self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64)); self.machine_st.p += 1; } &Instruction::GetLevelAndUnify(r) => { // let b0 = self.machine_st[perm_v!(1)]; let b0 = cell_as_fixnum!( self.machine_st.stack[stack_loc!(AndFrame, self.machine_st.e, 1)] ); let a = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); // unify_fn!(&mut self.machine_st, a, b0); self.machine_st.unify_fixnum(b0, a); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::Cut(r) => { let value = self.machine_st[r]; self.machine_st.cut_body(value); if self.machine_st.fail { self.machine_st.backtrack(); continue; } if (self.machine_st.run_cleaners_fn)(self) { continue; } self.machine_st.p += 1; } &Instruction::Allocate(num_cells) => { self.machine_st.allocate(num_cells); } &Instruction::DefaultCallAcyclicTerm(_) => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } &Instruction::DefaultExecuteAcyclicTerm(_) => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallArg(_) => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteArg(_) => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::DefaultCallCompare(_) => { try_or_throw!(self.machine_st, self.machine_st.compare()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteCompare(_) => { try_or_throw!(self.machine_st, self.machine_st.compare()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::DefaultCallTermGreaterThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } &Instruction::DefaultExecuteTermGreaterThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } &Instruction::DefaultCallTermLessThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } &Instruction::DefaultExecuteTermLessThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } &Instruction::DefaultCallTermGreaterThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Greater | Ordering::Equal) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Greater | Ordering::Equal) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallTermLessThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Less | Ordering::Equal) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteTermLessThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Less | Ordering::Equal) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallRead(_) => { try_or_throw!(self.machine_st, self.read()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteRead(_) => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallCopyTerm(_) => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteCopyTerm(_) => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallTermEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if self.machine_st.eq_test(a1, a2) { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } &Instruction::DefaultExecuteTermEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if self.machine_st.eq_test(a1, a2) { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallGround(_) => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } &Instruction::DefaultExecuteGround(_) => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallFunctor(_) => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteFunctor(_) => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallTermNotEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } &Instruction::DefaultExecuteTermNotEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallSort(_) => { try_or_throw!(self.machine_st, self.machine_st.sort()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteSort(_) => { try_or_throw!(self.machine_st, self.machine_st.sort()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::DefaultCallKeySort(_) => { try_or_throw!(self.machine_st, self.machine_st.keysort()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteKeySort(_) => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::DefaultCallIs(r, at, _) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::DefaultExecuteIs(r, at, _) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallAcyclicTerm(_) => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteAcyclicTerm(_) => { let addr = self.machine_st.registers[1]; if self.machine_st.is_cyclic_term(addr) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallArg(_) => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteArg(_) => { try_or_throw!(self.machine_st, self.machine_st.try_arg()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallCompare(_) => { try_or_throw!(self.machine_st, self.machine_st.compare()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteCompare(_) => { try_or_throw!(self.machine_st, self.machine_st.compare()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallTermGreaterThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } &Instruction::ExecuteTermGreaterThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } &Instruction::CallTermLessThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } &Instruction::ExecuteTermLessThan(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } &Instruction::CallTermGreaterThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Greater | Ordering::Equal) => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteTermGreaterThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Greater | Ordering::Equal) => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallTermLessThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Less | Ordering::Equal) => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteTermLessThanOrEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; match compare_term_test!(self.machine_st, a1, a2) { Some(Ordering::Less | Ordering::Equal) => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallRead(_) => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteRead(_) => { try_or_throw!(self.machine_st, self.read()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallCopyTerm(_) => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteCopyTerm(_) => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallTermEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if self.machine_st.eq_test(a1, a2) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteTermEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if self.machine_st.eq_test(a1, a2) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallGround(_) => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteGround(_) => { if self.machine_st.ground_test() { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallFunctor(_) => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteFunctor(_) => { try_or_throw!(self.machine_st, self.machine_st.try_functor()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallTermNotEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteTermNotEqual(_) => { let a1 = self.machine_st.registers[1]; let a2 = self.machine_st.registers[2]; if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallSort(_) => { try_or_throw!(self.machine_st, self.machine_st.sort()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteSort(_) => { try_or_throw!(self.machine_st, self.machine_st.sort()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallKeySort(_) => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteKeySort(_) => { try_or_throw!(self.machine_st, self.machine_st.keysort()); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallIs(r, at, _) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } &Instruction::ExecuteIs(r, at, _) => { try_or_throw!(self.machine_st, self.machine_st.is(r, at)); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } &Instruction::CallN(arity, _) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { self.machine_st.registers[i - 1] = self.machine_st.registers[i]; } self.machine_st.registers[arity] = pred; try_or_throw!( self.machine_st, self.call_n(atom!("user"), arity) ); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } &Instruction::ExecuteN(arity, _) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { self.machine_st.registers[i - 1] = self.machine_st.registers[i]; } self.machine_st.registers[arity] = pred; try_or_throw!( self.machine_st, self.execute_n(atom!("user"), arity) ); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } &Instruction::DefaultCallN(arity, _) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { self.machine_st.registers[i - 1] = self.machine_st.registers[i]; } self.machine_st.registers[arity] = pred; try_or_throw!( self.machine_st, self.call_n(atom!("user"), arity) ); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::DefaultExecuteN(arity, _) => { let pred = self.machine_st.registers[1]; for i in 2..arity + 1 { self.machine_st.registers[i - 1] = self.machine_st.registers[i]; } self.machine_st.registers[arity] = pred; try_or_throw!( self.machine_st, self.execute_n(atom!("user"), arity) ); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::CallNumberLessThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less | Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less | Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallNumberEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteNumberEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallNumberNotEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.backtrack(); } _ => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } } } &Instruction::ExecuteNumberNotEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.backtrack(); } _ => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } } } &Instruction::CallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater | Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater | Ordering::Equal => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallNumberGreaterThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteNumberGreaterThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallNumberLessThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteNumberLessThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less => { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallNumberLessThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less | Ordering::Equal => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less | Ordering::Equal => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallNumberNotEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.backtrack(); } _ => { self.machine_st.p += 1; } } } &Instruction::DefaultExecuteNumberNotEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.backtrack(); } _ => { self.machine_st.p = self.machine_st.cp; } } } &Instruction::DefaultCallNumberEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteNumberEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Equal => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater | Ordering::Equal => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater | Ordering::Equal => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallNumberGreaterThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteNumberGreaterThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Greater => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultCallNumberLessThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::DefaultExecuteNumberLessThan(ref at_1, ref at_2, _) => { let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1)); let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2)); match n1.cmp(&n2) { Ordering::Less => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } // &Instruction::CallIsAtom(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Atom, (_name, arity)) => { if arity == 0 { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } (HeapCellValueTag::Char) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } ); } &Instruction::ExecuteIsAtom(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Atom, (_name, arity)) => { if arity == 0 { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } (HeapCellValueTag::Char) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } ); } &Instruction::CallIsAtomic(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | HeapCellValueTag::Cons) => { self.machine_st.p += 1; } (HeapCellValueTag::Atom, (_name, arity)) => { if arity == 0 { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } ); } &Instruction::ExecuteIsAtomic(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | HeapCellValueTag::Cons) => { self.machine_st.p = self.machine_st.cp; } (HeapCellValueTag::Atom, (_name, arity)) => { if arity == 0 { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } ); } &Instruction::CallIsCompound(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => { self.machine_st.p += 1; } (HeapCellValueTag::Atom, (_name, arity)) => { if arity > 0 { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } ); } &Instruction::ExecuteIsCompound(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => { self.machine_st.p = self.machine_st.cp; } (HeapCellValueTag::Atom, (_name, arity)) => { if arity > 0 { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } ); } &Instruction::CallIsInteger(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(Number::Fixnum(_) | Number::Integer(_)) => { self.machine_st.p += 1; } Ok(Number::Rational(n)) => { if n.denom() == &1 { self.machine_st.p += 1; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteIsInteger(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(Number::Fixnum(_) | Number::Integer(_)) => { self.machine_st.p = self.machine_st.cp; } Ok(Number::Rational(n)) => { if n.denom() == &1 { self.machine_st.p = self.machine_st.cp; } else { self.machine_st.backtrack(); } } _ => { self.machine_st.backtrack(); } } } &Instruction::CallIsNumber(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(_) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteIsNumber(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(_) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallIsRational(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Cons, ptr) => { match_untyped_arena_ptr!(ptr, (ArenaHeaderTag::Rational, _r) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } ); } _ => { self.machine_st.backtrack(); } ); } &Instruction::ExecuteIsRational(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, (HeapCellValueTag::Cons, ptr) => { match_untyped_arena_ptr!(ptr, (ArenaHeaderTag::Rational, _r) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } ); } _ => { self.machine_st.backtrack(); } ); } &Instruction::CallIsFloat(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(Number::Float(_)) => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteIsFloat(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match Number::try_from(d) { Ok(Number::Float(_)) => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallIsNonVar(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar => { self.machine_st.backtrack(); } _ => { self.machine_st.p += 1; } } } &Instruction::ExecuteIsNonVar(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar => { self.machine_st.backtrack(); } _ => { self.machine_st.p = self.machine_st.cp; } } } &Instruction::CallIsVar(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar => { self.machine_st.p += 1; } _ => { self.machine_st.backtrack(); } } } &Instruction::ExecuteIsVar(r, _) => { let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r])); match d.get_tag() { HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar => { self.machine_st.p = self.machine_st.cp; } _ => { self.machine_st.backtrack(); } } } &Instruction::CallNamed(arity, name, ref idx, _) => { let idx = idx.get(); try_or_throw!( self.machine_st, self.try_call(name, arity, idx) ); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } &Instruction::ExecuteNamed(arity, name, ref idx, _) => { let idx = idx.get(); try_or_throw!( self.machine_st, self.try_execute(name, arity, idx) ); if self.machine_st.fail { self.machine_st.backtrack(); } else { try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } &Instruction::DefaultCallNamed(arity, name, ref idx, _) => { let idx = idx.get(); try_or_throw!( self.machine_st, self.try_call(name, arity, idx) ); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::DefaultExecuteNamed(arity, name, ref idx, _) => { let idx = idx.get(); try_or_throw!( self.machine_st, self.try_execute(name, arity, idx) ); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::Deallocate => { self.machine_st.deallocate() } &Instruction::JmpByCall(arity, offset, _) => { self.machine_st.num_of_args = arity; self.machine_st.b0 = self.machine_st.b; self.machine_st.cp = self.machine_st.p + 1; self.machine_st.p += offset; } &Instruction::JmpByExecute(arity, offset, _) => { self.machine_st.num_of_args = arity; self.machine_st.b0 = self.machine_st.b; self.machine_st.p += offset; } &Instruction::RevJmpBy(offset) => { self.machine_st.p -= offset; } &Instruction::Proceed => { self.machine_st.p = self.machine_st.cp; } &Instruction::GetConstant(_, c, reg) => { let value = self.machine_st.deref(self.machine_st[reg]); self.machine_st.write_literal_to_var(value, c); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::GetList(_, reg) => { let deref_v = self.machine_st.deref(self.machine_st[reg]); let store_v = self.machine_st.store(deref_v); read_heap_cell!(store_v, (HeapCellValueTag::PStrLoc, h) => { let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, h); self.machine_st.s = HeapPtr::PStrChar(h, n.get_num() as usize); self.machine_st.s_offset = 0; self.machine_st.mode = MachineMode::Read; } (HeapCellValueTag::CStr) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(store_v); self.machine_st.s = HeapPtr::PStrChar(h, 0); self.machine_st.s_offset = 0; self.machine_st.mode = MachineMode::Read; } (HeapCellValueTag::Lis, l) => { self.machine_st.s = HeapPtr::HeapCell(l); self.machine_st.s_offset = 0; self.machine_st.mode = MachineMode::Read; } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(list_loc_as_cell!(h+1)); self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h)); self.machine_st.mode = MachineMode::Write; } _ => { self.machine_st.backtrack(); continue; } ); self.machine_st.p += 1; } &Instruction::GetPartialString(_, string, reg, has_tail) => { let deref_v = self.machine_st.deref(self.machine_st[reg]); let store_v = self.machine_st.store(deref_v); read_heap_cell!(store_v, (HeapCellValueTag::Str | HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var | HeapCellValueTag::CStr) => { self.machine_st.match_partial_string(store_v, string, has_tail); } _ => { self.machine_st.backtrack(); continue; } ); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::GetStructure(name, arity, reg) => { let deref_v = self.machine_st.deref(self.machine_st[reg]); let store_v = self.machine_st.store(deref_v); read_heap_cell!(store_v, (HeapCellValueTag::Str, a) => { read_heap_cell!(self.machine_st.heap[a], (HeapCellValueTag::Atom, (result_name, result_arity)) => { if arity == result_arity && name == result_name { self.machine_st.s = HeapPtr::HeapCell(a + 1); self.machine_st.s_offset = 0; self.machine_st.mode = MachineMode::Read; } else { self.machine_st.backtrack(); continue; } } _ => { unreachable!(); } ); } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(str_loc_as_cell!(h+1)); self.machine_st.heap.push(atom_as_cell!(name, arity)); self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h)); self.machine_st.mode = MachineMode::Write; } _ => { self.machine_st.backtrack(); continue; } ); self.machine_st.p += 1; } &Instruction::GetVariable(norm, arg) => { self.machine_st[norm] = self.machine_st.registers[arg]; self.machine_st.p += 1; } &Instruction::GetValue(norm, arg) => { let norm_addr = self.machine_st[norm]; let reg_addr = self.machine_st.registers[arg]; unify_fn!(&mut self.machine_st, norm_addr, reg_addr); if self.machine_st.fail { self.machine_st.backtrack(); continue; } self.machine_st.p += 1; } &Instruction::UnifyConstant(v) => { match self.machine_st.mode { MachineMode::Read => { let addr = self.machine_st.read_s(); self.machine_st.write_literal_to_var(addr, v); if self.machine_st.fail { self.machine_st.backtrack(); continue; } else { self.machine_st.s_offset += 1; } } MachineMode::Write => { self.machine_st.heap.push(v); } } self.machine_st.p += 1; } &Instruction::UnifyLocalValue(reg) => { match self.machine_st.mode { MachineMode::Read => { let reg_addr = self.machine_st[reg]; let value = self.machine_st.read_s(); unify_fn!(&mut self.machine_st, reg_addr, value); if self.machine_st.fail { self.machine_st.backtrack(); continue; } else { self.machine_st.s_offset += 1; } } MachineMode::Write => { let value = self.machine_st.store(self.machine_st.deref(self.machine_st[reg])); let h = self.machine_st.heap.len(); read_heap_cell!(value, (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => { let value = self.machine_st.heap[hc]; self.machine_st.heap.push(value); self.machine_st.s_offset += 1; } _ => { self.machine_st.heap.push(heap_loc_as_cell!(h)); (self.machine_st.bind_fn)( &mut self.machine_st, Ref::heap_cell(h), value, ); } ); } } self.machine_st.p += 1; } &Instruction::UnifyVariable(reg) => { match self.machine_st.mode { MachineMode::Read => { self.machine_st[reg] = self.machine_st.read_s(); self.machine_st.s_offset += 1; } MachineMode::Write => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); self.machine_st[reg] = heap_loc_as_cell!(h); } } self.machine_st.p += 1; } &Instruction::UnifyValue(reg) => { match self.machine_st.mode { MachineMode::Read => { let reg_addr = self.machine_st[reg]; let value = self.machine_st.read_s(); unify_fn!(&mut self.machine_st, reg_addr, value); if self.machine_st.fail { self.machine_st.backtrack(); continue; } else { self.machine_st.s_offset += 1; } } MachineMode::Write => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); let addr = self.machine_st.store(self.machine_st[reg]); (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr); // the former code of this match arm was: // let addr = self.machine_st.store(self.machine_st[reg]); // self.machine_st.heap.push(HeapCellValue::Addr(addr)); // the old code didn't perform the occurs // check when enabled and so it was changed to // the above, which is only slightly less // efficient when the occurs_check is disabled. } } self.machine_st.p += 1; } &Instruction::UnifyVoid(n) => { match self.machine_st.mode { MachineMode::Read => { self.machine_st.s_offset += n; } MachineMode::Write => { let h = self.machine_st.heap.len(); for i in h..h + n { self.machine_st.heap.push(heap_loc_as_cell!(i)); } } } self.machine_st.p += 1; } &Instruction::IndexingCode(ref indexing_lines) => { match &indexing_lines[self.machine_st.oip as usize] { IndexingLine::Indexing(_) => { self.execute_switch_on_term(); if self.machine_st.fail { self.machine_st.backtrack(); } } IndexingLine::IndexedChoice(ref indexed_choice) => { match &indexed_choice[self.machine_st.iip as usize] { &IndexedChoiceInstruction::Try(offset) => { self.machine_st.indexed_try(offset); } &IndexedChoiceInstruction::Retry(l) => { self.retry(l); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } &IndexedChoiceInstruction::Trust(l) => { self.trust(l); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } IndexingLine::DynamicIndexedChoice(_) => { let p = self.machine_st.p; match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip) { Some((offset, oi, ii, is_next_clause)) => { self.machine_st.p = p; self.machine_st.oip = oi; self.machine_st.iip = ii; match self.machine_st.dynamic_mode { FirstOrNext::First if !is_next_clause => { self.machine_st.p = p + offset; } FirstOrNext::First => { // there's a leading DynamicElse that sets self.machine_st.cc. // self.machine_st.cc = self.machine_st.global_clock; // see that there is a following dynamic_else // clause so we avoid generating a choice // point in case there isn't. match self.find_living_dynamic(oi, ii + 1) { Some(_) => { self.machine_st.registers[self.machine_st.num_of_args + 1] = fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64)); self.machine_st.num_of_args += 1; self.machine_st.indexed_try(offset); self.machine_st.num_of_args -= 1; } None => { self.machine_st.p = p + offset; self.machine_st.oip = 0; self.machine_st.iip = 0; } } } FirstOrNext::Next => { let b = self.machine_st.b; let n = self.machine_st .stack .index_or_frame(b) .prelude .univ_prelude .num_cells; self.machine_st.cc = cell_as_fixnum!( self.machine_st.stack[stack_loc!(OrFrame, b, n-1)] ).get_num() as usize; if is_next_clause { match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip + 1) { // if we're executing the last instruction // of the internal block pointed to by // self.machine_st.iip, we want trust, not retry. // this is true iff ii + 1 < len. Some(_) => { self.retry(offset); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } _ => { self.trust(offset); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } else { self.trust(offset); try_or_throw!( self.machine_st, (self.machine_st.increment_call_count_fn)(&mut self.machine_st) ); } } } } None => { self.machine_st.fail = true; } } self.machine_st.dynamic_mode = FirstOrNext::Next; if self.machine_st.fail { self.machine_st.backtrack(); } } } } &Instruction::PutConstant(_, c, reg) => { self.machine_st[reg] = c; self.machine_st.p += 1; } &Instruction::PutList(_, reg) => { self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.len()); self.machine_st.p += 1; } &Instruction::PutPartialString(_, string, reg, has_tail) => { let pstr_addr = if has_tail { if string != atom!("") { let h = self.machine_st.heap.len(); self.machine_st.heap.push(string_as_pstr_cell!(string)); // the tail will be pushed by the next // instruction, so don't push one here. pstr_loc_as_cell!(h) } else { empty_list_as_cell!() } } else { string_as_cstr_cell!(string) }; self.machine_st[reg] = pstr_addr; self.machine_st.p += 1; } &Instruction::PutStructure(name, arity, reg) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(atom_as_cell!(name, arity)); self.machine_st[reg] = str_loc_as_cell!(h); self.machine_st.p += 1; } &Instruction::PutUnsafeValue(n, arg) => { let s = stack_loc!(AndFrame, self.machine_st.e, n); let addr = self.machine_st.store(self.machine_st.deref(stack_loc_as_cell!(s))); if addr.is_protected(self.machine_st.e) { self.machine_st.registers[arg] = addr; } else { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr); self.machine_st.registers[arg] = heap_loc_as_cell!(h); } self.machine_st.p += 1; } &Instruction::PutValue(norm, arg) => { self.machine_st.registers[arg] = self.machine_st[norm]; self.machine_st.p += 1; } &Instruction::PutVariable(norm, arg) => { match norm { RegType::Perm(n) => { self.machine_st[norm] = stack_loc_as_cell!(AndFrame, self.machine_st.e, n); self.machine_st.registers[arg] = self.machine_st[norm]; } RegType::Temp(_) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); self.machine_st[norm] = heap_loc_as_cell!(h); self.machine_st.registers[arg] = heap_loc_as_cell!(h); } }; self.machine_st.p += 1; } &Instruction::SetConstant(c) => { self.machine_st.heap.push(c); self.machine_st.p += 1; } &Instruction::SetLocalValue(reg) => { let addr = self.machine_st.deref(self.machine_st[reg]); let stored_v = self.machine_st.store(addr); if stored_v.is_stack_var() { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), stored_v); } else { self.machine_st.heap.push(stored_v); } self.machine_st.p += 1; } &Instruction::SetVariable(reg) => { let h = self.machine_st.heap.len(); self.machine_st.heap.push(heap_loc_as_cell!(h)); self.machine_st[reg] = heap_loc_as_cell!(h); self.machine_st.p += 1; } &Instruction::SetValue(reg) => { let heap_val = self.machine_st.store(self.machine_st[reg]); self.machine_st.heap.push(heap_val); self.machine_st.p += 1; } &Instruction::SetVoid(n) => { let h = self.machine_st.heap.len(); for i in h..h + n { self.machine_st.heap.push(heap_loc_as_cell!(i)); } self.machine_st.p += 1; } // &Instruction::CallAtomChars(_) => { self.atom_chars(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteAtomChars(_) => { self.atom_chars(); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::CallAtomCodes(_) => { try_or_throw!(self.machine_st, self.atom_codes()); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p += 1; } } &Instruction::ExecuteAtomCodes(_) => { try_or_throw!(self.machine_st, self.atom_codes()); if self.machine_st.fail { self.machine_st.backtrack(); } else { self.machine_st.p = self.machine_st.cp; } } &Instruction::CallAtomLength(_) => { self.atom_length(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteAtomLength(_) => { self.atom_length(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallBindFromRegister(_) => { self.bind_from_register(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteBindFromRegister(_) => { self.bind_from_register(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallContinuation(_) => { try_or_throw!(self.machine_st, self.call_continuation(false)); } &Instruction::ExecuteContinuation(_) => { try_or_throw!(self.machine_st, self.call_continuation(true)); } &Instruction::CallCharCode(_) => { try_or_throw!(self.machine_st, self.char_code()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCharCode(_) => { try_or_throw!(self.machine_st, self.char_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCharType(_) => { self.char_type(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCharType(_) => { self.char_type(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCharsToNumber(_) => { try_or_throw!(self.machine_st, self.chars_to_number()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCharsToNumber(_) => { try_or_throw!(self.machine_st, self.chars_to_number()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCodesToNumber(_) => { try_or_throw!(self.machine_st, self.codes_to_number()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCodesToNumber(_) => { try_or_throw!(self.machine_st, self.codes_to_number()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCopyTermWithoutAttrVars(_) => { self.copy_term_without_attr_vars(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCopyTermWithoutAttrVars(_) => { self.copy_term_without_attr_vars(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCheckCutPoint(_) => { self.check_cut_point(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCheckCutPoint(_) => { self.check_cut_point(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallClose(_) => { try_or_throw!(self.machine_st, self.close()); self.machine_st.p += 1; } &Instruction::ExecuteClose(_) => { try_or_throw!(self.machine_st, self.close()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallCopyToLiftedHeap(_) => { self.copy_to_lifted_heap(); self.machine_st.p += 1; } &Instruction::ExecuteCopyToLiftedHeap(_) => { self.copy_to_lifted_heap(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallCreatePartialString(_) => { self.create_partial_string(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCreatePartialString(_) => { self.create_partial_string(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCurrentHostname(_) => { self.current_hostname(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCurrentHostname(_) => { self.current_hostname(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCurrentInput(_) => { try_or_throw!(self.machine_st, self.current_input()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCurrentInput(_) => { try_or_throw!(self.machine_st, self.current_input()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCurrentOutput(_) => { try_or_throw!(self.machine_st, self.current_output()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCurrentOutput(_) => { try_or_throw!(self.machine_st, self.current_output()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDirectoryFiles(_) => { try_or_throw!(self.machine_st, self.directory_files()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDirectoryFiles(_) => { try_or_throw!(self.machine_st, self.directory_files()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFileSize(_) => { self.file_size(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFileSize(_) => { self.file_size(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFileExists(_) => { self.file_exists(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFileExists(_) => { self.file_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDirectoryExists(_) => { self.directory_exists(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDirectoryExists(_) => { self.directory_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDirectorySeparator(_) => { self.directory_separator(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDirectorySeparator(_) => { self.directory_separator(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallMakeDirectory(_) => { self.make_directory(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteMakeDirectory(_) => { self.make_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallMakeDirectoryPath(_) => { self.make_directory_path(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteMakeDirectoryPath(_) => { self.make_directory_path(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDeleteFile(_) => { self.delete_file(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDeleteFile(_) => { self.delete_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallRenameFile(_) => { self.rename_file(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteRenameFile(_) => { self.rename_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallWorkingDirectory(_) => { try_or_throw!(self.machine_st, self.working_directory()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteWorkingDirectory(_) => { try_or_throw!(self.machine_st, self.working_directory()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDeleteDirectory(_) => { self.delete_directory(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDeleteDirectory(_) => { self.delete_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPathCanonical(_) => { try_or_throw!(self.machine_st, self.path_canonical()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePathCanonical(_) => { try_or_throw!(self.machine_st, self.path_canonical()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFileTime(_) => { self.file_time(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFileTime(_) => { self.file_time(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDeleteAttribute(_) => { self.delete_attribute(); self.machine_st.p += 1; } &Instruction::ExecuteDeleteAttribute(_) => { self.delete_attribute(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallDeleteHeadAttribute(_) => { self.delete_head_attribute(); self.machine_st.p += 1; } &Instruction::ExecuteDeleteHeadAttribute(_) => { self.delete_head_attribute(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallDynamicModuleResolution(arity, _) => { let (module_name, key) = try_or_throw!( self.machine_st, self.dynamic_module_resolution(arity - 2) ); try_or_throw!(self.machine_st, self.call_clause(module_name, key)); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::ExecuteDynamicModuleResolution(arity, _) => { let (module_name, key) = try_or_throw!( self.machine_st, self.dynamic_module_resolution(arity - 2) ); try_or_throw!(self.machine_st, self.execute_clause(module_name, key)); if self.machine_st.fail { self.machine_st.backtrack(); } } &Instruction::CallEnqueueAttributedVar(_) => { self.enqueue_attributed_var(); self.machine_st.p += 1; } &Instruction::ExecuteEnqueueAttributedVar(_) => { self.enqueue_attributed_var(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallFetchGlobalVar(_) => { self.fetch_global_var(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFetchGlobalVar(_) => { self.fetch_global_var(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFirstStream(_) => { self.first_stream(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFirstStream(_) => { self.first_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFlushOutput(_) => { try_or_throw!(self.machine_st, self.flush_output()); self.machine_st.p += 1; } &Instruction::ExecuteFlushOutput(_) => { try_or_throw!(self.machine_st, self.flush_output()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallGetByte(_) => { try_or_throw!(self.machine_st, self.get_byte()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetByte(_) => { try_or_throw!(self.machine_st, self.get_byte()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetChar(_) => { try_or_throw!(self.machine_st, self.get_char()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetChar(_) => { try_or_throw!(self.machine_st, self.get_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetNChars(_) => { try_or_throw!(self.machine_st, self.get_n_chars()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetNChars(_) => { try_or_throw!(self.machine_st, self.get_n_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetCode(_) => { try_or_throw!(self.machine_st, self.get_code()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetCode(_) => { try_or_throw!(self.machine_st, self.get_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetSingleChar(_) => { try_or_throw!(self.machine_st, self.get_single_char()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetSingleChar(_) => { try_or_throw!(self.machine_st, self.get_single_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallResetAttrVarState(_) => { self.reset_attr_var_state(); self.machine_st.p += 1; } &Instruction::ExecuteResetAttrVarState(_) => { self.reset_attr_var_state(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) => { self.truncate_if_no_lifted_heap_growth_diff(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) => { self.truncate_if_no_lifted_heap_growth_diff(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) => { self.truncate_if_no_lifted_heap_growth(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) => { self.truncate_if_no_lifted_heap_growth(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetAttributedVariableList(_) => { self.get_attributed_variable_list(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetAttributedVariableList(_) => { self.get_attributed_variable_list(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetAttrVarQueueDelimiter(_) => { self.get_attr_var_queue_delimiter(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetAttrVarQueueDelimiter(_) => { self.get_attr_var_queue_delimiter(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetAttrVarQueueBeyond(_) => { self.get_attr_var_queue_beyond(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetAttrVarQueueBeyond(_) => { self.get_attr_var_queue_beyond(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetBValue(_) => { self.get_b_value(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetBValue(_) => { self.get_b_value(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetContinuationChunk(_) => { self.get_continuation_chunk(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetContinuationChunk(_) => { self.get_continuation_chunk(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetNextDBRef(_) => { self.get_next_db_ref(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetNextDBRef(_) => { self.get_next_db_ref(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetNextOpDBRef(_) => { self.get_next_op_db_ref(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetNextOpDBRef(_) => { self.get_next_op_db_ref(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallIsPartialString(_) => { self.is_partial_string(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteIsPartialString(_) => { self.is_partial_string(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallHalt(_) => { self.halt(); self.machine_st.p += 1; } &Instruction::ExecuteHalt(_) => { self.halt(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallGetLiftedHeapFromOffset(_) => { self.get_lifted_heap_from_offset(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetLiftedHeapFromOffset(_) => { self.get_lifted_heap_from_offset(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetLiftedHeapFromOffsetDiff(_) => { self.get_lifted_heap_from_offset_diff(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) => { self.get_lifted_heap_from_offset_diff(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetSCCCleaner(_) => { self.get_scc_cleaner(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetSCCCleaner(_) => { self.get_scc_cleaner(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallHeadIsDynamic(_) => { self.head_is_dynamic(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteHeadIsDynamic(_) => { self.head_is_dynamic(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallInstallSCCCleaner(_) => { self.install_scc_cleaner(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteInstallSCCCleaner(_) => { self.install_scc_cleaner(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallInstallInferenceCounter(_) => { try_or_throw!(self.machine_st, self.install_inference_counter()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteInstallInferenceCounter(_) => { try_or_throw!(self.machine_st, self.install_inference_counter()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLiftedHeapLength(_) => { self.lifted_heap_length(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLiftedHeapLength(_) => { self.lifted_heap_length(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadLibraryAsStream(_) => { try_or_throw!(self.machine_st, self.load_library_as_stream()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadLibraryAsStream(_) => { try_or_throw!(self.machine_st, self.load_library_as_stream()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallModuleExists(_) => { self.module_exists(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteModuleExists(_) => { self.module_exists(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallNextEP(_) => { self.next_ep(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteNextEP(_) => { self.next_ep(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallNoSuchPredicate(_) => { try_or_throw!(self.machine_st, self.no_such_predicate()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteNoSuchPredicate(_) => { try_or_throw!(self.machine_st, self.no_such_predicate()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallNumberToChars(_) => { self.number_to_chars(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteNumberToChars(_) => { self.number_to_chars(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallNumberToCodes(_) => { self.number_to_codes(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteNumberToCodes(_) => { self.number_to_codes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallOpDeclaration(_) => { try_or_throw!(self.machine_st, self.op_declaration()); self.machine_st.p += 1; } &Instruction::ExecuteOpDeclaration(_) => { try_or_throw!(self.machine_st, self.op_declaration()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallOpen(_) => { try_or_throw!(self.machine_st, self.open()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteOpen(_) => { try_or_throw!(self.machine_st, self.open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetStreamOptions(_) => { try_or_throw!(self.machine_st, self.set_stream_options()); self.machine_st.p += 1; } &Instruction::ExecuteSetStreamOptions(_) => { try_or_throw!(self.machine_st, self.set_stream_options()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallNextStream(_) => { self.next_stream(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteNextStream(_) => { self.next_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPartialStringTail(_) => { self.partial_string_tail(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePartialStringTail(_) => { self.partial_string_tail(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPeekByte(_) => { try_or_throw!(self.machine_st, self.peek_byte()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePeekByte(_) => { try_or_throw!(self.machine_st, self.peek_byte()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPeekChar(_) => { try_or_throw!(self.machine_st, self.peek_char()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePeekChar(_) => { try_or_throw!(self.machine_st, self.peek_char()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPeekCode(_) => { try_or_throw!(self.machine_st, self.peek_code()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePeekCode(_) => { try_or_throw!(self.machine_st, self.peek_code()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPointsToContinuationResetMarker(_) => { self.points_to_continuation_reset_marker(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePointsToContinuationResetMarker(_) => { self.points_to_continuation_reset_marker(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPutByte(_) => { try_or_throw!(self.machine_st, self.put_byte()); self.machine_st.p += 1; } &Instruction::ExecutePutByte(_) => { try_or_throw!(self.machine_st, self.put_byte()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPutChar(_) => { try_or_throw!(self.machine_st, self.put_char()); self.machine_st.p += 1; } &Instruction::ExecutePutChar(_) => { try_or_throw!(self.machine_st, self.put_char()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPutChars(_) => { try_or_throw!(self.machine_st, self.put_chars()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePutChars(_) => { try_or_throw!(self.machine_st, self.put_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPutCode(_) => { try_or_throw!(self.machine_st, self.put_code()); self.machine_st.p += 1; } &Instruction::ExecutePutCode(_) => { try_or_throw!(self.machine_st, self.put_code()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallReadQueryTerm(_) => { try_or_throw!(self.machine_st, self.read_query_term()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteReadQueryTerm(_) => { try_or_throw!(self.machine_st, self.read_query_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallReadTerm(_) => { try_or_throw!(self.machine_st, self.read_term()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteReadTerm(_) => { try_or_throw!(self.machine_st, self.read_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallRedoAttrVarBinding(_) => { self.redo_attr_var_binding(); self.machine_st.p += 1; } &Instruction::ExecuteRedoAttrVarBinding(_) => { self.redo_attr_var_binding(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallRemoveCallPolicyCheck(_) => { self.remove_call_policy_check(); self.machine_st.p += 1; } &Instruction::ExecuteRemoveCallPolicyCheck(_) => { self.remove_call_policy_check(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallRemoveInferenceCounter(_) => { self.remove_inference_counter(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteRemoveInferenceCounter(_) => { self.remove_inference_counter(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallResetContinuationMarker(_) => { self.reset_continuation_marker(); self.machine_st.p += 1; } &Instruction::ExecuteResetContinuationMarker(_) => { self.reset_continuation_marker(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallRestoreCutPolicy(_) => { self.restore_cut_policy(); self.machine_st.p += 1; } &Instruction::ExecuteRestoreCutPolicy(_) => { self.restore_cut_policy(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSetCutPoint(r, _) => { if !self.set_cut_point(r) { step_or_fail!(self, self.machine_st.p += 1); } } &Instruction::ExecuteSetCutPoint(r, _) => { let cp = self.machine_st.cp; if !self.set_cut_point(r) { step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } else { // run_cleaners in set_cut_point calls call_by_index. // replace the effect of call_by_index with that // of execute_by_index here. self.machine_st.cp = cp; } } &Instruction::CallSetInput(_) => { try_or_throw!(self.machine_st, self.set_input()); self.machine_st.p += 1; } &Instruction::ExecuteSetInput(_) => { try_or_throw!(self.machine_st, self.set_input()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSetOutput(_) => { try_or_throw!(self.machine_st, self.set_output()); self.machine_st.p += 1; } &Instruction::ExecuteSetOutput(_) => { try_or_throw!(self.machine_st, self.set_output()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallStoreBacktrackableGlobalVar(_) => { self.store_backtrackable_global_var(); self.machine_st.p += 1; } &Instruction::ExecuteStoreBacktrackableGlobalVar(_) => { self.store_backtrackable_global_var(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallStoreGlobalVar(_) => { self.store_global_var(); self.machine_st.p += 1; } &Instruction::ExecuteStoreGlobalVar(_) => { self.store_global_var(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallStreamProperty(_) => { try_or_throw!(self.machine_st, self.stream_property()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteStreamProperty(_) => { try_or_throw!(self.machine_st, self.stream_property()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetStreamPosition(_) => { try_or_throw!(self.machine_st, self.set_stream_position()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSetStreamPosition(_) => { try_or_throw!(self.machine_st, self.set_stream_position()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallInferenceLevel(_) => { self.inference_level(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteInferenceLevel(_) => { self.inference_level(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCleanUpBlock(_) => { self.clean_up_block(); self.machine_st.p += 1; } &Instruction::ExecuteCleanUpBlock(_) => { self.clean_up_block(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallEraseBall(_) => { self.erase_ball(); self.machine_st.p += 1; } &Instruction::ExecuteEraseBall(_) => { self.erase_ball(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallFail(_) | &Instruction::ExecuteFail(_) => { self.machine_st.backtrack(); } &Instruction::CallGetBall(_) => { self.get_ball(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetBall(_) => { self.get_ball(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetCurrentBlock(_) => { self.get_current_block(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetCurrentBlock(_) => { self.get_current_block(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetCutPoint(_) => { self.get_cut_point(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetCutPoint(_) => { self.get_cut_point(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetStaggeredCutPoint(_) => { self.get_staggered_cut_point(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetStaggeredCutPoint(_) => { self.get_staggered_cut_point(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetDoubleQuotes(_) => { self.get_double_quotes(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetDoubleQuotes(_) => { self.get_double_quotes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallInstallNewBlock(_) => { self.machine_st.install_new_block(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteInstallNewBlock(_) => { self.machine_st.install_new_block(self.machine_st.registers[1]); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallMaybe(_) => { self.maybe(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteMaybe(_) => { self.maybe(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCpuNow(_) => { self.cpu_now(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCpuNow(_) => { self.cpu_now(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDeterministicLengthRundown(_) => { try_or_throw!(self.machine_st, self.det_length_rundown()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDeterministicLengthRundown(_) => { try_or_throw!(self.machine_st, self.det_length_rundown()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallHttpOpen(_) => { try_or_throw!(self.machine_st, self.http_open()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteHttpOpen(_) => { try_or_throw!(self.machine_st, self.http_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCurrentTime(_) => { self.current_time(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCurrentTime(_) => { self.current_time(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallQuotedToken(_) => { self.quoted_token(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteQuotedToken(_) => { self.quoted_token(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallReadTermFromChars(_) => { try_or_throw!(self.machine_st, self.read_term_from_chars()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteReadTermFromChars(_) => { try_or_throw!(self.machine_st, self.read_term_from_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallResetBlock(_) => { self.reset_block(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteResetBlock(_) => { self.reset_block(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallReturnFromVerifyAttr(_) | &Instruction::ExecuteReturnFromVerifyAttr(_) => { self.return_from_verify_attr(); } &Instruction::CallSetBall(_) => { self.set_ball(); self.machine_st.p += 1; } &Instruction::ExecuteSetBall(_) => { self.set_ball(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSetCutPointByDefault(r, _) => { self.set_cut_point_by_default(r); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSetCutPointByDefault(r, _) => { self.set_cut_point_by_default(r); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetDoubleQuotes(_) => { self.set_double_quotes(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSetDoubleQuotes(_) => { self.set_double_quotes(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetSeed(_) => { self.set_seed(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSetSeed(_) => { self.set_seed(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSkipMaxList(_) => { try_or_throw!(self.machine_st, self.machine_st.skip_max_list()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSkipMaxList(_) => { try_or_throw!(self.machine_st, self.machine_st.skip_max_list()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSleep(_) => { self.sleep(); self.machine_st.p += 1; } &Instruction::ExecuteSleep(_) => { self.sleep(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSocketClientOpen(_) => { try_or_throw!(self.machine_st, self.socket_client_open()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSocketClientOpen(_) => { try_or_throw!(self.machine_st, self.socket_client_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSocketServerOpen(_) => { try_or_throw!(self.machine_st, self.socket_server_open()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSocketServerOpen(_) => { try_or_throw!(self.machine_st, self.socket_server_open()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSocketServerAccept(_) => { try_or_throw!(self.machine_st, self.socket_server_accept()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteSocketServerAccept(_) => { try_or_throw!(self.machine_st, self.socket_server_accept()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSocketServerClose(_) => { try_or_throw!(self.machine_st, self.socket_server_close()); self.machine_st.p += 1; } &Instruction::ExecuteSocketServerClose(_) => { try_or_throw!(self.machine_st, self.socket_server_close()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallTLSAcceptClient(_) => { try_or_throw!(self.machine_st, self.tls_accept_client()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTLSAcceptClient(_) => { try_or_throw!(self.machine_st, self.tls_accept_client()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallTLSClientConnect(_) => { try_or_throw!(self.machine_st, self.tls_client_connect()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTLSClientConnect(_) => { try_or_throw!(self.machine_st, self.tls_client_connect()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSucceed(_) => { self.machine_st.p += 1; } &Instruction::ExecuteSucceed(_) => { self.machine_st.p = self.machine_st.cp; } &Instruction::CallTermAttributedVariables(_) => { self.term_attributed_variables(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTermAttributedVariables(_) => { self.term_attributed_variables(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallTermVariables(_) => { self.term_variables(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTermVariables(_) => { self.term_variables(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallTermVariablesUnderMaxDepth(_) => { self.term_variables_under_max_depth(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteTermVariablesUnderMaxDepth(_) => { self.term_variables_under_max_depth(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallTruncateLiftedHeapTo(_) => { self.truncate_lifted_heap_to(); self.machine_st.p += 1; } &Instruction::ExecuteTruncateLiftedHeapTo(_) => { self.truncate_lifted_heap_to(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallUnifyWithOccursCheck(_) => { self.unify_with_occurs_check(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteUnifyWithOccursCheck(_) => { self.unify_with_occurs_check(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallUnwindEnvironments(_) => { if !self.unwind_environments() { self.machine_st.p += 1; } } &Instruction::ExecuteUnwindEnvironments(_) => { if !self.unwind_environments() { self.machine_st.p = self.machine_st.cp; } } &Instruction::CallUnwindStack(_) | &Instruction::ExecuteUnwindStack(_) => { self.machine_st.unwind_stack(); self.machine_st.backtrack(); } &Instruction::CallWAMInstructions(_) => { try_or_throw!(self.machine_st, self.wam_instructions()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteWAMInstructions(_) => { try_or_throw!(self.machine_st, self.wam_instructions()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallWriteTerm(_) => { try_or_throw!(self.machine_st, self.write_term()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteWriteTerm(_) => { try_or_throw!(self.machine_st, self.write_term()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallWriteTermToChars(_) => { try_or_throw!(self.machine_st, self.write_term_to_chars()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteWriteTermToChars(_) => { try_or_throw!(self.machine_st, self.write_term_to_chars()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallScryerPrologVersion(_) => { self.scryer_prolog_version(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteScryerPrologVersion(_) => { self.scryer_prolog_version(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoRandomByte(_) => { self.crypto_random_byte(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoRandomByte(_) => { self.crypto_random_byte(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoDataHash(_) => { self.crypto_data_hash(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoDataHash(_) => { self.crypto_data_hash(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoDataHKDF(_) => { self.crypto_data_hkdf(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoDataHKDF(_) => { self.crypto_data_hkdf(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoPasswordHash(_) => { self.crypto_password_hash(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoPasswordHash(_) => { self.crypto_password_hash(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoDataEncrypt(_) => { self.crypto_data_encrypt(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoDataEncrypt(_) => { self.crypto_data_encrypt(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoDataDecrypt(_) => { self.crypto_data_decrypt(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoDataDecrypt(_) => { self.crypto_data_decrypt(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCryptoCurveScalarMult(_) => { self.crypto_curve_scalar_mult(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCryptoCurveScalarMult(_) => { self.crypto_curve_scalar_mult(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallEd25519Sign(_) => { self.ed25519_sign(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteEd25519Sign(_) => { self.ed25519_sign(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallEd25519Verify(_) => { self.ed25519_verify(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteEd25519Verify(_) => { self.ed25519_verify(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallEd25519NewKeyPair(_) => { self.ed25519_new_key_pair(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteEd25519NewKeyPair(_) => { self.ed25519_new_key_pair(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallEd25519KeyPairPublicKey(_) => { self.ed25519_key_pair_public_key(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteEd25519KeyPairPublicKey(_) => { self.ed25519_key_pair_public_key(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCurve25519ScalarMult(_) => { self.curve25519_scalar_mult(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCurve25519ScalarMult(_) => { self.curve25519_scalar_mult(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFirstNonOctet(_) => { self.first_non_octet(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFirstNonOctet(_) => { self.first_non_octet(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadHTML(_) => { self.load_html(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadHTML(_) => { self.load_html(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadXML(_) => { self.load_xml(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadXML(_) => { self.load_xml(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallGetEnv(_) => { self.get_env(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteGetEnv(_) => { self.get_env(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetEnv(_) => { self.set_env(); self.machine_st.p += 1; } &Instruction::ExecuteSetEnv(_) => { self.set_env(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallUnsetEnv(_) => { self.unset_env(); self.machine_st.p += 1; } &Instruction::ExecuteUnsetEnv(_) => { self.unset_env(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallShell(_) => { self.shell(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteShell(_) => { self.shell(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPID(_) => { self.pid(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePID(_) => { self.pid(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallCharsBase64(_) => { try_or_throw!(self.machine_st, self.chars_base64()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteCharsBase64(_) => { try_or_throw!(self.machine_st, self.chars_base64()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDevourWhitespace(_) => { try_or_throw!(self.machine_st, self.devour_whitespace()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDevourWhitespace(_) => { try_or_throw!(self.machine_st, self.devour_whitespace()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallIsSTOEnabled(_) => { self.is_sto_enabled(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteIsSTOEnabled(_) => { self.is_sto_enabled(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallSetSTOAsUnify(_) => { self.set_sto_as_unify(); self.machine_st.p += 1; } &Instruction::ExecuteSetSTOAsUnify(_) => { self.set_sto_as_unify(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSetNSTOAsUnify(_) => { self.set_nsto_as_unify(); self.machine_st.p += 1; } &Instruction::ExecuteSetNSTOAsUnify(_) => { self.set_nsto_as_unify(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallSetSTOWithErrorAsUnify(_) => { self.set_sto_with_error_as_unify(); self.machine_st.p += 1; } &Instruction::ExecuteSetSTOWithErrorAsUnify(_) => { self.set_sto_with_error_as_unify(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallHomeDirectory(_) => { self.home_directory(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteHomeDirectory(_) => { self.home_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDebugHook(_) => { self.debug_hook(); self.machine_st.p += 1; } &Instruction::ExecuteDebugHook(_) => { self.debug_hook(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPopCount(_) => { self.pop_count(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePopCount(_) => { self.pop_count(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallAddDiscontiguousPredicate(_) => { try_or_throw!(self.machine_st, self.add_discontiguous_predicate()); self.machine_st.p += 1; } &Instruction::ExecuteAddDiscontiguousPredicate(_) => { try_or_throw!(self.machine_st, self.add_discontiguous_predicate()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddDynamicPredicate(_) => { try_or_throw!(self.machine_st, self.add_dynamic_predicate()); self.machine_st.p += 1; } &Instruction::ExecuteAddDynamicPredicate(_) => { try_or_throw!(self.machine_st, self.add_dynamic_predicate()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddMultifilePredicate(_) => { try_or_throw!(self.machine_st, self.add_multifile_predicate()); self.machine_st.p += 1; } &Instruction::ExecuteAddMultifilePredicate(_) => { try_or_throw!(self.machine_st, self.add_multifile_predicate()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddGoalExpansionClause(_) => { try_or_throw!(self.machine_st, self.add_goal_expansion_clause()); self.machine_st.p += 1; } &Instruction::ExecuteAddGoalExpansionClause(_) => { try_or_throw!(self.machine_st, self.add_goal_expansion_clause()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddTermExpansionClause(_) => { try_or_throw!(self.machine_st, self.add_term_expansion_clause()); self.machine_st.p += 1; } &Instruction::ExecuteAddTermExpansionClause(_) => { try_or_throw!(self.machine_st, self.add_term_expansion_clause()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddInSituFilenameModule(_) => { try_or_throw!(self.machine_st, self.add_in_situ_filename_module()); self.machine_st.p += 1; } &Instruction::ExecuteAddInSituFilenameModule(_) => { try_or_throw!(self.machine_st, self.add_in_situ_filename_module()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallClauseToEvacuable(_) => { try_or_throw!(self.machine_st, self.clause_to_evacuable()); self.machine_st.p += 1; } &Instruction::ExecuteClauseToEvacuable(_) => { try_or_throw!(self.machine_st, self.clause_to_evacuable()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallScopedClauseToEvacuable(_) => { try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable()); self.machine_st.p += 1; } &Instruction::ExecuteScopedClauseToEvacuable(_) => { try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallConcludeLoad(_) => { try_or_throw!(self.machine_st, self.conclude_load()); self.machine_st.p += 1; } &Instruction::ExecuteConcludeLoad(_) => { try_or_throw!(self.machine_st, self.conclude_load()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallDeclareModule(_) => { try_or_throw!(self.machine_st, self.declare_module()); self.machine_st.p += 1; } &Instruction::ExecuteDeclareModule(_) => { try_or_throw!(self.machine_st, self.declare_module()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallLoadCompiledLibrary(_) => { try_or_throw!(self.machine_st, self.load_compiled_library()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadCompiledLibrary(_) => { try_or_throw!(self.machine_st, self.load_compiled_library()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadContextSource(_) => { self.load_context_source(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadContextSource(_) => { self.load_context_source(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadContextFile(_) => { self.load_context_file(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadContextFile(_) => { self.load_context_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadContextDirectory(_) => { self.load_context_directory(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadContextDirectory(_) => { self.load_context_directory(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadContextModule(_) => { self.load_context_module(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadContextModule(_) => { self.load_context_module(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadContextStream(_) => { self.load_context_stream(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadContextStream(_) => { self.load_context_stream(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallPopLoadContext(_) => { self.pop_load_context(); self.machine_st.p += 1; } &Instruction::ExecutePopLoadContext(_) => { self.pop_load_context(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPopLoadStatePayload(_) => { self.pop_load_state_payload(); self.machine_st.p += 1; } &Instruction::ExecutePopLoadStatePayload(_) => { self.pop_load_state_payload(); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPushLoadContext(_) => { try_or_throw!(self.machine_st, self.push_load_context()); self.machine_st.p += 1; } &Instruction::ExecutePushLoadContext(_) => { try_or_throw!(self.machine_st, self.push_load_context()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallPushLoadStatePayload(_) => { self.push_load_state_payload(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecutePushLoadStatePayload(_) => { self.push_load_state_payload(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallUseModule(_) => { try_or_throw!(self.machine_st, self.use_module()); self.machine_st.p += 1; } &Instruction::ExecuteUseModule(_) => { try_or_throw!(self.machine_st, self.use_module()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallBuiltInProperty(_) => { self.builtin_property(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteBuiltInProperty(_) => { self.builtin_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallMetaPredicateProperty(_) => { self.meta_predicate_property(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteMetaPredicateProperty(_) => { self.meta_predicate_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallMultifileProperty(_) => { self.multifile_property(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteMultifileProperty(_) => { self.multifile_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDiscontiguousProperty(_) => { self.discontiguous_property(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDiscontiguousProperty(_) => { self.discontiguous_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDynamicProperty(_) => { self.dynamic_property(); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDynamicProperty(_) => { self.dynamic_property(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallAbolishClause(_) => { try_or_throw!(self.machine_st, self.abolish_clause()); self.machine_st.p += 1; } &Instruction::ExecuteAbolishClause(_) => { try_or_throw!(self.machine_st, self.abolish_clause()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAsserta(_) => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend)); self.machine_st.p += 1; } &Instruction::ExecuteAsserta(_) => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend)); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAssertz(_) => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append)); self.machine_st.p += 1; } &Instruction::ExecuteAssertz(_) => { try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append)); self.machine_st.p = self.machine_st.cp; } &Instruction::CallRetract(_) => { try_or_throw!(self.machine_st, self.retract_clause()); self.machine_st.p += 1; } &Instruction::ExecuteRetract(_) => { try_or_throw!(self.machine_st, self.retract_clause()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallIsConsistentWithTermQueue(_) => { try_or_throw!(self.machine_st, self.is_consistent_with_term_queue()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteIsConsistentWithTermQueue(_) => { try_or_throw!(self.machine_st, self.is_consistent_with_term_queue()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::CallFlushTermQueue(_) => { try_or_throw!(self.machine_st, self.flush_term_queue()); self.machine_st.p += 1; } &Instruction::ExecuteFlushTermQueue(_) => { try_or_throw!(self.machine_st, self.flush_term_queue()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallRemoveModuleExports(_) => { try_or_throw!(self.machine_st, self.remove_module_exports()); self.machine_st.p += 1; } &Instruction::ExecuteRemoveModuleExports(_) => { try_or_throw!(self.machine_st, self.remove_module_exports()); self.machine_st.p = self.machine_st.cp; } &Instruction::CallAddNonCountedBacktracking(_) => { try_or_throw!(self.machine_st, self.add_non_counted_backtracking()); self.machine_st.p += 1; } &Instruction::ExecuteAddNonCountedBacktracking(_) => { try_or_throw!(self.machine_st, self.add_non_counted_backtracking()); self.machine_st.p = self.machine_st.cp; } } } let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed); match INTERRUPT.compare_exchange( interrupted, false, std::sync::atomic::Ordering::Relaxed, std::sync::atomic::Ordering::Relaxed, ) { Ok(interruption) => { if interruption { self.machine_st.throw_interrupt_exception(); self.machine_st.backtrack(); } } Err(_) => unreachable!(), } } } }