fix cut expansions.
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!()),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.")))
|
||||
}
|
||||
|
||||
@@ -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)) => {
|
||||
|
||||
Submodule src/prolog/parser updated: 737d6ba091...ba9bd0098e
Reference in New Issue
Block a user