inline atomic and var.

This commit is contained in:
Mark Thom
2017-11-03 20:41:01 -06:00
parent 2abec91360
commit 57cc8ccac9
10 changed files with 105 additions and 45 deletions

2
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
[root]
name = "rusty-wam"
version = "0.7.0"
version = "0.7.1"
dependencies = [
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package]
name = "rusty-wam"
version = "0.7.0"
version = "0.7.1"
authors = ["Mark Thom"]
[dependencies]

View File

@@ -54,6 +54,7 @@ The following predicates are built-in to rusty-wam.
* (\\+)/1
* (=)/2
* throw/1
* true/0
* var/1
## Tutorial

View File

@@ -47,7 +47,7 @@ pub trait Allocator<'a>
fn get(&self, var: &'a Var) -> RegType {
self.bindings().get(var).unwrap().as_reg_type()
}
}
fn record_register(&mut self, var: &'a Var, r: RegType) {
match self.bindings_mut().get_mut(var).unwrap() {

View File

@@ -273,10 +273,12 @@ pub enum Term {
Var(Cell<VarReg>, Var)
}
pub enum QueryTerm {
pub enum QueryTerm {
CallN(Vec<Box<Term>>),
Catch(Vec<Box<Term>>),
Cut,
IsAtomic(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>),
Term(Term),
Throw(Vec<Box<Term>>)
}
@@ -290,6 +292,10 @@ impl QueryTerm {
QueryTermRef::Catch(terms),
&QueryTerm::Cut =>
QueryTermRef::Cut,
&QueryTerm::IsAtomic(ref terms) =>
QueryTermRef::IsAtomic(terms.first().unwrap()),
&QueryTerm::IsVar(ref terms) =>
QueryTermRef::IsVar(terms.first().unwrap()),
&QueryTerm::Term(ref term) =>
QueryTermRef::Term(term),
&QueryTerm::Throw(ref t) =>
@@ -314,10 +320,9 @@ pub enum ClauseType<'a> {
impl<'a> ClauseType<'a> {
pub fn level_of_subterms(self) -> Level {
match self {
ClauseType::CallN | ClauseType::Catch | ClauseType::Throw => Level::Shallow,
match self {
ClauseType::Deep(_, _, _) => Level::Deep,
ClauseType::Root => Level::Shallow,
_ => Level::Shallow
}
}
}
@@ -338,11 +343,8 @@ impl<'a> TermRef<'a> {
| TermRef::Cons(lvl, _, _, _)
| TermRef::Constant(lvl, _, _)
| TermRef::Var(lvl, _, _) => lvl,
TermRef::Clause(ClauseType::Root, _) => Level::Shallow,
TermRef::Clause(ClauseType::Deep(lvl, _, _), _) => lvl,
TermRef::Clause(ClauseType::CallN, _) => Level::Shallow,
TermRef::Clause(ClauseType::Throw, _) => Level::Shallow,
TermRef::Clause(ClauseType::Catch, _) => Level::Shallow
_ => Level::Shallow
}
}
}
@@ -352,6 +354,8 @@ pub enum QueryTermRef<'a> {
CallN(&'a Vec<Box<Term>>),
Catch(&'a Vec<Box<Term>>),
Cut,
IsAtomic(&'a Term),
IsVar(&'a Term),
Term(&'a Term),
Throw(&'a Vec<Box<Term>>)
}
@@ -361,6 +365,8 @@ impl<'a> QueryTermRef<'a> {
match self {
QueryTermRef::Catch(_) => 3,
QueryTermRef::Throw(_) => 1,
QueryTermRef::IsAtomic(_) => 1,
QueryTermRef::IsVar(_) => 1,
QueryTermRef::CallN(terms) => terms.len(),
QueryTermRef::Cut => 0,
QueryTermRef::Term(term) => term.arity(),
@@ -415,10 +421,11 @@ pub enum BuiltInInstruction {
GetCurrentBlock,
InstallNewBlock,
InternalCallN,
IsAtomic,
IsVar,
IsAtomic(RegType),
IsVar(RegType),
ResetBlock,
SetBall,
Succeed,
Unify,
UnwindStack
}
@@ -432,7 +439,7 @@ pub enum ControlInstruction {
Deallocate,
Execute(Atom, usize),
ExecuteN(usize),
Goto(usize, usize),
Goto(usize, usize), // p, arity.
Proceed,
ThrowCall,
ThrowExecute

View File

@@ -18,9 +18,9 @@ pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
fn get_builtins() -> Code {
vec![internal_call_n!(), // callN/N, 0.
is_atomic!(), // atomic/1, 1.
is_atomic!(temp_v!(1)), // atomic/1, 1.
proceed!(),
is_var!(), // var/1, 3.
is_var!(temp_v!(1)), // var/1, 3.
proceed!(),
allocate!(4), // catch/3, 5.
fact![get_var_in_fact!(perm_v!(2), 1),
@@ -104,6 +104,7 @@ fn get_builtins() -> Code {
proceed!(),
fact![get_value!(temp_v!(1), 2)], // =/2, 73.
proceed!(),
succeed!(), // true/0, 75.
]
}
@@ -134,6 +135,7 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir)
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));
(builtin_code, code_dir, op_dir)
}

View File

@@ -207,13 +207,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn add_conditional_call(compiled_query: &mut Code, qt: QueryTermRef, pvs: usize)
{
match qt {
match qt {
QueryTermRef::CallN(terms) => {
let call = ControlInstruction::CallN(terms.len());
compiled_query.push(Line::Control(call));
},
QueryTermRef::Catch(_) =>
compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
compiled_query.push(Line::Control(call));
@@ -228,31 +228,31 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}
}
fn lco(body: &mut Code, toc: QueryTermRef<'a>) -> usize
fn lco(code: &mut Code, toc: QueryTermRef<'a>) -> usize
{
let last_arity = toc.arity();
let mut dealloc_index = body.len() - 1;
let mut dealloc_index = code.len() - 1;
match toc {
QueryTermRef::Term(&Term::Clause(_, ref name, _))
| QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref name))) =>
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
*ctrl = ControlInstruction::Execute(name.clone(), last_arity);
},
QueryTermRef::CallN(terms) =>
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
*ctrl = ControlInstruction::ExecuteN(terms.len());
},
QueryTermRef::Catch(_) =>
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
*ctrl = ControlInstruction::CatchExecute;
},
QueryTermRef::Cut => {},
QueryTermRef::Throw(_) =>
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
*ctrl = ControlInstruction::ThrowExecute;
},
_ => dealloc_index = body.len()
_ => dealloc_index = code.len()
};
dealloc_index
@@ -261,7 +261,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn compile_seq(&mut self,
iter: ChunkedIterator<'a>,
conjunct_info: &ConjunctInfo<'a>,
body: &mut Code,
code: &mut Code,
is_exposed: bool)
{
for (chunk_num, _, terms) in iter {
@@ -275,29 +275,63 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
match term {
&QueryTermRef::Cut if i + 1 < terms.len() => {
body.push(if chunk_num == 0 {
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(Terminal::Non))
} else {
Line::Cut(CutInstruction::Cut(Terminal::Non))
});
},
&QueryTermRef::Cut => {
body.push(if chunk_num == 0 {
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(Terminal::Terminal))
} else {
Line::Cut(CutInstruction::Cut(Terminal::Terminal))
});
},
&QueryTermRef::IsAtomic(term) =>
match term {
&Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(goto!(61, 0)); // goto false/0.
},
&Term::Constant(_, _) => {
code.push(goto!(75, 0)); // goto succeed/0.
},
&Term::Var(ref vr, ref name) => {
let mut target = Vec::new();
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
code.push(Line::Query(target));
code.push(is_atomic!(vr.get().norm()));
}
},
&QueryTermRef::IsVar(term) =>
match term {
&Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(goto!(61, 0)); // goto false/0.
},
&Term::AnonVar => {
code.push(goto!(75, 0)); // goto succeed/0.
},
&Term::Var(ref vr, ref name) => {
let mut target = Vec::new();
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
code.push(Line::Query(target));
code.push(is_var!(vr.get().norm()));
}
},
_ if chunk_num == 0 => {
self.marker.advance(GenContext::Head, *term);
let iter = term.post_order_iter();
body.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
Self::add_conditional_call(body, *term, conjunct_info.perm_vars());
code.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
Self::add_conditional_call(code, *term, conjunct_info.perm_vars());
},
_ => {
let num_vars = conjunct_info.perm_vs.vars_above_threshold(i + 1);
self.compile_query_line(*term, term_loc, body, num_vars, is_exposed);
self.compile_query_line(*term, term_loc, code, num_vars, is_exposed);
},
};
@@ -393,7 +427,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code
{
let iter = ChunkedIterator::from_fact(term);
self.collect_var_data(iter);
self.marker.advance(GenContext::Head, QueryTermRef::Term(term));

View File

@@ -77,7 +77,8 @@ impl<'a> QueryIterator<'a> {
let state = IteratorState::Clause(0, ClauseType::Catch, terms);
QueryIterator { state_stack: vec![state] }
},
QueryTermRef::Term(term) => Self::from_term(term),
QueryTermRef::IsAtomic(term) | QueryTermRef::IsVar(term) | QueryTermRef::Term(term) =>
Self::from_term(term),
QueryTermRef::Throw(term) => {
let state = IteratorState::Clause(0, ClauseType::Throw, term);
QueryIterator { state_stack: vec![state] }
@@ -106,10 +107,10 @@ impl<'a> Iterator for QueryIterator<'a> {
match ct {
ClauseType::CallN =>
self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
ClauseType::Root | ClauseType::Throw | ClauseType::Catch =>
return None,
ClauseType::Deep(_, _, _) =>
return Some(TermRef::Clause(ct, child_terms))
return Some(TermRef::Clause(ct, child_terms)),
_ =>
return None
};
} else {
self.push_clause(child_num + 1, ct, child_terms);
@@ -317,6 +318,8 @@ impl<'a> ChunkedIterator<'a>
arity = child_terms.len();
break;
},
QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
result.push(term),
QueryTermRef::Cut => {
result.push(term);

View File

@@ -421,10 +421,14 @@ impl Machine {
self.query_stepper();
match self.ms.p {
CodePtr::TopLevel(_, p) if p > 0 => {},
CodePtr::TopLevel(_, p) if p > 0 => {},
_ => break
};
}
if let CodePtr::TopLevel(cn, _) = self.ms.p {
self.record_var_places(cn, alloc_locs, heap_locs);
}
}
fn fail<'a>(&mut self) -> EvalSession<'a>
@@ -1388,16 +1392,16 @@ impl MachineState {
self.b = self.block;
self.fail = true;
},
&BuiltInInstruction::IsAtomic => {
let d = self.deref(self[temp_v!(1)].clone());
&BuiltInInstruction::IsAtomic(r) => {
let d = self.deref(self[r].clone());
match d {
Addr::Con(_) => self.p += 1,
_ => self.fail = true
};
},
&BuiltInInstruction::IsVar => {
let d = self.deref(self[temp_v!(1)].clone());
&BuiltInInstruction::IsVar(r) => {
let d = self.deref(self[r].clone());
match d {
Addr::HeapCell(_) | Addr::StackCell(_,_) =>
@@ -1410,6 +1414,9 @@ impl MachineState {
&BuiltInInstruction::Fail => {
self.fail = true;
self.p += 1;
},
&BuiltInInstruction::Succeed => {
self.p += 1;
}
};
}

View File

@@ -100,14 +100,14 @@ macro_rules! try_me_else {
}
macro_rules! is_atomic {
() => (
Line::BuiltIn(BuiltInInstruction::IsAtomic)
($reg:expr) => (
Line::BuiltIn(BuiltInInstruction::IsAtomic($reg))
)
}
macro_rules! is_var {
() => (
Line::BuiltIn(BuiltInInstruction::IsVar)
($reg:expr) => (
Line::BuiltIn(BuiltInInstruction::IsVar($reg))
)
}
@@ -221,6 +221,12 @@ macro_rules! fail {
)
}
macro_rules! succeed {
() => (
Line::BuiltIn(BuiltInInstruction::Succeed)
)
}
macro_rules! duplicate_term {
() => (
Line::BuiltIn(BuiltInInstruction::DuplicateTerm)