}
}
-pub type Predicate = Vec<PredicateClause>;
+pub struct Predicate(pub Vec<PredicateClause>);
+
+impl Predicate {
+ pub fn name(&self) -> Option<ClauseName> {
+ self.0.first().and_then(|t| t.name())
+ }
+
+ pub fn arity(&self) -> usize {
+ if let Some(ref clause) = self.0.first() {
+ clause.arity()
+ } else {
+ 0
+ }
+ }
+
+ pub fn clauses(self) -> Vec<PredicateClause> {
+ self.0
+ }
+}
pub enum PredicateClause {
Fact(Term),
&TopLevel::Declaration(_) => None,
&TopLevel::Fact(ref term) => term.name(),
&TopLevel::Predicate(ref clauses) =>
- clauses.first().and_then(|ref term| term.name()),
+ clauses.0.first().and_then(|ref term| term.name()),
&TopLevel::Query(_) => None,
&TopLevel::Rule(Rule { ref head, .. }) =>
Some(head.0.clone())
&TopLevel::Declaration(_) => 0,
&TopLevel::Fact(ref term) => term.arity(),
&TopLevel::Predicate(ref clauses) =>
- clauses.first().map(|t| t.arity()).unwrap_or(0),
+ clauses.0.first().map(|t| t.arity()).unwrap_or(0),
&TopLevel::Query(_) => 0,
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
}
}
- pub fn as_predicate(self) -> Option<Predicate> {
+ pub fn as_predicate(self) -> Result<Predicate, TopLevel> {
match self {
- TopLevel::Fact(term) => Some(vec![PredicateClause::Fact(term)]),
- TopLevel::Rule(rule) => Some(vec![PredicateClause::Rule(rule)]),
- TopLevel::Predicate(pred) => Some(pred),
- _ => None
+ TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])),
+ TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])),
+ TopLevel::Predicate(pred) => Ok(pred),
+ _ => Err(self)
}
}
}
pub enum QueryTerm {
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
- UnblockedCut,
+ UnblockedCut(Cell<VarReg>),
Jump(JumpStub)
}
pub fn arity(&self) -> usize {
match self {
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
- &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => 0,
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0,
&QueryTerm::Jump(ref vars) => vars.len()
}
}
};
match *term {
- &QueryTerm::UnblockedCut =>
- code.push(set_cp!(self.marker.get(rc_atom!("!")))),
+ &QueryTerm::UnblockedCut(ref cell) =>
+ code.push(set_cp!(cell.get().norm())),
&QueryTerm::BlockedCut =>
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
{
// add a proceed to bookend any trailing cuts.
match toc {
- &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()),
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
_ => {}
};
for term_ref in iter {
if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
let mut status = self.0.remove(var)
- .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), Vec::new()));
+ .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)),
+ Vec::new()));
status.1.push(cell);
&TopLevel::Declaration(_) | &TopLevel::Query(_) =>
Err(ParserError::ExpectedRel),
&TopLevel::Predicate(ref clauses) =>
- cg.compile_predicate(clauses),
+ cg.compile_predicate(&clauses.0),
&TopLevel::Fact(ref fact) =>
Ok(cg.compile_fact(fact)),
&TopLevel::Rule(ref rule) =>
print_code(&code);
if !code.is_empty() {
- wam.add_user_code(name, tl.arity(), code, tl.as_predicate().unwrap())
+ wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
} else {
EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
}
use std::collections::VecDeque;
use std::iter::*;
+use std::rc::Rc;
use std::vec::Vec;
pub struct QueryIterator<'a> {
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut =>
+ &QueryTerm::BlockedCut =>
QueryIterator { state_stack: vec![] },
+ &QueryTerm::UnblockedCut(ref cell) => {
+ let state = TermIterState::Var(Level::Root, cell, rc_atom!("!"));
+ QueryIterator { state_stack: vec![state] }
+ },
&QueryTerm::Jump(ref vars) => {
let state_stack = vars.iter().rev().map(|t| {
TermIterState::subterm_to_state(Level::Shallow, t)
if contains_cut_var(vars.iter()) && !self.cut_var_in_head {
self.deep_cut_encountered = true;
}
-
+
break;
},
ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => {
self.deep_cut_encountered = true;
}
},
- ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut) =>
- result.push(term),
+ ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) =>
+ result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
-Subproject commit 737d6ba091bb5909b0af31c221f290debc95bf2d
+Subproject commit ba9bd0098e66227006b799a6c5c2c583fa9d9009