From 78ef18ad75546a58386adddd5da883256664f9a0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 18 Sep 2018 20:58:42 -0600 Subject: [PATCH 1/4] stop treating copier as trait object --- src/prolog/copier.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/prolog/copier.rs b/src/prolog/copier.rs index 2ee845c6..1988c350 100644 --- a/src/prolog/copier.rs +++ b/src/prolog/copier.rs @@ -9,7 +9,7 @@ pub(crate) struct RedirectInfo { trail: Trail } -pub(crate) trait CopierTarget +pub(crate) trait CopierTarget: IndexMut { fn source(&self) -> usize; fn threshold(&self) -> usize; @@ -19,7 +19,6 @@ pub(crate) trait CopierTarget fn stack(&mut self) -> &mut AndStack; fn unwind_trail(&mut self, redirect: RedirectInfo) - where Self: IndexMut { for (r, hcv) in redirect.trail { match r { @@ -30,7 +29,6 @@ pub(crate) trait CopierTarget } fn reinstantiate_var(&mut self, ra: Addr, scan: usize, trail: &mut Trail) - where Self: IndexMut { self[scan] = HeapCellValue::Addr(Addr::HeapCell(scan)); @@ -49,7 +47,6 @@ pub(crate) trait CopierTarget // at L1 to L2. trail is kept to restore the innards of L1 after // it's been copied to L2. fn duplicate_term_impl(&mut self, addr: Addr) -> RedirectInfo - where Self: IndexMut { let mut trail = Trail::new(); let mut scan = self.source(); @@ -153,7 +150,6 @@ pub(crate) trait CopierTarget } fn duplicate_term(&mut self, addr: Addr) - where Self: IndexMut { let redirect = self.duplicate_term_impl(addr); self.unwind_trail(redirect); From 908972eff14a2ca8bd05537a179ccd64683cf700 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 18 Sep 2018 22:44:03 -0600 Subject: [PATCH 2/4] incorporate term_expansion phase in compilation --- src/main.rs | 3 +- src/prolog/instructions.rs | 24 +++- src/prolog/lib/numbervars.pl | 2 - src/prolog/machine/machine_state.rs | 15 ++- src/prolog/machine/machine_state_impl.rs | 18 +-- src/prolog/machine/mod.rs | 20 +++- src/prolog/machine/term_expansion.rs | 141 +++++++++++++++++++++++ src/prolog/machine/term_writer.rs | 54 --------- src/prolog/read.rs | 6 +- src/prolog/toplevel.rs | 17 +-- 10 files changed, 211 insertions(+), 89 deletions(-) create mode 100644 src/prolog/machine/term_expansion.rs delete mode 100644 src/prolog/machine/term_writer.rs diff --git a/src/main.rs b/src/main.rs index fd910dee..3f0076e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,8 +39,7 @@ fn prolog_repl() { wam.clear(); continue; }, - Err(e) => - print(&mut wam, EvalSession::from(e)) + Err(e) => print(&mut wam, EvalSession::from(e)) }; wam.reset(); diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 8e5168af..55815445 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -337,10 +337,22 @@ pub enum BuiltInClauseType { Sort, } +#[derive(Clone, Copy)] +pub enum CompileTimeHook { + TermExpansion +} + +impl CompileTimeHook { + pub fn name(self) -> ClauseName { + clause_name!("term_expansion") + } +} + #[derive(Clone)] pub enum ClauseType { BuiltIn(BuiltInClauseType), CallN, + Hook(CompileTimeHook), Inlined(InlinedClauseType), Named(ClauseName, CodeIndex), Op(ClauseName, Fixity, CodeIndex), @@ -442,6 +454,7 @@ impl ClauseType { match self { &ClauseType::CallN => clause_name!("call"), &ClauseType::BuiltIn(ref built_in) => built_in.name(), + &ClauseType::Hook(ref hook) => hook.name(), &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()), &ClauseType::Op(ref name, ..) => name.clone(), &ClauseType::Named(ref name, ..) => name.clone(), @@ -840,7 +853,7 @@ impl CodePtr { match self { &CodePtr::BuiltInClause(_, ref local) | &CodePtr::CallN(_, ref local) - | &CodePtr::Local(ref local) => local.clone() + | &CodePtr::Local(ref local) => local.clone() } } } @@ -849,6 +862,7 @@ impl CodePtr { pub enum LocalCodePtr { DirEntry(usize, ClauseName), // offset, resident module name. TopLevel(usize, usize), // chunk_num, offset. + UserTermExpansion(usize) } impl LocalCodePtr { @@ -901,7 +915,8 @@ impl Add for LocalCodePtr { fn add(self, rhs: usize) -> Self::Output { match self { LocalCodePtr::DirEntry(p, name) => LocalCodePtr::DirEntry(p + rhs, name), - LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs) + LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs), + LocalCodePtr::UserTermExpansion(p) => LocalCodePtr::UserTermExpansion(p + rhs) } } } @@ -909,8 +924,9 @@ impl Add for LocalCodePtr { impl AddAssign for LocalCodePtr { fn add_assign(&mut self, rhs: usize) { match self { - &mut LocalCodePtr::DirEntry(ref mut p, _) | - &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs + &mut LocalCodePtr::UserTermExpansion(ref mut p) + | &mut LocalCodePtr::DirEntry(ref mut p, _) + | &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs } } } diff --git a/src/prolog/lib/numbervars.pl b/src/prolog/lib/numbervars.pl index 26bc5494..84a1431d 100644 --- a/src/prolog/lib/numbervars.pl +++ b/src/prolog/lib/numbervars.pl @@ -10,8 +10,6 @@ numbervars(Term, NewTerm, N) :- numbervars(Term, NewTerm, N1, N2) :- var(Term), !, NewTerm = '$VAR'(N1), N2 is N1 + 1. -numbervars([Arg | Args], NewTerms, N1, N2) :- !, - fold_numbervars([Arg | Args], NewTerms, N1, N2). numbervars(Term, NewTerm, N1, N2) :- compound(Term), !, Term =.. [Name | Args], NewTerm =.. [Name | NewArgs], diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index a5328ef4..9a7ec668 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -527,7 +527,7 @@ pub(crate) trait CallPolicy: Any { machine_st.fail = !machine_st.is_cyclic_term(addr); return_from_clause!(machine_st.last_call, machine_st) }, - &BuiltInClauseType::Read => { + &BuiltInClauseType::Read => { match machine_st.read(stdin(), &indices.op_dir) { Ok(offset) => { let addr = machine_st[temp_v!(1)].clone(); @@ -642,6 +642,17 @@ pub(crate) trait CallPolicy: Any { } } + fn compile_hook(&mut self, machine_st: &mut MachineState, _: &CompileTimeHook) -> CallResult + { + machine_st.cp = LocalCodePtr::TopLevel(0, 0); + + machine_st.num_of_args = 2; + machine_st.b0 = machine_st.b; + machine_st.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0)); + + Ok(()) + } + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, indices: MachineCodeIndices<'a>) //code_dirs: CodeDirs) -> CallResult @@ -674,7 +685,7 @@ pub(crate) trait CallPolicy: Any { return Err(machine_st.error_form(MachineError::existence_error(h, name, arity), stub)); }, - ClauseType::System(_) => { + ClauseType::Hook(_) | ClauseType::System(_) => { let name = Addr::Con(Constant::Atom(name, None)); let stub = MachineError::functor_stub(clause_name!("call"), arity + 1); diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index d510879e..62db2efa 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -196,7 +196,7 @@ impl MachineState { self.fail = true; }, (Addr::Lis(a1), Addr::Con(Constant::String(ref mut s))) - | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1)) + | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1)) if self.flags.double_quotes.is_chars() => { if let Some(c) = s.head() { pdl.push(Addr::Con(Constant::String(s.tail()))); @@ -233,7 +233,7 @@ impl MachineState { self.fail = true; }, (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s))) - | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList)) + | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList)) if self.flags.double_quotes.is_chars() => { if s.is_expandable() && s.is_empty() { s.set_non_expandable(); @@ -314,7 +314,7 @@ impl MachineState { } } } - + fn trail(&mut self, r: Ref) { match r { Ref::HeapCell(hc) => @@ -1457,7 +1457,7 @@ impl MachineState { for (v1, v2) in iter { match (v1, v2) { (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Con(Constant::String(_)))) - | (HeapCellValue::Addr(Addr::Con(Constant::String(_))), HeapCellValue::Addr(Addr::Lis(_))) + | (HeapCellValue::Addr(Addr::Con(Constant::String(_))), HeapCellValue::Addr(Addr::Lis(_))) if self.flags.double_quotes.is_chars() => {}, (HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), HeapCellValue::Addr(Addr::Con(Constant::String(ref s)))) @@ -1577,7 +1577,7 @@ impl MachineState { (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => continue, (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _)) - | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) => + | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) => if ar == 2 && n.as_str() == "." { continue; } else if ar < 2 { @@ -2045,7 +2045,7 @@ impl MachineState { self.p += 1; } - + fn handle_call_clause<'a>(&mut self, indices: MachineCodeIndices<'a>, call_policy: &mut Box, cut_policy: &mut Box, @@ -2068,6 +2068,8 @@ impl MachineState { try_or_fail!(self, call_policy.call_builtin(self, ct, indices)), &ClauseType::CallN => try_or_fail!(self, call_policy.call_n(self, arity, indices)), + &ClauseType::Hook(ref hook) => + try_or_fail!(self, call_policy.compile_hook(self, hook)), &ClauseType::Inlined(ref ct) => self.execute_inlined(ct), &ClauseType::Named(ref name, ref idx) | &ClauseType::Op(ref name, _, ref idx) => @@ -2087,8 +2089,8 @@ impl MachineState { &ControlInstruction::Allocate(num_cells) => self.allocate(num_cells), &ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) => - self.handle_call_clause(indices, call_policy, cut_policy, ct, arity, lco, - use_default_cp), + self.handle_call_clause(indices, call_policy, cut_policy, + ct, arity, lco, use_default_cp), &ControlInstruction::Deallocate => self.deallocate(), &ControlInstruction::JmpBy(arity, offset, _, lco) => { if !lco { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index de4c613f..8c46b57c 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -7,6 +7,7 @@ use prolog::heap_print::*; mod machine_errors; pub(super) mod machine_state; +pub(super) mod term_expansion; #[macro_use] mod machine_state_impl; mod system_calls; @@ -53,7 +54,8 @@ pub struct Machine { code: Code, pub(super) code_dir: Rc>, pub(super) op_dir: OpDir, -// term_dir: TermDir, + term_dir: TermDir, + term_expanders: Code, pub(super) modules: ModuleDir, cached_query: Option } @@ -80,7 +82,8 @@ impl Index for Machine { &None => panic!("Out-of-bounds top level index.") } }, - LocalCodePtr::DirEntry(p, _) => &self.code[p] + LocalCodePtr::DirEntry(p, _) => &self.code[p], + LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p] } } } @@ -115,6 +118,7 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> { static LISTS: &str = include_str!("../lib/lists.pl"); static CONTROL: &str = include_str!("../lib/control.pl"); static QUEUES: &str = include_str!("../lib/queues.pl"); +static NUMVARS: &str = include_str!("../lib/numbervars.pl"); impl Machine { pub fn new() -> Self { @@ -125,7 +129,8 @@ impl Machine { code: Code::new(), code_dir: Rc::new(RefCell::new(CodeDir::new())), op_dir: default_op_dir(), - // term_dir: TermDir::new(), + term_dir: TermDir::new(), + term_expanders: Code::new(), modules: HashMap::new(), cached_query: None }; @@ -137,6 +142,7 @@ impl Machine { compile_user_module(&mut wam, LISTS.as_bytes()); compile_user_module(&mut wam, CONTROL.as_bytes()); compile_user_module(&mut wam, QUEUES.as_bytes()); + compile_user_module(&mut wam, NUMVARS.as_bytes()); wam } @@ -245,6 +251,12 @@ impl Machine { fn lookup_instr(&self, p: CodePtr) -> Option { match p { + CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => + if p < self.term_expanders.len() { + Some(self.term_expanders[p].clone()) + } else { + None + }, CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => match &self.cached_query { &Some(ref cq) => Some(cq[p].clone()), @@ -340,6 +352,8 @@ impl Machine { match self.ms.p { CodePtr::Local(LocalCodePtr::DirEntry(p, _)) if p < self.code.len() => {}, + CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.term_expanders.len() => {}, + CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.ms.fail = true, CodePtr::Local(_) => break, _ => {} }; diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs new file mode 100644 index 00000000..eabca7a9 --- /dev/null +++ b/src/prolog/machine/term_expansion.rs @@ -0,0 +1,141 @@ +use prolog_parser::ast::*; +use prolog_parser::parser::*; + +use prolog::heap_iter::*; +use prolog::instructions::HeapCellValue; +use prolog::machine::*; +use prolog::read::*; + +use std::cell::Cell; +use std::io::Read; + +pub struct TermStream { + stack: Vec, + parser: Parser, + in_module: bool +} + +impl TermStream { + pub fn new(src: R, atom_tbl: TabledData, flags: MachineFlags) -> Self { + TermStream { + stack: Vec::new(), + parser: Parser::new(src, atom_tbl, flags), + in_module: false + } + } + + #[inline] + pub fn eof(&mut self) -> Result { + Ok(self.stack.is_empty() && self.parser.eof()?) + } + + #[inline] + pub fn empty_tokens(&mut self) { + self.parser.reset(); + } + + fn enqueue_term(&mut self, term: Term) -> Result<(), ParserError> { + match term { + Term::Cons(_, head, tail) => { + let mut terms = vec![*head]; + let mut tail = *tail; + + while let Term::Cons(_, head, next_tail) = tail { + terms.push(*head); + tail = *next_tail; + } + + if let Term::Constant(_, Constant::EmptyList) = tail { + Ok(self.stack.extend(terms.into_iter().rev())) + } else { + Err(ParserError::ExpectedTopLevelTerm) + } + }, + Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => + Ok(self.stack.push(term)), + _ => Err(ParserError::ExpectedTopLevelTerm) + } + } + + pub fn read_term(&mut self, wam: &mut Machine, op_dir: &OpDir) -> Result + { + loop { + while let Some(term) = self.stack.pop() { + match wam.try_expand_term(&term)? { + Some(term) => self.enqueue_term(term)?, + None => return Ok(term) + }; + } + + let term = self.parser.read_term(composite_op!(self.in_module, &wam.op_dir, op_dir))?; + self.stack.push(term); + } + } +} + +impl Machine { + fn try_expand_term(&mut self, term: &Term) -> Result, ParserError> { + let term_h = write_term_to_heap(term, &mut self.ms); + let h = self.ms.heap.h; + + self.ms[temp_v!(1)] = Addr::HeapCell(term_h); + self.ms.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); + self.ms[temp_v!(2)] = Addr::HeapCell(h); + + let code = vec![call_clause!(ClauseType::Hook(CompileTimeHook::TermExpansion), 2, 0, true)]; + self.submit_query(code, AllocVarDict::new()); + + if self.failed() { + self.reset(); + Ok(None) + } else { + Ok(Some(read_term_from_heap(&self.ms, Addr::HeapCell(h))?)) + } + } +} + +pub fn read_term_from_heap(machine_st: &MachineState, addr: Addr) -> Result +{ + let pre_order_iter = HCPreOrderIterator::new(machine_st, addr); + let post_order_iter = HCPostOrderIterator::new(pre_order_iter); + + let mut stack = vec![]; + + for value in post_order_iter { + match value { + HeapCellValue::NamedStr(arity, ref name, fixity) + if stack.len() >= arity => { + let stack_len = stack.len(); + let subterms: Vec<_> = stack.drain(stack_len - arity ..).collect(); + + stack.push(Box::new(Term::Clause(Cell::default(), name.clone(), subterms, + fixity))); + }, + HeapCellValue::Addr(Addr::Con(constant)) => + stack.push(Box::new(Term::Constant(Cell::default(), constant))), + HeapCellValue::Addr(Addr::Lis(_)) + if stack.len() >= 2 => { + let stack_len = stack.len(); + let (head, tail) = { + let mut iter = stack.drain(stack_len - 2 ..); + (iter.next().unwrap(), iter.next().unwrap()) + }; + + stack.push(Box::new(Term::Cons(Cell::default(), head, tail))); + }, + HeapCellValue::Addr(Addr::HeapCell(h)) => + stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}", h))))), + HeapCellValue::Addr(Addr::StackCell(fr, sc)) => + stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}_{}", sc, fr))))), + _ => return Err(ParserError::IncompleteReduction) + } + } + + if let Some(term) = stack.pop() { + if stack.is_empty() { + return Ok(*term); + } + } + + Err(ParserError::IncompleteReduction) +} diff --git a/src/prolog/machine/term_writer.rs b/src/prolog/machine/term_writer.rs deleted file mode 100644 index d094a236..00000000 --- a/src/prolog/machine/term_writer.rs +++ /dev/null @@ -1,54 +0,0 @@ -use prolog_parser::ast::*; - -use prolog::heap_iter::*; -use prolog::instructions::*; -use prolog::machine::machine_state::MachineState; - -use std::cell::Cell; -use std::rc::Rc; - -pub fn term_write(machine_st: &MachineState, addr: Addr) -> Result -{ - let pre_order_iter = HCPreOrderIterator::new(machine_st, addr); - let post_order_iter = HCPostOrderIterator::new(pre_order_iter); - - let mut stack = vec![]; - - for value in post_order_iter { - match value { - HeapCellValue::NamedStr(arity, ref name, fixity) - if stack.len() >= arity => { - let stack_len = stack.len(); - let subterms: Vec<_> = stack.drain(stack_len - arity ..).collect(); - - stack.push(Box::new(Term::Clause(Cell::default(), name.clone(), subterms, - fixity))); - }, - HeapCellValue::Addr(Addr::Con(constant)) => - stack.push(Box::new(Term::Constant(Cell::default(), constant))), - HeapCellValue::Addr(Addr::Lis(_)) - if stack.len() >= 2 => { - let stack_len = stack.len(); - let mut iter = stack.drain(stack_len - 2 ..); - - let head = iter.next().unwrap(); - let tail = iter.next().unwrap(); - - stack.push(Box::new(Term::Cons(Cell::default(), head, tail))); - }, - HeapCellValue::Addr(Addr::HeapCell(h)) => - stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}", h))))), - HeapCellValue::Addr(Addr::StackCell(fr, sc)) => - stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}_{}", sc, fr))))), - _ => return Err(ParserError::IncompleteReduction) - } - } - - if let Some(term) = stack.pop() { - if stack.is_empty() { - return Ok(*term); - } - } - - Err(ParserError::IncompleteReduction) -} diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 68e09f84..0b880373 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -57,7 +57,7 @@ impl MachineState { let mut parser = Parser::new(inner, self.atom_tbl.clone(), self.flags); let term = parser.read_term(composite_op!(op_dir))?; - Ok(write_term_to_heap(term, self)) + Ok(write_term_to_heap(&term, self)) } } @@ -77,13 +77,13 @@ fn modify_head_of_queue(machine_st: &mut MachineState, queue: &mut SubtermDeque, } } -fn write_term_to_heap(term: Term, machine_st: &mut MachineState) -> usize { +pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> usize { let h = machine_st.heap.h; let mut queue = SubtermDeque::new(); let mut var_dict = HeapVarDict::new(); - for term in breadth_first_iter(&term, true) { + for term in breadth_first_iter(term, true) { let h = machine_st.heap.h; match &term { diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 2c752f96..040524f9 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -5,6 +5,7 @@ use prolog_parser::tabled_rc::*; use prolog::instructions::*; use prolog::iterators::*; use prolog::machine::*; +use prolog::machine::term_expansion::*; use prolog::num::*; use std::collections::{HashSet, VecDeque}; @@ -691,7 +692,7 @@ fn consume_term<'a>(static_code_dir: Rc>, term: Term, } pub struct TopLevelBatchWorker { - parser: Parser, + term_stream: TermStream, rel_worker: RelationWorker, static_code_dir: Rc>, pub results: Vec<(Predicate, VecDeque)>, @@ -703,19 +704,13 @@ impl TopLevelBatchWorker { static_code_dir: Rc>) -> Self { - TopLevelBatchWorker { parser: Parser::new(inner, atom_tbl, flags), + TopLevelBatchWorker { term_stream: TermStream::new(inner, atom_tbl, flags), rel_worker: RelationWorker::new(), static_code_dir, results: vec![], in_module: false } } - #[inline] - fn read_term(&mut self, static_op_dir: &OpDir, op_dir: &OpDir) -> Result { - let composite_op = composite_op!(self.in_module, op_dir, static_op_dir); - self.parser.read_term(composite_op) - } - pub fn consume<'a, 'b : 'a>(&mut self, wam: &mut Machine, indices: &'a mut MachineCodeIndices<'b>) -> Result, SessionError> @@ -724,11 +719,11 @@ impl TopLevelBatchWorker { let mut indices = composite_indices!(self.in_module, indices, self.static_code_dir.clone()); - while !self.parser.eof()? { - self.parser.reset(); // empty the parser stack of token descriptions. + while !self.term_stream.eof()? { + self.term_stream.empty_tokens(); // empty the parser stack of token descriptions. let mut new_rel_worker = RelationWorker::new(); - let term = self.read_term(&wam.op_dir, &indices.local.op_dir)?; + let term = self.term_stream.read_term(wam, &indices.local.op_dir)?; let tl = new_rel_worker.try_term_to_tl(&mut indices, term, true)?; From 4d57989c2b209f4753b7070b99005a7f84e98b32 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 22 Sep 2018 16:25:32 -0600 Subject: [PATCH 3/4] term_expansion beginnings --- Cargo.lock | 4 +-- Cargo.toml | 2 +- src/prolog/compile.rs | 2 ++ src/prolog/instructions.rs | 14 ++++---- src/prolog/lib/builtins.pl | 2 -- src/prolog/lib/numbervars.pl | 6 ++-- src/prolog/machine/mod.rs | 19 ++++++++++- src/prolog/machine/system_calls.rs | 11 ++----- src/prolog/machine/term_expansion.rs | 5 +++ src/prolog/read.rs | 9 ++--- src/prolog/toplevel.rs | 49 +++++++++++++++++++++++++--- 11 files changed, 86 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5053b63b..d46db9b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -87,7 +87,6 @@ dependencies = [ [[package]] name = "prolog_parser" version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -113,7 +112,7 @@ dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prolog_parser 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", + "prolog_parser 0.7.14", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -152,7 +151,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" -"checksum prolog_parser 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5a7a659f57a1c0e9c375a82cc224462dc1b7c259e645fcc283928ef38947b584" "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 8fb7c224..6fa9e632 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ license = "BSD-3-Clause" downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" -prolog_parser = "0.7.14" +prolog_parser = { path = "../prolog_parser", version = "0.7.14" } [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index 4eaafc8a..557bb162 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -235,6 +235,8 @@ impl ListingCompiler { -> Result<(), SessionError> { match decl { + Declaration::Hook(CompileTimeHook::TermExpansion, clause) => + Ok(wam.add_term_expansion_clause(clause)?), Declaration::NonCountedBacktracking(name, arity) => Ok(self.add_non_counted_bt_flag(name, arity)), Declaration::Op(op_decl) => diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index 55815445..b8267a5c 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -238,8 +238,7 @@ pub enum SystemClauseType { SetDoubleQuotes, SkipMaxList, Succeed, - UnwindStack, - CompileAndRunQuery + UnwindStack } impl SystemClauseType { @@ -277,7 +276,6 @@ impl SystemClauseType { &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), &SystemClauseType::Succeed => clause_name!("$succeed"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), - &SystemClauseType::CompileAndRunQuery => clause_name!("$compile_and_run_query") } } @@ -311,7 +309,6 @@ impl SystemClauseType { ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), - ("$compile_and_run_query", 1) => Some(SystemClauseType::CompileAndRunQuery), _ => None } } @@ -1176,9 +1173,10 @@ impl SubModuleUser for Module { } } -pub enum Declaration { - NonCountedBacktracking(ClauseName, usize), // name, arity +pub enum Declaration { + Hook(CompileTimeHook, PredicateClause), Module(ModuleDecl), + NonCountedBacktracking(ClauseName, usize), // name, arity Op(OpDecl), UseModule(ClauseName), UseQualifiedModule(ClauseName, Vec) @@ -1193,10 +1191,10 @@ impl Declaration { pub enum TopLevel { Declaration(Declaration), - Fact(Term), + Fact(Term), Predicate(Predicate), Query(Vec), - Rule(Rule) + Rule(Rule), } impl TopLevel { diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index bb6a18a4..5e82723a 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -307,5 +307,3 @@ handle_ball(C, C, R) :- !, '$erase_ball', call(R). handle_ball(_, _, _) :- '$unwind_stack'. throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. - -repl :- read(X), '$compile_and_run_query'(X), repl. diff --git a/src/prolog/lib/numbervars.pl b/src/prolog/lib/numbervars.pl index 84a1431d..7d81e89f 100644 --- a/src/prolog/lib/numbervars.pl +++ b/src/prolog/lib/numbervars.pl @@ -14,7 +14,7 @@ numbervars(Term, NewTerm, N1, N2) :- compound(Term), !, Term =.. [Name | Args], NewTerm =.. [Name | NewArgs], fold_numbervars(Args, NewArgs, N1, N2). -numbervars(_, _, _, _). +numbervars(_, _, N, N). marked_already(Term, NewTerm) :- var(Term), nonvar(NewTerm), NewTerm = '$VAR'(_). @@ -23,9 +23,7 @@ marked_already(Term, NewTerm) :- fold_numbervars([HeadTerm | Terms], [NewHeadTerm | NewTerms], N1, Nn) :- ( marked_already(HeadTerm, NewHeadTerm) -> N1 = N2 - ; numbervars(HeadTerm, NewHeadTerm, N1, N2), - ( var(N2) -> N1 = N2 - ; true ) + ; numbervars(HeadTerm, NewHeadTerm, N1, N2) ), fold_numbervars(Terms, NewTerms, N2, Nn). fold_numbervars([], [], _, _). diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 8c46b57c..bbc3e863 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -1,9 +1,11 @@ use prolog_parser::ast::*; use prolog_parser::tabled_rc::*; -use prolog::instructions::*; +use prolog::codegen::*; use prolog::compile::*; +use prolog::debray_allocator::*; use prolog::heap_print::*; +use prolog::instructions::*; mod machine_errors; pub(super) mod machine_state; @@ -249,6 +251,21 @@ impl Machine { } } + #[inline] + pub(super) + fn add_term_expansion_clause(&mut self, clause: PredicateClause) -> Result<(), ParserError> + { + let key = (clause_name!("term_expansion"), 2); + let preds = self.term_dir.entry(key).or_insert(Predicate(vec![])); + + preds.0.push(clause); + + let mut cg = CodeGenerator::::new(false, self.ms.flags); + let code = cg.compile_predicate(&preds.0)?; + + Ok(self.term_expanders = code) + } + fn lookup_instr(&self, p: CodePtr) -> Option { match p { CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 5c69e5d6..f94800e2 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -203,7 +203,7 @@ impl MachineState { }, &SystemClauseType::GetDoubleQuotes => { let a1 = self[temp_v!(1)].clone(); - + match self.flags.double_quotes { DoubleQuotes::Chars => self.unify(a1, Addr::Con(atom!("chars"))), @@ -435,14 +435,7 @@ impl MachineState { return Err(err); }, &SystemClauseType::Succeed => {}, - &SystemClauseType::UnwindStack => self.unwind_stack(), - &SystemClauseType::CompileAndRunQuery => {} -/* let addr = self[temp_v!(1)].clone(); - - match term_write(&self, addr) { - Err(e) => machine_error - Ok(term) => - }*/ + &SystemClauseType::UnwindStack => self.unwind_stack() }; self.set_p(); diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index eabca7a9..cc9337fa 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -24,6 +24,11 @@ impl TermStream { } } + #[inline] + pub fn add_to_top(&mut self, buf: &str) { + self.parser.add_to_top(buf); + } + #[inline] pub fn eof(&mut self) -> Result { Ok(self.stack.is_empty() && self.parser.eof()?) diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 0b880373..b546f5ae 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -5,6 +5,7 @@ use prolog::instructions::*; use prolog::iterators::*; use prolog::machine::*; use prolog::machine::machine_state::MachineState; +use prolog::machine::term_expansion::*; use std::collections::VecDeque; use std::io::{Read, stdin}; @@ -29,7 +30,7 @@ pub enum Input { Term(Term) } -pub fn read_toplevel(wam: &Machine) -> Result { +pub fn read_toplevel(wam: &mut Machine) -> Result { let mut buffer = String::new(); let stdin = stdin(); @@ -43,10 +44,10 @@ pub fn read_toplevel(wam: &Machine) -> Result { Ok(Input::Batch) }, _ => { - let mut parser = Parser::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags()); - parser.add_to_top(buffer.as_str()); + let mut term_stream = TermStream::new(stdin.lock(), wam.atom_tbl(), wam.machine_flags()); + term_stream.add_to_top(buffer.as_str()); - Ok(Input::Term(parser.read_term(composite_op!(&wam.op_dir))?)) + Ok(Input::Term(term_stream.read_term(wam, &OpDir::new())?)) } } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 040524f9..23134fff 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -69,6 +69,21 @@ impl<'a, 'b : 'a> CompositeIndices<'a, 'b> } } +#[inline] +fn is_term_expansion(name: &ClauseName, terms: &Vec>) -> bool { + if name.as_str() == ":-" { + if let Some(ref term) = terms.first() { + if let &Term::Clause(_, ref name, ref terms, None) = term.as_ref() { + return (name.as_str(), terms.len()) == ("term_expansion", 2); + } + } + } else if name.as_str() == "term_expansion" { + return terms.len() == 2; + } + + false +} + fn setup_fact(term: Term) -> Result { match term { @@ -604,6 +619,24 @@ impl RelationWorker { Ok(query_terms) } + fn setup_hook(&mut self, indices: &mut CompositeIndices, term: Term) + -> Result<(CompileTimeHook, PredicateClause), ParserError> + { + match term { + Term::Clause(r, name, terms, _) => + if name.as_str() == "term_expansion" && terms.len() == 2 { + let term = Term::Clause(r, name, terms, None); + Ok((CompileTimeHook::TermExpansion, PredicateClause::Fact(term))) + } else if name.as_str() == ":-" { + let rule = self.setup_rule(indices, terms, false)?; + Ok((CompileTimeHook::TermExpansion, PredicateClause::Rule(rule))) + } else { + Err(ParserError::InvalidHook) + }, + _ => Err(ParserError::InvalidHook) + } + } + fn setup_rule(&mut self, indices: &mut CompositeIndices, mut terms: Vec>, blocks_cuts: bool) -> Result { @@ -626,7 +659,12 @@ impl RelationWorker { { match term { Term::Clause(r, name, mut terms, fixity) => - if name.as_str() == "?-" { + if is_term_expansion(&name, &terms) { + let term = Term::Clause(r, name, terms, fixity); + let (hook, clauses) = self.setup_hook(indices, term)?; + + Ok(TopLevel::Declaration(Declaration::Hook(hook, clauses))) + } else if name.as_str() == "?-" { Ok(TopLevel::Query(try!(self.setup_query(indices, terms, blocks_cuts)))) } else if name.as_str() == ":-" && terms.len() > 1 { Ok(TopLevel::Rule(try!(self.setup_rule(indices, terms, blocks_cuts)))) @@ -634,8 +672,9 @@ impl RelationWorker { let term = *terms.pop().unwrap(); Ok(TopLevel::Declaration(try!(setup_declaration(term)))) } else { - Ok(TopLevel::Fact(try!(setup_fact(Term::Clause(r, name, terms, fixity))))) - }, + let term = Term::Clause(r, name, terms, fixity); + Ok(TopLevel::Fact(try!(setup_fact(term)))) + }, term => Ok(TopLevel::Fact(try!(setup_fact(term)))) } } @@ -660,8 +699,8 @@ impl RelationWorker { while let Some(terms) = self.queue.pop_front() { let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?; queue.push_back(clauses); + } - Ok(queue) } @@ -738,7 +777,7 @@ impl TopLevelBatchWorker { TopLevel::Fact(fact) => preds.push(PredicateClause::Fact(fact)), TopLevel::Rule(rule) => preds.push(PredicateClause::Rule(rule)), TopLevel::Predicate(pred) => preds.extend(pred.0), - TopLevel::Declaration(decl) => return Ok(Some(decl)), + TopLevel::Declaration(decl) => return Ok(Some(decl)), TopLevel::Query(_) => return Err(SessionError::NamelessEntry) } } From 66584cee5ed42815a734f7af31154354e451199c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 22 Sep 2018 17:05:19 -0600 Subject: [PATCH 4/4] add term_expansion basics --- Cargo.lock | 8 +++++--- Cargo.toml | 4 ++-- src/prolog/machine/term_expansion.rs | 4 +++- src/prolog/toplevel.rs | 28 +++++++++++++++------------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d46db9b5..064bcf48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,7 +86,8 @@ dependencies = [ [[package]] name = "prolog_parser" -version = "0.7.14" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -107,12 +108,12 @@ dependencies = [ [[package]] name = "rusty-wam" -version = "0.7.13" +version = "0.7.14" dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "prolog_parser 0.7.14", + "prolog_parser 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -151,6 +152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" +"checksum prolog_parser 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "11f378539616d1cd7b8fc006f309b5a4b483b82cbab76e898a9f1c99318b4dfa" "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" diff --git a/Cargo.toml b/Cargo.toml index 6fa9e632..787ffe60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.7.13" +version = "0.7.14" authors = ["Mark Thom "] repository = "https://github.com/mthom/rusty-wam" description = "The Warren Abstract Machine in Rust." @@ -10,7 +10,7 @@ license = "BSD-3-Clause" downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" -prolog_parser = { path = "../prolog_parser", version = "0.7.14" } +prolog_parser = "0.7.15" [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index cc9337fa..a743a555 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -94,7 +94,9 @@ impl Machine { self.reset(); Ok(None) } else { - Ok(Some(read_term_from_heap(&self.ms, Addr::HeapCell(h))?)) + let term = read_term_from_heap(&self.ms, Addr::HeapCell(h))?; + self.reset(); + Ok(Some(term)) } } } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 23134fff..2ec9c50c 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -1,5 +1,4 @@ use prolog_parser::ast::*; -use prolog_parser::parser::*; use prolog_parser::tabled_rc::*; use prolog::instructions::*; @@ -623,12 +622,12 @@ impl RelationWorker { -> Result<(CompileTimeHook, PredicateClause), ParserError> { match term { - Term::Clause(r, name, terms, _) => + Term::Clause(r, name, terms, _) => if name.as_str() == "term_expansion" && terms.len() == 2 { let term = Term::Clause(r, name, terms, None); Ok((CompileTimeHook::TermExpansion, PredicateClause::Fact(term))) } else if name.as_str() == ":-" { - let rule = self.setup_rule(indices, terms, false)?; + let rule = self.setup_rule(indices, terms, false)?; Ok((CompileTimeHook::TermExpansion, PredicateClause::Rule(rule))) } else { Err(ParserError::InvalidHook) @@ -636,7 +635,7 @@ impl RelationWorker { _ => Err(ParserError::InvalidHook) } } - + fn setup_rule(&mut self, indices: &mut CompositeIndices, mut terms: Vec>, blocks_cuts: bool) -> Result { @@ -662,7 +661,7 @@ impl RelationWorker { if is_term_expansion(&name, &terms) { let term = Term::Clause(r, name, terms, fixity); let (hook, clauses) = self.setup_hook(indices, term)?; - + Ok(TopLevel::Declaration(Declaration::Hook(hook, clauses))) } else if name.as_str() == "?-" { Ok(TopLevel::Query(try!(self.setup_query(indices, terms, blocks_cuts)))) @@ -672,9 +671,9 @@ impl RelationWorker { let term = *terms.pop().unwrap(); Ok(TopLevel::Declaration(try!(setup_declaration(term)))) } else { - let term = Term::Clause(r, name, terms, fixity); + let term = Term::Clause(r, name, terms, fixity); Ok(TopLevel::Fact(try!(setup_fact(term)))) - }, + }, term => Ok(TopLevel::Fact(try!(setup_fact(term)))) } } @@ -699,7 +698,7 @@ impl RelationWorker { while let Some(terms) = self.queue.pop_front() { let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?; queue.push_back(clauses); - + } Ok(queue) } @@ -709,9 +708,12 @@ impl RelationWorker { } } -// used to parse queries in test. mostly. +// used to parse queries in test. +#[cfg(test)] pub fn parse_term(wam: &Machine, buf: R) -> Result { + use prolog_parser::parser::*; + let mut parser = Parser::new(buf, wam.atom_tbl(), wam.machine_flags()); parser.read_term(composite_op!(&wam.op_dir)) } @@ -723,7 +725,7 @@ fn consume_term<'a>(static_code_dir: Rc>, term: Term, { let mut rel_worker = RelationWorker::new(); let mut indices = composite_indices!(false, &mut indices, static_code_dir); - + let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?; let results = rel_worker.parse_queue(&mut indices)?; @@ -762,8 +764,8 @@ impl TopLevelBatchWorker { self.term_stream.empty_tokens(); // empty the parser stack of token descriptions. let mut new_rel_worker = RelationWorker::new(); - let term = self.term_stream.read_term(wam, &indices.local.op_dir)?; - + let term = self.term_stream.read_term(wam, &indices.local.op_dir)?; + let tl = new_rel_worker.try_term_to_tl(&mut indices, term, true)?; if !is_consistent(&tl, &preds) { // if is_consistent returns false, preds is non-empty. @@ -777,7 +779,7 @@ impl TopLevelBatchWorker { TopLevel::Fact(fact) => preds.push(PredicateClause::Fact(fact)), TopLevel::Rule(rule) => preds.push(PredicateClause::Rule(rule)), TopLevel::Predicate(pred) => preds.extend(pred.0), - TopLevel::Declaration(decl) => return Ok(Some(decl)), + TopLevel::Declaration(decl) => return Ok(Some(decl)), TopLevel::Query(_) => return Err(SessionError::NamelessEntry) } }