TryMeElse(usize)
}
-#[derive(Clone, Copy)]
-pub enum Terminal {
- Terminal, Non
-}
-
pub enum CutInstruction {
- Cut(Terminal),
+ Cut,
GetLevel,
- NeckCut(Terminal)
+ NeckCut
}
pub enum IndexedChoiceInstruction {
Fail,
GetBall,
GetCurrentBlock,
- GetCutPoint,
+ GetCutPoint(RegType),
InstallNewBlock,
InternalCallN,
IsAtomic(RegType),
IsVar(RegType),
ResetBlock,
SetBall,
- SetCutPoint,
+ SetNeckCutPoint(RegType),
+ SetNonNeckCutPoint(RegType),
Succeed,
Unify,
UnwindStack
get_level!(),
fact![get_var_in_fact!(perm_v!(2), 3)],
unify!(),
- cut!(non_terminal!()),
+ cut!(),
erase_ball!(),
query![put_value!(perm_v!(2), 1)],
deallocate!(),
allocate!(1),
get_level!(),
call_n!(1),
- cut!(non_terminal!()),
+ cut!(),
deallocate!(),
goto!(61, 0),
trust_me!(),
trust_me!(),
query![put_value!(temp_v!(2), 1)],
execute_n!(1),
- allocate!(3), // ','/2, 81.
- fact![get_var_in_fact!(perm_v!(2), 1),
- get_var_in_fact!(perm_v!(1), 2)],
- query![put_var!(perm_v!(3), 1)],
- get_cp!(),
- query![put_value!(perm_v!(2), 1),
- put_value!(perm_v!(1), 2),
- put_unsafe_value!(3, 3)],
- deallocate!(),
- goto!(88, 3),
- try_me_else!(25), // ','/3, 88.
+ get_cp!(temp_v!(3)), // ','/2, 81
+ goto!(83, 3),
+ try_me_else!(18), // ','/3, 83.
switch_on_term!(4, 1, 0, 0),
indexed_try!(4),
- retry!(11),
- trust!(14),
- try_me_else!(8),
- allocate!(3),
+ retry!(7),
+ trust!(10),
+ try_me_else!(4),
fact![get_constant!(Constant::from("!"), temp_v!(1)),
get_structure!(String::from(","), 2, temp_v!(2)),
- unify_variable!(perm_v!(2)),
- unify_variable!(perm_v!(1)),
- get_var_in_fact!(perm_v!(3), 3)],
- query![put_value!(perm_v!(3), 1)],
- set_cp!(),
- query![put_unsafe_value!(2, 1),
- put_unsafe_value!(1, 2),
- put_value!(perm_v!(3), 3)],
- deallocate!(),
- goto!(88, 3),
+ unify_variable!(temp_v!(1)),
+ unify_variable!(temp_v!(2))],
+ set_neck_cut!(temp_v!(3)),
+ goto!(83, 3),
retry_me_else!(4),
fact![get_constant!(Constant::from("!"), temp_v!(1)),
get_constant!(Constant::from("!"), temp_v!(2))],
- query![put_value!(temp_v!(3), 1)],
- set_cp!(),
+ set_neck_cut!(temp_v!(3)),
+ proceed!(),
trust_me!(),
- allocate!(1),
- fact![get_constant!(Constant::from("!"), temp_v!(1)),
- get_var_in_fact!(perm_v!(1), 2)],
- query![put_value!(temp_v!(3), 1)],
- set_cp!(),
- query![put_value!(perm_v!(1), 1)],
- deallocate!(),
+ fact![get_constant!(Constant::from("!"), temp_v!(1))],
+ set_neck_cut!(temp_v!(3)),
+ query![put_value!(temp_v!(2), 1)],
execute_n!(1),
retry_me_else!(8),
- allocate!(1),
- fact![get_constant!(Constant::from("!"), temp_v!(2)),
- get_var_in_fact!(perm_v!(1), 3)],
- neck_cut!(non_terminal!()),
- call_n!(1),
- query![put_value!(perm_v!(1), 1)],
- deallocate!(),
- set_cp!(),
- retry_me_else!(8), // 121.
- allocate!(3),
+ allocate!(2),
fact![get_structure!(String::from(","), 2, temp_v!(2)),
unify_variable!(perm_v!(2)),
- unify_variable!(perm_v!(1)),
- get_var_in_fact!(perm_v!(3), 3)],
- neck_cut!(non_terminal!()),
+ unify_variable!(perm_v!(1))],
+ neck_cut!(),
call_n!(1),
query![put_unsafe_value!(2, 1),
- put_unsafe_value!(1, 2),
- put_value!(perm_v!(3), 3)],
+ put_unsafe_value!(1, 2)],
deallocate!(),
- goto!(88, 3),
+ goto!(83, 3),
+ retry_me_else!(9),
+ allocate!(1),
+ get_level!(),
+ fact![get_constant!(Constant::from("!"), temp_v!(2))],
+ neck_cut!(),
+ call_n!(1),
+ set_non_neck_cut!(temp_v!(3)),
+ deallocate!(),
+ proceed!(),
trust_me!(),
allocate!(1),
- fact![get_var_in_fact!(perm_v!(1), 2)],
+ fact![get_var_in_fact!(perm_v!(1), 2)],
call_n!(1),
query![put_value!(perm_v!(1), 1)],
deallocate!(),
execute_n!(1),
- allocate!(2), // (->)/2, 136.
+ allocate!(2), // (->)/2, 124.
get_level!(),
fact![get_var_in_fact!(perm_v!(2), 2)],
call_n!(1),
- cut!(non_terminal!()),
+ cut!(),
query![put_value!(perm_v!(2), 1)],
deallocate!(),
execute_n!(1)
// control operators.
op_dir.insert((String::from(";"), Fixity::In), (XFY, 1100));
op_dir.insert((String::from("->"), Fixity::In), (XFY, 1050));
-
+
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
// (an extra register is needed for the predicate name)
for arity in 0 .. 63 {
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59));
code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73));
- code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75));
+ code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75));
code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 76));
- code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81));
- code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 136));
-
+ code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 81));
+ code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 124));
+
(builtin_code, code_dir, op_dir)
}
if !target.is_empty() {
code.push(Line::Query(target));
}
-
+
vr.get().norm()
}
}
}
-
+
fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
}
- fn add_conditional_call_inlined(_: &InlinedQueryTerm, code: &mut Code)
- {
- code.push(proceed!());
- }
-
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
{
match qt {
},
&QueryTerm::Catch(_) =>
code.push(Line::Control(ControlInstruction::CatchCall)),
- &QueryTerm::Inlined(ref term) =>
- Self::add_conditional_call_inlined(term, code),
+ &QueryTerm::Inlined(_) =>
+ code.push(proceed!()),
&QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
code.push(Line::Control(call));
{
let mut dealloc_index = code.len() - 1;
- if let Some(&mut Line::Control(ref mut ctrl)) = code.last_mut() {
- let mut instr = ControlInstruction::Proceed;
- swap(ctrl, &mut instr);
-
- match instr {
- ControlInstruction::Call(name, arity, _) =>
- *ctrl = ControlInstruction::Execute(name, arity),
- ControlInstruction::CallN(arity) =>
- *ctrl = ControlInstruction::ExecuteN(arity),
- ControlInstruction::CatchCall =>
- *ctrl = ControlInstruction::CatchExecute,
- ControlInstruction::ThrowCall =>
- *ctrl = ControlInstruction::ThrowExecute,
- ControlInstruction::IsCall(r, at) =>
- *ctrl = ControlInstruction::IsExecute(r, at),
- ControlInstruction::Proceed => {},
- _ => dealloc_index += 1 // = code.len()
- }
- }
+ match code.last_mut() {
+ Some(&mut Line::Control(ref mut ctrl)) => {
+ let mut instr = ControlInstruction::Proceed;
+ swap(ctrl, &mut instr);
+
+ match instr {
+ ControlInstruction::Call(name, arity, _) =>
+ *ctrl = ControlInstruction::Execute(name, arity),
+ ControlInstruction::CallN(arity) =>
+ *ctrl = ControlInstruction::ExecuteN(arity),
+ ControlInstruction::CatchCall =>
+ *ctrl = ControlInstruction::CatchExecute,
+ ControlInstruction::ThrowCall =>
+ *ctrl = ControlInstruction::ThrowExecute,
+ ControlInstruction::IsCall(r, at) =>
+ *ctrl = ControlInstruction::IsExecute(r, at),
+ ControlInstruction::Proceed => {},
+ _ => dealloc_index += 1 // = code.len()
+ }
+ },
+ Some(&mut Line::Cut(CutInstruction::Cut)) =>
+ dealloc_index += 1,
+ _ => {}
+ };
dealloc_index
}
let r = self.mark_non_callable(name, 1, term_loc, vr, code);
code.push(is_var!(r));
}
- }
+ }
}
Ok(())
match *term {
&QueryTerm::Cut => {
- let is_terminal = if i + 1 < terms.len() {
- Terminal::Non
- } else {
- Terminal::Terminal
- };
-
code.push(if chunk_num == 0 {
- Line::Cut(CutInstruction::NeckCut(is_terminal))
+ Line::Cut(CutInstruction::NeckCut)
} else {
- Line::Cut(CutInstruction::Cut(is_terminal))
+ Line::Cut(CutInstruction::Cut)
});
},
&QueryTerm::Is(ref terms) => {
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode);
-
+
match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name,
term_loc,
vr,
code);
-
+
code.push(is_call!(r, at.unwrap_or(interm!(1))));
},
&Term::Constant(_, Constant::Float(fl)) => {
if !query.is_empty() {
code.push(Line::Query(query));
}
-
+
Self::add_conditional_call(code, term, conjunct_info.perm_vars());
},
_ => {
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
{
match toc {
- &QueryTerm::Inlined(ref term) =>
- Self::add_conditional_call_inlined(term, code),
+ &QueryTerm::Inlined(_) | &QueryTerm::Cut =>
+ code.push(proceed!()),
_ => {}
};
}
}
-impl fmt::Display for Terminal {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &Terminal::Terminal =>
- write!(f, "terminal"),
- &Terminal::Non =>
- write!(f, "non_terminal")
- }
- }
-}
-
impl fmt::Display for BuiltInInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
write!(f, "get_ball X1"),
&BuiltInInstruction::GetCurrentBlock =>
write!(f, "get_current_block X1"),
- &BuiltInInstruction::GetCutPoint =>
- write!(f, "get_cp"),
+ &BuiltInInstruction::GetCutPoint(r) =>
+ write!(f, "get_cp {}", r),
&BuiltInInstruction::InstallNewBlock =>
write!(f, "install_new_block"),
&BuiltInInstruction::InternalCallN =>
write!(f, "reset_block"),
&BuiltInInstruction::SetBall =>
write!(f, "set_ball"),
- &BuiltInInstruction::SetCutPoint =>
- write!(f, "set_cp"),
+ &BuiltInInstruction::SetNeckCutPoint(r) =>
+ write!(f, "set_neck_cp {}", r),
+ &BuiltInInstruction::SetNonNeckCutPoint(r) =>
+ write!(f, "set_non_neck_cp {}", r),
&BuiltInInstruction::Succeed =>
write!(f, "true"),
&BuiltInInstruction::UnwindStack =>
impl fmt::Display for CutInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &CutInstruction::Cut(_) =>
+ &CutInstruction::Cut =>
write!(f, "cut"),
- &CutInstruction::NeckCut(_) =>
+ &CutInstruction::NeckCut =>
write!(f, "neck_cut"),
&CutInstruction::GetLevel =>
write!(f, "get_level")
Err(e) => return EvalSession::ParserError(e)
};
+ print_code(&compiled_pred);
wam.add_predicate(clauses, compiled_pred)
},
&TopLevel::Fact(ref fact) => {
self.write_constant_to_var(addr, &c);
self.p += 1;
},
- &BuiltInInstruction::GetCutPoint => {
- let c = Constant::Usize(self.b);
- let addr = self[temp_v!(1)].clone();
-
- self.write_constant_to_var(addr, &c);
- self.p += 1;
- },
&BuiltInInstruction::EraseBall => {
self.ball.0 = 0;
self.ball.1.truncate(0);
_ => self.fail = true
};
},
+ &BuiltInInstruction::GetCutPoint(r) => {
+ let c = Constant::Usize(self.b);
+ self[r] = Addr::Con(c);
+
+ self.p += 1;
+ },
&BuiltInInstruction::SetBall => {
let addr = self[temp_v!(1)].clone();
self.ball.0 = self.heap.h;
self.p += 1;
},
- &BuiltInInstruction::SetCutPoint => {
- let nb = self.store(self.deref(self[temp_v!(1)].clone()));
+ &BuiltInInstruction::SetNeckCutPoint(r) => {
+ let addr = self.store(self.deref(self[r].clone()));
- match nb {
+ match addr {
Addr::Con(Constant::Usize(nb)) => {
- self.or_stack.truncate(nb);
self.b = nb;
-
- self.tidy_trail();
+ self.neck_cut();
+ },
+ _ => self.fail = true
+ };
+ },
+ &BuiltInInstruction::SetNonNeckCutPoint(r) => {
+ let addr = self.store(self.deref(self[r].clone()));
- self.p += 1;
+ match addr {
+ Addr::Con(Constant::Usize(nb)) => {
+ self.b = nb;
+ self.non_neck_cut();
},
_ => self.fail = true
};
}
}
- fn neck_cut(&mut self, term: Terminal)
+ fn neck_cut(&mut self)
{
let b = self.b;
let b0 = self.b0;
self.tidy_trail();
}
- if let Terminal::Terminal = term {
- self.p = self.cp;
- } else {
- self.p += 1;
- }
+ self.p += 1;
}
- fn non_neck_cut(&mut self, term: Terminal)
+ fn non_neck_cut(&mut self)
{
let b = self.b;
let e = self.e;
self.tidy_trail();
}
- if let Terminal::Terminal = term {
- self.p = self.cp;
- } else {
- self.p += 1;
- }
+ self.p += 1;
}
fn execute_cut_instr(&mut self, instr: &CutInstruction) {
match instr {
- &CutInstruction::Cut(term) =>
- self.non_neck_cut(term),
+ &CutInstruction::Cut =>
+ self.non_neck_cut(),
&CutInstruction::GetLevel => {
let b0 = self.b0;
let e = self.e;
self.and_stack[e].b0 = b0;
self.p += 1;
},
- &CutInstruction::NeckCut(term) =>
- self.neck_cut(term)
+ &CutInstruction::NeckCut =>
+ self.neck_cut()
}
}
)
}
-macro_rules! non_terminal {
- () => (
- Terminal::Non
- )
-}
-
macro_rules! cut {
- ($term:expr) => (
- Line::Cut(CutInstruction::Cut($term))
+ () => (
+ Line::Cut(CutInstruction::Cut)
)
}
macro_rules! neck_cut {
- ($term:expr) => (
- Line::Cut(CutInstruction::NeckCut($term))
+ () => (
+ Line::Cut(CutInstruction::NeckCut)
)
}
)
}
-macro_rules! get_cp {
- () => (
- Line::BuiltIn(BuiltInInstruction::GetCutPoint)
- )
-}
-
-macro_rules! set_cp {
- () => (
- Line::BuiltIn(BuiltInInstruction::SetCutPoint)
- )
-}
-
macro_rules! get_constant {
($c:expr, $r:expr) => (
FactInstruction::GetConstant(Level::Shallow, $c, $r)
FactInstruction::UnifyVariable($r)
)
}
+
+macro_rules! set_neck_cut {
+ ($r:expr) => (
+ Line::BuiltIn(BuiltInInstruction::SetNeckCutPoint($r))
+ )
+}
+
+macro_rules! set_non_neck_cut {
+ ($r:expr) => (
+ Line::BuiltIn(BuiltInInstruction::SetNonNeckCutPoint($r))
+ )
+}
+
+macro_rules! get_cp {
+ ($r:expr) => (
+ Line::BuiltIn(BuiltInInstruction::GetCutPoint($r))
+ )
+}
+
+