use prolog::ast::*;
use prolog::fixtures::*;
-use prolog::tabled_rc::*;
use std::cell::Cell;
use std::cmp::{min, max};
let state = match term {
&Term::AnonVar =>
return Err(ArithmeticError::InvalidTerm),
- &Term::Clause(_, _, ref terms, _) =>
- TermIterState::Clause(0, ClauseType::Root, terms),
+ &Term::Clause(_, ref name, ref terms, _) =>
+ TermIterState::Clause(0, ClauseType::Root(name), terms),
&Term::Constant(ref cell, ref cons) =>
TermIterState::Constant(Level::Shallow, cell, cons),
&Term::Cons(_, _, _) =>
pub enum ArithTermRef<'a> {
Constant(&'a Constant),
- Op(ClauseType<'a>, &'a Vec<Box<Term>>),
+ Op(&'a str, usize), // name, arity.
Var(&'a Cell<VarReg>, &'a Var)
}
TermIterState::AnonVar(_) =>
return Some(Err(ArithmeticError::UninstantiatedVar)),
TermIterState::Clause(child_num, ct, child_terms) => {
- if child_num == child_terms.len() {
- return Some(Ok(ArithTermRef::Op(ct, child_terms)));
+ let arity = child_terms.len();
+
+ if child_num == arity {
+ return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
} else {
self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict<'a>,
interm: Vec<ArithmeticTerm>,
- interm_c: usize
+ interm_c: usize
}
-pub trait ArithmeticTermIter<'a> {
+pub trait ArithmeticTermIter<'a> {
type Iter : Iterator<Item=Result<ArithTermRef<'a>, ArithmeticError>>;
-
+
fn iter(&self) -> Result<Self::Iter, ArithmeticError>;
- fn root_name(&self) -> Result<TabledRc<Atom>, ArithmeticError>;
}
-impl<'a> ArithmeticTermIter<'a> for &'a Term {
- type Iter = ArithInstructionIterator<'a>;
+impl<'a> ArithmeticTermIter<'a> for &'a Term {
+ type Iter = ArithInstructionIterator<'a>;
fn iter(&self) -> Result<Self::Iter, ArithmeticError> {
ArithInstructionIterator::new(self)
}
-
- fn root_name(&self) -> Result<TabledRc<Atom>, ArithmeticError> {
- match self {
- &&Term::Clause(_, ref name, _, _) => Ok(name.clone()),
- _ => Err(ArithmeticError::InvalidTerm)
- }
- }
}
impl<'a> ArithmeticEvaluator<'a>
pub fn new(bindings: &'a AllocVarDict<'a>, target_int: usize) -> Self {
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
}
-
- fn get_unary_instr(name: &Atom, a1: ArithmeticTerm, t: usize)
+
+ fn get_unary_instr(name: &str, a1: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
- match name.as_str() {
+ match name {
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
_ => Err(ArithmeticError::InvalidOp)
}
}
- fn get_binary_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
+ fn get_binary_instr(name: &str, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
- match name.as_str() {
+ match name {
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
_ => Err(ArithmeticError::InvalidOp)
}
}
-
+
fn incr_interm(&mut self) -> usize {
let temp = self.interm_c;
temp
}
- fn instr_from_clause(&mut self, name: &Atom, terms: &Vec<Box<Term>>)
+ fn instr_from_clause(&mut self, name: &str, arity: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
- match terms.len() {
+ match arity {
1 => {
let a1 = self.interm.pop().unwrap();
where Iter: ArithmeticTermIter<'a>
{
let mut code = vec![];
-
+
for term_ref in src.iter()?
{
match term_ref? {
self.interm.push(ArithmeticTerm::Reg(r));
},
- ArithTermRef::Op(ClauseType::Deep(_, _, name, _), terms) => {
- code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?));
- },
- ArithTermRef::Op(ClauseType::Root, terms) => {
- let name = src.root_name()?;
- code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?));
- },
- _ =>
- return Err(ArithmeticError::InvalidTerm)
+ ArithTermRef::Op(name, arity) => {
+ code.push(Line::Arithmetic(self.instr_from_clause(&*name, arity)?));
+ }
}
}
#[derive(Clone, Copy)]
pub enum ClauseType<'a> {
+ Arg,
CallN,
Catch,
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
+ Display,
+ DuplicateTerm,
+ Functor,
Is,
- Root,
+ Root(&'a TabledRc<Atom>),
Throw,
}
impl<'a> ClauseType<'a> {
+ pub fn name(&self) -> &'a str {
+ match self {
+ &ClauseType::Arg => "arg",
+ &ClauseType::CallN => "call",
+ &ClauseType::Catch => "catch",
+ &ClauseType::Deep(_, _, name, _) => name.as_str(),
+ &ClauseType::Display => "display",
+ &ClauseType::DuplicateTerm => "duplicate_term",
+ &ClauseType::Functor => "functor",
+ &ClauseType::Is => "is",
+ &ClauseType::Root(name) => name.as_str(),
+ &ClauseType::Throw => "throw"
+ }
+ }
+
pub fn level_of_subterms(self) -> Level {
match self {
ClauseType::Deep(..) => Level::Deep,
let state = match term {
&Term::AnonVar =>
return QueryIterator { state_stack: vec![] },
- &Term::Clause(.., ref terms, _) =>
- TermIterState::Clause(0, ClauseType::Root, terms),
+ &Term::Clause(_, ref name, ref terms, _) =>
+ TermIterState::Clause(0, ClauseType::Root(name), terms),
&Term::Cons(..) =>
return QueryIterator { state_stack: vec![] },
&Term::Constant(_, _) =>
let state = TermIterState::Clause(0, ClauseType::Catch, terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::Display(ref terms)
- | &QueryTerm::DuplicateTerm(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Root, terms);
+ &QueryTerm::Display(ref terms) => {
+ let state = TermIterState::Clause(0, ClauseType::Display, terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::Arg(ref terms)
- | &QueryTerm::Functor(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Root, terms);
+ &QueryTerm::DuplicateTerm(ref terms) => {
+ let state = TermIterState::Clause(0, ClauseType::DuplicateTerm, terms);
+ QueryIterator { state_stack: vec![state] }
+ },
+ &QueryTerm::Arg(ref terms) => {
+ let state = TermIterState::Clause(0, ClauseType::Arg, terms);
+ QueryIterator { state_stack: vec![state] }
+ },
+ &QueryTerm::Functor(ref terms) => {
+ let state = TermIterState::Clause(0, ClauseType::Functor, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(_, ref terms))
| &QueryTerm::Is(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Is, terms);
QueryIterator { state_stack: vec![state] }
- },
+ },
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) =>
impl<'a> Iterator for QueryIterator<'a> {
type Item = TermRef<'a>;
-
+
fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() {
match iter_state {
};
}
- None
+ None
}
}
let states = match term {
&Term::AnonVar =>
vec![TermIterState::AnonVar(Level::Shallow)],
- &Term::Clause(.., ref terms, _) =>
- vec![TermIterState::Clause(0, ClauseType::Root, terms)],
+ &Term::Clause(.., ref name, ref terms, _) =>
+ vec![TermIterState::Clause(0, ClauseType::Root(name), terms)],
&Term::Cons(ref cell, ref head, ref tail) =>
vec![TermIterState::InitialCons(Level::Shallow,
cell,
{
let inner_iter = Box::new(once(p1));
let iter = inner_iter.chain(clauses.iter());
-
+
ChunkedIterator {
term_loc: GenContext::Last(0),
iter: Box::new(iter),
term_loc: GenContext::Head,
iter: Box::new(iter),
deep_cut_encountered: false,
- }
+ }
}
pub fn encountered_deep_cut(&self) -> bool {
let mut arity = 0;
let mut item = Some(term);
let mut result = Vec::new();
-
+
while let Some(term) = item {
match term {
- &QueryTerm::Term(ref inner_term) =>
+ &QueryTerm::Term(ref inner_term) =>
if let GenContext::Head = self.term_loc {
result.push(term);
self.term_loc = GenContext::Last(0);
} else {
result.push(term);
-
+
if inner_term.is_callable() {
arity = inner_term.arity();
break;
}
- },
+ },
&QueryTerm::CallN(ref child_terms) => {
result.push(term);
arity = child_terms.len() + 1;