]> Repositorios git - scryer-prolog.git/commitdiff
inline atomic and var.
authorMark Thom <[email protected]>
Sat, 4 Nov 2017 02:41:01 +0000 (20:41 -0600)
committerMark Thom <[email protected]>
Sat, 4 Nov 2017 02:41:01 +0000 (20:41 -0600)
Cargo.lock
Cargo.toml
README.md
src/prolog/allocator.rs
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/codegen.rs
src/prolog/iterators.rs
src/prolog/machine.rs
src/prolog/macros.rs

index 3d7dbbb20add69c2cb2f8d17646f549aab55074c..0a442cf1573c314a01fddc8afdfbd8c93efc7bf5 100644 (file)
@@ -1,6 +1,6 @@
 [root]
 name = "rusty-wam"
-version = "0.7.0"
+version = "0.7.1"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
index de3f9c1339a113929a226b5a5cf46b98b932f842..bfa6fff124254dbf428399911775f8067cee8a89 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.7.0"
+version = "0.7.1"
 authors = ["Mark Thom"]
 
 [dependencies]
index b5b4bee3e804e1a5664a1765543a882358b0577e..d636b368fc4f630e7d94c7e8d071ea6a541dfbe5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -54,6 +54,7 @@ The following predicates are built-in to rusty-wam.
 * (\\+)/1
 * (=)/2
 * throw/1
+* true/0
 * var/1
 
 ## Tutorial
