[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)",
[package]
name = "rusty-wam"
-version = "0.7.0"
+version = "0.7.1"
authors = ["Mark Thom"]
[dependencies]
* (\\+)/1
* (=)/2
* throw/1
+* true/0
* var/1
## Tutorial
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() {
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>>)
}
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) =>
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
}
}
}
| 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
}
}
}
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>>)
}
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(),
GetCurrentBlock,
InstallNewBlock,
InternalCallN,
- IsAtomic,
- IsVar,
+ IsAtomic(RegType),
+ IsVar(RegType),
ResetBlock,
SetBall,
+ Succeed,
Unify,
UnwindStack
}
Deallocate,
Execute(Atom, usize),
ExecuteN(usize),
- Goto(usize, usize),
+ Goto(usize, usize), // p, arity.
Proceed,
ThrowCall,
ThrowExecute
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),
proceed!(),
fact![get_value!(temp_v!(1), 2)], // =/2, 73.
proceed!(),
+ succeed!(), // true/0, 75.
]
}
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)
}
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));
}
}
- 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
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 {
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);
},
};
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));
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] }
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);
arity = child_terms.len();
break;
},
+ QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+ result.push(term),
QueryTermRef::Cut => {
result.push(term);
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>
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(_,_) =>
&BuiltInInstruction::Fail => {
self.fail = true;
self.p += 1;
+ },
+ &BuiltInInstruction::Succeed => {
+ self.p += 1;
}
};
}
}
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))
)
}
)
}
+macro_rules! succeed {
+ () => (
+ Line::BuiltIn(BuiltInInstruction::Succeed)
+ )
+}
+
macro_rules! duplicate_term {
() => (
Line::BuiltIn(BuiltInInstruction::DuplicateTerm)