From: Mark Thom Date: Sun, 28 Feb 2021 17:41:32 +0000 (-0700) Subject: add occurs_check flag (#309) X-Git-Tag: v0.9.0~150^2~9 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=a36781234890f26085d8fa79a9a541ad2a49ace4;p=scryer-prolog.git add occurs_check flag (#309) --- diff --git a/src/clause_types.rs b/src/clause_types.rs index 1804040a..dc2d0150 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -304,6 +304,9 @@ pub enum SystemClauseType { UnsetEnv, CharsBase64, DevourWhitespace, + IsSTOEnabled, + SetSTOAsUnify, + SetNSTOAsUnify, } impl SystemClauseType { @@ -585,6 +588,9 @@ impl SystemClauseType { &SystemClauseType::CharsBase64 => clause_name!("$chars_base64"), &SystemClauseType::LoadLibraryAsStream => clause_name!("$load_library_as_stream"), &SystemClauseType::DevourWhitespace => clause_name!("$devour_whitespace"), + &SystemClauseType::IsSTOEnabled => clause_name!("$is_sto_enabled"), + &SystemClauseType::SetSTOAsUnify => clause_name!("$set_sto_as_unify"), + &SystemClauseType::SetNSTOAsUnify => clause_name!("$set_nsto_as_unify"), } } @@ -830,6 +836,9 @@ impl SystemClauseType { ("$devour_whitespace", 1) => { Some(SystemClauseType::DevourWhitespace) } + ("$is_sto_enabled", 1) => Some(SystemClauseType::IsSTOEnabled), + ("$set_sto_as_unify", 0) => Some(SystemClauseType::SetSTOAsUnify), + ("$set_nsto_as_unify", 0) => Some(SystemClauseType::SetNSTOAsUnify), _ => None, } } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index bc393c40..3c9a380e 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -133,6 +133,10 @@ current_prolog_flag(Flag, Value) :- Flag == double_quotes, !, '$get_double_quote current_prolog_flag(double_quotes, Value) :- '$get_double_quotes'(Value). current_prolog_flag(Flag, _) :- Flag == max_integer, !, '$fail'. current_prolog_flag(Flag, _) :- Flag == min_integer, !, '$fail'. +current_prolog_flag(Flag, OccursCheckEnabled) :- + Flag == occurs_check, + !, + '$is_sto_enabled'(OccursCheckEnabled). current_prolog_flag(Flag, _) :- atom(Flag), throw(error(domain_error(prolog_flag, Flag), current_prolog_flag/2)). % 8.17.2.3 b @@ -163,6 +167,10 @@ set_prolog_flag(double_quotes, atom) :- !, '$set_double_quotes'(atom). % 7.11.2.5, list of char codes (UTF8). set_prolog_flag(double_quotes, codes) :- !, '$set_double_quotes'(codes). +set_prolog_flag(occurs_check, true) :- + !, '$set_sto_as_unify'. +set_prolog_flag(occurs_check, false) :- + !, '$set_nsto_as_unify'. set_prolog_flag(double_quotes, Value) :- throw(error(domain_error(flag_value, double_quotes + Value), set_prolog_flag/2)). % 8.17.1.3 e diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 8b09a46c..a98c8fc0 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1631,8 +1631,7 @@ impl Machine { .push(HeapCellValue::Atom(path_atom, None)), ); - self.machine_st - .unify(path_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(path_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -1652,9 +1651,7 @@ impl Machine { .push(HeapCellValue::Atom(file_name_atom, None)), ); - self.machine_st - .unify(file_name_addr, self.machine_st[temp_v!(1)]); - + self.machine_st.unify(file_name_addr, self.machine_st[temp_v!(1)]); return; } _ => { @@ -1680,8 +1677,7 @@ impl Machine { .push(HeapCellValue::Atom(directory_atom, None)), ); - self.machine_st - .unify(directory_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(directory_addr, self.machine_st[temp_v!(1)]); return; } } @@ -1697,8 +1693,7 @@ impl Machine { .push(HeapCellValue::Atom(load_context.module.clone(), None)), ); - self.machine_st - .unify(module_name_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(module_name_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -1712,8 +1707,7 @@ impl Machine { .push(HeapCellValue::Stream(load_context.stream.clone())), ); - self.machine_st - .unify(stream_addr, self.machine_st[temp_v!(1)]); + self.machine_st.unify(stream_addr, self.machine_st[temp_v!(1)]); } else { self.machine_st.fail = true; } @@ -2064,8 +2058,8 @@ impl Machine { self.machine_st .heap .push(HeapCellValue::Addr(Addr::HeapCell(list_loc))); - self.machine_st - .unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); + + self.machine_st.unify(Addr::HeapCell(heap_loc), self.machine_st[temp_v!(4)]); } None => { self.machine_st.fail = true; diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 71801f3b..87af5a41 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -275,7 +275,7 @@ pub enum FirstOrNext { Next, } -#[derive(Debug)] +// #[derive(Debug)] pub struct MachineState { pub(crate) atom_tbl: TabledData, pub(super) s: HeapPtr, @@ -299,11 +299,48 @@ pub struct MachineState { pub(super) lifted_heap: Heap, pub(super) interms: Vec, // intermediate numbers. pub(super) last_call: bool, - pub(crate) heap_locs: HeapVarDict, pub(crate) flags: MachineFlags, pub(crate) cc: usize, pub(crate) global_clock: usize, pub(crate) dynamic_mode: FirstOrNext, + pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr), +} + +impl fmt::Debug for MachineState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("MachineState") + .field("atom_tbl", &self.atom_tbl) + .field("s", &self.s) + .field("p", &self.p) + .field("b", &self.b) + .field("b0", &self.b0) + .field("e", &self.e) + .field("num_of_args", &self.num_of_args) + .field("cp", &self.cp) + .field("attr_var_init", &self.attr_var_init) + .field("fail", &self.fail) + .field("heap", &self.heap) + .field("mode", &self.mode) + .field("stack", &self.stack) + .field("registers", &self.registers) + .field("trail", &self.trail) + .field("tr", &self.tr) + .field("hb", &self.hb) + .field("block", &self.block) + .field("ball", &self.ball) + .field("lifted_heap", &self.lifted_heap) + .field("interms", &self.interms) + .field("last_call", &self.last_call) + .field("flags", &self.flags) + .field("cc", &self.cc) + .field("global_clock", &self.global_clock) + .field("dynamic_mode", &self.dynamic_mode) + .field("unify_fn", + if self.unify_fn as usize == MachineState::unify as usize + { &"MachineState::unify" } + else { &"MachineState::unify_with_occurs_check" }) + .finish() + } } impl MachineState { @@ -354,7 +391,7 @@ impl MachineState { match self.read(stream.clone(), self.atom_tbl.clone(), &indices.op_dir) { Ok(term_write_result) => { let term = self[temp_v!(2)]; - self.unify(Addr::HeapCell(term_write_result.heap_loc), term); + (self.unify_fn)(self, Addr::HeapCell(term_write_result.heap_loc), term); if self.fail { return Ok(()); @@ -398,7 +435,7 @@ impl MachineState { let singletons_offset = Addr::HeapCell(self.heap.to_list(singleton_var_list.into_iter())); - self.unify(singletons_offset, singleton_addr); + (self.unify_fn)(self, singletons_offset, singleton_addr); if self.fail { return Ok(()); @@ -407,7 +444,7 @@ impl MachineState { let vars_addr = self[temp_v!(4)]; let vars_offset = Addr::HeapCell(self.heap.to_list(var_list.into_iter())); - self.unify(vars_offset, vars_addr); + (self.unify_fn)(self, vars_offset, vars_addr); if self.fail { return Ok(()); @@ -417,7 +454,7 @@ impl MachineState { let var_names_offset = Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter())); - return Ok(self.unify(var_names_offset, var_names_addr)); + return Ok((self.unify_fn)(self, var_names_offset, var_names_addr)); } Err(err) => { if let ParserError::UnexpectedEOF = err { @@ -1027,7 +1064,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let h = machine_st.heap.h(); machine_st.heap.push(atom); - machine_st.unify(a1, Addr::Con(h)); + (machine_st.unify_fn)(machine_st, a1, Addr::Con(h)); return_from_clause!(machine_st.last_call, machine_st) } @@ -1049,7 +1086,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { ) { Ok(offset) => { let addr = machine_st[temp_v!(1)]; - machine_st.unify(addr, Addr::HeapCell(offset.heap_loc)); + (machine_st.unify_fn)(machine_st, addr, Addr::HeapCell(offset.heap_loc)); } Err(ParserError::UnexpectedEOF) => { let addr = machine_st[temp_v!(1)]; @@ -1057,7 +1094,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let atom = machine_st.heap.to_unifiable(HeapCellValue::Atom(eof, None)); - machine_st.unify(addr, atom); + (machine_st.unify_fn)(machine_st, addr, atom); } Err(e) => { let h = machine_st.heap.h(); @@ -1121,7 +1158,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter())); let r2 = machine_st[temp_v!(2)]; - machine_st.unify(r2, heap_addr); + (machine_st.unify_fn)(machine_st, r2, heap_addr); return_from_clause!(machine_st.last_call, machine_st) } @@ -1147,7 +1184,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs)); let r2 = machine_st[temp_v!(2)]; - machine_st.unify(r2, heap_addr); + (machine_st.unify_fn)(machine_st, r2, heap_addr); return_from_clause!(machine_st.last_call, machine_st) } @@ -1156,7 +1193,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { let n2 = machine_st.get_number(at)?; let n2 = machine_st.heap.put_constant(n2.into()); - machine_st.unify(a1, n2); + (machine_st.unify_fn)(machine_st, a1, n2); return_from_clause!(machine_st.last_call, machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 3262daa5..5ae448f9 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -52,11 +52,11 @@ impl MachineState { lifted_heap: Heap::new(), interms: vec![Number::default(); 256], last_call: false, - heap_locs: HeapVarDict::new(), flags: MachineFlags::default(), cc: 0, global_clock: 0, dynamic_mode: FirstOrNext::First, + unify_fn: MachineState::unify, } } @@ -770,7 +770,7 @@ impl MachineState { self.heap.put_complete_string(&string[prefix_len..]) }; - self.unify(Addr::Lis(l), pstr_addr); + (self.unify_fn)(self, Addr::Lis(l), pstr_addr); } _ => { self.fail = true; @@ -839,7 +839,7 @@ impl MachineState { } Addr::Lis(l) => { let addr = self.heap.put_constant(c.clone()); - self.unify(Addr::Lis(l), addr); + (self.unify_fn)(self, Addr::Lis(l), addr); } Addr::PStrLocation(h, n) => { if let Constant::String(ref s2) = c { @@ -857,7 +857,7 @@ impl MachineState { if let Some(r) = addr.as_var() { self.bind(r, c); } else { - self.unify(addr, c); + (self.unify_fn)(self, addr, c); } } }; @@ -1209,7 +1209,7 @@ impl MachineState { let norm_addr = self[norm]; let reg_addr = self.registers[arg]; - self.unify(norm_addr, reg_addr); + (self.unify_fn)(self, norm_addr, reg_addr); } &FactInstruction::UnifyConstant(ref c) => { match self.mode { @@ -1247,7 +1247,7 @@ impl MachineState { MachineMode::Read => { let reg_addr = self[reg]; - self.unify(reg_addr, self.s.read(&self.heap)); + (self.unify_fn)(self, reg_addr, self.s.read(&self.heap)); self.increment_s_ptr(1); } MachineMode::Write => { @@ -1275,7 +1275,7 @@ impl MachineState { MachineMode::Read => { let reg_addr = self[reg]; - self.unify(reg_addr, self.s.read(&self.heap)); + (self.unify_fn)(self, reg_addr, self.s.read(&self.heap)); self.increment_s_ptr(1); } MachineMode::Write => { @@ -1778,7 +1778,7 @@ impl MachineState { let a3 = self[temp_v!(3)]; let h_a = Addr::HeapCell(o + n); - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } _ => { self.fail = true; @@ -1789,7 +1789,7 @@ impl MachineState { let a3 = self[temp_v!(3)]; let h_a = Addr::HeapCell(l + n - 1); - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } else { self.fail = true; } @@ -1812,7 +1812,7 @@ impl MachineState { unreachable!() }; - self.unify(a3, h_a); + (self.unify_fn)(self, a3, h_a); } else { self.fail = true; } @@ -2396,10 +2396,10 @@ impl MachineState { let a2 = self[temp_v!(2)]; let a3 = self[temp_v!(3)]; - self.unify(a2, name); + (self.unify_fn)(self, a2, name); if !self.fail { - self.unify(a3, Addr::Usize(arity)); + (self.unify_fn)(self, a3, Addr::Usize(arity)); } } @@ -2520,7 +2520,7 @@ impl MachineState { | Addr::Usize(_) if arity == 0 => { - self.unify(a1, name); + (self.unify_fn)(self, a1, name); } Addr::Con(h) => { if let HeapCellValue::Atom(name, spec) = self.heap.clone(h) { @@ -2763,7 +2763,7 @@ impl MachineState { copy_term(CopyTerm::new(self), a1, attr_var_policy); - self.unify(Addr::HeapCell(old_h), a2); + (self.unify_fn)(self, Addr::HeapCell(old_h), a2); } // returns true on failure. @@ -3505,7 +3505,7 @@ impl MachineState { let b0 = self[perm_v!(1)]; let a = self[r]; - self.unify(a, b0); + (self.unify_fn)(self, a, b0); self.p += 1; } &CutInstruction::Cut(r) => { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index a2307ed2..0dacd2aa 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -253,11 +253,11 @@ impl MachineState { fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) { let target_n = self[temp_v!(1)]; - self.unify(Addr::Usize(n), target_n); + (self.unify_fn)(self, Addr::Usize(n), target_n); if !self.fail { let xs = self[temp_v!(4)]; - self.unify(addr, xs); + (self.unify_fn)(self, addr, xs); } } @@ -313,7 +313,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - self.unify(xs0, xs); + (self.unify_fn)(self, xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -323,7 +323,7 @@ impl MachineState { let xs0 = self[temp_v!(3)]; let xs = self[temp_v!(4)]; - self.unify(xs0, xs); + (self.unify_fn)(self, xs0, xs); } else { self.skip_max_list_result(max_steps_n); } @@ -630,19 +630,19 @@ impl MachineState { } Ok(Term::Constant(_, Constant::Rational(n))) => { let addr = self.heap.put_constant(Constant::Rational(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Float(n))) => { let addr = self.heap.put_constant(Constant::Float(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Integer(n))) => { let addr = self.heap.put_constant(Constant::Integer(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } Ok(Term::Constant(_, Constant::Fixnum(n))) => { let addr = self.heap.put_constant(Constant::Fixnum(n)); - self.unify(nx, addr); + (self.unify_fn)(self, nx, addr); } _ => { let err = ParserError::ParseBigInt(0, 0); @@ -668,7 +668,7 @@ impl MachineState { let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter())); let target = self[temp_v!(1)]; - self.unify(attr_goals, target); + (self.unify_fn)(self, attr_goals, target); } fn call_continuation_chunk(&mut self, chunk: Addr, return_p: LocalCodePtr) -> LocalCodePtr { @@ -742,7 +742,7 @@ impl MachineState { let target = self[temp_v!(n)]; let addr = self[temp_v!(1)]; - self.unify(addr, target); + (self.unify_fn)(self, addr, target); return return_from_clause!(self.last_call, self); } } @@ -758,7 +758,7 @@ impl MachineState { None, )); - self.unify(self[temp_v!(1)], hostname); + (self.unify_fn)(self, self[temp_v!(1)], hostname); return return_from_clause!(self.last_call, self); } None => {} @@ -777,7 +777,7 @@ impl MachineState { match addr { addr if addr.is_ref() => { let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream)); - self.unify(stream, addr); + (self.unify_fn)(self, stream, addr); } Addr::Stream(other_stream) => { if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] { @@ -802,7 +802,7 @@ impl MachineState { match addr { addr if addr.is_ref() => { let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream)); - self.unify(stream, addr); + (self.unify_fn)(self, stream, addr); } Addr::Stream(other_stream) => { if let HeapCellValue::Stream(ref other_stream) = &self.heap[other_stream] { @@ -849,7 +849,7 @@ impl MachineState { } let files_list = Addr::HeapCell(self.heap.to_list(files.into_iter())); - self.unify(self[temp_v!(2)], files_list); + (self.unify_fn)(self, self[temp_v!(2)], files_list); } &SystemClauseType::FileSize => { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -857,7 +857,7 @@ impl MachineState { let len = self.heap.to_unifiable(HeapCellValue::Integer(Rc::new(len))); - self.unify(self[temp_v!(2)], len); + (self.unify_fn)(self, self[temp_v!(2)], len); } &SystemClauseType::FileExists => { let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -880,7 +880,7 @@ impl MachineState { let addr = self .heap .put_constant(Constant::Char(std::path::MAIN_SEPARATOR)); - self.unify(self[temp_v!(1)], addr); + (self.unify_fn)(self, self[temp_v!(1)], addr); } &SystemClauseType::MakeDirectory => { let directory = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); @@ -919,7 +919,7 @@ impl MachineState { }; let chars = self.heap.put_complete_string(current); - self.unify(self[temp_v!(1)], chars); + (self.unify_fn)(self, self[temp_v!(1)], chars); let next = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); @@ -952,7 +952,7 @@ impl MachineState { } }; let chars = self.heap.put_complete_string(cs); - self.unify(self[temp_v!(2)], chars); + (self.unify_fn)(self, self[temp_v!(2)], chars); } _ => { self.fail = true; @@ -986,7 +986,7 @@ impl MachineState { } } { let chars = self.systemtime_to_timestamp(time); - self.unify(self[temp_v!(3)], chars); + (self.unify_fn)(self, self[temp_v!(3)], chars); } else { self.fail = true; return Ok(()); @@ -1005,14 +1005,14 @@ impl MachineState { let list_of_chars = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_chars); + (self.unify_fn)(self, a2, list_of_chars); } Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { let s = self.heap.put_complete_string(name.as_str()); let a2 = self[temp_v!(2)]; - self.unify(s, a2); + (self.unify_fn)(self, s, a2); } else { unreachable!() } @@ -1023,7 +1023,7 @@ impl MachineState { let list_of_chars = Addr::HeapCell(self.heap.to_list(chars.into_iter())); - self.unify(a2, list_of_chars); + (self.unify_fn)(self, a2, list_of_chars); } addr if addr.is_ref() => { let mut iter = self.heap_pstr_iter(self[temp_v!(2)]); @@ -1032,13 +1032,13 @@ impl MachineState { match iter.focus() { Addr::EmptyList => { if &string == "[]" { - self.unify(addr, Addr::EmptyList); + (self.unify_fn)(self, addr, Addr::EmptyList); } else { let chars = clause_name!(string, self.atom_tbl); let atom = self.heap.to_unifiable(HeapCellValue::Atom(chars, None)); - self.unify(addr, atom); + (self.unify_fn)(self, addr, atom); } } focus => { @@ -1071,7 +1071,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(name, _) = self.heap.clone(h) { @@ -1081,7 +1081,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } else { unreachable!() } @@ -1092,7 +1092,7 @@ impl MachineState { let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter())); let a2 = self[temp_v!(2)]; - self.unify(a2, list_of_codes); + (self.unify_fn)(self, a2, list_of_codes); } addr if addr.is_ref() => { let stub = MachineError::functor_stub(clause_name!("atom_codes"), 2); @@ -1180,7 +1180,7 @@ impl MachineState { let a2 = self[temp_v!(2)]; - self.unify(a2, len); + (self.unify_fn)(self, a2, len); } &SystemClauseType::CallContinuation => { let stub = MachineError::functor_stub(clause_name!("call_continuation"), 1); @@ -1244,13 +1244,13 @@ impl MachineState { } let pstr = self.heap.allocate_pstr(atom.as_str()); - self.unify(self[temp_v!(2)], pstr); + (self.unify_fn)(self, self[temp_v!(2)], pstr); if !self.fail { let h = self.heap.h(); let pstr_tail = self.heap[h - 1].as_addr(h - 1); - self.unify(self[temp_v!(3)], pstr_tail); + (self.unify_fn)(self, self[temp_v!(3)], pstr_tail); } } &SystemClauseType::IsPartialString => { @@ -1288,14 +1288,14 @@ impl MachineState { let tail = self.heap[h + 1].as_addr(h + 1); let target = self[temp_v!(2)]; - self.unify(tail, target); + (self.unify_fn)(self, tail, target); } else { self.fail = true; return Ok(()); } } Addr::Lis(h) => { - self.unify(Addr::HeapCell(h + 1), self[temp_v!(2)]); + (self.unify_fn)(self, Addr::HeapCell(h + 1), self[temp_v!(2)]); } Addr::EmptyList => { self.fail = true; @@ -1328,7 +1328,7 @@ impl MachineState { if stream.at_end_of_stream() { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], Addr::Fixnum(-1)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Fixnum(-1)); return return_from_clause!(self.last_call, self); } @@ -1432,7 +1432,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -1535,7 +1535,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -1645,7 +1645,7 @@ impl MachineState { let chars = string.trim().chars().map(|c| Addr::Char(c)); let char_list = Addr::HeapCell(self.heap.to_list(chars)); - self.unify(char_list, chs); + (self.unify_fn)(self, char_list, chs); } &SystemClauseType::NumberToCodes => { let n = self[temp_v!(1)]; @@ -1672,7 +1672,7 @@ impl MachineState { let codes_list = Addr::HeapCell(self.heap.to_list(codes)); - self.unify(codes_list, chs); + (self.unify_fn)(self, codes_list, chs); } &SystemClauseType::CodesToNumber => { let stub = MachineError::functor_stub(clause_name!("number_codes"), 2); @@ -1698,7 +1698,7 @@ impl MachineState { let a1 = self[temp_v!(1)]; let lh_len = Addr::Usize(self.lifted_heap.h()); - self.unify(a1, lh_len); + (self.unify_fn)(self, a1, lh_len); } &SystemClauseType::CharCode => { let a1 = self[temp_v!(1)]; @@ -1717,11 +1717,11 @@ impl MachineState { }; let a2 = self[temp_v!(2)]; - self.unify(Addr::Fixnum(c as isize), a2); + (self.unify_fn)(self, Addr::Fixnum(c as isize), a2); } Addr::Char(c) => { let a2 = self[temp_v!(2)]; - self.unify(Addr::Fixnum(c as isize), a2); + (self.unify_fn)(self, Addr::Fixnum(c as isize), a2); } addr if addr.is_ref() => { let a2 = self[temp_v!(2)]; @@ -1738,7 +1738,7 @@ impl MachineState { } }; - self.unify(Addr::Char(c), addr); + (self.unify_fn)(self, Addr::Char(c), addr); } _ => { unreachable!(); @@ -1869,14 +1869,14 @@ impl MachineState { Some((ref ball, ref mut loc)) => { match loc { Some(ref value_addr) => { - self.unify(addr, *value_addr); + (self.unify_fn)(self, addr, *value_addr); } loc @ None if !ball.stub.is_empty() => { let h = self.heap.h(); let stub = ball.copy_and_align(h); self.heap.extend(stub.into_iter()); - self.unify(addr, Addr::HeapCell(h)); + (self.unify_fn)(self, addr, Addr::HeapCell(h)); if !self.fail { *loc = Some(Addr::HeapCell(h)); @@ -2204,7 +2204,7 @@ impl MachineState { } _ => { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], Addr::Fixnum(-1)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Fixnum(-1)); return return_from_clause!(self.last_call, self); } } @@ -2238,7 +2238,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -2357,7 +2357,7 @@ impl MachineState { } }; let string = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(3)], string); + (self.unify_fn)(self, self[temp_v!(3)], string); } &SystemClauseType::GetCode => { let mut stream = @@ -2387,7 +2387,7 @@ impl MachineState { stream.set_past_end_of_stream(); - self.unify(self[temp_v!(2)], end_of_file); + (self.unify_fn)(self, self[temp_v!(2)], end_of_file); return return_from_clause!(self.last_call, self); } @@ -2580,7 +2580,7 @@ impl MachineState { let a1 = self[temp_v!(1)]; - self.unify(Addr::Char(c), a1); + (self.unify_fn)(self, Addr::Char(c), a1); } &SystemClauseType::HeadIsDynamic => { let module_name = atom_from!(self, self.store(self.deref(self[temp_v!(1)]))); @@ -2933,10 +2933,10 @@ impl MachineState { let atom = self.heap.to_unifiable(HeapCellValue::Atom(name, spec)); - self.unify(a2, atom); + (self.unify_fn)(self, a2, atom); if !self.fail { - self.unify(a3, Addr::Usize(arity)); + (self.unify_fn)(self, a3, Addr::Usize(arity)); } } _ => { @@ -2986,14 +2986,14 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(name, Some(shared_op_desc))); - self.unify(Addr::Usize(priority), prec); + (self.unify_fn)(self, Addr::Usize(priority), prec); if !self.fail { - self.unify(a3, specifier); + (self.unify_fn)(self, a3, specifier); } if !self.fail { - self.unify(a4, op); + (self.unify_fn)(self, a4, op); } } _ => { @@ -3018,11 +3018,11 @@ impl MachineState { let a2 = ProcessTime::now().as_duration().as_secs_f64(); let addr = self.heap.put_constant(Constant::Float(OrderedFloat(a2))); - self.unify(a1, addr); + (self.unify_fn)(self, a1, addr); } &SystemClauseType::CurrentTime => { let str = self.systemtime_to_timestamp(SystemTime::now()); - self.unify(self[temp_v!(1)], str); + (self.unify_fn)(self, self[temp_v!(1)], str); } &SystemClauseType::OpDeclaration => { let priority = self[temp_v!(1)]; @@ -3176,7 +3176,7 @@ impl MachineState { let addr = self[temp_v!(1)]; let value = Addr::Usize(self.attr_var_init.attr_var_queue.len()); - self.unify(addr, value); + (self.unify_fn)(self, addr, value); } &SystemClauseType::GetAttrVarQueueBeyond => { let addr = self[temp_v!(1)]; @@ -3200,7 +3200,7 @@ impl MachineState { let var_list_addr = Addr::HeapCell(self.heap.to_list(iter)); let list_addr = self[temp_v!(2)]; - self.unify(var_list_addr, list_addr); + (self.unify_fn)(self, var_list_addr, list_addr); } } &SystemClauseType::GetContinuationChunk => { @@ -3245,7 +3245,7 @@ impl MachineState { self.heap.push(HeapCellValue::Addr(p_functor)); self.heap.extend(addrs.into_iter().map(HeapCellValue::Addr)); - self.unify(self[temp_v!(3)], chunk); + (self.unify_fn)(self, self[temp_v!(3)], chunk); } &SystemClauseType::GetLiftedHeapFromOffsetDiff => { let lh_offset = self[temp_v!(1)]; @@ -3256,8 +3256,8 @@ impl MachineState { let solutions = self[temp_v!(2)]; let diff = self[temp_v!(3)]; - self.unify(solutions, Addr::EmptyList); - self.unify(diff, Addr::EmptyList); + (self.unify_fn)(self, solutions, Addr::EmptyList); + (self.unify_fn)(self, diff, Addr::EmptyList); } else { let h = self.heap.h(); let mut last_index = h; @@ -3285,14 +3285,14 @@ impl MachineState { addr_opt.map(|addr| { let diff = self[temp_v!(3)]; - self.unify(diff, addr); + (self.unify_fn)(self, diff, addr); }); } self.lifted_heap.truncate(lh_offset); let solutions = self[temp_v!(2)]; - self.unify(Addr::HeapCell(h), solutions); + (self.unify_fn)(self, Addr::HeapCell(h), solutions); } } _ => { @@ -3307,7 +3307,7 @@ impl MachineState { Addr::Usize(lh_offset) => { if lh_offset >= self.lifted_heap.h() { let solutions = self[temp_v!(2)]; - self.unify(solutions, Addr::EmptyList); + (self.unify_fn)(self, solutions, Addr::EmptyList); } else { let h = self.heap.h(); @@ -3325,7 +3325,7 @@ impl MachineState { self.lifted_heap.truncate(lh_offset); let solutions = self[temp_v!(2)]; - self.unify(Addr::HeapCell(h), solutions); + (self.unify_fn)(self, Addr::HeapCell(h), solutions); } } _ => { @@ -3342,21 +3342,21 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(clause_name!("chars"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } DoubleQuotes::Atom => { let atom = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("atom"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } DoubleQuotes::Codes => { let atom = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("codes"), None)); - self.unify(a1, atom); + (self.unify_fn)(self, a1, atom); } } } @@ -3460,7 +3460,7 @@ impl MachineState { .to_unifiable(HeapCellValue::Integer(Rc::new(count))); let a3 = self[temp_v!(3)]; - self.unify(a3, count); + (self.unify_fn)(self, a3, count); } None => { panic!( @@ -3645,7 +3645,7 @@ impl MachineState { let a2 = self[temp_v!(2)]; - self.unify(a2, count); + (self.unify_fn)(self, a2, count); } _ => { panic!("remove_inference_counter: expected Usize in A1."); @@ -3795,13 +3795,13 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Atom(clause_name!("!"), None)); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } else { let a2 = self .heap .to_unifiable(HeapCellValue::Atom(clause_name!("true"), None)); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } } _ => { @@ -3860,13 +3860,13 @@ impl MachineState { let a1 = self[temp_v!(1)]; let a2 = Addr::Usize(self.b); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } &SystemClauseType::GetCutPoint => { let a1 = self[temp_v!(1)]; let a2 = Addr::CutPoint(self.b0); - self.unify(a1, a2); + (self.unify_fn)(self, a1, a2); } &SystemClauseType::InstallNewBlock => { self.install_new_block(temp_v!(1)); @@ -3891,10 +3891,10 @@ impl MachineState { let p = cp.as_functor(&mut self.heap); - self.unify(self[temp_v!(2)], e); + (self.unify_fn)(self, self[temp_v!(2)], e); if !self.fail { - self.unify(self[temp_v!(3)], p); + (self.unify_fn)(self, self[temp_v!(3)], p); } } else { unreachable!() @@ -3918,10 +3918,10 @@ impl MachineState { let e = Addr::Usize(e); - self.unify(self[temp_v!(2)], e); + (self.unify_fn)(self, self[temp_v!(2)], e); if !self.fail { - self.unify(self[temp_v!(3)], p); + (self.unify_fn)(self, self[temp_v!(3)], p); } } _ => { @@ -4288,7 +4288,7 @@ impl MachineState { self.bind(addr.as_var().unwrap(), tcp_listener); if had_zero_port { - self.unify(self[temp_v!(2)], Addr::Usize(port)); + (self.unify_fn)(self, self[temp_v!(2)], Addr::Usize(port)); } } &SystemClauseType::SocketServerAccept => { @@ -4510,7 +4510,7 @@ impl MachineState { }; let property = self.heap.to_unifiable(property); - self.unify(self[temp_v!(3)], property); + (self.unify_fn)(self, self[temp_v!(3)], property); } &SystemClauseType::StoreGlobalVar => { let key = match self.store(self.deref(self[temp_v!(1)])) { @@ -4580,7 +4580,7 @@ impl MachineState { let seen_vars = self.attr_vars_of_term(self[temp_v!(1)]); let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); - self.unify(self[temp_v!(2)], outcome); + (self.unify_fn)(self, self[temp_v!(2)], outcome); } &SystemClauseType::TermVariables => { let a1 = self[temp_v!(1)]; @@ -4595,7 +4595,7 @@ impl MachineState { } let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); - self.unify(self[temp_v!(2)], outcome); + (self.unify_fn)(self, self[temp_v!(2)], outcome); } &SystemClauseType::TruncateLiftedHeapTo => { match self.store(self.deref(self[temp_v!(1)])) { @@ -4732,7 +4732,7 @@ impl MachineState { let listing = Addr::HeapCell(self.heap.to_list(functor_list.into_iter())); let listing_var = self[temp_v!(4)]; - self.unify(listing, listing_var); + (self.unify_fn)(self, listing, listing_var); } &SystemClauseType::WriteTerm => { let mut stream = @@ -4819,7 +4819,7 @@ impl MachineState { let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown"); let chars = buffer.chars().map(|c| Addr::Char(c)); let result = Addr::HeapCell(self.heap.to_list(chars)); - self.unify(version, result); + (self.unify_fn)(self, version, result); } &SystemClauseType::CryptoRandomByte => { let arg = self[temp_v!(1)]; @@ -4840,7 +4840,7 @@ impl MachineState { .heap .to_unifiable(HeapCellValue::Integer(Rc::new(Integer::from(bytes[0])))); - self.unify(arg, byte); + (self.unify_fn)(self, arg, byte); } &SystemClauseType::CryptoDataHash => { let encoding = self.atom_argument_to_string(2); @@ -4963,7 +4963,7 @@ impl MachineState { } }; - self.unify(self[temp_v!(3)], ints_list); + (self.unify_fn)(self, self[temp_v!(3)], ints_list); } &SystemClauseType::CryptoDataHKDF => { let encoding = self.atom_argument_to_string(2); @@ -5023,7 +5023,7 @@ impl MachineState { ) }; - self.unify(self[temp_v!(7)], ints_list); + (self.unify_fn)(self, self[temp_v!(7)], ints_list); } &SystemClauseType::CryptoPasswordHash => { let stub1 = MachineError::functor_stub(clause_name!("crypto_password_hash"), 3); @@ -5066,7 +5066,7 @@ impl MachineState { ) }; - self.unify(self[temp_v!(4)], ints_list); + (self.unify_fn)(self, self[temp_v!(4)], ints_list); } &SystemClauseType::CryptoDataEncrypt => { let encoding = self.atom_argument_to_string(3); @@ -5107,8 +5107,8 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(6)], tag_list); - self.unify(self[temp_v!(7)], complete_string); + (self.unify_fn)(self, self[temp_v!(6)], tag_list); + (self.unify_fn)(self, self[temp_v!(7)], complete_string); } &SystemClauseType::CryptoDataDecrypt => { let data = self.string_encoding_bytes(1, "octet"); @@ -5152,7 +5152,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(6)], complete_string); + (self.unify_fn)(self, self[temp_v!(6)], complete_string); } &SystemClauseType::CryptoCurveScalarMult => { let curve = self.atom_argument_to_string(1); @@ -5196,8 +5196,8 @@ impl MachineState { .heap .put_complete_string(&ry.to_dec_str().unwrap().to_string()); - self.unify(self[temp_v!(4)], sx); - self.unify(self[temp_v!(5)], sy); + (self.unify_fn)(self, self[temp_v!(4)], sx); + (self.unify_fn)(self, self[temp_v!(5)], sy); } &SystemClauseType::Ed25519NewKeyPair => { let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap(); @@ -5206,7 +5206,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(1)], complete_string); + (self.unify_fn)(self, self[temp_v!(1)], complete_string); } &SystemClauseType::Ed25519KeyPairPublicKey => { let bytes = self.string_encoding_bytes(1, "octet"); @@ -5226,7 +5226,7 @@ impl MachineState { self.heap.put_complete_string(&buffer) }; - self.unify(self[temp_v!(2)], complete_string); + (self.unify_fn)(self, self[temp_v!(2)], complete_string); } &SystemClauseType::Ed25519Sign => { let key = self.string_encoding_bytes(1, "octet"); @@ -5251,7 +5251,7 @@ impl MachineState { ), ); - self.unify(self[temp_v!(4)], sig_list); + (self.unify_fn)(self, self[temp_v!(4)], sig_list); } &SystemClauseType::Ed25519Verify => { let key = self.string_encoding_bytes(1, "octet"); @@ -5282,21 +5282,21 @@ impl MachineState { let string = String::from_iter(result[..].iter().map(|b| *b as char)); let cstr = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(3)], cstr); + (self.unify_fn)(self, self[temp_v!(3)], cstr); } &SystemClauseType::LoadHTML => { let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); let doc = select::document::Document::from_read(string.as_bytes()).unwrap(); let result = self.html_node_to_term(indices, doc.nth(0).unwrap()); - self.unify(self[temp_v!(2)], result); + (self.unify_fn)(self, self[temp_v!(2)], result); } &SystemClauseType::LoadXML => { let string = self.heap_pstr_iter(self[temp_v!(1)]).to_string(); match roxmltree::Document::parse(&string) { Ok(doc) => { let result = self.xml_node_to_term(indices, doc.root_element()); - self.unify(self[temp_v!(2)], result); + (self.unify_fn)(self, self[temp_v!(2)], result); } _ => { self.fail = true; @@ -5309,7 +5309,7 @@ impl MachineState { match env::var(key) { Ok(value) => { let cstr = self.heap.put_complete_string(&value); - self.unify(self[temp_v!(2)], cstr); + (self.unify_fn)(self, self[temp_v!(2)], cstr); } _ => { self.fail = true; @@ -5352,7 +5352,7 @@ impl MachineState { Ok(bs) => { let string = String::from_iter(bs.iter().map(|b| *b as char)); let cstr = self.heap.put_complete_string(&string); - self.unify(self[temp_v!(1)], cstr); + (self.unify_fn)(self, self[temp_v!(1)], cstr); } _ => { self.fail = true; @@ -5379,7 +5379,7 @@ impl MachineState { let b64 = base64::encode_config(bytes, config); let cstr = self.heap.put_complete_string(&b64); - self.unify(self[temp_v!(2)], cstr); + (self.unify_fn)(self, self[temp_v!(2)], cstr); } } &SystemClauseType::LoadLibraryAsStream => { @@ -5433,6 +5433,27 @@ impl MachineState { } } } + &SystemClauseType::IsSTOEnabled => { + if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize { + let value = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!("true"), None), + ); + + (self.unify_fn)(self, self[temp_v!(1)], value); + } else { + let value = self.heap.to_unifiable( + HeapCellValue::Atom(clause_name!("false"), None), + ); + + (self.unify_fn)(self, self[temp_v!(1)], value); + } + } + &SystemClauseType::SetSTOAsUnify => { + self.unify_fn = MachineState::unify_with_occurs_check; + } + &SystemClauseType::SetNSTOAsUnify => { + self.unify_fn = MachineState::unify; + } }; return_from_clause!(self.last_call, self)