adjust for nested throws.
This commit is contained in:
@@ -698,10 +698,10 @@ mod tests {
|
|||||||
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(y))."), true);
|
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(y))."), true);
|
||||||
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(z))."), false);
|
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(z))."), false);
|
||||||
|
|
||||||
submit(&mut wam, "f(X) :- throw(stuff). f(X) :- throw(other_stuff).");
|
submit(&mut wam, "f(X) :- throw(stuff).");
|
||||||
submit(&mut wam, "handle(stuff). handle(other_stuff).");
|
submit(&mut wam, "handle(stuff). handle(other_stuff).");
|
||||||
|
|
||||||
// this should deterministically succeed with Exception = stuff.
|
// the first 3 cases should deterministically succeed.
|
||||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
|
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
|
||||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(stuff))."), true);
|
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(stuff))."), true);
|
||||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(other_stuff))."), true);
|
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(other_stuff))."), true);
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ impl Default for VarReg {
|
|||||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
UInt64(usize),
|
BlockNum(usize),
|
||||||
EmptyList
|
EmptyList
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +292,8 @@ impl IndexedChoiceInstruction {
|
|||||||
|
|
||||||
pub enum BuiltInInstruction {
|
pub enum BuiltInInstruction {
|
||||||
CleanUpBlock,
|
CleanUpBlock,
|
||||||
CopyTerm,
|
DuplicateTerm,
|
||||||
|
EraseBall,
|
||||||
Fail,
|
Fail,
|
||||||
GetBall,
|
GetBall,
|
||||||
GetCurrentBlock,
|
GetCurrentBlock,
|
||||||
@@ -311,23 +312,27 @@ pub enum ControlInstruction {
|
|||||||
Allocate(usize),
|
Allocate(usize),
|
||||||
Call(Atom, usize, usize),
|
Call(Atom, usize, usize),
|
||||||
CallN(usize),
|
CallN(usize),
|
||||||
Catch,
|
CatchCall,
|
||||||
|
CatchExecute,
|
||||||
Deallocate,
|
Deallocate,
|
||||||
Execute(Atom, usize),
|
Execute(Atom, usize),
|
||||||
ExecuteN(usize),
|
ExecuteN(usize),
|
||||||
Proceed,
|
Proceed,
|
||||||
Throw
|
ThrowCall,
|
||||||
|
ThrowExecute
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControlInstruction {
|
impl ControlInstruction {
|
||||||
pub fn is_jump_instr(&self) -> bool {
|
pub fn is_jump_instr(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
&ControlInstruction::Call(_, _, _) => true,
|
&ControlInstruction::Call(_, _, _) => true,
|
||||||
&ControlInstruction::Catch => true,
|
&ControlInstruction::CatchCall => true,
|
||||||
|
&ControlInstruction::CatchExecute => true,
|
||||||
&ControlInstruction::Execute(_, _) => true,
|
&ControlInstruction::Execute(_, _) => true,
|
||||||
&ControlInstruction::CallN(_) => true,
|
&ControlInstruction::CallN(_) => true,
|
||||||
&ControlInstruction::ExecuteN(_) => true,
|
&ControlInstruction::ExecuteN(_) => true,
|
||||||
&ControlInstruction::Throw => true,
|
&ControlInstruction::ThrowCall => true,
|
||||||
|
&ControlInstruction::ThrowExecute => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,87 +19,84 @@ fn get_builtins() -> Code {
|
|||||||
is_var!(), // var/1, 3.
|
is_var!(), // var/1, 3.
|
||||||
proceed!(),
|
proceed!(),
|
||||||
allocate!(4), // catch/3, 5.
|
allocate!(4), // catch/3, 5.
|
||||||
query![get_var_in_query!(perm_v!(2), 1),
|
fact![get_var_in_fact!(perm_v!(2), 1),
|
||||||
get_var_in_query!(perm_v!(3), 2),
|
get_var_in_fact!(perm_v!(3), 2),
|
||||||
get_var_in_query!(perm_v!(1), 3),
|
get_var_in_fact!(perm_v!(1), 3)],
|
||||||
put_var!(perm_v!(4), 1)],
|
query![put_var!(perm_v!(4), 1)],
|
||||||
get_current_block!(),
|
get_current_block!(),
|
||||||
query![put_value!(perm_v!(2), 1),
|
query![put_value!(perm_v!(2), 1),
|
||||||
put_value!(perm_v!(3), 2),
|
put_value!(perm_v!(3), 2),
|
||||||
put_value!(perm_v!(1), 3),
|
put_value!(perm_v!(1), 3),
|
||||||
put_unsafe_value!(4, 4)],
|
put_unsafe_value!(4, 4)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto!(11, 4),
|
goto!(12, 4), // goto catch/4.
|
||||||
try_me_else!(9), // catch/4, 11.
|
try_me_else!(10), // catch/4, 12.
|
||||||
allocate!(3),
|
allocate!(3),
|
||||||
query![get_var_in_query!(perm_v!(3), 1),
|
fact![get_var_in_fact!(perm_v!(3), 1),
|
||||||
get_var_in_query!(perm_v!(2), 4),
|
get_var_in_fact!(perm_v!(2), 4)],
|
||||||
put_var!(perm_v!(1), 1)],
|
query![put_var!(perm_v!(1), 1)],
|
||||||
install_new_block!(),
|
install_new_block!(),
|
||||||
query![put_value!(perm_v!(3), 1)],
|
query![put_value!(perm_v!(3), 1)],
|
||||||
call_n!(1),
|
call_n!(1),
|
||||||
query![put_value!(perm_v!(2), 1),
|
query![put_value!(perm_v!(2), 1),
|
||||||
put_unsafe_value!(1, 2)],
|
put_unsafe_value!(1, 2)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto!(42, 2), // goto end_block/2 at 42.
|
goto!(44, 2), //21: goto end_block/2.
|
||||||
trust_me!(),
|
trust_me!(),
|
||||||
allocate!(4),
|
allocate!(3),
|
||||||
query![get_var_in_query!(perm_v!(2), 2),
|
fact![get_var_in_fact!(perm_v!(2), 2),
|
||||||
get_var_in_query!(perm_v!(1), 3),
|
get_var_in_fact!(perm_v!(1), 3)],
|
||||||
get_var_in_query!(temp_v!(2), 1),
|
query![get_var_in_query!(temp_v!(2), 1),
|
||||||
put_value!(temp_v!(4), 1)],
|
put_value!(temp_v!(4), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
query![put_var!(perm_v!(4), 1)],
|
query![put_var!(perm_v!(3), 1)],
|
||||||
get_ball!(),
|
get_ball!(),
|
||||||
query![put_value!(perm_v!(4), 1),
|
|
||||||
put_var!(perm_v!(3), 2)],
|
|
||||||
copy_term!(),
|
|
||||||
query![put_unsafe_value!(3, 1),
|
query![put_unsafe_value!(3, 1),
|
||||||
put_value!(perm_v!(2), 2),
|
put_value!(perm_v!(2), 2),
|
||||||
put_value!(perm_v!(1), 3)],
|
put_value!(perm_v!(1), 3)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto!(31, 2), // goto handle_ball/2.
|
goto!(32, 2), // goto handle_ball/2.
|
||||||
try_me_else!(10), // handle_ball/2, 31.
|
try_me_else!(10), // handle_ball/2, 32.
|
||||||
allocate!(2),
|
allocate!(2),
|
||||||
get_level!(),
|
get_level!(),
|
||||||
query![get_var_in_query!(perm_v!(2), 3)],
|
fact![get_var_in_fact!(perm_v!(2), 3)],
|
||||||
unify!(),
|
unify!(),
|
||||||
cut!(non_terminal!()),
|
cut!(non_terminal!()),
|
||||||
|
erase_ball!(),
|
||||||
query![put_value!(perm_v!(2), 1)],
|
query![put_value!(perm_v!(2), 1)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
execute_n!(1),
|
execute_n!(1),
|
||||||
trust_me!(),
|
trust_me!(),
|
||||||
unwind_stack!(),
|
unwind_stack!(),
|
||||||
try_me_else!(8), // end_block/2, 42.
|
try_me_else!(9), // end_block/2, 44.
|
||||||
allocate!(1),
|
allocate!(1),
|
||||||
query![get_var_in_query!(perm_v!(1), 1),
|
fact![get_var_in_fact!(perm_v!(1), 1)],
|
||||||
put_value!(temp_v!(2), 1)],
|
query![put_value!(temp_v!(2), 1)],
|
||||||
clean_up_block!(),
|
clean_up_block!(),
|
||||||
query![put_value!(perm_v!(1), 1)],
|
query![put_value!(perm_v!(1), 1)],
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
trust_me!(),
|
trust_me!(), // 53.
|
||||||
allocate!(0),
|
allocate!(0),
|
||||||
query![get_var_in_query!(temp_v!(3), 1),
|
query![get_var_in_query!(temp_v!(3), 1),
|
||||||
put_value!(temp_v!(2), 1)],
|
put_value!(temp_v!(2), 1)],
|
||||||
reset_block!(),
|
reset_block!(),
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto!(58, 0), // goto false.
|
goto!(61, 0),
|
||||||
set_ball!(), // throw/1, 56.
|
set_ball!(), // throw/1, 59.
|
||||||
unwind_stack!(),
|
unwind_stack!(),
|
||||||
fail!(), // false/0, 58.
|
fail!(), // false/0, 61.
|
||||||
proceed!(),
|
try_me_else!(7), // not/1, 62.
|
||||||
try_me_else!(7), // not/1, 60.
|
|
||||||
allocate!(1),
|
allocate!(1),
|
||||||
get_level!(),
|
get_level!(),
|
||||||
call_n!(1),
|
call_n!(1),
|
||||||
cut!(non_terminal!()),
|
cut!(non_terminal!()),
|
||||||
deallocate!(),
|
deallocate!(),
|
||||||
goto!(58, 0), // goto false.
|
goto!(61, 0),
|
||||||
trust_me!(),
|
trust_me!(),
|
||||||
proceed!(),
|
proceed!(),
|
||||||
copy_term!(), // copy_term/2, 69.
|
duplicate_term!(), // duplicate_term/2, 71.
|
||||||
proceed!()]
|
proceed!()]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +112,11 @@ pub fn build_code_dir() -> (Code, CodeDir) {
|
|||||||
|
|
||||||
code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
||||||
code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
||||||
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 58));
|
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 61));
|
||||||
code_dir.insert((String::from("not"), 1), (PredicateKeyType::BuiltIn, 60));
|
code_dir.insert((String::from("not"), 1), (PredicateKeyType::BuiltIn, 62));
|
||||||
code_dir.insert((String::from("copy_term"), 2), (PredicateKeyType::BuiltIn, 69));
|
code_dir.insert((String::from("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
|
||||||
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
||||||
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 56));
|
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59));
|
||||||
|
|
||||||
(builtin_code, code_dir)
|
(builtin_code, code_dir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
compiled_query.push(Line::Control(call));
|
compiled_query.push(Line::Control(call));
|
||||||
},
|
},
|
||||||
QueryTermRef::Catch(_) =>
|
QueryTermRef::Catch(_) =>
|
||||||
compiled_query.push(Line::Control(ControlInstruction::Catch)),
|
compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
|
||||||
QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
|
QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
|
||||||
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
|
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
|
||||||
compiled_query.push(Line::Control(call));
|
compiled_query.push(Line::Control(call));
|
||||||
@@ -222,7 +222,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
compiled_query.push(Line::Control(call));
|
compiled_query.push(Line::Control(call));
|
||||||
},
|
},
|
||||||
QueryTermRef::Throw(_) =>
|
QueryTermRef::Throw(_) =>
|
||||||
compiled_query.push(Line::Control(ControlInstruction::Throw)),
|
compiled_query.push(Line::Control(ControlInstruction::ThrowCall)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,6 +242,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
|
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
|
||||||
*ctrl = ControlInstruction::ExecuteN(terms.len());
|
*ctrl = ControlInstruction::ExecuteN(terms.len());
|
||||||
},
|
},
|
||||||
|
QueryTermRef::Catch(_) =>
|
||||||
|
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
|
||||||
|
*ctrl = ControlInstruction::CatchExecute;
|
||||||
|
},
|
||||||
|
QueryTermRef::Throw(_) =>
|
||||||
|
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
|
||||||
|
*ctrl = ControlInstruction::ThrowExecute;
|
||||||
|
},
|
||||||
_ => dealloc_index = body.len()
|
_ => dealloc_index = body.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
102
src/prolog/copier.rs
Normal file
102
src/prolog/copier.rs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
use prolog::and_stack::*;
|
||||||
|
use prolog::ast::*;
|
||||||
|
|
||||||
|
use std::ops::IndexMut;
|
||||||
|
|
||||||
|
pub trait CopierTarget
|
||||||
|
{
|
||||||
|
fn source(&self) -> usize;
|
||||||
|
fn threshold(&self) -> usize;
|
||||||
|
fn push(&mut self, HeapCellValue);
|
||||||
|
fn store(&self, Addr) -> Addr;
|
||||||
|
fn deref(&self, Addr) -> Addr;
|
||||||
|
fn stack(&mut self) -> &mut AndStack;
|
||||||
|
|
||||||
|
// duplicate_term(L1, L2) uses Cheney's algorithm to copy the term at
|
||||||
|
// L1 to L2. forwarding_terms is kept to restore the innards of L1
|
||||||
|
// after it's been copied to L2.
|
||||||
|
fn duplicate_term(&mut self, a: Addr) where Self: IndexMut<usize, Output=HeapCellValue>
|
||||||
|
{
|
||||||
|
let mut forward_trail: Vec<(Ref, HeapCellValue)>= Vec::new();
|
||||||
|
let mut scan = self.source();
|
||||||
|
let old_h = self.threshold();
|
||||||
|
|
||||||
|
self.push(HeapCellValue::from(a));
|
||||||
|
|
||||||
|
while scan < self.threshold() {
|
||||||
|
match self[scan].clone() {
|
||||||
|
HeapCellValue::Con(_) | HeapCellValue::NamedStr(_, _) =>
|
||||||
|
scan += 1,
|
||||||
|
HeapCellValue::Lis(a) => {
|
||||||
|
self[scan] = HeapCellValue::Lis(self.threshold());
|
||||||
|
|
||||||
|
let hcv = self[a].clone();
|
||||||
|
self.push(hcv);
|
||||||
|
|
||||||
|
let hcv = self[a+1].clone();
|
||||||
|
self.push(hcv);
|
||||||
|
|
||||||
|
scan += 1;
|
||||||
|
},
|
||||||
|
HeapCellValue::Ref(r) => {
|
||||||
|
let ra = Addr::from(r);
|
||||||
|
let rd = self.store(self.deref(ra.clone()));
|
||||||
|
|
||||||
|
match rd {
|
||||||
|
Addr::HeapCell(hc) if hc >= old_h => {
|
||||||
|
self[scan] = HeapCellValue::Ref(Ref::HeapCell(hc));
|
||||||
|
scan += 1;
|
||||||
|
},
|
||||||
|
_ if ra == rd => {
|
||||||
|
self[scan] = HeapCellValue::Ref(Ref::HeapCell(scan));
|
||||||
|
|
||||||
|
match r {
|
||||||
|
Ref::HeapCell(hc) =>
|
||||||
|
self[hc] = HeapCellValue::Ref(Ref::HeapCell(scan)),
|
||||||
|
Ref::StackCell(fr, sc) =>
|
||||||
|
self.stack()[fr][sc] = Addr::HeapCell(scan)
|
||||||
|
};
|
||||||
|
|
||||||
|
forward_trail.push((r, HeapCellValue::Ref(r)));
|
||||||
|
scan += 1;
|
||||||
|
},
|
||||||
|
_ => self[scan] = HeapCellValue::from(rd)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
HeapCellValue::Str(s) => {
|
||||||
|
match self[s].clone() {
|
||||||
|
HeapCellValue::NamedStr(arity, name) => {
|
||||||
|
let threshold = self.threshold();
|
||||||
|
|
||||||
|
self[scan] = HeapCellValue::Str(threshold);
|
||||||
|
self[s] = HeapCellValue::Str(threshold);
|
||||||
|
|
||||||
|
forward_trail.push((Ref::HeapCell(s),
|
||||||
|
HeapCellValue::NamedStr(arity, name.clone())));
|
||||||
|
|
||||||
|
self.push(HeapCellValue::NamedStr(arity, name));
|
||||||
|
|
||||||
|
for i in 0 .. arity {
|
||||||
|
let hcv = self[s + 1 + i].clone();
|
||||||
|
self.push(hcv);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
HeapCellValue::Str(o) =>
|
||||||
|
self[scan] = HeapCellValue::Str(o),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
scan += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r, hcv) in forward_trail {
|
||||||
|
match r {
|
||||||
|
Ref::HeapCell(hc) => self[hc] = hcv,
|
||||||
|
Ref::StackCell(fr, sc) => self.stack()[fr][sc] = hcv.as_addr(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ impl fmt::Display for Constant {
|
|||||||
write!(f, "{}", atom),
|
write!(f, "{}", atom),
|
||||||
&Constant::EmptyList =>
|
&Constant::EmptyList =>
|
||||||
write!(f, "[]"),
|
write!(f, "[]"),
|
||||||
&Constant::UInt64(integer) =>
|
&Constant::BlockNum(integer) =>
|
||||||
write!(f, "u{}", integer)
|
write!(f, "u{}", integer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ impl fmt::Display for FactInstruction {
|
|||||||
&FactInstruction::GetValue(ref x, ref a) =>
|
&FactInstruction::GetValue(ref x, ref a) =>
|
||||||
write!(f, "get_value {}, A{}", x, a),
|
write!(f, "get_value {}, A{}", x, a),
|
||||||
&FactInstruction::GetVariable(ref x, ref a) =>
|
&FactInstruction::GetVariable(ref x, ref a) =>
|
||||||
write!(f, "get_variable {}, A{}", x, a),
|
write!(f, "fact:get_variable {}, A{}", x, a),
|
||||||
&FactInstruction::UnifyConstant(ref constant) =>
|
&FactInstruction::UnifyConstant(ref constant) =>
|
||||||
write!(f, "unify_constant {}", constant),
|
write!(f, "unify_constant {}", constant),
|
||||||
&FactInstruction::UnifyVariable(ref r) =>
|
&FactInstruction::UnifyVariable(ref r) =>
|
||||||
@@ -62,7 +62,7 @@ impl fmt::Display for QueryInstruction {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&QueryInstruction::GetVariable(ref x, ref a) =>
|
&QueryInstruction::GetVariable(ref x, ref a) =>
|
||||||
write!(f, "get_variable {}, A{}", x, a),
|
write!(f, "query:get_variable {}, A{}", x, a),
|
||||||
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
|
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
|
||||||
write!(f, "put_constant {}, A{}", constant, r.reg_num()),
|
write!(f, "put_constant {}, A{}", constant, r.reg_num()),
|
||||||
&QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
|
&QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
|
||||||
@@ -104,8 +104,10 @@ impl fmt::Display for ControlInstruction {
|
|||||||
write!(f, "call {}/{}, {}", name, arity, pvs),
|
write!(f, "call {}/{}, {}", name, arity, pvs),
|
||||||
&ControlInstruction::CallN(arity) =>
|
&ControlInstruction::CallN(arity) =>
|
||||||
write!(f, "call_N {}", arity),
|
write!(f, "call_N {}", arity),
|
||||||
&ControlInstruction::Catch =>
|
&ControlInstruction::CatchCall =>
|
||||||
write!(f, "catch"),
|
write!(f, "call_catch"),
|
||||||
|
&ControlInstruction::CatchExecute =>
|
||||||
|
write!(f, "execute_catch"),
|
||||||
&ControlInstruction::ExecuteN(arity) =>
|
&ControlInstruction::ExecuteN(arity) =>
|
||||||
write!(f, "execute_N {}", arity),
|
write!(f, "execute_N {}", arity),
|
||||||
&ControlInstruction::Deallocate =>
|
&ControlInstruction::Deallocate =>
|
||||||
@@ -114,8 +116,10 @@ impl fmt::Display for ControlInstruction {
|
|||||||
write!(f, "execute {}/{}", name, arity),
|
write!(f, "execute {}/{}", name, arity),
|
||||||
&ControlInstruction::Proceed =>
|
&ControlInstruction::Proceed =>
|
||||||
write!(f, "proceed"),
|
write!(f, "proceed"),
|
||||||
&ControlInstruction::Throw =>
|
&ControlInstruction::ThrowCall =>
|
||||||
write!(f, "throw")
|
write!(f, "call_throw"),
|
||||||
|
&ControlInstruction::ThrowExecute =>
|
||||||
|
write!(f, "execute_throw")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,6 +372,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
|
|||||||
|
|
||||||
if is_consistent(clauses) {
|
if is_consistent(clauses) {
|
||||||
let compiled_pred = cg.compile_predicate(clauses);
|
let compiled_pred = cg.compile_predicate(clauses);
|
||||||
|
print_code(&compiled_pred);
|
||||||
wam.add_predicate(clauses, compiled_pred)
|
wam.add_predicate(clauses, compiled_pred)
|
||||||
} else {
|
} else {
|
||||||
let msg = r"Error: predicate is inconsistent.
|
let msg = r"Error: predicate is inconsistent.
|
||||||
@@ -386,12 +391,14 @@ Each predicate must have the same name and arity.";
|
|||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||||
|
|
||||||
let compiled_rule = cg.compile_rule(rule);
|
let compiled_rule = cg.compile_rule(rule);
|
||||||
|
print_code(&compiled_rule);
|
||||||
wam.add_rule(rule, compiled_rule)
|
wam.add_rule(rule, compiled_rule)
|
||||||
},
|
},
|
||||||
&TopLevel::Query(ref query) => {
|
&TopLevel::Query(ref query) => {
|
||||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||||
|
|
||||||
let compiled_query = cg.compile_query(query);
|
let compiled_query = cg.compile_query(query);
|
||||||
|
print_code(&compiled_query);
|
||||||
wam.submit_query(compiled_query, cg.take_vars())
|
wam.submit_query(compiled_query, cg.take_vars())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
use prolog::builtins::*;
|
use prolog::builtins::*;
|
||||||
use prolog::codegen::*;
|
use prolog::codegen::*;
|
||||||
|
use prolog::copier::*;
|
||||||
use prolog::heapview::*;
|
use prolog::heapview::*;
|
||||||
use prolog::and_stack::*;
|
use prolog::and_stack::*;
|
||||||
use prolog::or_stack::*;
|
use prolog::or_stack::*;
|
||||||
@@ -35,7 +36,122 @@ struct MachineState {
|
|||||||
tr: usize,
|
tr: usize,
|
||||||
hb: usize,
|
hb: usize,
|
||||||
block: usize, // an offset into the OR stack.
|
block: usize, // an offset into the OR stack.
|
||||||
ball: Addr
|
ball: Heap
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DuplicateTerm<'a> {
|
||||||
|
state: &'a mut MachineState
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DuplicateTerm<'a> {
|
||||||
|
fn new(state: &'a mut MachineState) -> Self {
|
||||||
|
DuplicateTerm { state: state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Index<usize> for DuplicateTerm<'a> {
|
||||||
|
type Output = HeapCellValue;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.state.heap[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IndexMut<usize> for DuplicateTerm<'a> {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
&mut self.state.heap[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the ordinary, heap term copier, used by duplicate_term.
|
||||||
|
impl<'a> CopierTarget for DuplicateTerm<'a> {
|
||||||
|
fn source(&self) -> usize {
|
||||||
|
self.state.h
|
||||||
|
}
|
||||||
|
|
||||||
|
fn threshold(&self) -> usize {
|
||||||
|
self.state.h
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, hcv: HeapCellValue) {
|
||||||
|
self.state.heap.push(hcv);
|
||||||
|
self.state.h += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(&self, a: Addr) -> Addr {
|
||||||
|
self.state.store(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref(&self, a: Addr) -> Addr {
|
||||||
|
self.state.deref(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack(&mut self) -> &mut AndStack {
|
||||||
|
&mut self.state.and_stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DuplicateBallTerm<'a> {
|
||||||
|
state: &'a mut MachineState,
|
||||||
|
heap_boundary: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DuplicateBallTerm<'a> {
|
||||||
|
fn new(state: &'a mut MachineState) -> Self {
|
||||||
|
let hb = state.heap.len();
|
||||||
|
DuplicateBallTerm { state: state, heap_boundary: hb }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Index<usize> for DuplicateBallTerm<'a> {
|
||||||
|
type Output = HeapCellValue;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
if index < self.heap_boundary {
|
||||||
|
&self.state.heap[index]
|
||||||
|
} else {
|
||||||
|
let index = index - self.heap_boundary;
|
||||||
|
&self.state.ball[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IndexMut<usize> for DuplicateBallTerm<'a> {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
if index < self.heap_boundary {
|
||||||
|
&mut self.state.heap[index]
|
||||||
|
} else {
|
||||||
|
let index = index - self.heap_boundary;
|
||||||
|
&mut self.state.ball[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the ordinary, heap term copier, used by duplicate_term.
|
||||||
|
impl<'a> CopierTarget for DuplicateBallTerm<'a> {
|
||||||
|
fn source(&self) -> usize {
|
||||||
|
self.heap_boundary
|
||||||
|
}
|
||||||
|
|
||||||
|
fn threshold(&self) -> usize {
|
||||||
|
self.heap_boundary + self.state.ball.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, hcv: HeapCellValue) {
|
||||||
|
self.state.ball.push(hcv);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(&self, a: Addr) -> Addr {
|
||||||
|
self.state.store(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deref(&self, a: Addr) -> Addr {
|
||||||
|
self.state.deref(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack(&mut self) -> &mut AndStack {
|
||||||
|
&mut self.state.and_stack
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Machine {
|
pub struct Machine {
|
||||||
@@ -368,7 +484,7 @@ impl Machine {
|
|||||||
|
|
||||||
while let Some(view) = viewer.next() {
|
while let Some(view) = viewer.next() {
|
||||||
match view {
|
match view {
|
||||||
CellView::Con(&Constant::UInt64(integer)) =>
|
CellView::Con(&Constant::BlockNum(integer)) =>
|
||||||
result += integer.to_string().as_str(),
|
result += integer.to_string().as_str(),
|
||||||
CellView::Con(&Constant::EmptyList) =>
|
CellView::Con(&Constant::EmptyList) =>
|
||||||
result += "[]",
|
result += "[]",
|
||||||
@@ -442,10 +558,10 @@ impl MachineState {
|
|||||||
tr: 0,
|
tr: 0,
|
||||||
hb: 0,
|
hb: 0,
|
||||||
block: 0,
|
block: 0,
|
||||||
ball: Addr::Con(Constant::UInt64(0))
|
ball: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_frames(&self) -> usize {
|
fn num_frames(&self) -> usize {
|
||||||
self.and_stack.len() + self.or_stack.len()
|
self.and_stack.len() + self.or_stack.len()
|
||||||
}
|
}
|
||||||
@@ -1003,96 +1119,6 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy_term(L1, L2) uses Cheney's algorithm to copy the term at
|
|
||||||
// L1 to L2. forwarding_terms is kept to restore the innards of L1
|
|
||||||
// after it's been copied to L2.
|
|
||||||
fn copy_term(&mut self, a: Addr)
|
|
||||||
{
|
|
||||||
let mut forward_trail = Vec::new(); // list of (Ref, HeapCellValue) items.
|
|
||||||
let mut scan = self.h;
|
|
||||||
let old_h = self.h;
|
|
||||||
|
|
||||||
self.heap.push(HeapCellValue::from(a));
|
|
||||||
self.h += 1;
|
|
||||||
|
|
||||||
while scan < self.h {
|
|
||||||
match self.heap[scan].clone() {
|
|
||||||
HeapCellValue::Con(_) | HeapCellValue::NamedStr(_, _) =>
|
|
||||||
scan += 1,
|
|
||||||
HeapCellValue::Lis(a) => {
|
|
||||||
let hcv = self.heap[a].clone();
|
|
||||||
self.heap.push(hcv);
|
|
||||||
|
|
||||||
let hcv = self.heap[a+1].clone();
|
|
||||||
self.heap.push(hcv);
|
|
||||||
|
|
||||||
self.heap[scan] = HeapCellValue::Lis(self.h);
|
|
||||||
|
|
||||||
self.h += 2;
|
|
||||||
scan += 1;
|
|
||||||
},
|
|
||||||
HeapCellValue::Ref(r) => {
|
|
||||||
let ra = Addr::from(r);
|
|
||||||
let rd = self.store(self.deref(ra.clone()));
|
|
||||||
|
|
||||||
match rd {
|
|
||||||
Addr::HeapCell(hc) if hc >= old_h => {
|
|
||||||
self.heap[scan] = HeapCellValue::Ref(Ref::HeapCell(hc));
|
|
||||||
scan += 1;
|
|
||||||
},
|
|
||||||
_ if ra == rd => {
|
|
||||||
self.heap[scan] = HeapCellValue::Ref(Ref::HeapCell(scan));
|
|
||||||
|
|
||||||
match r {
|
|
||||||
Ref::HeapCell(hc) =>
|
|
||||||
self.heap[hc] = HeapCellValue::Ref(Ref::HeapCell(scan)),
|
|
||||||
Ref::StackCell(fr, sc) =>
|
|
||||||
self.and_stack[fr][sc] = Addr::HeapCell(scan),
|
|
||||||
};
|
|
||||||
|
|
||||||
forward_trail.push((r, HeapCellValue::Ref(r)));
|
|
||||||
scan += 1;
|
|
||||||
},
|
|
||||||
_ => self.heap[scan] = HeapCellValue::from(rd)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
HeapCellValue::Str(s) => {
|
|
||||||
match self.heap[s].clone() {
|
|
||||||
HeapCellValue::NamedStr(arity, name) => {
|
|
||||||
self.heap[scan] = HeapCellValue::Str(self.h);
|
|
||||||
self.heap[s] = HeapCellValue::Str(self.h);
|
|
||||||
|
|
||||||
forward_trail.push((Ref::HeapCell(s),
|
|
||||||
HeapCellValue::NamedStr(arity, name.clone())));
|
|
||||||
|
|
||||||
self.heap.push(HeapCellValue::NamedStr(arity, name));
|
|
||||||
self.h += 1;
|
|
||||||
|
|
||||||
for i in 0 .. arity {
|
|
||||||
let hcv = self.heap[s + 1 + i].clone();
|
|
||||||
self.heap.push(hcv);
|
|
||||||
self.h += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
HeapCellValue::Str(o) =>
|
|
||||||
self.heap[scan] = HeapCellValue::Str(o),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
scan += 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (r, hcv) in forward_trail {
|
|
||||||
match r {
|
|
||||||
Ref::HeapCell(hc) => self.heap[hc] = hcv,
|
|
||||||
Ref::StackCell(fr, sc) => self.and_stack[fr][sc] = hcv.as_addr(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_internal_call_n(&mut self, code_dir: &CodeDir)
|
fn handle_internal_call_n(&mut self, code_dir: &CodeDir)
|
||||||
{
|
{
|
||||||
let arity = self.num_of_args + 1;
|
let arity = self.num_of_args + 1;
|
||||||
@@ -1146,30 +1172,28 @@ impl MachineState {
|
|||||||
Some((name, arity + narity - 1))
|
Some((name, arity + narity - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_null_ball(&self) -> bool
|
|
||||||
{
|
|
||||||
if let &Addr::Con(Constant::UInt64(_)) = &self.ball {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
|
fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
|
||||||
{
|
{
|
||||||
match instr {
|
match instr {
|
||||||
&BuiltInInstruction::CopyTerm => {
|
&BuiltInInstruction::DuplicateTerm => {
|
||||||
let old_h = self.h;
|
let old_h = self.h;
|
||||||
let a = self[temp_v!(1)].clone();
|
|
||||||
self.copy_term(a);
|
let a1 = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
let a2 = self[temp_v!(2)].clone();
|
let a2 = self[temp_v!(2)].clone();
|
||||||
|
|
||||||
|
// drop the mutable references contained in gadget
|
||||||
|
// once the term has been duplicated.
|
||||||
|
{
|
||||||
|
let mut gadget = DuplicateTerm::new(self);
|
||||||
|
gadget.duplicate_term(a1);
|
||||||
|
}
|
||||||
|
|
||||||
self.unify(Addr::HeapCell(old_h), a2);
|
self.unify(Addr::HeapCell(old_h), a2);
|
||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::GetCurrentBlock => {
|
&BuiltInInstruction::GetCurrentBlock => {
|
||||||
let c = Constant::UInt64(self.block);
|
let c = Constant::BlockNum(self.block);
|
||||||
let addr = self[temp_v!(1)].clone();
|
let addr = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
self.write_constant_to_var(addr, &c);
|
self.write_constant_to_var(addr, &c);
|
||||||
@@ -1182,15 +1206,25 @@ impl MachineState {
|
|||||||
self.unify(a1, a2);
|
self.unify(a1, a2);
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
|
&BuiltInInstruction::EraseBall => {
|
||||||
|
self.ball.truncate(0);
|
||||||
|
self.p += 1;
|
||||||
|
},
|
||||||
&BuiltInInstruction::GetBall => {
|
&BuiltInInstruction::GetBall => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let ball = self.ball.clone();
|
let h = self.h;
|
||||||
|
|
||||||
if self.has_null_ball() {
|
if self.ball.len() > 0 {
|
||||||
|
let copied_ball_iter = self.ball.iter().cloned();
|
||||||
|
self.heap.extend(copied_ball_iter);
|
||||||
|
self.h += self.ball.len();
|
||||||
|
} else {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ball = self.heap[h].as_addr(h);
|
||||||
|
|
||||||
match addr.as_ref() {
|
match addr.as_ref() {
|
||||||
Some(r) => {
|
Some(r) => {
|
||||||
self.bind(r, ball);
|
self.bind(r, ball);
|
||||||
@@ -1200,14 +1234,20 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::SetBall => {
|
&BuiltInInstruction::SetBall => {
|
||||||
self.ball = self[temp_v!(1)].clone();
|
let addr = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut duplicator = DuplicateBallTerm::new(self);
|
||||||
|
duplicator.duplicate_term(addr);
|
||||||
|
}
|
||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&BuiltInInstruction::CleanUpBlock => {
|
&BuiltInInstruction::CleanUpBlock => {
|
||||||
let nb = self.store(self.deref(self[temp_v!(1)].clone()));
|
let nb = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
match nb {
|
match nb {
|
||||||
Addr::Con(Constant::UInt64(nb)) => {
|
Addr::Con(Constant::BlockNum(nb)) => {
|
||||||
let b = self.b - 1;
|
let b = self.b - 1;
|
||||||
|
|
||||||
if nb > 0 && self.or_stack[b].b == nb {
|
if nb > 0 && self.or_stack[b].b == nb {
|
||||||
@@ -1221,7 +1261,7 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
&BuiltInInstruction::InstallNewBlock => {
|
&BuiltInInstruction::InstallNewBlock => {
|
||||||
self.block = self.b;
|
self.block = self.b;
|
||||||
let c = Constant::UInt64(self.block);
|
let c = Constant::BlockNum(self.block);
|
||||||
let addr = self[temp_v!(1)].clone();
|
let addr = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
self.write_constant_to_var(addr, &c);
|
self.write_constant_to_var(addr, &c);
|
||||||
@@ -1231,7 +1271,7 @@ impl MachineState {
|
|||||||
let addr = self.deref(self[temp_v!(1)].clone());
|
let addr = self.deref(self[temp_v!(1)].clone());
|
||||||
|
|
||||||
match self.store(addr) {
|
match self.store(addr) {
|
||||||
Addr::Con(Constant::UInt64(b)) => {
|
Addr::Con(Constant::BlockNum(b)) => {
|
||||||
self.block = b;
|
self.block = b;
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
@@ -1286,12 +1326,17 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
&ControlInstruction::Call(ref name, arity, _) =>
|
&ControlInstruction::Call(ref name, arity, _) =>
|
||||||
self.try_call_predicate(code_dir, name.clone(), arity),
|
self.try_call_predicate(code_dir, name.clone(), arity),
|
||||||
&ControlInstruction::Catch => {
|
&ControlInstruction::CatchCall => {
|
||||||
self.cp = self.p + 1;
|
self.cp = self.p + 1;
|
||||||
self.num_of_args = 3;
|
self.num_of_args = 3;
|
||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
self.p = CodePtr::DirEntry(5);
|
self.p = CodePtr::DirEntry(5);
|
||||||
},
|
},
|
||||||
|
&ControlInstruction::CatchExecute => {
|
||||||
|
self.num_of_args = 3;
|
||||||
|
self.b0 = self.b;
|
||||||
|
self.p = CodePtr::DirEntry(5);
|
||||||
|
},
|
||||||
&ControlInstruction::CallN(arity) =>
|
&ControlInstruction::CallN(arity) =>
|
||||||
if let Some((name, arity)) = self.setup_call_n(arity) {
|
if let Some((name, arity)) = self.setup_call_n(arity) {
|
||||||
self.try_call_predicate(code_dir, name, arity);
|
self.try_call_predicate(code_dir, name, arity);
|
||||||
@@ -1312,11 +1357,16 @@ impl MachineState {
|
|||||||
},
|
},
|
||||||
&ControlInstruction::Proceed =>
|
&ControlInstruction::Proceed =>
|
||||||
self.p = self.cp,
|
self.p = self.cp,
|
||||||
&ControlInstruction::Throw => {
|
&ControlInstruction::ThrowCall => {
|
||||||
self.cp = self.p + 1;
|
self.cp = self.p + 1;
|
||||||
self.num_of_args = 1;
|
self.num_of_args = 1;
|
||||||
self.b0 = self.b;
|
self.b0 = self.b;
|
||||||
self.p = CodePtr::DirEntry(56);
|
self.p = CodePtr::DirEntry(59);
|
||||||
|
},
|
||||||
|
&ControlInstruction::ThrowExecute => {
|
||||||
|
self.num_of_args = 1;
|
||||||
|
self.b0 = self.b;
|
||||||
|
self.p = CodePtr::DirEntry(59);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ macro_rules! query {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! fact {
|
||||||
|
[$($x:expr),+] => (
|
||||||
|
Line::Fact(vec![$($x),+])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! temp_v {
|
macro_rules! temp_v {
|
||||||
($x:expr) => (
|
($x:expr) => (
|
||||||
RegType::Temp($x)
|
RegType::Temp($x)
|
||||||
@@ -40,6 +46,12 @@ macro_rules! get_var_in_query {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! get_var_in_fact {
|
||||||
|
($r:expr, $arg:expr) => (
|
||||||
|
FactInstruction::GetVariable($r, $arg)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! put_var {
|
macro_rules! put_var {
|
||||||
($r:expr, $arg:expr) => (
|
($r:expr, $arg:expr) => (
|
||||||
QueryInstruction::PutVariable($r, $arg)
|
QueryInstruction::PutVariable($r, $arg)
|
||||||
@@ -150,6 +162,12 @@ macro_rules! get_ball {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! erase_ball {
|
||||||
|
() => (
|
||||||
|
Line::BuiltIn(BuiltInInstruction::EraseBall)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! unify {
|
macro_rules! unify {
|
||||||
() => (
|
() => (
|
||||||
Line::BuiltIn(BuiltInInstruction::Unify)
|
Line::BuiltIn(BuiltInInstruction::Unify)
|
||||||
@@ -180,9 +198,9 @@ macro_rules! fail {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! copy_term {
|
macro_rules! duplicate_term {
|
||||||
() => (
|
() => (
|
||||||
Line::BuiltIn(BuiltInInstruction::CopyTerm)
|
Line::BuiltIn(BuiltInInstruction::DuplicateTerm)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pub mod allocator;
|
|||||||
pub mod and_stack;
|
pub mod and_stack;
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod codegen;
|
pub mod codegen;
|
||||||
|
pub mod copier;
|
||||||
pub mod debray_allocator;
|
pub mod debray_allocator;
|
||||||
pub mod fixtures;
|
pub mod fixtures;
|
||||||
pub mod heapview;
|
pub mod heapview;
|
||||||
|
|||||||
Reference in New Issue
Block a user