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 {
|
pub enum PredicateClause {
|
||||||
Fact(Term),
|
Fact(Term),
|
||||||
@@ -260,7 +278,7 @@ impl TopLevel {
|
|||||||
&TopLevel::Declaration(_) => None,
|
&TopLevel::Declaration(_) => None,
|
||||||
&TopLevel::Fact(ref term) => term.name(),
|
&TopLevel::Fact(ref term) => term.name(),
|
||||||
&TopLevel::Predicate(ref clauses) =>
|
&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::Query(_) => None,
|
||||||
&TopLevel::Rule(Rule { ref head, .. }) =>
|
&TopLevel::Rule(Rule { ref head, .. }) =>
|
||||||
Some(head.0.clone())
|
Some(head.0.clone())
|
||||||
@@ -272,18 +290,18 @@ impl TopLevel {
|
|||||||
&TopLevel::Declaration(_) => 0,
|
&TopLevel::Declaration(_) => 0,
|
||||||
&TopLevel::Fact(ref term) => term.arity(),
|
&TopLevel::Fact(ref term) => term.arity(),
|
||||||
&TopLevel::Predicate(ref clauses) =>
|
&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::Query(_) => 0,
|
||||||
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
|
&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 {
|
match self {
|
||||||
TopLevel::Fact(term) => Some(vec![PredicateClause::Fact(term)]),
|
TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])),
|
||||||
TopLevel::Rule(rule) => Some(vec![PredicateClause::Rule(rule)]),
|
TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])),
|
||||||
TopLevel::Predicate(pred) => Some(pred),
|
TopLevel::Predicate(pred) => Ok(pred),
|
||||||
_ => None
|
_ => Err(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,7 +687,7 @@ pub type JumpStub = Vec<Term>;
|
|||||||
pub enum QueryTerm {
|
pub enum QueryTerm {
|
||||||
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
|
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
|
||||||
BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
|
BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
|
||||||
UnblockedCut,
|
UnblockedCut(Cell<VarReg>),
|
||||||
Jump(JumpStub)
|
Jump(JumpStub)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +695,7 @@ impl QueryTerm {
|
|||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
|
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
|
||||||
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => 0,
|
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0,
|
||||||
&QueryTerm::Jump(ref vars) => vars.len()
|
&QueryTerm::Jump(ref vars) => vars.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,8 +408,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
};
|
};
|
||||||
|
|
||||||
match *term {
|
match *term {
|
||||||
&QueryTerm::UnblockedCut =>
|
&QueryTerm::UnblockedCut(ref cell) =>
|
||||||
code.push(set_cp!(self.marker.get(rc_atom!("!")))),
|
code.push(set_cp!(cell.get().norm())),
|
||||||
&QueryTerm::BlockedCut =>
|
&QueryTerm::BlockedCut =>
|
||||||
code.push(if chunk_num == 0 {
|
code.push(if chunk_num == 0 {
|
||||||
Line::Cut(CutInstruction::NeckCut)
|
Line::Cut(CutInstruction::NeckCut)
|
||||||
@@ -482,7 +482,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
{
|
{
|
||||||
// add a proceed to bookend any trailing cuts.
|
// add a proceed to bookend any trailing cuts.
|
||||||
match toc {
|
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 {
|
for term_ref in iter {
|
||||||
if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
|
if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
|
||||||
let mut status = self.0.remove(var)
|
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);
|
status.1.push(cell);
|
||||||
|
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
|
|||||||
&TopLevel::Declaration(_) | &TopLevel::Query(_) =>
|
&TopLevel::Declaration(_) | &TopLevel::Query(_) =>
|
||||||
Err(ParserError::ExpectedRel),
|
Err(ParserError::ExpectedRel),
|
||||||
&TopLevel::Predicate(ref clauses) =>
|
&TopLevel::Predicate(ref clauses) =>
|
||||||
cg.compile_predicate(clauses),
|
cg.compile_predicate(&clauses.0),
|
||||||
&TopLevel::Fact(ref fact) =>
|
&TopLevel::Fact(ref fact) =>
|
||||||
Ok(cg.compile_fact(fact)),
|
Ok(cg.compile_fact(fact)),
|
||||||
&TopLevel::Rule(ref rule) =>
|
&TopLevel::Rule(ref rule) =>
|
||||||
@@ -576,7 +576,7 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
|||||||
print_code(&code);
|
print_code(&code);
|
||||||
|
|
||||||
if !code.is_empty() {
|
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 {
|
} else {
|
||||||
EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
|
EvalSession::from(EvalError::ImpermissibleEntry(String::from("no code generated.")))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use prolog::ast::*;
|
|||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::iter::*;
|
use std::iter::*;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
pub struct QueryIterator<'a> {
|
pub struct QueryIterator<'a> {
|
||||||
@@ -50,8 +51,12 @@ impl<'a> QueryIterator<'a> {
|
|||||||
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
|
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
|
||||||
QueryIterator { state_stack: vec![state] }
|
QueryIterator { state_stack: vec![state] }
|
||||||
},
|
},
|
||||||
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut =>
|
&QueryTerm::BlockedCut =>
|
||||||
QueryIterator { state_stack: vec![] },
|
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) => {
|
&QueryTerm::Jump(ref vars) => {
|
||||||
let state_stack = vars.iter().rev().map(|t| {
|
let state_stack = vars.iter().rev().map(|t| {
|
||||||
TermIterState::subterm_to_state(Level::Shallow, t)
|
TermIterState::subterm_to_state(Level::Shallow, t)
|
||||||
@@ -332,7 +337,7 @@ impl<'a> ChunkedIterator<'a>
|
|||||||
self.deep_cut_encountered = true;
|
self.deep_cut_encountered = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut) =>
|
ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) =>
|
||||||
result.push(term),
|
result.push(term),
|
||||||
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
|
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
|
||||||
result.push(term),
|
result.push(term),
|
||||||
|
|||||||
Submodule src/prolog/parser updated: 737d6ba091...ba9bd0098e
Reference in New Issue
Block a user