From 569040953488e3d38dfe4e11f3ed3b53791d8346 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 12 May 2018 15:51:20 -0600 Subject: [PATCH] correct faulty bind (two tests now fail: conjunctive_queries and lists) --- src/prolog/ast.rs | 83 ++++++++++++------------ src/prolog/codegen.rs | 2 +- src/prolog/machine/machine_errors.rs | 76 +++++++++++----------- src/prolog/machine/machine_state.rs | 58 ++++++++--------- src/prolog/machine/machine_state_impl.rs | 72 +++++++++++++------- src/prolog/machine/mod.rs | 5 +- src/prolog/macros.rs | 8 ++- 7 files changed, 163 insertions(+), 141 deletions(-) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index f9ea9c0c..f17c97cd 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -592,21 +592,6 @@ impl InlinedClauseType { } } - pub fn arity(&self) -> usize { - match self { - &InlinedClauseType::CompareNumber(..) => 2, - &InlinedClauseType::IsAtom(..) => 1, - &InlinedClauseType::IsAtomic(..) => 1, - &InlinedClauseType::IsCompound(..) => 1, - &InlinedClauseType::IsInteger (..) => 1, - &InlinedClauseType::IsRational(..) => 1, - &InlinedClauseType::IsString(..) => 1, - &InlinedClauseType::IsFloat (..) => 1, - &InlinedClauseType::IsNonVar(..) => 1, - &InlinedClauseType::IsVar(..) => 1 - } - } - pub fn from(name: &str, arity: usize) -> Option { let r1 = temp_v!(1); let r2 = temp_v!(2); @@ -738,31 +723,6 @@ pub enum SystemClauseType { } impl SystemClauseType { - pub fn arity(&self) -> usize { - match self { - &SystemClauseType::InstallCleaner => 1, - &SystemClauseType::InstallInferenceCounter => 3, - &SystemClauseType::RemoveCallPolicyCheck => 1, - &SystemClauseType::RemoveInferenceCounter => 2, - &SystemClauseType::RestoreCutPolicy => 0, - &SystemClauseType::SetCutPoint(_) => 1, - &SystemClauseType::GetArg => 3, - &SystemClauseType::InferenceLevel => 2, - &SystemClauseType::CleanUpBlock => 1, - &SystemClauseType::EraseBall => 0, - &SystemClauseType::Fail => 0, - &SystemClauseType::GetBall => 1, - &SystemClauseType::GetCurrentBlock => 1, - &SystemClauseType::GetCutPoint => 1, - &SystemClauseType::InstallNewBlock => 1, - &SystemClauseType::ResetBlock => 1, - &SystemClauseType::SetBall => 1, - &SystemClauseType::SkipMaxList => 4, - &SystemClauseType::Succeed => 0, - &SystemClauseType::UnwindStack => 0 - } - } - pub fn fixity(&self) -> Option { None } @@ -1502,6 +1462,38 @@ pub enum Addr { Str(usize) } +impl PartialEq for Addr { + fn eq(&self, r: &Ref) -> bool { + self.as_var() == Some(*r) + } +} + +// for use in MachineState::bind. +impl PartialOrd for Addr { + fn partial_cmp(&self, r: &Ref) -> Option { + match self { + &Addr::StackCell(fr, sc) => + match *r { + Ref::HeapCell(_) => Some(Ordering::Greater), + Ref::StackCell(fr1, sc1) => + if fr1 < fr || (fr1 == fr && sc1 < sc) { + Some(Ordering::Greater) + } else if fr1 == fr && sc1 == sc { + Some(Ordering::Equal) + } else { + Some(Ordering::Less) + } + }, + &Addr::HeapCell(h) => + match r { + Ref::StackCell(..) => Some(Ordering::Less), + Ref::HeapCell(h1) => h.partial_cmp(h1) + }, + _ => None + } + } +} + impl Addr { pub fn is_ref(&self) -> bool { match self { @@ -1520,7 +1512,7 @@ impl Addr { pub fn is_protected(&self, e: usize) -> bool { match self { - &Addr::StackCell(fr, _) if fr > e => false, + &Addr::StackCell(addr, _) if addr >= e => false, _ => true } } @@ -1567,6 +1559,15 @@ pub enum Ref { StackCell(usize, usize) } +impl Ref { + pub fn as_addr(self) -> Addr { + match self { + Ref::HeapCell(h) => Addr::HeapCell(h), + Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) + } + } +} + #[derive(Clone, PartialEq)] pub enum HeapCellValue { Addr(Addr), diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index de0f8018..6a01d348 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -19,7 +19,7 @@ pub struct CodeGenerator { pub struct ConjunctInfo<'a> { pub perm_vs: VariableFixtures<'a>, pub num_of_chunks: usize, - pub has_deep_cut: bool + pub has_deep_cut: bool, } impl<'a> ConjunctInfo<'a> diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index df7d3e3f..a220cf9b 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -10,41 +10,41 @@ pub(super) type MachineStub = Vec; // from 7.12.2 b) of 13211-1:1995 #[derive(Clone, Copy)] pub enum ValidType { - Atom, - Atomic, - Byte, +// Atom, +// Atomic, +// Byte, Callable, - Character, +// Character, Compound, - Evaluable, - InByte, - InCharacter, +// Evaluable, +// InByte, +// InCharacter, Integer, List, - Number, +// Number, Pair, - PredicateIndicator, - Variable +// PredicateIndicator, +// Variable } impl ValidType { pub fn as_str(self) -> &'static str { match self { - ValidType::Atom => "atom", - ValidType::Atomic => "atomic", - ValidType::Byte => "byte", +// ValidType::Atom => "atom", +// ValidType::Atomic => "atomic", +// ValidType::Byte => "byte", ValidType::Callable => "callable", - ValidType::Character => "character", +// ValidType::Character => "character", ValidType::Compound => "compound", - ValidType::Evaluable => "evaluable", - ValidType::InByte => "in_byte", - ValidType::InCharacter => "in_character", +// ValidType::Evaluable => "evaluable", +// ValidType::InByte => "in_byte", +// ValidType::InCharacter => "in_character", ValidType::Integer => "integer", ValidType::List => "list", - ValidType::Number => "number", +// ValidType::Number => "number", ValidType::Pair => "pair", - ValidType::PredicateIndicator => "predicate_indicator", - ValidType::Variable => "variable" +// ValidType::PredicateIndicator => "predicate_indicator", +// ValidType::Variable => "variable" } } } @@ -52,23 +52,23 @@ impl ValidType { // from 7.12.2 f) of 13211-1:1995 #[derive(Clone, Copy)] pub enum RepFlag { - Character, - CharacterCode, - InCharacterCode, +// Character, +// CharacterCode, +// InCharacterCode, MaxArity, - MaxInteger, - MinInteger +// MaxInteger, +// MinInteger } impl RepFlag { pub fn as_str(self) -> &'static str { match self { - RepFlag::Character => "character", - RepFlag::CharacterCode => "character_code", - RepFlag::InCharacterCode => "in_character_code", +// RepFlag::Character => "character", +// RepFlag::CharacterCode => "character_code", +// RepFlag::InCharacterCode => "in_character_code", RepFlag::MaxArity => "max_arity", - RepFlag::MaxInteger => "max_integer", - RepFlag::MinInteger => "min_integer" +// RepFlag::MaxInteger => "max_integer", +// RepFlag::MinInteger => "min_integer" } } } @@ -76,20 +76,20 @@ impl RepFlag { // from 7.12.2 g) of 13211-1:1995 #[derive(Clone, Copy)] pub enum EvalError { - FloatOverflow, - IntOverflow, - Undefined, - Underflow, +// FloatOverflow, +// IntOverflow, +// Undefined, +// Underflow, ZeroDivisor } impl EvalError { pub fn as_str(self) -> &'static str { match self { - EvalError::FloatOverflow => "float_overflow", - EvalError::IntOverflow => "int_overflow", - EvalError::Undefined => "undefined", - EvalError::Underflow => "underflow", +// EvalError::FloatOverflow => "float_overflow", +// EvalError::IntOverflow => "int_overflow", +// EvalError::Undefined => "undefined", +// EvalError::Underflow => "underflow", EvalError::ZeroDivisor => "zero_divisor" } } diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 5e0889b7..bbbdf618 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -222,6 +222,7 @@ pub struct MachineState { pub(super) block: usize, // an offset into the OR stack. pub(super) ball: Ball, pub(super) interms: Vec, // intermediate numbers. + pub(super) last_call: bool } pub(crate) type CallResult = Result<(), Vec>; @@ -323,8 +324,7 @@ pub(crate) trait CallPolicy: Any { let b = machine_st.b - 1; let n = machine_st.or_stack[b].num_args(); - for i in 1 .. n + 1 { - let addr = machine_st.store(machine_st.deref(machine_st.or_stack[b][i].clone())); + for i in 1 .. n + 1 { machine_st.registers[i] = machine_st.or_stack[b][i].clone(); } @@ -352,10 +352,10 @@ pub(crate) trait CallPolicy: Any { } fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, - idx: CodeIndex, lco: bool) + idx: CodeIndex) -> CallResult { - if lco { + if machine_st.last_call { self.try_execute(machine_st, name, arity, idx) } else { self.try_call(machine_st, name, arity, idx) @@ -401,14 +401,14 @@ pub(crate) trait CallPolicy: Any { Ok(()) } - fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) + fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType) -> CallResult { match ct { &BuiltInClauseType::AcyclicTerm => { let addr = machine_st[temp_v!(1)].clone(); machine_st.fail = machine_st.is_cyclic_term(addr); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Compare => { let a1 = machine_st[temp_v!(1)].clone(); @@ -422,7 +422,7 @@ pub(crate) trait CallPolicy: Any { }); machine_st.unify(a1, c); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::CompareTerm(qt) => { match qt { @@ -433,12 +433,12 @@ pub(crate) trait CallPolicy: Any { _ => machine_st.compare_term(qt) }; - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::CyclicTerm => { let addr = machine_st[temp_v!(1)].clone(); machine_st.fail = !machine_st.is_cyclic_term(addr); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Display => { let output = machine_st.print_term(machine_st[temp_v!(1)].clone(), @@ -446,27 +446,27 @@ pub(crate) trait CallPolicy: Any { PrinterOutputter::new()); println!("{}", output.result()); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::DuplicateTerm => { machine_st.duplicate_term(); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Eq => { machine_st.fail = machine_st.eq_test(); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Ground => { machine_st.fail = machine_st.ground_test(); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Functor => { machine_st.try_functor()?; - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::NotEq => { machine_st.fail = !machine_st.eq_test(); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Sort => { machine_st.check_sort_errors()?; @@ -482,7 +482,7 @@ pub(crate) trait CallPolicy: Any { let r2 = machine_st[temp_v!(2)].clone(); machine_st.unify(r2, heap_addr); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::KeySort => { machine_st.check_keysort_errors()?; @@ -504,22 +504,19 @@ pub(crate) trait CallPolicy: Any { let r2 = machine_st[temp_v!(2)].clone(); machine_st.unify(r2, heap_addr); - return_from_clause!(lco, machine_st) + return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Is => { let a = machine_st[temp_v!(1)].clone(); let result = machine_st.arith_eval_by_metacall(temp_v!(2))?; machine_st.unify(a, Addr::Con(Constant::Number(result))); - machine_st.p += 1; // TODO: change this!! - - Ok(()) + return_from_clause!(machine_st.last_call, machine_st) }, } } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, - code_dirs: CodeDirs<'a>, lco: bool) + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>) -> CallResult { if let Some((name, arity)) = machine_st.setup_call_n(arity) { @@ -541,11 +538,11 @@ pub(crate) trait CallPolicy: Any { machine_st.execute_inlined(&inlined), ClauseType::Op(..) | ClauseType::Named(..) => if let Some(idx) = code_dirs.get(name.clone(), arity, user) { - self.context_call(machine_st, name, arity, idx, lco)?; + self.context_call(machine_st, name, arity, idx)?; } else { return Err(machine_st.existence_error(name, arity)); }, - ClauseType::System(ct) => + ClauseType::System(_) => return Err(machine_st.type_error(ValidType::Callable, Addr::Con(Constant::Atom(name)))) }; @@ -557,10 +554,10 @@ pub(crate) trait CallPolicy: Any { impl CallPolicy for CallWithInferenceLimitCallPolicy { fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex, lco: bool) + arity: usize, idx: CodeIndex) -> CallResult { - self.prev_policy.context_call(machine_st, name, arity, idx, lco)?; + self.prev_policy.context_call(machine_st, name, arity, idx)?; self.increment() } @@ -588,18 +585,17 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy { self.increment() } - fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) + fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType) -> CallResult { - self.prev_policy.call_builtin(machine_st, ct, lco)?; + self.prev_policy.call_builtin(machine_st, ct)?; self.increment() } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>, - lco: bool) + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>) -> CallResult { - self.prev_policy.call_n(machine_st, arity, code_dirs, lco)?; + self.prev_policy.call_n(machine_st, arity, code_dirs)?; self.increment() } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 9cd820b8..71374ae9 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -49,7 +49,8 @@ impl MachineState { hb: 0, block: 0, ball: Ball::new(), - interms: vec![Number::default(); 256] + interms: vec![Number::default(); 256], + last_call: false } } @@ -80,16 +81,31 @@ impl MachineState { } pub(super) fn bind(&mut self, r1: Ref, a2: Addr) { - let t2 = self.store(a2); + let t1 = self.store(r1.as_addr()); + let t2 = self.store(a2.clone()); - match r1 { - Ref::StackCell(fr, sc) => - self.and_stack[fr][sc] = t2, - Ref::HeapCell(hc) => - self.heap[hc] = HeapCellValue::Addr(t2) - }; + if t1.is_ref() && (!t2.is_ref() || a2 < r1) { + match r1 { + Ref::StackCell(fr, sc) => + self.and_stack[fr][sc] = t2, + Ref::HeapCell(h) => + self.heap[h] = HeapCellValue::Addr(t2) + }; - self.trail(r1); + self.trail(r1); + } else { + match a2.as_var() { + Some(Ref::StackCell(fr, sc)) => { + self.and_stack[fr][sc] = t1; + self.trail(Ref::StackCell(fr, sc)); + }, + Some(Ref::HeapCell(h)) => { + self.heap[h] = HeapCellValue::Addr(t1); + self.trail(Ref::HeapCell(h)); + }, + None => {} + } + } } pub(super) @@ -711,9 +727,9 @@ impl MachineState { self.write_constant_to_var(addr, c.clone()); }, &FactInstruction::GetList(_, reg) => { - let addr = self.deref(self[reg].clone()); + let addr = self.store(self.deref(self[reg].clone())); - match self.store(addr.clone()) { + match addr { Addr::HeapCell(hc) => { let h = self.heap.h; @@ -955,10 +971,8 @@ impl MachineState { self.registers[arg] = self.heap[h].as_addr(h); } }, - &QueryInstruction::PutValue(norm, arg) => { - let addr = self.store(self.deref(self[norm].clone())); - self.registers[arg] = self[norm].clone(); - }, + &QueryInstruction::PutValue(norm, arg) => + self.registers[arg] = self[norm].clone(), &QueryInstruction::PutVariable(norm, arg) => { match norm { RegType::Perm(n) => { @@ -1724,20 +1738,26 @@ impl MachineState { match instr { &ControlInstruction::Allocate(num_cells) => self.allocate(num_cells), - &ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) => - try_or_fail!(self, call_policy.call_n(self, arity, code_dirs, lco)), - &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => - try_or_fail!(self, call_policy.call_builtin(self, ct, lco)), + &ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) => { + self.last_call = lco; + try_or_fail!(self, call_policy.call_n(self, arity, code_dirs)); + }, + &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => { + self.last_call = lco; + try_or_fail!(self, call_policy.call_builtin(self, ct)); + }, &ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) => self.execute_inlined(ct), &ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco) - | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => - try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(), - lco)), - &ControlInstruction::CallClause(ClauseType::System(ref ct), arity, _, lco) => { + | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => { + self.last_call = lco; + try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone())); + }, + &ControlInstruction::CallClause(ClauseType::System(ref ct), _, _, lco) => { + self.last_call = lco; try_or_fail!(self, self.system_call(ct, call_policy, cut_policy)); - if lco { + if self.last_call { self.p = CodePtr::Local(self.cp.clone()); } else { self.p += 1; @@ -1785,11 +1805,13 @@ impl MachineState { self.fail = true; }, &ControlInstruction::IsClause(lco, r, ref at) => { + self.last_call = lco; + let a1 = self[r].clone(); let a2 = try_or_fail!(self, self.get_number(at)); self.unify(a1, Addr::Con(Constant::Number(a2))); - try_or_fail!(self, return_from_clause!(lco, self)); + try_or_fail!(self, return_from_clause!(self.last_call, self)); }, &ControlInstruction::JmpBy(arity, offset, _, lco) => { if !lco { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 74b261c8..e1112fae 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -233,9 +233,10 @@ impl Machine { CodePtr::Local(LocalCodePtr::DirEntry(p, _)) => Some(self.code[p].clone()), CodePtr::BuiltInClause(built_in, _) => - Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), 0)), + Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), + 0, self.ms.last_call)), CodePtr::CallN(arity, _) => - Some(call_clause!(ClauseType::CallN, arity, 0)) + Some(call_clause!(ClauseType::CallN, arity, 0, self.ms.last_call)) } } diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 36a1b438..9019233c 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -134,7 +134,10 @@ macro_rules! is_var { macro_rules! call_clause { ($ct:expr, $arity:expr, $pvs:expr) => ( Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, false)) - ) + ); + ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => ( + Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, $lco)) + ) } macro_rules! proceed { @@ -144,9 +147,8 @@ macro_rules! proceed { } macro_rules! is_call { - ($r:expr, $at:expr) => ( + ($r:expr, $at:expr) => ( Line::Control(ControlInstruction::IsClause(false, $r, $at)) - ) } -- 2.54.0