From 2d4e4c59de3c51a2420b1b153f3cc59ffd30dbd1 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 25 Dec 2017 00:04:52 -0700 Subject: [PATCH] remove Terminal, correct , bugs --- src/prolog/ast.rs | 14 +++--- src/prolog/builtins.rs | 99 +++++++++++++++++------------------------- src/prolog/codegen.rs | 78 +++++++++++++++------------------ src/prolog/io.rs | 26 ++++------- src/prolog/machine.rs | 58 ++++++++++++------------- src/prolog/macros.rs | 46 ++++++++++---------- 6 files changed, 141 insertions(+), 180 deletions(-) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 77f06586..9e6f4935 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -422,15 +422,10 @@ pub enum ChoiceInstruction { TryMeElse(usize) } -#[derive(Clone, Copy)] -pub enum Terminal { - Terminal, Non -} - pub enum CutInstruction { - Cut(Terminal), + Cut, GetLevel, - NeckCut(Terminal) + NeckCut } pub enum IndexedChoiceInstruction { @@ -722,14 +717,15 @@ pub enum BuiltInInstruction { Fail, GetBall, GetCurrentBlock, - GetCutPoint, + GetCutPoint(RegType), InstallNewBlock, InternalCallN, IsAtomic(RegType), IsVar(RegType), ResetBlock, SetBall, - SetCutPoint, + SetNeckCutPoint(RegType), + SetNonNeckCutPoint(RegType), Succeed, Unify, UnwindStack diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index cdb7f53e..cb81fd3a 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -65,7 +65,7 @@ fn get_builtins() -> Code { get_level!(), fact![get_var_in_fact!(perm_v!(2), 3)], unify!(), - cut!(non_terminal!()), + cut!(), erase_ball!(), query![put_value!(perm_v!(2), 1)], deallocate!(), @@ -95,7 +95,7 @@ fn get_builtins() -> Code { allocate!(1), get_level!(), call_n!(1), - cut!(non_terminal!()), + cut!(), deallocate!(), goto!(61, 0), trust_me!(), @@ -110,83 +110,62 @@ fn get_builtins() -> Code { trust_me!(), query![put_value!(temp_v!(2), 1)], execute_n!(1), - allocate!(3), // ','/2, 81. - fact![get_var_in_fact!(perm_v!(2), 1), - get_var_in_fact!(perm_v!(1), 2)], - query![put_var!(perm_v!(3), 1)], - get_cp!(), - query![put_value!(perm_v!(2), 1), - put_value!(perm_v!(1), 2), - put_unsafe_value!(3, 3)], - deallocate!(), - goto!(88, 3), - try_me_else!(25), // ','/3, 88. + get_cp!(temp_v!(3)), // ','/2, 81 + goto!(83, 3), + try_me_else!(18), // ','/3, 83. switch_on_term!(4, 1, 0, 0), indexed_try!(4), - retry!(11), - trust!(14), - try_me_else!(8), - allocate!(3), + retry!(7), + trust!(10), + try_me_else!(4), fact![get_constant!(Constant::from("!"), temp_v!(1)), get_structure!(String::from(","), 2, temp_v!(2)), - unify_variable!(perm_v!(2)), - unify_variable!(perm_v!(1)), - get_var_in_fact!(perm_v!(3), 3)], - query![put_value!(perm_v!(3), 1)], - set_cp!(), - query![put_unsafe_value!(2, 1), - put_unsafe_value!(1, 2), - put_value!(perm_v!(3), 3)], - deallocate!(), - goto!(88, 3), + unify_variable!(temp_v!(1)), + unify_variable!(temp_v!(2))], + set_neck_cut!(temp_v!(3)), + goto!(83, 3), retry_me_else!(4), fact![get_constant!(Constant::from("!"), temp_v!(1)), get_constant!(Constant::from("!"), temp_v!(2))], - query![put_value!(temp_v!(3), 1)], - set_cp!(), + set_neck_cut!(temp_v!(3)), + proceed!(), trust_me!(), - allocate!(1), - fact![get_constant!(Constant::from("!"), temp_v!(1)), - get_var_in_fact!(perm_v!(1), 2)], - query![put_value!(temp_v!(3), 1)], - set_cp!(), - query![put_value!(perm_v!(1), 1)], - deallocate!(), + fact![get_constant!(Constant::from("!"), temp_v!(1))], + set_neck_cut!(temp_v!(3)), + query![put_value!(temp_v!(2), 1)], execute_n!(1), retry_me_else!(8), - allocate!(1), - fact![get_constant!(Constant::from("!"), temp_v!(2)), - get_var_in_fact!(perm_v!(1), 3)], - neck_cut!(non_terminal!()), - call_n!(1), - query![put_value!(perm_v!(1), 1)], - deallocate!(), - set_cp!(), - retry_me_else!(8), // 121. - allocate!(3), + allocate!(2), fact![get_structure!(String::from(","), 2, temp_v!(2)), unify_variable!(perm_v!(2)), - unify_variable!(perm_v!(1)), - get_var_in_fact!(perm_v!(3), 3)], - neck_cut!(non_terminal!()), + unify_variable!(perm_v!(1))], + neck_cut!(), call_n!(1), query![put_unsafe_value!(2, 1), - put_unsafe_value!(1, 2), - put_value!(perm_v!(3), 3)], + put_unsafe_value!(1, 2)], deallocate!(), - goto!(88, 3), + goto!(83, 3), + retry_me_else!(9), + allocate!(1), + get_level!(), + fact![get_constant!(Constant::from("!"), temp_v!(2))], + neck_cut!(), + call_n!(1), + set_non_neck_cut!(temp_v!(3)), + deallocate!(), + proceed!(), trust_me!(), allocate!(1), - fact![get_var_in_fact!(perm_v!(1), 2)], + fact![get_var_in_fact!(perm_v!(1), 2)], call_n!(1), query![put_value!(perm_v!(1), 1)], deallocate!(), execute_n!(1), - allocate!(2), // (->)/2, 136. + allocate!(2), // (->)/2, 124. get_level!(), fact![get_var_in_fact!(perm_v!(2), 2)], call_n!(1), - cut!(non_terminal!()), + cut!(), query![put_value!(perm_v!(2), 1)], deallocate!(), execute_n!(1) @@ -237,7 +216,7 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir) // control operators. op_dir.insert((String::from(";"), Fixity::In), (XFY, 1100)); op_dir.insert((String::from("->"), Fixity::In), (XFY, 1050)); - + // there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62 // (an extra register is needed for the predicate name) for arity in 0 .. 63 { @@ -252,11 +231,11 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir) code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5)); code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59)); code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73)); - code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75)); + code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75)); code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 76)); - code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81)); - code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 136)); - + code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81)); + code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 124)); + (builtin_code, code_dir, op_dir) } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index c21a1bc0..1a8bc30b 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -99,12 +99,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> if !target.is_empty() { code.push(Line::Query(target)); } - + vr.get().norm() } } } - + fn add_or_increment_void_instr(target: &mut Vec) where Target: CompilationTarget<'a> { @@ -233,11 +233,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> ConjunctInfo::new(vs, num_of_chunks, has_deep_cut) } - fn add_conditional_call_inlined(_: &InlinedQueryTerm, code: &mut Code) - { - code.push(proceed!()); - } - fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) { match qt { @@ -247,8 +242,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> }, &QueryTerm::Catch(_) => code.push(Line::Control(ControlInstruction::CatchCall)), - &QueryTerm::Inlined(ref term) => - Self::add_conditional_call_inlined(term, code), + &QueryTerm::Inlined(_) => + code.push(proceed!()), &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => { let call = ControlInstruction::Call(atom.clone(), 0, pvs); code.push(Line::Control(call)); @@ -267,25 +262,30 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> { let mut dealloc_index = code.len() - 1; - if let Some(&mut Line::Control(ref mut ctrl)) = code.last_mut() { - let mut instr = ControlInstruction::Proceed; - swap(ctrl, &mut instr); - - match instr { - ControlInstruction::Call(name, arity, _) => - *ctrl = ControlInstruction::Execute(name, arity), - ControlInstruction::CallN(arity) => - *ctrl = ControlInstruction::ExecuteN(arity), - ControlInstruction::CatchCall => - *ctrl = ControlInstruction::CatchExecute, - ControlInstruction::ThrowCall => - *ctrl = ControlInstruction::ThrowExecute, - ControlInstruction::IsCall(r, at) => - *ctrl = ControlInstruction::IsExecute(r, at), - ControlInstruction::Proceed => {}, - _ => dealloc_index += 1 // = code.len() - } - } + match code.last_mut() { + Some(&mut Line::Control(ref mut ctrl)) => { + let mut instr = ControlInstruction::Proceed; + swap(ctrl, &mut instr); + + match instr { + ControlInstruction::Call(name, arity, _) => + *ctrl = ControlInstruction::Execute(name, arity), + ControlInstruction::CallN(arity) => + *ctrl = ControlInstruction::ExecuteN(arity), + ControlInstruction::CatchCall => + *ctrl = ControlInstruction::CatchExecute, + ControlInstruction::ThrowCall => + *ctrl = ControlInstruction::ThrowExecute, + ControlInstruction::IsCall(r, at) => + *ctrl = ControlInstruction::IsExecute(r, at), + ControlInstruction::Proceed => {}, + _ => dealloc_index += 1 // = code.len() + } + }, + Some(&mut Line::Cut(CutInstruction::Cut)) => + dealloc_index += 1, + _ => {} + }; dealloc_index } @@ -330,7 +330,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> let r = self.mark_non_callable(name, 1, term_loc, vr, code); code.push(is_var!(r)); } - } + } } Ok(()) @@ -361,22 +361,16 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> match *term { &QueryTerm::Cut => { - let is_terminal = if i + 1 < terms.len() { - Terminal::Non - } else { - Terminal::Terminal - }; - code.push(if chunk_num == 0 { - Line::Cut(CutInstruction::NeckCut(is_terminal)) + Line::Cut(CutInstruction::NeckCut) } else { - Line::Cut(CutInstruction::Cut(is_terminal)) + Line::Cut(CutInstruction::Cut) }); }, &QueryTerm::Is(ref terms) => { let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?; code.append(&mut acode); - + match terms[0].as_ref() { &Term::Var(ref vr, ref name) => { let r = self.mark_non_callable(name, @@ -384,7 +378,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> term_loc, vr, code); - + code.push(is_call!(r, at.unwrap_or(interm!(1)))); }, &Term::Constant(_, Constant::Float(fl)) => { @@ -423,7 +417,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> if !query.is_empty() { code.push(Line::Query(query)); } - + Self::add_conditional_call(code, term, conjunct_info.perm_vars()); }, _ => { @@ -455,8 +449,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) { match toc { - &QueryTerm::Inlined(ref term) => - Self::add_conditional_call_inlined(term, code), + &QueryTerm::Inlined(_) | &QueryTerm::Cut => + code.push(proceed!()), _ => {} }; diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 5780dec3..6305006d 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -141,17 +141,6 @@ impl fmt::Display for IndexedChoiceInstruction { } } -impl fmt::Display for Terminal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Terminal::Terminal => - write!(f, "terminal"), - &Terminal::Non => - write!(f, "non_terminal") - } - } -} - impl fmt::Display for BuiltInInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -169,8 +158,8 @@ impl fmt::Display for BuiltInInstruction { write!(f, "get_ball X1"), &BuiltInInstruction::GetCurrentBlock => write!(f, "get_current_block X1"), - &BuiltInInstruction::GetCutPoint => - write!(f, "get_cp"), + &BuiltInInstruction::GetCutPoint(r) => + write!(f, "get_cp {}", r), &BuiltInInstruction::InstallNewBlock => write!(f, "install_new_block"), &BuiltInInstruction::InternalCallN => @@ -183,8 +172,10 @@ impl fmt::Display for BuiltInInstruction { write!(f, "reset_block"), &BuiltInInstruction::SetBall => write!(f, "set_ball"), - &BuiltInInstruction::SetCutPoint => - write!(f, "set_cp"), + &BuiltInInstruction::SetNeckCutPoint(r) => + write!(f, "set_neck_cp {}", r), + &BuiltInInstruction::SetNonNeckCutPoint(r) => + write!(f, "set_non_neck_cp {}", r), &BuiltInInstruction::Succeed => write!(f, "true"), &BuiltInInstruction::UnwindStack => @@ -272,9 +263,9 @@ impl fmt::Display for ArithmeticInstruction { impl fmt::Display for CutInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &CutInstruction::Cut(_) => + &CutInstruction::Cut => write!(f, "cut"), - &CutInstruction::NeckCut(_) => + &CutInstruction::NeckCut => write!(f, "neck_cut"), &CutInstruction::GetLevel => write!(f, "get_level") @@ -382,6 +373,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<' Err(e) => return EvalSession::ParserError(e) }; + print_code(&compiled_pred); wam.add_predicate(clauses, compiled_pred) }, &TopLevel::Fact(ref fact) => { diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 4ea6dc2c..00a99f74 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -1622,13 +1622,6 @@ impl MachineState { self.write_constant_to_var(addr, &c); self.p += 1; }, - &BuiltInInstruction::GetCutPoint => { - let c = Constant::Usize(self.b); - let addr = self[temp_v!(1)].clone(); - - self.write_constant_to_var(addr, &c); - self.p += 1; - }, &BuiltInInstruction::EraseBall => { self.ball.0 = 0; self.ball.1.truncate(0); @@ -1655,6 +1648,12 @@ impl MachineState { _ => self.fail = true }; }, + &BuiltInInstruction::GetCutPoint(r) => { + let c = Constant::Usize(self.b); + self[r] = Addr::Con(c); + + self.p += 1; + }, &BuiltInInstruction::SetBall => { let addr = self[temp_v!(1)].clone(); self.ball.0 = self.heap.h; @@ -1666,17 +1665,24 @@ impl MachineState { self.p += 1; }, - &BuiltInInstruction::SetCutPoint => { - let nb = self.store(self.deref(self[temp_v!(1)].clone())); + &BuiltInInstruction::SetNeckCutPoint(r) => { + let addr = self.store(self.deref(self[r].clone())); - match nb { + match addr { Addr::Con(Constant::Usize(nb)) => { - self.or_stack.truncate(nb); self.b = nb; - - self.tidy_trail(); + self.neck_cut(); + }, + _ => self.fail = true + }; + }, + &BuiltInInstruction::SetNonNeckCutPoint(r) => { + let addr = self.store(self.deref(self[r].clone())); - self.p += 1; + match addr { + Addr::Con(Constant::Usize(nb)) => { + self.b = nb; + self.non_neck_cut(); }, _ => self.fail = true }; @@ -2019,7 +2025,7 @@ impl MachineState { } } - fn neck_cut(&mut self, term: Terminal) + fn neck_cut(&mut self) { let b = self.b; let b0 = self.b0; @@ -2029,14 +2035,10 @@ impl MachineState { self.tidy_trail(); } - if let Terminal::Terminal = term { - self.p = self.cp; - } else { - self.p += 1; - } + self.p += 1; } - fn non_neck_cut(&mut self, term: Terminal) + fn non_neck_cut(&mut self) { let b = self.b; let e = self.e; @@ -2047,17 +2049,13 @@ impl MachineState { self.tidy_trail(); } - if let Terminal::Terminal = term { - self.p = self.cp; - } else { - self.p += 1; - } + self.p += 1; } fn execute_cut_instr(&mut self, instr: &CutInstruction) { match instr { - &CutInstruction::Cut(term) => - self.non_neck_cut(term), + &CutInstruction::Cut => + self.non_neck_cut(), &CutInstruction::GetLevel => { let b0 = self.b0; let e = self.e; @@ -2065,8 +2063,8 @@ impl MachineState { self.and_stack[e].b0 = b0; self.p += 1; }, - &CutInstruction::NeckCut(term) => - self.neck_cut(term) + &CutInstruction::NeckCut => + self.neck_cut() } } diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index bd7e72cc..680ee2b1 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -165,21 +165,15 @@ macro_rules! proceed { ) } -macro_rules! non_terminal { - () => ( - Terminal::Non - ) -} - macro_rules! cut { - ($term:expr) => ( - Line::Cut(CutInstruction::Cut($term)) + () => ( + Line::Cut(CutInstruction::Cut) ) } macro_rules! neck_cut { - ($term:expr) => ( - Line::Cut(CutInstruction::NeckCut($term)) + () => ( + Line::Cut(CutInstruction::NeckCut) ) } @@ -297,18 +291,6 @@ macro_rules! trust { ) } -macro_rules! get_cp { - () => ( - Line::BuiltIn(BuiltInInstruction::GetCutPoint) - ) -} - -macro_rules! set_cp { - () => ( - Line::BuiltIn(BuiltInInstruction::SetCutPoint) - ) -} - macro_rules! get_constant { ($c:expr, $r:expr) => ( FactInstruction::GetConstant(Level::Shallow, $c, $r) @@ -326,3 +308,23 @@ macro_rules! unify_variable { FactInstruction::UnifyVariable($r) ) } + +macro_rules! set_neck_cut { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::SetNeckCutPoint($r)) + ) +} + +macro_rules! set_non_neck_cut { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::SetNonNeckCutPoint($r)) + ) +} + +macro_rules! get_cp { + ($r:expr) => ( + Line::BuiltIn(BuiltInInstruction::GetCutPoint($r)) + ) +} + + -- 2.54.0