fix cut expansions.

This commit is contained in:
Mark Thom
2018-04-07 16:44:51 -06:00
parent 5d0674a667
commit d6c148d5e9
6 changed files with 45 additions and 21 deletions

View File

@@ -101,7 +101,25 @@ impl GenContext {
}
}
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),
@@ -260,7 +278,7 @@ impl TopLevel {
&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())
@@ -272,18 +290,18 @@ impl TopLevel {
&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)
}
}
}
@@ -669,7 +687,7 @@ pub type JumpStub = Vec<Term>;
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)
}
@@ -677,7 +695,7 @@ impl QueryTerm {
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()
}
}

View File

@@ -408,8 +408,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
};
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)
@@ -482,7 +482,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
{
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()),
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
_ => {}
};

View File

@@ -159,7 +159,8 @@ impl<'a> VariableFixtures<'a>
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);

View File

@@ -492,7 +492,7 @@ fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
&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) =>
@@ -576,7 +576,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
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.")))
}

View File

@@ -2,6 +2,7 @@ use prolog::ast::*;
use std::collections::VecDeque;
use std::iter::*;
use std::rc::Rc;
use std::vec::Vec;
pub struct QueryIterator<'a> {
@@ -50,8 +51,12 @@ impl<'a> 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)
@@ -322,7 +327,7 @@ impl<'a> ChunkedIterator<'a>
if contains_cut_var(vars.iter()) && !self.cut_var_in_head {
self.deep_cut_encountered = true;
}
break;
},
ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => {
@@ -332,8 +337,8 @@ impl<'a> ChunkedIterator<'a>
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)) => {