]> Repositorios git - scryer-prolog.git/commitdiff
optimizations
authorMark Thom <[email protected]>
Thu, 23 Mar 2017 04:30:45 +0000 (22:30 -0600)
committerMark Thom <[email protected]>
Thu, 23 Mar 2017 04:30:45 +0000 (22:30 -0600)
Cargo.lock
Cargo.toml
README.md
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/io.rs
src/prolog/machine.rs

index 99f64f8eb755549c57ee8f2e7ccbe3cdba0bf6c1..eadb9dbd690c398a4e10d17cd9f95dbf3c39b81f 100644 (file)
@@ -1,6 +1,6 @@
 [root]
 name = "rusty-wam"
-version = "0.5.0"
+version = "0.5.3"
 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 8017f46b18ef7f8070a71c780b5f0e19f8d2b376..fc29ae3b630555adbf582c9c3f97b92efb0815e6 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.5.0"
+version = "0.5.4"
 authors = ["Mark Thom"]
 
 build = "build.rs"
index 11bfc8770c50dc4cebc3f080ed235e29db66f22c..e9c3d65b02a839236fede82e21f795e15f03f38a 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
-middle of section 5.2. Atoms and lists are the only two data types
-currently supported.
+to the end of section 5.3, 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 4f42990e27685c6fc718c967981f024780e88191..da1646caa0070748803ce80e7517ce77af0744f8 100644 (file)
@@ -80,6 +80,10 @@ impl VarReg {
         }
     }
 
+    pub fn is_temp(self) -> bool {
+        !self.norm().is_perm()
+    }
+    
     pub fn root_register(self) -> usize {
         match self {
             VarReg::ArgAndNorm(_, root) => root,
@@ -126,10 +130,11 @@ pub enum FactInstruction {
     GetList(Level, RegType),
     GetStructure(Level, Atom, usize, RegType),
     GetValue(RegType, usize),
-    GetVariable(RegType, usize),
+    GetVariable(RegType, usize),    
     UnifyConstant(Constant),
     UnifyVariable(RegType),
-    UnifyValue(RegType)
+    UnifyValue(RegType),
+    UnifyVoid(usize)
 }
 
 pub enum QueryInstruction {
@@ -140,7 +145,8 @@ pub enum QueryInstruction {
     PutVariable(RegType, usize),
     SetConstant(Constant),
     SetVariable(RegType),
-    SetValue(RegType)
+    SetValue(RegType),
+    SetVoid(usize)
 }
 
 pub enum ChoiceInstruction {
index c8af1746f89ba52ec4e23361aa0cda5ed1d137e8..5e10a308a76a805eb7cf04f85d1ae18b6369b48a 100644 (file)
@@ -11,9 +11,10 @@ trait CompilationTarget<'a> {
 
     fn iter(&'a Term) -> Self::Iterator;
 
-    fn to_structure(Level, Atom, usize, RegType) -> Self;
     fn to_constant(Level, Constant, RegType) -> Self;
     fn to_list(Level, RegType) -> Self;
+    fn to_structure(Level, Atom, usize, RegType) -> Self;
+    fn to_void(usize) -> Self;
 
     fn constant_subterm(Constant) -> Self;
 
@@ -33,18 +34,22 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
         term.breadth_first_iter()
     }
 
-    fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
-        FactInstruction::GetStructure(lvl, atom, arity, reg)
-    }
-
     fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
         FactInstruction::GetConstant(lvl, constant, reg)
     }
 
+    fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
+        FactInstruction::GetStructure(lvl, atom, arity, reg)
+    }
+
     fn to_list(lvl: Level, reg: RegType) -> Self {
         FactInstruction::GetList(lvl, reg)
     }
 
+    fn to_void(subterms: usize) -> Self {
+        FactInstruction::UnifyVoid(subterms)
+    }
+
     fn constant_subterm(constant: Constant) -> Self {
         FactInstruction::UnifyConstant(constant)
     }
@@ -76,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)
     }
@@ -89,6 +94,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
         QueryInstruction::PutList(lvl, reg)
     }
 
+    fn to_void(subterms: usize) -> Self {
+        QueryInstruction::SetVoid(subterms)
+    }
+
     fn constant_subterm(constant: Constant) -> Self {
         QueryInstruction::SetConstant(constant)
     }
@@ -145,7 +154,7 @@ impl<'a> TermMarker<'a> {
     fn insert(&mut self, var: &'a Var, r: VarReg) {
         self.bindings.insert(var, r);
     }
-    
+
     fn mark_non_var(&mut self, lvl: Level, cell: &Cell<RegType>) {
         let reg_type = cell.get();
 
@@ -212,18 +221,18 @@ impl<'a> TermMarker<'a> {
                 reg
             }
         };
-        
-        self.insert(var, reg);                
+
+        self.insert(var, reg);
         reg
     }