index d985219ae7527d4eff8fccca3b928dcb988d93af..2df627ace7f4246df6daec2b15579683e1700e79 100644 (file)
@@ -47,7 +47,7 @@ pub trait Allocator<'a>
     
     fn get(&self, var: &'a Var) -> RegType {
         self.bindings().get(var).unwrap().as_reg_type()
-    }    
+    }
     
     fn record_register(&mut self, var: &'a Var, r: RegType) {
         match self.bindings_mut().get_mut(var).unwrap() {
index 8edb881ad6c617eb1ee6ce20a7dc6152b21071a2..8ce3e39332418bcaa0ef6d729f60213ce96714f0 100644 (file)
@@ -273,10 +273,12 @@ pub enum Term {
     Var(Cell<VarReg>, Var)
 }
 
-pub enum QueryTerm {
+pub enum QueryTerm {    
     CallN(Vec<Box<Term>>),
     Catch(Vec<Box<Term>>),
     Cut,
+    IsAtomic(Vec<Box<Term>>),
+    IsVar(Vec<Box<Term>>),
     Term(Term),
     Throw(Vec<Box<Term>>)
 }
@@ -290,6 +292,10 @@ impl QueryTerm {
                 QueryTermRef::Catch(terms),
             &QueryTerm::Cut =>
                 QueryTermRef::Cut,
+            &QueryTerm::IsAtomic(ref terms) =>
+                QueryTermRef::IsAtomic(terms.first().unwrap()),
+            &QueryTerm::IsVar(ref terms) =>
+                QueryTermRef::IsVar(terms.first().unwrap()),
             &QueryTerm::Term(ref term) =>
                 QueryTermRef::Term(term),
             &QueryTerm::Throw(ref t) =>
@@ -314,10 +320,9 @@ pub enum ClauseType<'a> {
 
 impl<'a> ClauseType<'a> {
     pub fn level_of_subterms(self) -> Level {
-        match self {
-            ClauseType::CallN | ClauseType::Catch | ClauseType::Throw => Level::Shallow,
+        match self {            
             ClauseType::Deep(_, _, _) => Level::Deep,
-            ClauseType::Root => Level::Shallow,
+            _ => Level::Shallow
         }
     }
 }
@@ -338,11 +343,8 @@ impl<'a> TermRef<'a> {
           | TermRef::Cons(lvl, _, _, _)
           | TermRef::Constant(lvl, _, _)
           | TermRef::Var(lvl, _, _) => lvl,
-            TermRef::Clause(ClauseType::Root, _) => Level::Shallow,
             TermRef::Clause(ClauseType::Deep(lvl, _, _), _) => lvl,
-            TermRef::Clause(ClauseType::CallN, _) => Level::Shallow,
-            TermRef::Clause(ClauseType::Throw, _) => Level::Shallow,
-            TermRef::Clause(ClauseType::Catch, _) => Level::Shallow
+            _ => Level::Shallow
         }
     }
 }
@@ -352,6 +354,8 @@ pub enum QueryTermRef<'a> {
     CallN(&'a Vec<Box<Term>>),
     Catch(&'a Vec<Box<Term>>),
     Cut,
+    IsAtomic(&'a Term),
+    IsVar(&'a Term),
     Term(&'a Term),
     Throw(&'a Vec<Box<Term>>)
 }
@@ -361,6 +365,8 @@ impl<'a> QueryTermRef<'a> {
         match self {
             QueryTermRef::Catch(_) => 3,
             QueryTermRef::Throw(_) => 1,
+            QueryTermRef::IsAtomic(_) => 1,
+            QueryTermRef::IsVar(_) => 1,
             QueryTermRef::CallN(terms) => terms.len(),
             QueryTermRef::Cut => 0,
             QueryTermRef::Term(term) => term.arity(),
@@ -415,10 +421,11 @@ pub enum BuiltInInstruction {
     GetCurrentBlock,
     InstallNewBlock,
     InternalCallN,
-    IsAtomic,
-    IsVar,
+    IsAtomic(RegType),
+    IsVar(RegType),
     ResetBlock,
     SetBall,
+    Succeed,
     Unify,
     UnwindStack
 }
@@ -432,7 +439,7 @@ pub enum ControlInstruction {
     Deallocate,
     Execute(Atom, usize),
     ExecuteN(usize),
-    Goto(usize, usize),
+    Goto(usize, usize), // p, arity.
     Proceed,
     ThrowCall,
     ThrowExecute
index d791859417bb3f801214e8d65d348cbf6fe717b1..08be6bfe1281f48091b7fd914601a105a1d64f0c 100644 (file)
@@ -18,9 +18,9 @@ pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
 
 fn get_builtins() -> Code {
     vec![internal_call_n!(), // callN/N, 0.
-         is_atomic!(), // atomic/1, 1.
+         is_atomic!(temp_v!(1)), // atomic/1, 1.
          proceed!(),
-         is_var!(),    // var/1, 3.
+         is_var!(temp_v!(1)),    // var/1, 3.
          proceed!(),
          allocate!(4), // catch/3, 5.
          fact![get_var_in_fact!(perm_v!(2), 1),
@@ -104,6 +104,7 @@ fn get_builtins() -> Code {
          proceed!(),
          fact![get_value!(temp_v!(1), 2)], // =/2, 73.
          proceed!(),
+         succeed!(), // true/0, 75.
     ]
 }
 
@@ -134,6 +135,7 @@ 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));
 
     (builtin_code, code_dir, op_dir)
 }
index 1a9bb7438c1b4ee44f5b53416abc1ebf4a92e59f..ac6d01d2ffeb9bf7c9ce6209dc55c500af8c8039 100644 (file)
@@ -207,13 +207,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
     fn add_conditional_call(compiled_query: &mut Code, qt: QueryTermRef, pvs: usize)
     {
-        match qt {            
+        match qt {
             QueryTermRef::CallN(terms) => {
                 let call = ControlInstruction::CallN(terms.len());
                 compiled_query.push(Line::Control(call));
             },
             QueryTermRef::Catch(_) =>
-                compiled_query.push(Line::Control(ControlInstruction::CatchCall)),            
+                compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
             QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
                 let call = ControlInstruction::Call(atom.clone(), 0, pvs);
                 compiled_query.push(Line::Control(call));
@@ -228,31 +228,31 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         }
     }
 
-    fn lco(body: &mut Code, toc: QueryTermRef<'a>) -> usize
+    fn lco(code: &mut Code, toc: QueryTermRef<'a>) -> usize
     {
         let last_arity = toc.arity();
-        let mut dealloc_index = body.len() - 1;
+        let mut dealloc_index = code.len() - 1;
 
         match toc {
             QueryTermRef::Term(&Term::Clause(_, ref name, _))
           | QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref name))) =>
-                if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
+                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
                     *ctrl = ControlInstruction::Execute(name.clone(), last_arity);
                 },
             QueryTermRef::CallN(terms) =>
-                if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
+                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
                     *ctrl = ControlInstruction::ExecuteN(terms.len());
                 },
             QueryTermRef::Catch(_) =>
-                if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
+                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
                     *ctrl = ControlInstruction::CatchExecute;
                 },
             QueryTermRef::Cut => {},
             QueryTermRef::Throw(_) =>
-                if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
+                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
                     *ctrl = ControlInstruction::ThrowExecute;
                 },
-            _ => dealloc_index = body.len()
+            _ => dealloc_index = code.len()
         };
 
         dealloc_index
@@ -261,7 +261,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
     fn compile_seq(&mut self,
                    iter: ChunkedIterator<'a>,
                    conjunct_info: &ConjunctInfo<'a>,
-                   body: &mut Code,
+                   code: &mut Code,
                    is_exposed: bool)
     {
         for (chunk_num, _, terms) in iter {
@@ -275,29 +275,63 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
                 match term {
                     &QueryTermRef::Cut if i + 1 < terms.len() => {
-                        body.push(if chunk_num == 0 {
+                        code.push(if chunk_num == 0 {
                             Line::Cut(CutInstruction::NeckCut(Terminal::Non))
                         } else {
                             Line::Cut(CutInstruction::Cut(Terminal::Non))
                         });
                     },
                     &QueryTermRef::Cut => {
-                        body.push(if chunk_num == 0 {
+                        code.push(if chunk_num == 0 {
                             Line::Cut(CutInstruction::NeckCut(Terminal::Terminal))
                         } else {
                             Line::Cut(CutInstruction::Cut(Terminal::Terminal))
                         });
                     },
+                    &QueryTermRef::IsAtomic(term) =>
+                        match term {
+                            &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
+                                code.push(goto!(61, 0)); // goto false/0.
+                            },
+                            &Term::Constant(_, _) => {
+                                code.push(goto!(75, 0)); // goto succeed/0.
+                            },
+                            &Term::Var(ref vr, ref name) => {
+                                let mut target = Vec::new();
+
+                                self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
+
+                                code.push(Line::Query(target));
+                                code.push(is_atomic!(vr.get().norm()));
+                            }
+                        },
+                    &QueryTermRef::IsVar(term) =>
+                        match term {
+                            &Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
+                                code.push(goto!(61, 0)); // goto false/0.
+                            },
+                            &Term::AnonVar => {
+                                code.push(goto!(75, 0)); // goto succeed/0.
+                            },
+                            &Term::Var(ref vr, ref name) => {
+                                let mut target = Vec::new();
+
+                                self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
+
+                                code.push(Line::Query(target));
+                                code.push(is_var!(vr.get().norm()));
+                            }
+                        },
                     _ if chunk_num == 0 => {
                         self.marker.advance(GenContext::Head, *term);
 
                         let iter = term.post_order_iter();
-                        body.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
-                        Self::add_conditional_call(body, *term, conjunct_info.perm_vars());
+                        code.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
+                        Self::add_conditional_call(code, *term, conjunct_info.perm_vars());
                     },
                     _ => {
                         let num_vars = conjunct_info.perm_vs.vars_above_threshold(i + 1);
-                        self.compile_query_line(*term, term_loc, body, num_vars, is_exposed);
+                        self.compile_query_line(*term, term_loc, code, num_vars, is_exposed);
                     },
                 };
 
@@ -393,7 +427,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
     pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code
     {
         let iter = ChunkedIterator::from_fact(term);
-        
+
         self.collect_var_data(iter);
         self.marker.advance(GenContext::Head, QueryTermRef::Term(term));
 
index 014908b97976df3fc14b8eb929881210a417977b..ea469b61b32d6787bb48cf7117afac60c98d061d 100644 (file)
@@ -77,7 +77,8 @@ impl<'a> QueryIterator<'a> {
                 let state = IteratorState::Clause(0, ClauseType::Catch, terms);
                 QueryIterator { state_stack: vec![state] }
             },
-            QueryTermRef::Term(term)  => Self::from_term(term),
+            QueryTermRef::IsAtomic(term) | QueryTermRef::IsVar(term) | QueryTermRef::Term(term) =>
+                Self::from_term(term),
             QueryTermRef::Throw(term) => {
                 let state = IteratorState::Clause(0, ClauseType::Throw, term);
                 QueryIterator { state_stack: vec![state] }
@@ -106,10 +107,10 @@ impl<'a> Iterator for QueryIterator<'a> {
                         match ct {
                             ClauseType::CallN =>
                                 self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
-                            ClauseType::Root | ClauseType::Throw | ClauseType::Catch =>
-                                return None,
                             ClauseType::Deep(_, _, _) =>
-                                return Some(TermRef::Clause(ct, child_terms))
+                                return Some(TermRef::Clause(ct, child_terms)),
+                            _ =>
+                                return None
                         };
                     } else {
                         self.push_clause(child_num + 1, ct, child_terms);
@@ -317,6 +318,8 @@ impl<'a> ChunkedIterator<'a>
                     arity = child_terms.len();
                     break;
                 },
+                QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+                    result.push(term),
                 QueryTermRef::Cut => {
                     result.push(term);
 
index 3c93ff67b1cf5bc84efcdd9045818bdf1c012403..09876f2a7a3109e4eab7b76fc105af552384a37d 100644 (file)
@@ -421,10 +421,14 @@ impl Machine {
             self.query_stepper();
 
             match self.ms.p {
-                CodePtr::TopLevel(_, p) if p > 0 => {},
+                CodePtr::TopLevel(_, p) if p > 0 => {},                
                 _ => break
             };
         }
+
+        if let CodePtr::TopLevel(cn, _) = self.ms.p {
+            self.record_var_places(cn, alloc_locs, heap_locs);
+        }
     }
 
     fn fail<'a>(&mut self) -> EvalSession<'a>
@@ -1388,16 +1392,16 @@ impl MachineState {
                 self.b = self.block;
                 self.fail = true;
             },
-            &BuiltInInstruction::IsAtomic => {
-                let d = self.deref(self[temp_v!(1)].clone());
+            &BuiltInInstruction::IsAtomic(r) => {
+                let d = self.deref(self[r].clone());
 
                 match d {
                     Addr::Con(_) => self.p += 1,
                     _ => self.fail = true
                 };
             },
-            &BuiltInInstruction::IsVar => {
-                let d = self.deref(self[temp_v!(1)].clone());
+            &BuiltInInstruction::IsVar(r) => {
+                let d = self.deref(self[r].clone());
 
                 match d {
                     Addr::HeapCell(_) | Addr::StackCell(_,_) =>
@@ -1410,6 +1414,9 @@ impl MachineState {
             &BuiltInInstruction::Fail => {
                 self.fail = true;
                 self.p += 1;
+            },
+            &BuiltInInstruction::Succeed => {
+                self.p += 1;
             }
         };
     }
index 8ac0f3861c41d3c5a9a1e79b0cf042b47fdcd700..4e83e320194303b75ac74919a49bc5a7912d8b84 100644 (file)
@@ -100,14 +100,14 @@ macro_rules! try_me_else {
 }
 
 macro_rules! is_atomic {
-    () => (
-        Line::BuiltIn(BuiltInInstruction::IsAtomic)
+    ($reg:expr) => (
+        Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
     )
 }
 
 macro_rules! is_var {
-    () => (
-        Line::BuiltIn(BuiltInInstruction::IsVar)
+    ($reg:expr) => (
+        Line::BuiltIn(BuiltInInstruction::IsVar($reg))
     )
 }
 
@@ -221,6 +221,12 @@ macro_rules! fail {
     )
 }
 
+macro_rules! succeed {
+    () => (
+        Line::BuiltIn(BuiltInInstruction::Succeed)
+    )
+}
+
 macro_rules! duplicate_term {
     () => (
         Line::BuiltIn(BuiltInInstruction::DuplicateTerm)