From: Mark Thom Date: Thu, 23 Mar 2017 07:06:06 +0000 (-0600) Subject: optimizations up to section 5.7. X-Git-Tag: v0.8.110~755 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=e1cc5ecfd6360758bf263d246b036083e1f03675;p=scryer-prolog.git optimizations up to section 5.7. --- diff --git a/Cargo.lock b/Cargo.lock index eadb9dbd..44d3cb16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rusty-wam" -version = "0.5.3" +version = "0.5.5" dependencies = [ "lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index fc29ae3b..180309ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.5.4" +version = "0.5.6" authors = ["Mark Thom"] build = "build.rs" diff --git a/README.md b/README.md index e9c3d65b..dbedf0d3 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ pure Prolog. Pure Prolog is implemented as a simple REPL. "Pure Prolog" is Prolog without cut, meta- or extra-logical operators, or side effects of any kind. In terms of the tutorial pacing, the work has progressed to the -to the end of section 5.3, skipping past 5.4. Atoms and lists -are the only two data types currently supported. +to the end of section 5.6, skipping past 5.4. Atoms and lists are the +only two data types currently supported. ## Tutorial To enter a multi-clause predicate, the brackets ":{" and "}:" are used diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index da1646ca..27ebae67 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -117,6 +117,15 @@ pub struct Rule { pub clauses: Vec } +impl Rule { + pub fn last_clause(&self) -> &Term { + match self.clauses.last() { + None => &self.head.1, + Some(clause) => clause + } + } +} + pub enum TermRef<'a> { AnonVar(Level), Cons(Level, &'a Cell, &'a Term, &'a Term), @@ -159,6 +168,7 @@ pub enum ControlInstruction { Allocate(usize), Call(Atom, usize), Deallocate, + Execute(Atom, usize), Proceed } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 5e10a308..c275b9cf 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -81,7 +81,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { fn iter(term: &'a Term) -> Self::Iterator { term.post_order_iter() } - + fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self { QueryInstruction::PutStructure(lvl, atom, arity, reg) } @@ -443,7 +443,7 @@ impl<'a> CodeGenerator<'a> { continue; } } - + for subterm in terms { target.push(self.subterm_to_instr(subterm.as_ref())); } @@ -517,7 +517,8 @@ impl<'a> CodeGenerator<'a> { vfs } - fn add_conditional_call(compiled_query: &mut Code, term: &Term) { + fn add_conditional_call(compiled_query: &mut Code, term: &Term) + { match term { &Term::Constant(_, Constant::Atom(ref atom)) => { let call = ControlInstruction::Call(atom.clone(), 0); @@ -544,7 +545,9 @@ impl<'a> CodeGenerator<'a> { let mut body = Vec::new(); - body.push(Line::Control(ControlInstruction::Allocate(perm_vars))); + if clauses.len() > 0 { + body.push(Line::Control(ControlInstruction::Allocate(perm_vars))); + } self.marker.advance(p0); body.push(Line::Fact(self.compile_target(p0, false))); @@ -561,7 +564,23 @@ impl<'a> CodeGenerator<'a> { body }); - body.push(Line::Control(ControlInstruction::Deallocate)); + let last_arity = rule.last_clause().arity(); + let mut dealloc_index = body.len() - 1; + + match rule.last_clause() { + &Term::Clause(_, ref name, _) + | &Term::Constant(_, Constant::Atom(ref name)) => { + if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() { + *ctrl = ControlInstruction::Execute(name.clone(), last_arity); + } + }, + _ => dealloc_index = body.len() + }; + + if clauses.len() > 0 { + body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate)); + } + body } @@ -574,7 +593,7 @@ impl<'a> CodeGenerator<'a> { compiled_fact.push(proceed); compiled_fact } - + fn compile_internal_query(&mut self, term: &'a Term) -> Code { self.marker.advance(term); @@ -583,7 +602,7 @@ impl<'a> CodeGenerator<'a> { compiled_query } - + pub fn compile_query(&mut self, term: &'a Term) -> Code { self.marker.advance(term); diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 3d760447..e7823301 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -92,6 +92,8 @@ impl fmt::Display for ControlInstruction { write!(f, "call {}/{}", name, arity), &ControlInstruction::Deallocate => write!(f, "deallocate"), + &ControlInstruction::Execute(ref name, arity) => + write!(f, "execute {}/{}", name, arity), &ControlInstruction::Proceed => write!(f, "proceed") } @@ -233,7 +235,7 @@ Each predicate must have the same name and arity."; EvalResult::EntrySuccess }, &Ok(TopLevel::Query(ref query)) => { - let compiled_query = cg.compile_query(&query); + let compiled_query = cg.compile_query(&query); wam.run_query(compiled_query, &cg) }, &Err(_) => { diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 84dcce11..5d328f40 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -681,20 +681,23 @@ impl MachineState { }, &ControlInstruction::Deallocate => { let e = self.e; + + self.cp = self.and_stack[e].cp; + self.e = self.and_stack[e].e; - let num_frame_e = self.and_stack.top().unwrap().global_index; - let num_frame_b = self.or_stack - .top() - .map(|fr| fr.global_index) - .unwrap_or(0); - - self.p = self.and_stack[e].cp; - self.e = self.and_stack[e].e; + self.p += 1; + }, + &ControlInstruction::Execute(ref name, arity) => { + let compiled_tl_index = code_dir.get(&(name.clone(), arity)) + .map(|index| *index); - if num_frame_e > num_frame_b { - let top_e = self.and_stack.top().unwrap().e; - self.and_stack.drop_frames(top_e - self.e + 1); - } + match compiled_tl_index { + Some(compiled_tl_index) => { + self.num_of_args = arity; + self.p = CodePtr::DirEntry(compiled_tl_index); + }, + None => self.fail = true + }; }, &ControlInstruction::Proceed => self.p = self.cp,