From: Mark Thom Date: Sat, 4 Nov 2017 02:41:01 +0000 (-0600) Subject: inline atomic and var. X-Git-Tag: v0.8.110~687 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=57cc8ccac9a13914a015628803d829c20d573724;p=scryer-prolog.git inline atomic and var. --- diff --git a/Cargo.lock b/Cargo.lock index 3d7dbbb2..0a442cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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)", diff --git a/Cargo.toml b/Cargo.toml index de3f9c13..bfa6fff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.7.0" +version = "0.7.1" authors = ["Mark Thom"] [dependencies] diff --git a/README.md b/README.md index b5b4bee3..d636b368 100644 --- 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 diff --git a/src/prolog/allocator.rs b/src/prolog/allocator.rs index d985219a..2df627ac 100644 --- a/src/prolog/allocator.rs +++ b/src/prolog/allocator.rs @@ -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() { diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 8edb881a..8ce3e393 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -273,10 +273,12 @@ pub enum Term { Var(Cell, Var) } -pub enum QueryTerm { +pub enum QueryTerm { CallN(Vec>), Catch(Vec>), Cut, + IsAtomic(Vec>), + IsVar(Vec>), Term(Term), Throw(Vec>) } @@ -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>), Catch(&'a Vec>), Cut, + IsAtomic(&'a Term), + IsVar(&'a Term), Term(&'a Term), Throw(&'a Vec>) } @@ -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 diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index d7918594..08be6bfe 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -18,9 +18,9 @@ pub type CodeDir = HashMap; 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) } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 1a9bb743..ac6d01d2 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -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)); diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 014908b9..ea469b61 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -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); diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 3c93ff67..09876f2a 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -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; } }; } diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 8ac0f386..4e83e320 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -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)