-    
+
     fn mark_anon_var(&mut self, lvl: Level) -> VarReg {
         let inner_reg = {
             let temp = self.temp_c;
             self.temp_c += 1;
             RegType::Temp(temp)
         };
-        
+
         match lvl {
             Level::Deep => VarReg::Norm(inner_reg),
             Level::Shallow => {
@@ -233,7 +242,11 @@ impl<'a> TermMarker<'a> {
             }
         }
     }
-    
+
+    fn advance_arg(&mut self) {
+        self.arg_c += 1;
+    }
+
     fn advance_at_head(&mut self, term: &'a Term) {
         self.arg_c = 1;
         self.temp_c = max(term.subterms(), self.temp_c) + 1;
@@ -266,6 +279,46 @@ impl<'a> CodeGenerator<'a> {
         &self.marker.bindings
     }
 
+    #[allow(dead_code)]
+    fn count_vars(term: &Term) -> HashMap<&Var, usize> {
+        let mut var_count = HashMap::new();
+
+        for term in term.breadth_first_iter() {
+            if let TermRef::Var(_, _, ref var) = term {
+                let entry = var_count.entry(*var).or_insert(0);
+                *entry += 1;
+            }
+        }
+
+        var_count
+    }
+
+    #[allow(dead_code)]
+    fn all_singleton_vars(terms: &Vec<Box<Term>>,
+                          var_count: &HashMap<&Var, usize>)
+                          -> bool
+    {
+        for term in terms {
+            match term.as_ref() {
+                &Term::AnonVar => {},
+                &Term::Var(ref cell, ref var) if cell.get().is_temp() =>
+                    if var_count.get(var).unwrap() != &1 {
+                        return false;
+                    },
+                _ => return false
+            }
+        }
+
+        true
+    }
+
+    #[allow(dead_code)]
+    fn void_subterms<Target>(subterms: usize) -> Target
+        where Target: CompilationTarget<'a>
+    {
+        Target::to_void(subterms)
+    }
+
     fn to_structure<Target>(&mut self,
                             lvl: Level,
                             cell: &'a Cell<RegType>,
@@ -305,10 +358,10 @@ impl<'a> CodeGenerator<'a> {
         self.marker.mark_non_var(Level::Deep, cell);
         Target::constant_subterm(constant.clone())
     }
-    
+
     fn anon_var_term<Target>(&mut self, lvl: Level) -> Target
         where Target: CompilationTarget<'a>
-    {        
+    {
         let reg = self.marker.mark_anon_var(lvl);
 
         match reg {
@@ -318,7 +371,7 @@ impl<'a> CodeGenerator<'a> {
                 Target::subterm_to_variable(norm)
         }
     }
-    
+
     fn var_term<Target>(&mut self,
                         lvl: Level,
                         cell: &'a Cell<VarReg>,
@@ -371,17 +424,26 @@ impl<'a> CodeGenerator<'a> {
         }
     }
 
-    fn compile_target<Target>(&mut self, term: &'a Term) -> Vec<Target>
+    fn compile_target<Target>(&mut self, term: &'a Term, has_exposed_vars: bool)
+                              -> Vec<Target>
         where Target: CompilationTarget<'a>
     {
         let iter       = Target::iter(term);
         let mut target = Vec::new();
+        let var_count  = Self::count_vars(term);
 
         for term in iter {
             match term {
                 TermRef::Clause(lvl, cell, atom, terms) => {
                     target.push(self.to_structure(lvl, cell, atom, terms.len()));
 
+                    if !has_exposed_vars {
+                        if Self::all_singleton_vars(terms, &var_count) {
+                            target.push(Self::void_subterms(terms.len()));
+                            continue;
+                        }
+                    }
+                    
                     for subterm in terms {
                         target.push(self.subterm_to_instr(subterm.as_ref()));
                     }
@@ -394,8 +456,13 @@ impl<'a> CodeGenerator<'a> {
                 },
                 TermRef::Constant(lvl @ Level::Shallow, cell, constant) =>
                     target.push(self.to_constant(lvl, cell, constant)),
-                TermRef::AnonVar(lvl @ Level::Shallow) =>
-                    target.push(self.anon_var_term(lvl)),
+                TermRef::AnonVar(lvl @ Level::Shallow) => {
+                    if has_exposed_vars {
+                        target.push(self.anon_var_term(lvl));
+                    } else {
+                        self.marker.advance_arg();
+                    }
+                },
                 TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
                     target.push(self.var_term(lvl, cell, var)),
                 _ => {}
@@ -480,15 +547,15 @@ impl<'a> CodeGenerator<'a> {
         body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
 
         self.marker.advance(p0);
-        body.push(Line::Fact(self.compile_target(p0)));
+        body.push(Line::Fact(self.compile_target(p0, false)));
 
         self.marker.advance_at_head(p1);
-        body.push(Line::Query(self.compile_target(p1)));
+        body.push(Line::Query(self.compile_target(p1, false)));
 
         Self::add_conditional_call(&mut body, p1);
 
         body = clauses.iter()
-            .map(|ref term| self.compile_query(term))
+            .map(|ref term| self.compile_internal_query(term))
             .fold(body, |mut body, ref mut cqs| {
                 body.append(cqs);
                 body
@@ -501,17 +568,26 @@ impl<'a> CodeGenerator<'a> {
     pub fn compile_fact(&mut self, term: &'a Term) -> Code {
         self.marker.advance(term);
 
-        let mut compiled_fact = vec![Line::Fact(self.compile_target(term))];
+        let mut compiled_fact = vec![Line::Fact(self.compile_target(term, false))];
         let proceed = Line::Control(ControlInstruction::Proceed);
 
         compiled_fact.push(proceed);
         compiled_fact
     }
+    
+    fn compile_internal_query(&mut self, term: &'a Term) -> Code {
+        self.marker.advance(term);
+
+        let mut compiled_query = vec![Line::Query(self.compile_target(term, false))];
+        Self::add_conditional_call(&mut compiled_query, term);
 
+        compiled_query
+    }
+    
     pub fn compile_query(&mut self, term: &'a Term) -> Code {
         self.marker.advance(term);
 
-        let mut compiled_query = vec![Line::Query(self.compile_target(term))];
+        let mut compiled_query = vec![Line::Query(self.compile_target(term, true))];
         Self::add_conditional_call(&mut compiled_query, term);
 
         compiled_query
index 6fbf313476e71031814a544a50ad952dd39f606f..3d76044721acc40a947887068c16e0bb6e12ee16 100644 (file)
@@ -14,7 +14,7 @@ impl fmt::Display for Constant {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             &Constant::Atom(ref atom) =>
-                write!(f, "{}", atom),        
+                write!(f, "{}", atom),
             &Constant::EmptyList =>
                 write!(f, "[]")
         }
@@ -45,7 +45,9 @@ impl fmt::Display for FactInstruction {
             &FactInstruction::UnifyVariable(ref r) =>
                 write!(f, "unify_variable {}", r),
             &FactInstruction::UnifyValue(ref r) =>
-                write!(f, "unify_value {}", r)
+                write!(f, "unify_value {}", r),
+            &FactInstruction::UnifyVoid(n) =>
+                write!(f, "unify_void {}", n)
         }
     }
 }
@@ -74,7 +76,9 @@ impl fmt::Display for QueryInstruction {
             &QueryInstruction::SetVariable(ref r) =>
                 write!(f, "set_variable {}", r),
             &QueryInstruction::SetValue(ref r) =>
-                write!(f, "set_value {}", r)
+                write!(f, "set_value {}", r),
+            &QueryInstruction::SetVoid(n) =>
+                write!(f, "set_void {}", n)
         }
     }
 }
@@ -207,7 +211,7 @@ pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
         &Ok(TopLevel::Predicate(ref clauses)) => {
             if is_consistent(clauses) {
                 let compiled_pred = cg.compile_predicate(clauses);
-                wam.add_predicate(clauses, compiled_pred);                
+                wam.add_predicate(clauses, compiled_pred);
 
                 EvalResult::EntrySuccess
             } else {
@@ -229,8 +233,8 @@ Each predicate must have the same name and arity.";
             EvalResult::EntrySuccess
         },
         &Ok(TopLevel::Query(ref query)) => {
-            let compiled_query = cg.compile_query(&query);
-            wam.run_query(compiled_query, &cg)            
+            let compiled_query = cg.compile_query(&query);            
+            wam.run_query(compiled_query, &cg)
         },
         &Err(_) => {
             println!("Grammatical error of some kind!");
@@ -251,7 +255,7 @@ pub fn print(wam: &mut Machine, result: EvalResult) {
             'outer: loop {
                 let mut result = EvalResult::QueryFailure;
                 let bindings = wam.heap_view(&heap_locs);
-                
+
                 let stdin  = stdin();
                 let mut stdout = stdout().into_raw_mode().unwrap();
 
index 3e8f3fd351339cbef83ae8a58739c254f8e45be6..84dcce11595615066c7341cf5f648d200cc7a0db 100644 (file)
@@ -585,6 +585,21 @@ impl MachineState {
                 };
 
                 self.s += 1;
+            },
+            &FactInstruction::UnifyVoid(n) => {
+                match self.mode {
+                    MachineMode::Read =>
+                        self.s += n,
+                    MachineMode::Write => {
+                        let h = self.h;
+
+                        for i in h .. h + n {
+                            self.heap.push(HeapCellValue::Ref(Ref::HeapCell(i)));
+                        }
+
+                        self.h += n;
+                    }
+                };
             }
         };
     }
@@ -628,6 +643,15 @@ impl MachineState {
 
                 self.h += 1;
             },
+            &QueryInstruction::SetVoid(n) => {
+                let h = self.h;
+
+                for i in h .. h + n {
+                    self.heap.push(HeapCellValue::Ref(Ref::HeapCell(i)));
+                }
+
+                self.h += n;
+            }
         }
     }