From 9c72177b601382945456bed10ea4eb4bc4c685c0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 8 May 2017 14:33:27 -0600 Subject: [PATCH] cleanup of run_query --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/main.rs | 6 +-- src/prolog/ast.rs | 22 ++++++++--- src/prolog/codegen.rs | 6 +-- src/prolog/io.rs | 20 +++++----- src/prolog/machine.rs | 87 +++++++++++++++++++------------------------ 7 files changed, 73 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f5be324b..c1aa2759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rusty-wam" -version = "0.6.1" +version = "0.6.2" 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 736bac4e..50bcf612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.6.1" +version = "0.6.2" authors = ["Mark Thom"] build = "build.rs" diff --git a/src/main.rs b/src/main.rs index d7b46e1f..ea274c4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,9 +16,9 @@ mod tests { match parse_TopLevel(buffer.trim()) { Ok(tl) => match eval(wam, &tl) { - EvalResult::InitialQuerySuccess(_, _) | - EvalResult::EntrySuccess | - EvalResult::SubsequentQuerySuccess => + EvalSession::InitialQuerySuccess(_, _) | + EvalSession::EntrySuccess | + EvalSession::SubsequentQuerySuccess => true, _ => false }, diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 6674f261..592c9312 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -213,6 +213,16 @@ pub enum ControlInstruction { Proceed } +impl ControlInstruction { + pub fn is_jump_instr(&self) -> bool { + match self { + &ControlInstruction::Call(_, _, _) => true, + &ControlInstruction::Execute(_, _) => true, + _ => false + } + } +} + pub enum IndexingInstruction { SwitchOnTerm(usize, usize, usize, usize), SwitchOnConstant(usize, HashMap), @@ -362,7 +372,7 @@ impl HeapCellValue { #[derive(Clone, Copy, PartialEq)] pub enum CodePtr { DirEntry(usize), - TopLevel(usize, usize, usize) // chunk_num, e, offset. + TopLevel(usize, usize) // chunk_num, offset. } impl PartialOrd for CodePtr { @@ -370,9 +380,9 @@ impl PartialOrd for CodePtr { match (self, other) { (&CodePtr::DirEntry(p1), &CodePtr::DirEntry(ref p2)) => p1.partial_cmp(p2), - (&CodePtr::DirEntry(_), &CodePtr::TopLevel(_, _, _)) => + (&CodePtr::DirEntry(_), &CodePtr::TopLevel(_, _)) => Some(Ordering::Less), - (&CodePtr::TopLevel(_, _, p1), &CodePtr::TopLevel(_, _, ref p2)) => + (&CodePtr::TopLevel(_, p1), &CodePtr::TopLevel(_, ref p2)) => p1.partial_cmp(p2), _ => Some(Ordering::Greater) } @@ -381,7 +391,7 @@ impl PartialOrd for CodePtr { impl Default for CodePtr { fn default() -> Self { - CodePtr::TopLevel(0, 0, 0) + CodePtr::TopLevel(0, 0) } } @@ -391,7 +401,7 @@ impl Add for CodePtr { fn add(self, rhs: usize) -> Self::Output { match self { CodePtr::DirEntry(p) => CodePtr::DirEntry(p + rhs), - CodePtr::TopLevel(cn, e, p) => CodePtr::TopLevel(cn, e, p + rhs) + CodePtr::TopLevel(cn, p) => CodePtr::TopLevel(cn, p + rhs) } } } @@ -400,7 +410,7 @@ impl AddAssign for CodePtr { fn add_assign(&mut self, rhs: usize) { match self { &mut CodePtr::DirEntry(ref mut p) | - &mut CodePtr::TopLevel(_, _, ref mut p) => *p += rhs + &mut CodePtr::TopLevel(_, ref mut p) => *p += rhs } } } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 25e0f248..193e145e 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -14,7 +14,7 @@ pub struct CodeGenerator<'a, TermMarker> { var_count: HashMap<&'a Var, usize> } -pub enum EvalResult<'a> { +pub enum EvalSession<'a> { EntryFailure, EntrySuccess, InitialQuerySuccess(AllocVarDict<'a>, HeapVarDict<'a>), @@ -22,10 +22,10 @@ pub enum EvalResult<'a> { SubsequentQuerySuccess, } -impl<'a> EvalResult<'a> { +impl<'a> EvalSession<'a> { #[allow(dead_code)] pub fn failed_query(&self) -> bool { - if let &EvalResult::QueryFailure = self { + if let &EvalSession::QueryFailure = self { true } else { false diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 37c872ba..5bce6df1 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -257,7 +257,7 @@ pub fn read() -> String { result } -pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalResult<'b> +pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b> { match tl { &TopLevel::Predicate(ref clauses) => { @@ -267,13 +267,13 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalResult<'b let compiled_pred = cg.compile_predicate(clauses); wam.add_predicate(clauses, compiled_pred); - EvalResult::EntrySuccess + EvalSession::EntrySuccess } else { let msg = r"Error: predicate is inconsistent. Each predicate must have the same name and arity."; println!("{}", msg); - EvalResult::EntryFailure + EvalSession::EntryFailure } }, &TopLevel::Fact(ref fact) => { @@ -282,7 +282,7 @@ Each predicate must have the same name and arity."; let compiled_fact = cg.compile_fact(fact); wam.add_fact(fact, compiled_fact); - EvalResult::EntrySuccess + EvalSession::EntrySuccess }, &TopLevel::Rule(ref rule) => { let mut cg = CodeGenerator::::new(); @@ -290,7 +290,7 @@ Each predicate must have the same name and arity."; let compiled_rule = cg.compile_rule(rule); wam.add_rule(rule, compiled_rule); - EvalResult::EntrySuccess + EvalSession::EntrySuccess }, &TopLevel::Query(ref query) => { let mut cg = CodeGenerator::::new(); @@ -301,9 +301,9 @@ Each predicate must have the same name and arity."; } } -pub fn print(wam: &mut Machine, result: EvalResult) { +pub fn print(wam: &mut Machine, result: EvalSession) { match result { - EvalResult::InitialQuerySuccess(alloc_locs, mut heap_locs) => { + EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => { println!("yes"); if heap_locs.is_empty() { @@ -311,7 +311,7 @@ pub fn print(wam: &mut Machine, result: EvalResult) { } 'outer: loop { - let mut result = EvalResult::QueryFailure; + let mut result = EvalSession::QueryFailure; let bindings = wam.heap_view(&heap_locs); let stdin = stdin(); @@ -336,7 +336,7 @@ pub fn print(wam: &mut Machine, result: EvalResult) { } } - if let &EvalResult::QueryFailure = &result { + if let &EvalSession::QueryFailure = &result { write!(stdout, "no\n\r").unwrap(); stdout.flush().unwrap(); break; @@ -346,7 +346,7 @@ pub fn print(wam: &mut Machine, result: EvalResult) { } } }, - EvalResult::QueryFailure => println!("no"), + EvalSession::QueryFailure => println!("no"), _ => {} }; } diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 4af0fdc4..2e96de5c 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -75,7 +75,7 @@ impl Index for Machine { fn index(&self, ptr: CodePtr) -> &Self::Output { match ptr { - CodePtr::TopLevel(_, _, p) => { + CodePtr::TopLevel(_, p) => { match &self.cached_query { &Some(ref cq) => &cq[p], &None => panic!("Out-of-bounds top level index.") @@ -142,13 +142,13 @@ impl Machine { } } - fn execute_instr(&mut self, ptr: CodePtr) + fn execute_instr(&mut self) { // can't use self[ptr] or self.index(ptr) to set the value of // instr! instr is then typed as Line, not &Line. WHY???? // This is a compiler bug. Has to be. - let instr = match ptr { - CodePtr::TopLevel(_, _, p) => { + let instr = match self.ms.p { + CodePtr::TopLevel(_, p) => { match &self.cached_query { &Some(ref cq) => &cq[p], &None => return @@ -203,13 +203,13 @@ impl Machine { let b = self.ms.b - 1; self.ms.or_stack[b].bp } else { - self.ms.p = CodePtr::TopLevel(0, 0, 0); + self.ms.p = CodePtr::TopLevel(0, 0); return; }; self.ms.p = p; - if let CodePtr::TopLevel(_, _, p) = p { + if let CodePtr::TopLevel(_, p) = p { self.ms.fail = p == 0; self.ms.b0 = b0; @@ -219,19 +219,18 @@ impl Machine { } } - fn query_stepper<'a>(&mut self, mut ptr: CodePtr) + fn query_stepper<'a>(&mut self) { loop { - self.execute_instr(ptr); + self.execute_instr(); if self.failed() { self.backtrack(); } match self.ms.p { - CodePtr::DirEntry(p) if p < self.code.len() => - ptr = self.ms.p, + CodePtr::DirEntry(p) if p < self.code.len() => {}, _ => break }; } @@ -239,22 +238,22 @@ impl Machine { fn record_var_places<'a>(&self, chunk_num: usize, - e: usize, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>) { for (var, var_data) in alloc_locs { match var_data { &VarData::Perm(_) => { + let e = self.ms.e; let r = var_data.as_reg_type().reg_num(); let addr = self.ms.and_stack[e][r].clone(); - + heap_locs.insert(var, addr); }, &VarData::Temp(cn, _, _) if cn == chunk_num => { let r = var_data.as_reg_type(); let addr = self.ms[r].clone(); - + heap_locs.insert(var, addr); }, _ => {} @@ -264,38 +263,30 @@ impl Machine { fn run_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>) { - let end_ptr = CodePtr::TopLevel(0, 0, self.cached_query_size()); - let mut tl_ptr = self.ms.p; - - while tl_ptr < end_ptr { - self.query_stepper(tl_ptr); - - tl_ptr = self.ms.p; - - if let &mut CodePtr::TopLevel(ref mut cn, ref mut e, p) = &mut tl_ptr { - if p == 0 { - break; + let end_ptr = CodePtr::TopLevel(0, self.cached_query_size()); + + while self.ms.p < end_ptr { + if let CodePtr::TopLevel(mut cn, p) = self.ms.p { + if let &Line::Control(ref ctrl_instr) = &self[CodePtr::TopLevel(cn, p)] { + if ctrl_instr.is_jump_instr() { + self.record_var_places(cn, alloc_locs, heap_locs); + cn += 1; + } } - match &self[CodePtr::TopLevel(*cn, *e, p)] { - &Line::Control(ControlInstruction::Call(_, _, _)) - | &Line::Control(ControlInstruction::Execute(_, _)) => { - self.record_var_places(*cn, *e, alloc_locs, heap_locs); - *cn += 1; - }, - &Line::Control(ControlInstruction::Allocate(_)) => - *e = self.ms.e, - _ => {} - }; - - self.ms.p = CodePtr::TopLevel(*cn, *e, p); - } else { - break; + self.ms.p = CodePtr::TopLevel(cn, p); } + + self.query_stepper(); + + match self.ms.p { + CodePtr::TopLevel(_, p) if p > 0 => {}, + _ => break + }; } } - pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalResult<'a> + pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalSession<'a> { let mut heap_locs = HashMap::new(); self.cached_query = Some(code); @@ -303,38 +294,38 @@ impl Machine { self.run_query(&alloc_locs, &mut heap_locs); if self.failed() { - EvalResult::QueryFailure + EvalSession::QueryFailure } else { - EvalResult::InitialQuerySuccess(alloc_locs, heap_locs) + EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) } } pub fn continue_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>) - -> EvalResult + -> EvalSession { if !self.or_stack_is_empty() { if self.ms.b == 0 { - return EvalResult::QueryFailure; + return EvalSession::QueryFailure; } let b = self.ms.b - 1; self.ms.p = self.ms.or_stack[b].bp; - if let CodePtr::TopLevel(_, _, 0) = self.ms.p { - return EvalResult::QueryFailure + if let CodePtr::TopLevel(_, 0) = self.ms.p { + return EvalSession::QueryFailure } self.run_query(alloc_locs, heap_locs); if self.failed() { - EvalResult::QueryFailure + EvalSession::QueryFailure } else { - EvalResult::SubsequentQuerySuccess + EvalSession::SubsequentQuerySuccess } } else { - EvalResult::QueryFailure + EvalSession::QueryFailure } } -- 2.54.0