[[package]]
name = "rusty-wam"
-version = "0.7.4"
+version = "0.7.5"
dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
use prolog::io::*;
use prolog::machine::*;
-use prolog::parser::toplevel::*;
#[cfg(test)]
mod tests;
fn process_buffer(wam: &mut Machine, buffer: &str)
{
- match parse_code(buffer, wam.atom_tbl(), wam.op_dir()) {
+ match parse_code(wam, buffer) {
Ok(tl) => {
- let result = eval(wam, &tl);
+ let result = compile(wam, &tl);
print(wam, result);
},
Err(s) => println!("{:?}", s)
Rule(Rule)
}
+impl TopLevel {
+ pub fn name(&self) -> Option<TabledRc<Atom>> {
+ match self {
+ &TopLevel::Declaration(_) => None,
+ &TopLevel::Fact(ref term) => term.name(),
+ &TopLevel::Predicate(ref clauses) =>
+ if let Some(ref term) = clauses.first() {
+ term.name()
+ } else {
+ None
+ },
+ &TopLevel::Query(_) => None,
+ &TopLevel::Rule(Rule { head: (QueryTerm::Term(ref term), _), .. }) =>
+ match term {
+ &Term::Clause(_, ref name, ..)
+ | &Term::Constant(_, Constant::Atom(ref name)) =>
+ Some(name.clone()),
+ _ =>
+ None
+ },
+ _ => None
+ }
+ }
+
+ pub fn arity(&self) -> usize {
+ match self {
+ &TopLevel::Declaration(_) => 0,
+ &TopLevel::Fact(ref term) => term.arity(),
+ &TopLevel::Predicate(ref clauses) =>
+ clauses.first().map(|t| t.arity()).unwrap_or(0),
+ &TopLevel::Query(_) => 0,
+ &TopLevel::Rule(Rule { head: (ref qt, _), ..}) => qt.arity(),
+ }
+ }
+}
+
#[derive(Clone, Copy)]
pub enum Level {
Deep, Shallow
pub enum ParserError
{
Arithmetic(ArithmeticError),
- CommaArityMismatch,
+ BuiltInArityMismatch(&'static str),
UnexpectedEOF,
FailedMatch(String),
IO(IOError),
+ ExpectedRel,
InadmissibleFact,
InadmissibleQueryTerm,
IncompleteReduction,
}
}
+#[derive(Clone)]
pub enum Term {
AnonVar,
Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
CompareNumber(CompareNumberQT, Vec<Box<Term>>),
IsAtomic(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>),
- IsInteger(Vec<Box<Term>>)
+ IsInteger(Vec<Box<Term>>)
}
impl InlinedQueryTerm {
&InlinedQueryTerm::CompareNumber(_, _) => 2,
&InlinedQueryTerm::IsAtomic(_) => 1,
&InlinedQueryTerm::IsInteger(_) => 1,
- &InlinedQueryTerm::IsVar(_) => 1,
+ &InlinedQueryTerm::IsVar(_) => 1,
}
}
}
Equal
}
+// vars of predicate, toplevel offset. Vec<Term> is always a vector
+// of vars (we get their adjoining cells this way).
+pub type JumpStub = (Vec<Term>, Rc<Cell<usize>>);
+
pub enum QueryTerm {
Arg(Vec<Box<Term>>),
CallN(Vec<Box<Term>>),
Functor(Vec<Box<Term>>),
Inlined(InlinedQueryTerm),
Is(Vec<Box<Term>>),
+ Jump(JumpStub),
Term(Term),
Throw(Vec<Box<Term>>)
}
&QueryTerm::Functor(_) => 3,
&QueryTerm::Inlined(ref term) => term.arity(),
&QueryTerm::Is(_) => 2,
+ &QueryTerm::Jump((ref vars, _)) => vars.len(),
&QueryTerm::CallN(ref terms) => terms.len(),
&QueryTerm::Cut => 0,
&QueryTerm::Term(ref term) => term.arity(),
&ClauseType::Display => "display",
&ClauseType::Deep(_, _, name, _) => name.as_str(),
&ClauseType::DuplicateTerm => "duplicate_term",
- &ClauseType::Functor => "functor",
+ &ClauseType::Functor => "functor",
&ClauseType::Is => "is",
&ClauseType::Root(name) => name.as_str(),
&ClauseType::Throw => "throw"
ExecuteN(usize),
FunctorCall,
FunctorExecute,
- Goto(usize, usize), // p, arity.
+ JmpByCall(usize, Rc<Cell<usize>>), // arity, global_offset.
+ JmpByExecute(usize, Rc<Cell<usize>>),
+ // GotoCall(usize, usize), // p, arity.
+ GotoExecute(usize, usize), // p, arity.
IsCall(RegType, ArithmeticTerm),
IsExecute(RegType, ArithmeticTerm),
Proceed,
&ControlInstruction::FunctorExecute => true,
&ControlInstruction::ThrowCall => true,
&ControlInstruction::ThrowExecute => true,
- &ControlInstruction::Goto(_, _) => true,
+ &ControlInstruction::GotoExecute(..) => true,
&ControlInstruction::Proceed => true,
- &ControlInstruction::IsCall(_, _) => true,
- &ControlInstruction::IsExecute(_, _) => true,
+ &ControlInstruction::IsCall(..) => true,
+ &ControlInstruction::IsExecute(..) => true,
+ &ControlInstruction::JmpByCall(..) => true,
+ &ControlInstruction::JmpByExecute(..) => true,
_ => false
}
}
put_value!(perm_v!(1), 3),
put_unsafe_value!(4, 4)],
deallocate!(),
- goto!(12, 4), // goto catch/4.
+ goto_execute!(12, 4), // goto catch/4.
try_me_else!(10), // catch/4, 12.
allocate!(3),
fact![get_var_in_fact!(perm_v!(3), 1),
query![put_value!(perm_v!(2), 1),
put_unsafe_value!(1, 2)],
deallocate!(),
- goto!(44, 2), //21: goto end_block/2.
+ goto_execute!(44, 2), //21: goto end_block/2.
trust_me!(),
allocate!(3),
fact![get_var_in_fact!(perm_v!(2), 2),
put_value!(perm_v!(2), 2),
put_value!(perm_v!(1), 3)],
deallocate!(),
- goto!(32, 2), // goto handle_ball/2.
+ goto_execute!(32, 2), // goto handle_ball/2.
try_me_else!(10), // handle_ball/2, 32.
allocate!(2),
get_level!(),
put_value!(temp_v!(2), 1)],
reset_block!(),
deallocate!(),
- goto!(61, 0),
+ goto_execute!(61, 0),
set_ball!(), // throw/1, 59.
unwind_stack!(),
fail!(), // false/0, 61.
call_n!(1),
cut!(),
deallocate!(),
- goto!(61, 0),
+ goto_execute!(61, 0),
trust_me!(),
proceed!(),
duplicate_term!(), // duplicate_term/2, 71.
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
set_cp!(temp_v!(3)),
- goto!(83, 3),
+ goto_execute!(83, 3),
retry_me_else!(4),
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
get_constant!(atom!("!", atom_tbl), temp_v!(2))],
put_unsafe_value!(1, 2),
put_value!(perm_v!(3), 3)],
deallocate!(),
- goto!(83, 3),
+ goto_execute!(83, 3),
retry_me_else!(10),
allocate!(1),
get_level!(),
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
- goto!(139, 3),
+ goto_execute!(139, 3),
trust_me!(),
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
unify_void!(2)],
put_value!(perm_v!(2), 4),
put_value!(perm_v!(4), 5)],
deallocate!(),
- goto!(173, 5), // goto arg_/3.
+ goto_execute!(173, 5), // goto arg_/3.
retry_me_else!(10),
allocate!(3),
fact![get_var_in_fact!(perm_v!(1), 1),
put_value!(perm_v!(2), 2),
put_value!(perm_v!(3), 3)],
deallocate!(),
- goto!(149, 3), // goto get_arg/3.
+ goto_execute!(149, 3), // goto get_arg/3.
trust_me!(),
query![get_var_in_query!(temp_v!(4), 1),
put_structure!(atom_tbl,
temp_v!(1),
None),
set_constant!(atom!("integer_expected", atom_tbl))],
- goto!(59, 1), // goto throw/1.
+ goto_execute!(59, 1), // goto throw/1.
try_me_else!(5), // arg_/3, 173.
fact![get_value!(temp_v!(1), 2),
get_value!(temp_v!(1), 3)],
neck_cut!(),
query![put_value!(temp_v!(4), 2),
put_value!(temp_v!(5), 3)],
- goto!(149, 3), // goto get_arg/3.
+ goto_execute!(149, 3), // goto get_arg/3.
retry_me_else!(4),
fact![get_value!(temp_v!(1), 2)],
query![put_value!(temp_v!(4), 2),
get_var_in_query!(temp_v!(6), 3),
put_value!(temp_v!(5), 3)],
- goto!(149, 3), // goto get_arg/3
+ goto_execute!(149, 3), // goto get_arg/3
trust_me!(),
allocate!(5),
fact![get_var_in_fact!(perm_v!(2), 1),
put_value!(perm_v!(3), 4),
put_value!(perm_v!(5), 5)],
deallocate!(),
- goto!(173, 3), // goto arg_/3.
+ goto_execute!(173, 3), // goto arg_/3.
display!(), // display/1, 192.
proceed!(),
dynamic_is!(), // is/2, 194.
SubsequentQuerySuccess,
}
+impl<'a> From<ParserError> for EvalSession<'a> {
+ fn from(err: ParserError) -> Self {
+ EvalSession::ParserError(err)
+ }
+}
+
pub struct ConjunctInfo<'a> {
pub perm_vs: VariableFixtures<'a>,
pub num_of_chunks: usize,
*self.var_count.get(var).unwrap()
}
- fn mark_non_callable(&mut self,
- name: &'a Atom,
- arity: usize,
- term_loc: GenContext,
- vr: &'a Cell<VarReg>,
- code: &mut Code)
+ fn mark_non_callable(&mut self, name: &'a Atom, arity: usize, term_loc: GenContext,
+ vr: &'a Cell<VarReg>, code: &mut Code)
-> RegType
{
match self.marker.bindings().get(name) {
};
}
- fn compile_clause<Target>(&mut self,
- ct: ClauseType<'a>,
- term_loc: GenContext,
- is_exposed: bool,
- terms: &'a Vec<Box<Term>>,
+ fn compile_clause<Target>(&mut self, ct: ClauseType<'a>, term_loc: GenContext,
+ is_exposed: bool, terms: &'a Vec<Box<Term>>,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
&QueryTerm::DuplicateTerm(_) =>
code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
&QueryTerm::Functor(_) =>
- code.push(Line::Control(ControlInstruction::FunctorCall)),
+ code.push(Line::Control(ControlInstruction::FunctorCall)),
&QueryTerm::Inlined(_) =>
code.push(proceed!()),
+ &QueryTerm::Jump((ref vars, ref offset)) => {
+ code.push(jmp_call!(vars.len(), offset.clone()));
+ },
&QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
code.push(Line::Control(call));
*ctrl = ControlInstruction::DuplicateTermExecute,
ControlInstruction::FunctorCall =>
*ctrl = ControlInstruction::FunctorExecute,
+ ControlInstruction::JmpByCall(arity, offset) =>
+ *ctrl = ControlInstruction::JmpByExecute(arity, offset),
ControlInstruction::CatchCall =>
*ctrl = ControlInstruction::CatchExecute,
ControlInstruction::ThrowCall =>
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(..) => {
}
},
&InlinedQueryTerm::IsInteger(ref inner_term) =>
- match inner_term[0].as_ref() {
+ match inner_term[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!());
},
let r = self.mark_non_callable(name, 1, term_loc, vr, code);
code.push(is_var!(r));
}
- }
+ }
}
Ok(())
evaluator.eval(term)
}
- fn compile_seq(&mut self,
- iter: ChunkedIterator<'a>,
- conjunct_info: &ConjunctInfo<'a>,
- code: &mut Code,
- is_exposed: bool)
+ fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>,
+ code: &mut Code, is_exposed: bool)
-> Result<(), ParserError>
{
for (chunk_num, _, terms) in iter {
match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => {
- let r = self.mark_non_callable(name,
- 2,
- term_loc,
- vr,
- code);
-
+ let r = self.mark_non_callable(name, 2, term_loc, vr, code);
code.push(is_call!(r, at.unwrap_or(interm!(1))));
},
&Term::Constant(_, ref c @ Constant::Number(_)) => {
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
{
+ // add a proceed to bookend any trailing inlines or cuts.
match toc {
&QueryTerm::Inlined(_) | &QueryTerm::Cut =>
code.push(proceed!()),
_ => {}
};
+ // perform lco.
let dealloc_index = Self::lco(code);
if conjunct_info.allocates() {
code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
}
+
+ // mark the first uninitialized jmp command (if there is one)
+ // by code.len() - index.
+ //TODO
}
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, ParserError>
use prolog::ast::*;
use prolog::codegen::*;
use prolog::debray_allocator::*;
+use prolog::fixtures::*;
use prolog::heap_print::*;
use prolog::machine::*;
+use prolog::parser::toplevel::*;
use termion::raw::IntoRawMode;
use termion::input::TermRead;
&CompareNumberQT::LessThan => write!(f, "<"),
&CompareNumberQT::LessThanOrEqual => write!(f, "<="),
&CompareNumberQT::NotEqual => write!(f, "=\\="),
- &CompareNumberQT::Equal => write!(f, "=:="),
+ &CompareNumberQT::Equal => write!(f, "=:="),
}
}
}
write!(f, "deallocate"),
&ControlInstruction::Execute(ref name, arity) =>
write!(f, "execute {}/{}", name, arity),
- &ControlInstruction::Goto(p, arity) =>
- write!(f, "goto {}/{}", p, arity),
+ &ControlInstruction::GotoExecute(p, arity) =>
+ write!(f, "goto_execute {}/{}", p, arity),
&ControlInstruction::IsCall(r, ref at) =>
write!(f, "is_call {}, {}", r, at),
&ControlInstruction::IsExecute(r, ref at) =>
write!(f, "is_execute {}, {}", r, at),
+ &ControlInstruction::JmpByCall(arity, ref offset) =>
+ write!(f, "jmp_by_call {}/{}", offset.get(), arity),
+ &ControlInstruction::JmpByExecute(arity, ref offset) =>
+ write!(f, "jmp_by_execute {}/{}", offset.get(), arity),
&ControlInstruction::Proceed =>
write!(f, "proceed"),
&ControlInstruction::ThrowCall =>
&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),
+ write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
&BuiltInInstruction::DynamicCompareNumber(cmp) =>
write!(f, "dynamic_number_test {}", cmp),
&BuiltInInstruction::EraseBall =>
&BuiltInInstruction::IsInteger(r) =>
write!(f, "is_integer {}", r),
&BuiltInInstruction::DynamicIs =>
- write!(f, "call_is"),
+ write!(f, "call_is"),
&BuiltInInstruction::IsVar(r) =>
- write!(f, "is_var {}", r),
+ write!(f, "is_var {}", r),
&BuiltInInstruction::ResetBlock =>
write!(f, "reset_block"),
&BuiltInInstruction::SetBall =>
}
}
+pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, ParserError>
+{
+ let mut worker = TopLevelWorker::new(wam.atom_tbl(), wam.op_dir());
+ worker.parse_code(buffer)
+}
+
pub fn read() -> String {
let _ = stdout().flush();
result
}
-pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'b>
+// throw errors if declaration or query found.
+fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
{
+ let mut cg = CodeGenerator::<DebrayAllocator>::new();
+
match tl {
- &TopLevel::Declaration(ref decl) =>
- wam.submit_decl(decl),
- &TopLevel::Predicate(ref clauses) => {
- let mut cg = CodeGenerator::<DebrayAllocator>::new();
+ &TopLevel::Declaration(_) | &TopLevel::Query(_) =>
+ Err(ParserError::ExpectedRel),
+ &TopLevel::Predicate(ref clauses) =>
+ cg.compile_predicate(clauses),
+ &TopLevel::Fact(ref fact) =>
+ Ok(cg.compile_fact(fact)),
+ &TopLevel::Rule(ref rule) =>
+ cg.compile_rule(rule)
+ }
+}
- let compiled_pred = match cg.compile_predicate(clauses) {
- Ok(pred) => pred,
- Err(e) => return EvalSession::ParserError(e)
- };
+// set first jmp_by_call or jmp_by_index instruction to code.len() - idx,
+// where idx is the place it occurs. It only does this to the *first* uninitialized
+// jmp index it encounters, then returns.
+fn set_first_index(code: &Code)
+{
+ for (idx, line) in code.iter().enumerate() {
+ match line {
+ &Line::Control(ControlInstruction::JmpByExecute(_, ref offset))
+ | &Line::Control(ControlInstruction::JmpByCall(_, ref offset)) if offset.get() == 0 => {
+ offset.set(code.len() - idx);
+ break;
+ },
+ _ => {}
+ };
+ }
+}
- wam.add_predicate(clauses, compiled_pred)
- },
- &TopLevel::Fact(ref fact) => {
- let mut cg = CodeGenerator::<DebrayAllocator>::new();
+fn compile_appendix(code: &mut Code, queue: &Vec<TopLevel>) -> Result<(), ParserError>
+{
+ for tl in queue.iter() {
+ set_first_index(code);
+ code.append(&mut compile_relation(tl)?);
+ }
- let compiled_fact = cg.compile_fact(fact);
- wam.add_fact(fact, compiled_fact)
- },
- &TopLevel::Rule(ref rule) => {
- let mut cg = CodeGenerator::<DebrayAllocator>::new();
+ Ok(())
+}
- let compiled_rule = match cg.compile_rule(rule) {
- Ok(rule) => rule,
- Err(e) => return EvalSession::ParserError(e)
- };
+fn compile_query<'a>(terms: &'a Vec<QueryTerm>, queue: &'a Vec<TopLevel>)
+ -> Result<(Code, AllocVarDict<'a>), ParserError>
+{
+ let mut cg = CodeGenerator::<DebrayAllocator>::new();
+ let mut code = try!(cg.compile_query(terms));
+
+ compile_appendix(&mut code, queue)?;
- wam.add_rule(rule, compiled_rule)
- },
- &TopLevel::Query(ref query) => {
- let mut cg = CodeGenerator::<DebrayAllocator>::new();
+ Ok((code, cg.take_vars()))
+}
- let compiled_query = match cg.compile_query(query) {
- Ok(query) => query,
+pub fn compile<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevelPacket) -> EvalSession<'b>
+{
+ match tl {
+ &TopLevelPacket::Query(ref terms, ref queue) =>
+ match compile_query(terms, queue) {
+ Ok((code, vars)) => wam.submit_query(code, vars),
+ Err(e) => EvalSession::from(e)
+ },
+ &TopLevelPacket::Decl(TopLevel::Declaration(ref decl), _) =>
+ wam.submit_decl(decl),
+ &TopLevelPacket::Decl(ref tl, ref queue) => {
+ let mut code = match compile_relation(tl) {
+ Ok(code) => code,
Err(e) => return EvalSession::ParserError(e)
};
- wam.submit_query(compiled_query, cg.take_vars())
+ if let Err(e) = compile_appendix(&mut code, queue) {
+ return EvalSession::from(e);
+ };
+
+ if !code.is_empty() {
+ if let Some(name) = tl.name() {
+ wam.add_user_code(name, tl.arity(), code)
+ } else {
+ EvalSession::NamelessEntry
+ }
+ } else {
+ EvalSession::ImpermissibleEntry(String::from("no code generated."))
+ }
}
}
}
loop {
let mut result = EvalSession::QueryFailure;
let mut output = PrinterOutputter::new();
-
+
let bindings = wam.heap_view(&heap_locs, output).result();
let stdin = stdin();
let state = TermIterState::Clause(0, ClauseType::Throw, term);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::Cut => QueryIterator { state_stack: vec![] }
+ &QueryTerm::Cut => QueryIterator { state_stack: vec![] },
+ &QueryTerm::Jump((ref vars, _)) => {
+ let state_stack = vars.iter().rev().map(|t| {
+ TermIterState::to_state(Level::Shallow, t)
+ }).collect();
+
+ QueryIterator { state_stack }
+ }
}
}
}
while let Some(term) = item {
match term {
+ &QueryTerm::Jump((ref vars, _)) => {
+ result.push(term);
+ arity = vars.len();
+ break;
+ },
&QueryTerm::Term(ref inner_term) =>
if let GenContext::Head = self.term_loc {
result.push(term);
let val = self.try_functor();
self.p = self.cp;
val
- }),
- &ControlInstruction::Goto(p, arity) => {
+ }),
+ &ControlInstruction::GotoExecute(p, arity) => {
self.num_of_args = arity;
self.b0 = self.b;
self.p = CodePtr::DirEntry(p);
self.unify(a1, Addr::Con(Constant::Number(a2)));
self.p = self.cp;
},
+ &ControlInstruction::JmpByCall(arity, ref offset) => {
+ self.cp = self.p + 1;
+ self.num_of_args = arity;
+ self.b0 = self.b;
+ self.p += offset.get();
+ },
+ &ControlInstruction::JmpByExecute(arity, ref offset) => {
+ self.num_of_args = arity;
+ self.b0 = self.b;
+ self.p += offset.get();
+ },
&ControlInstruction::Proceed =>
self.p = self.cp,
&ControlInstruction::ThrowCall => {
use std::mem::swap;
use std::ops::Index;
use std::rc::Rc;
-use std::vec::Vec;
pub struct Machine {
ms: machine_state::MachineState,
self.ms.atom_tbl.clone()
}
- fn add_user_code<'a>(&mut self, name: TabledRc<Atom>,
- arity: usize, offset: usize)
- -> EvalSession<'a>
+ pub fn add_user_code<'a>(&mut self, name: TabledRc<Atom>, arity: usize, mut code: Code)
+ -> EvalSession<'a>
{
match self.code_dir.get(&(name.clone(), arity)) {
Some(&(PredicateKeyType::BuiltIn, _)) =>
_ => {}
};
+ let offset = self.code.len();
+
+ self.code.append(&mut code);
self.code_dir.insert((name, arity), (PredicateKeyType::User, offset));
+
EvalSession::EntrySuccess
}
- pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a>
- {
- match fact {
- &Term::Clause(_, ref name, ..) | &Term::Constant(_, Constant::Atom(ref name)) => {
- let p = self.code.len();
- let arity = fact.arity();
-
- self.code.append(&mut code);
- self.add_user_code(name.clone(), arity, p)
- },
- _ => EvalSession::NamelessEntry
- }
- }
-
- pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a>
- {
- match &rule.head.0 {
- &QueryTerm::Term(Term::Clause(_, ref name, ..))
- | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
- let p = self.code.len();
- let arity = rule.head.0.arity();
-
- self.code.append(&mut code);
- self.add_user_code(name.clone(), arity, p)
- },
- _ => EvalSession::NamelessEntry
- }
- }
-
- pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
- -> EvalSession<'a>
- {
- let p = self.code.len();
-
- if let Some(ref clause) = clauses.first() {
- if let Some(name) = clause.name() {
- let arity = clause.arity();
-
- self.code.append(&mut code);
- self.add_user_code(name.clone(), arity, p)
- } else {
- EvalSession::NamelessEntry
- }
- } else {
- EvalSession::ImpermissibleEntry(String::from("predicate must have clauses."))
- }
- }
-
fn cached_query_size(&self) -> usize {
match &self.cached_query {
&Some(ref query) => query.len(),
},
_ => {}
}
-
+
self.ms.p = CodePtr::TopLevel(cn, p);
}
)
}
-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! goto {
+macro_rules! goto_execute {
($line:expr, $arity:expr) => (
- Line::Control(ControlInstruction::Goto($line, $arity))
+ Line::Control(ControlInstruction::GotoExecute($line, $arity))
)
}
CompareNumberQT::Equal
)
}
+
+macro_rules! jmp_call {
+ ($arity:expr, $offset:expr) => (
+ Line::Control(ControlInstruction::JmpByCall($arity, $offset))
+ )
+}
-Subproject commit aa164cabe63b508a1227f15e4bb40b517717a2f3
+Subproject commit 9e80f2bd8268425c2128772b336f616be8d2c5d8
use prolog::heap_print::*;
use prolog::io::*;
use prolog::machine::*;
-use prolog::parser::toplevel::*;
use std::collections::HashSet;
use std::mem::swap;
-> Vec<HashSet<String>>
{
let mut output = TestOutputter::new();
+
output = wam.heap_view(&heap_locs, output);
output.cache();
-> Vec<HashSet<String>>
{
let mut output = TestOutputter::new();
+
output = wam.heap_view(&heap_locs, output);
output.cache();
pub fn submit(wam: &mut Machine, buffer: &str) -> bool
{
wam.reset();
-
- match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
+
+ match parse_code(wam, buffer) {
Ok(tl) =>
- match eval(wam, &tl) {
+ match compile(wam, &tl) {
EvalSession::InitialQuerySuccess(_, _) |
EvalSession::EntrySuccess |
EvalSession::SubsequentQuerySuccess =>
{
wam.reset();
- match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
+ match parse_code(wam, buffer) {
Ok(tl) =>
- match eval(wam, &tl) {
+ match compile(wam, &tl) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
result == collect_test_output(wam, alloc_locs, heap_locs),
EvalSession::EntrySuccess => true,
{
wam.reset();
- match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
+ match parse_code(wam, buffer) {
Ok(tl) =>
- match eval(wam, &tl) {
+ match compile(wam, &tl) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
result == collect_test_output_with_limit(wam, alloc_locs,
heap_locs, limit),