]> Repositorios git - scryer-prolog.git/commitdiff
optimizations up to section 5.7.
authorMark Thom <[email protected]>
Thu, 23 Mar 2017 07:06:06 +0000 (01:06 -0600)
committerMark Thom <[email protected]>
Thu, 23 Mar 2017 07:06:06 +0000 (01:06 -0600)
Cargo.lock
Cargo.toml
README.md
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/io.rs
src/prolog/machine.rs

index eadb9dbd690c398a4e10d17cd9f95dbf3c39b81f..44d3cb16910818d2adbd3ee20f9e928f49e24c9c 100644 (file)
@@ -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)",
index fc29ae3b630555adbf582c9c3f97b92efb0815e6..180309ee210b57328679feed38cc6242c590a1f7 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.5.4"
+version = "0.5.6"
 authors = ["Mark Thom"]
 
 build = "build.rs"
index e9c3d65b02a839236fede82e21f795e15f03f38a..dbedf0d321edfb1d83b6db82f7486292a48d9ad4 100644 (file)
--- 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
index da1646caa0070748803ce80e7517ce77af0744f8..27ebae67a19ca37c0051146788110849052f123f 100644 (file)
@@ -117,6 +117,15 @@ pub struct Rule {
     pub clauses: Vec<Term>
 }
 
+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<RegType>, &'a Term, &'a Term),
@@ -159,6 +168,7 @@ pub enum ControlInstruction {
     Allocate(usize),
     Call(Atom, usize),
     Deallocate,
+    Execute(Atom, usize),
     Proceed
 }
 
index 5e10a308a76a805eb7cf04f85d1ae18b6369b48a..c275b9cf0900b767ea2706a0e656533c1ac5cc8a 100644 (file)
@@ -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);
 
index 3d76044721acc40a947887068c16e0bb6e12ee16..e7823301a74bba22487a657dfa95411e6f0829cc 100644 (file)
@@ -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(_) => {
index 84dcce11595615066c7341cf5f648d200cc7a0db..5d328f4092307f243883bd710b845cb56ee2a47e 100644 (file)
@@ -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,