state_stack: Vec<IteratorState<'a>>
}
+pub type ArithCont = (Code, Option<ArithmeticTerm>);
+
impl<'a> ArithExprIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(IteratorState::to_state(lvl, term));
pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict<'a>,
- target_int: usize,
interm: Vec<ArithmeticTerm>,
interm_c: usize
}
impl<'a> ArithmeticEvaluator<'a> {
pub fn new(bindings: &'a AllocVarDict<'a>, target_int: usize) -> Self {
- ArithmeticEvaluator { bindings, target_int, interm: Vec::new(), interm_c: target_int }
+ ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
}
fn get_unary_instr(name: &Atom, a1: ArithmeticTerm, t: usize)
Ok(())
}
- pub fn eval(&mut self, term: &Term) -> Result<Code, ArithmeticError> {
+ pub fn eval(&mut self, term: &Term) -> Result<ArithCont, ArithmeticError> {
let mut code = Vec::new();
for term_ref in term.arith_expr_iter()? {
}
}
-
- if let Some(arith_term) = self.interm.pop() {
- let t = self.target_int;
-
- match arith_term {
- n @ ArithmeticTerm::Integer(_) => code.push(move_at!(n, t)),
- n @ ArithmeticTerm::Float(_) => code.push(move_at!(n, t)),
- r @ ArithmeticTerm::Reg(_) => code.push(move_at!(r, t)),
- _ => {}
- };
- }
-
- Ok(code)
+ Ok((code, self.interm.pop()))
}
}
}
pub enum InlinedQueryTerm {
+ CompareNumber(CompareNumberQT, Vec<Box<Term>>),
IsAtomic(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>)
}
impl InlinedQueryTerm {
pub fn arity(&self) -> usize {
match self {
+ &InlinedQueryTerm::CompareNumber(_, _) => 2,
&InlinedQueryTerm::IsAtomic(_) => 1,
- &InlinedQueryTerm::IsVar(_) => 1
+ &InlinedQueryTerm::IsVar(_) => 1
}
}
}
pub enum QueryTerm {
CallN(Vec<Box<Term>>),
Catch(Vec<Box<Term>>),
- CompareNumber(CompareNumberQT, Vec<Box<Term>>),
Cut,
Is(Vec<Box<Term>>),
Inlined(InlinedQueryTerm),
pub fn arity(&self) -> usize {
match self {
&QueryTerm::Catch(_) => 3,
- &QueryTerm::CompareNumber(_, _) => 2,
&QueryTerm::Throw(_) => 1,
&QueryTerm::Inlined(ref term) => term.arity(),
&QueryTerm::Is(_) => 2,
pub enum BuiltInInstruction {
CleanUpBlock,
+ CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
DuplicateTerm,
EraseBall,
Fail,
Execute(Atom, usize),
ExecuteN(usize),
Goto(usize, usize), // p, arity.
- CompareNumberCall(CompareNumberQT),
- CompareNumberExecute(CompareNumberQT),
- IsCall(RegType),
- IsExecute(RegType),
+ IsCall(RegType, ArithmeticTerm),
+ IsExecute(RegType, ArithmeticTerm),
Proceed,
ThrowCall,
ThrowExecute,
&ControlInstruction::ThrowExecute => true,
&ControlInstruction::Goto(_, _) => true,
&ControlInstruction::Proceed => true,
- &ControlInstruction::IsCall(_) => true,
- &ControlInstruction::IsExecute(_) => true,
+ &ControlInstruction::IsCall(_, _) => true,
+ &ControlInstruction::IsExecute(_, _) => true,
_ => false
}
}
}
pub enum QueryInstruction {
- MoveArithmeticTerm(ArithmeticTerm, usize),
GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType),
PutList(Level, RegType),
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
}
- fn add_conditional_call_inlined(term: &InlinedQueryTerm, code: &mut Code)
+ fn add_conditional_call_inlined(_: &InlinedQueryTerm, code: &mut Code)
{
+ code.push(proceed!());
+
+ /*
match term {
&InlinedQueryTerm::IsAtomic(_) | &InlinedQueryTerm::IsVar(_) =>
code.push(proceed!())
};
+ */
}
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
*ctrl = ControlInstruction::Execute(name, arity),
ControlInstruction::CallN(arity) =>
*ctrl = ControlInstruction::ExecuteN(arity),
- ControlInstruction::CompareNumberCall(cmp) =>
- *ctrl = ControlInstruction::CompareNumberExecute(cmp),
- ControlInstruction::IsCall(r) =>
- *ctrl = ControlInstruction::IsExecute(r),
+ ControlInstruction::IsCall(r, at) =>
+ *ctrl = ControlInstruction::IsExecute(r, at),
ControlInstruction::CatchCall =>
*ctrl = ControlInstruction::CatchExecute,
ControlInstruction::ThrowCall =>
}
fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
+ -> Result<(), ParserError>
{
match term {
+ &InlinedQueryTerm::CompareNumber(cmp, ref terms) => {
+ let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
+ let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
+
+ code.append(&mut lcode);
+ code.append(&mut rcode);
+
+ code.push(compare_number_instr!(cmp,
+ at_1.unwrap_or(interm!(1)),
+ at_2.unwrap_or(interm!(2))));
+ },
&InlinedQueryTerm::IsAtomic(ref inner_term) =>
- match inner_term[0].as_ref() {
- &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
- code.push(fail!());
- },
- &Term::Constant(_, _) => {
- code.push(succeed!());
- },
- &Term::Var(ref vr, ref name) => {
- let r = self.mark_non_callable(name, 1, term_loc, vr, code);
- code.push(is_atomic!(r));
- }
- },
+ match inner_term[0].as_ref() {
+ &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
+ code.push(fail!());
+ },
+ &Term::Constant(_, _) => {
+ code.push(succeed!());
+ },
+ &Term::Var(ref vr, ref name) => {
+ let r = self.mark_non_callable(name, 1, term_loc, vr, code);
+ code.push(is_atomic!(r));
+ }
+ },
&InlinedQueryTerm::IsVar(ref inner_term) =>
match inner_term[0].as_ref() {
&Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
}
}
}
+
+ Ok(())
}
- fn call_arith_eval(&self, term: &'a Term, target_int: usize) -> Result<Code, ArithmeticError> {
+ fn call_arith_eval(&self, term: &'a Term, target_int: usize) -> Result<ArithCont, ArithmeticError>
+ {
let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings(), target_int);
evaluator.eval(term)
}
});
},
&QueryTerm::Inlined(ref term) =>
- self.compile_inlined(term, term_loc, code),
+ self.compile_inlined(term, term_loc, code)?,
&QueryTerm::Is(ref terms) => {
- let mut arith_code = self.call_arith_eval(terms[1].as_ref(), 1)?;
- code.append(&mut arith_code);
+ let (mut acode, at) = try!(self.call_arith_eval(terms[1].as_ref(), 1));
+ code.append(&mut acode);
match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => {
vr,
code);
- code.push(is_call!(r));
+ code.push(is_call!(r, at.unwrap_or(interm!(1))));
},
&Term::Constant(_, Constant::Float(fl)) => {
code.push(query![put_constant!(Level::Shallow,
Constant::Float(fl),
temp_v!(1))]);
- code.push(is_call!(temp_v!(1)));
+ code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
},
&Term::Constant(_, Constant::Integer(ref bi)) => {
let bi = bi.clone();
code.push(query![put_constant!(Level::Shallow,
Constant::Integer(bi),
temp_v!(1))]);
- code.push(is_call!(temp_v!(1)));
+ code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
},
_ => {
code.push(fail!());
}
}
- },
- &QueryTerm::CompareNumber(cmp, ref terms) => {
- let mut larith_code = self.call_arith_eval(terms[0].as_ref(), 1)?;
- let mut rarith_code = self.call_arith_eval(terms[1].as_ref(), 2)?;
-
- code.append(&mut larith_code);
- code.append(&mut rarith_code);
-
- code.push(compare_number_call!(cmp));
- },
+ },
_ if chunk_num == 0 => {
self.marker.reset_arg(term.arity());
impl fmt::Display for QueryInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &QueryInstruction::MoveArithmeticTerm(ref at, ref r) =>
- write!(f, "move_arithmetic_term {}, {}", at, r),
&QueryInstruction::GetVariable(ref x, ref a) =>
write!(f, "query:get_variable {}, A{}", x, a),
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
&ControlInstruction::CatchCall =>
write!(f, "call_catch"),
&ControlInstruction::CatchExecute =>
- write!(f, "execute_catch"),
- &ControlInstruction::CompareNumberCall(cmp) =>
- write!(f, "n_compare_call {}", cmp),
- &ControlInstruction::CompareNumberExecute(cmp) =>
- write!(f, "n_compare_execute {}", cmp),
+ write!(f, "execute_catch"),
&ControlInstruction::ExecuteN(arity) =>
write!(f, "execute_N {}", arity),
&ControlInstruction::Deallocate =>
write!(f, "call_throw"),
&ControlInstruction::ThrowExecute =>
write!(f, "execute_throw"),
- &ControlInstruction::IsCall(r) =>
- write!(f, "is_call {}", r),
- &ControlInstruction::IsExecute(r) =>
- write!(f, "is_execute {}", r),
+ &ControlInstruction::IsCall(r, ref at) =>
+ write!(f, "is_call {}, {}", r, at),
+ &ControlInstruction::IsExecute(r, ref at) =>
+ write!(f, "is_execute {}, {}", r, at),
}
}
}
match self {
&BuiltInInstruction::CleanUpBlock =>
write!(f, "clean_up_block"),
+ &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) =>
+ write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
&BuiltInInstruction::DuplicateTerm =>
write!(f, "duplicate_term X1"),
&BuiltInInstruction::EraseBall =>
let state = IteratorState::Clause(0, ClauseType::Catch, terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::CompareNumber(_, ref terms) | &QueryTerm::Is(ref terms) => {
- let state = IteratorState::Clause(0, ClauseType::Is, terms);
- QueryIterator { state_stack: vec![state] }
+ &QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(_, ref terms))
+ | &QueryTerm::Is(ref terms) => {
+ let state = IteratorState::Clause(0, ClauseType::Is, terms);
+ QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) =>
arity = child_terms.len();
break;
},
- &QueryTerm::Is(_) | &QueryTerm::CompareNumber(_, _) => {
+ &QueryTerm::Is(_) => {
result.push(term);
arity = 2;
break;
fn execute_query_instr(&mut self, instr: &QueryInstruction) {
match instr {
- &QueryInstruction::MoveArithmeticTerm(ref at, t) => {
- let n = try_or_fail!(self, self.get_number(at));
- self.interms[t - 1] = n;
- },
&QueryInstruction::GetVariable(norm, arg) =>
self[norm] = self.registers[arg].clone(),
&QueryInstruction::PutConstant(_, ref constant, reg) =>
fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
{
match instr {
+ &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => {
+ let n1 = try_or_fail!(self, self.get_number(at_1));
+ let n2 = try_or_fail!(self, self.get_number(at_2));
+
+ self.fail = match cmp {
+ CompareNumberQT::GreaterThan if !(n1.gt(n2)) => true,
+ CompareNumberQT::GreaterThanOrEqual if !(n1.gte(n2)) => true,
+ CompareNumberQT::LessThan if !(n1.lt(n2)) => true,
+ CompareNumberQT::LessThanOrEqual if !(n1.lte(n2)) => true,
+ CompareNumberQT::NotEqual if !(n1.ne(n2)) => true,
+ CompareNumberQT::Equal if !(n1.eq(n2)) => true,
+ _ => false
+ };
+
+ self.p += 1;
+ },
&BuiltInInstruction::DuplicateTerm => {
let old_h = self.h;
}
};
}
-
- fn handle_n_compare(&mut self, cmp: CompareNumberQT) {
- let n1 = self.interms[0].clone();
- let n2 = self.interms[1].clone();
-
- self.fail = match cmp {
- CompareNumberQT::GreaterThan if !(n1.gt(n2)) => true,
- CompareNumberQT::GreaterThanOrEqual if !(n1.gte(n2)) => true,
- CompareNumberQT::LessThan if !(n1.lt(n2)) => true,
- CompareNumberQT::LessThanOrEqual if !(n1.lte(n2)) => true,
- CompareNumberQT::NotEqual if !(n1.ne(n2)) => true,
- CompareNumberQT::Equal if !(n1.eq(n2)) => true,
- _ => false
- };
- }
fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
{
},
&ControlInstruction::ThrowExecute => {
self.goto_throw();
- },
- &ControlInstruction::CompareNumberCall(cmp) => {
- self.handle_n_compare(cmp);
- self.p += 1;
- },
- &ControlInstruction::CompareNumberExecute(cmp) => {
- self.handle_n_compare(cmp);
- self.p = self.cp;
- },
- &ControlInstruction::IsCall(r) => {
+ },
+ &ControlInstruction::IsCall(r, ref at) => {
let a1 = self[r].clone();
- let a2 = Addr::Con(Constant::from(self.interms[0].clone()));
+ let a2 = try_or_fail!(self, self.get_number(at));
- self.unify(a1, a2);
+ self.unify(a1, Addr::Con(Constant::from(a2)));
self.p += 1;
},
- &ControlInstruction::IsExecute(r) => {
+ &ControlInstruction::IsExecute(r, ref at) => {
let a1 = self[r].clone();
- let a2 = Addr::Con(Constant::from(self.interms[0].clone()));
+ let a2 = try_or_fail!(self, self.get_number(at));
- self.unify(a1, a2);
+ self.unify(a1, Addr::Con(Constant::from(a2)));
self.p = self.cp;
}
};
)
}
-macro_rules! move_at {
- ($at:expr, $r:expr) => (
- Line::Query(vec![QueryInstruction::MoveArithmeticTerm($at, $r)])
+macro_rules! compare_number {
+ ($cmp: expr, $terms: expr) => (
+ QueryTerm::Inlined(InlinedQueryTerm::CompareNumber($cmp, $terms))
+ )
+}
+
+macro_rules! compare_number_instr {
+ ($cmp: expr, $at_1: expr, $at_2: expr) => (
+ Line::BuiltIn(BuiltInInstruction::CompareNumber($cmp, $at_1, $at_2))
+ )
+}
+
+macro_rules! interm {
+ ($n: expr) => (
+ ArithmeticTerm::Interm($n)
)
}
)
}
-macro_rules! compare_number_call {
- ($cmp: expr) => (
- Line::Control(ControlInstruction::CompareNumberCall($cmp))
- )
-}
-
macro_rules! temp_v {
($x:expr) => (
RegType::Temp($x)
}
macro_rules! is_call {
- ($r:expr) => (
- Line::Control(ControlInstruction::IsCall($r))
+ ($r:expr, $at:expr) => (
+ Line::Control(ControlInstruction::IsCall($r, $at))
)
}
-Subproject commit c1058528434bb05237a034449adcfeb56e4b6214
+Subproject commit 87230857805adcfff30c8f0257179e87c531fb21