let atom_tbl = wam.atom_tbl();
let flags = wam.machine_flags();
- let index = MachineCodeIndices {
- code_dir: &mut wam.code_dir,
- op_dir: &mut wam.op_dir,
- };
+ let indices = machine_code_indices!(&mut wam.code_dir, &mut wam.op_dir, &mut HashMap::new());
- let mut worker = TopLevelWorker::new(buffer.as_bytes(), atom_tbl, flags, index);
+ let mut worker = TopLevelWorker::new(buffer.as_bytes(), atom_tbl, flags, indices);
worker.parse_code()
}
let mut code = try_eval_session!(compile_relation(&tl, false, wam.machine_flags()));
try_eval_session!(compile_appendix(&mut code, queue, false, wam.machine_flags()));
- if !code.is_empty() {
+ if !code.is_empty() {
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
} else {
EvalSession::from(SessionError::ImpermissibleEntry(String::from("no code generated.")))
}
pub fn compile_user_module(wam: &mut Machine, src_str: &str) -> EvalSession {
- let mut indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir());
+ let mut indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
+ &mut HashMap::new());
if let Some(ref builtins) = wam.modules.get(&clause_name!("builtins")) {
indices.use_module(builtins);
SetDoubleQuotes,
SkipMaxList,
Succeed,
- UnwindStack
+ UnwindStack,
+ CompileAndRunQuery
}
impl SystemClauseType {
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
&SystemClauseType::Succeed => clause_name!("$succeed"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
+ &SystemClauseType::CompileAndRunQuery => clause_name!("$compile_and_run_query")
}
}
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
+ ("$compile_and_run_query", 1) => Some(SystemClauseType::CompileAndRunQuery),
_ => None
}
}
handle_ball(_, _, _) :- '$unwind_stack'.
throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'.
+
+repl :- read(X), '$compile_and_run_query'(X), repl.
};
stub.extend(err.into_iter());
+
MachineError { stub, from: ErrorProvenance::Constructed }
}
use prolog::and_stack::*;
use prolog::copier::*;
use prolog::heap_print::*;
+use prolog::machine::MachineCodeIndices;
use prolog::machine::machine_errors::*;
use prolog::num::{BigInt, BigUint, Zero, One};
use prolog::or_stack::*;
CodeDirs { code_dir, op_dir, modules }
}
- pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
- {
- match in_mod.as_str() {
- "user" | "builtin" => self.code_dir.get(&(name, arity)).cloned(),
- _ =>
- match self.modules.get(&in_mod) {
- Some(&Module { ref code_dir, .. }) =>
- code_dir.get(&(name, arity)).cloned().map(CodeIndex::from),
- None => None
- }
- }
- }
-
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<ModuleCodeIndex> {
self.modules.get(&in_mod)
.and_then(|ref module| module.code_dir.get(&(name, arity)))
fn op_dir(&self) -> &OpDir;
}
+fn get_code_index(code_dir: &CodeDir, modules: &ModuleDir, key: PredicateKey, module: ClauseName)
+ -> Option<CodeIndex>
+{
+ match module.as_str() {
+ "user" | "builtin" => code_dir.get(&key).cloned(),
+ _ => modules.get(&module).and_then(|ref module| {
+ module.code_dir.get(&key).cloned().map(CodeIndex::from)
+ })
+ }
+}
+
+impl<'a> CodeDirsAdapter<'a> for MachineCodeIndices<'a> {
+ fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
+ get_code_index(&self.code_dir, &self.modules, key, module)
+ }
+
+ fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
+ self.op_dir.get(&key).cloned()
+ }
+
+ fn op_dir(&self) -> &OpDir {
+ &self.op_dir
+ }
+}
+
impl<'a> CodeDirsAdapter<'a> for CodeDirs<'a> {
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
- self.get(key.0, key.1, module)
+ get_code_index(&self.code_dir, &self.modules, key, module)
}
fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
}
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
- idx: CodeIndex, code_dirs: CodeDirs)
- -> CallResult
+ idx: CodeIndex, indices: MachineCodeIndices)
+ -> CallResult
{
if machine_st.last_call {
- self.try_execute(machine_st, name, arity, idx, code_dirs)
+ self.try_execute(machine_st, name, arity, idx, indices)
} else {
- self.try_call(machine_st, name, arity, idx, code_dirs)
+ self.try_call(machine_st, name, arity, idx, indices)
}
}
fn try_call<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
- idx: CodeIndex, code_dirs: CodeDirs)
+ idx: CodeIndex, indices: MachineCodeIndices<'a>)
-> CallResult
{
match idx.0.borrow().0 {
let module_name = idx.0.borrow().1.clone();
let h = machine_st.heap.h;
- if let Some(ref idx) = code_dirs.get_code_index((name.clone(), arity), module_name.clone())
+ if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
{
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
call_at_index(machine_st, module_name, arity, compiled_tl_index);
}
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName,
- arity: usize, idx: CodeIndex, code_dirs: CodeDirs)
+ arity: usize, idx: CodeIndex, indices: MachineCodeIndices<'a>)
-> CallResult
{
match idx.0.borrow().0 {
let module_name = idx.0.borrow().1.clone();
let h = machine_st.heap.h;
- if let Some(ref idx) = code_dirs.get_code_index((name.clone(), arity), module_name.clone())
+ if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
{
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
execute_at_index(machine_st, module_name, arity, compiled_tl_index);
}
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
- code_dirs: CodeDirs)
+ indices: MachineCodeIndices<'a>) //code_dirs: CodeDirs)
-> CallResult
{
- match ct {
+ match ct {
&BuiltInClauseType::AcyclicTerm => {
let addr = machine_st[temp_v!(1)].clone();
machine_st.fail = machine_st.is_cyclic_term(addr);
&BuiltInClauseType::Read => {
let mut reader = Reader::new(machine_st);
- match reader.read_stdin(code_dirs.op_dir()) {
+ match reader.read_stdin(&indices.op_dir) {
Ok(offset) => {
let addr = reader.machine_st[temp_v!(1)].clone();
reader.machine_st.unify(addr, Addr::HeapCell(offset));
let stub = MachineError::functor_stub(clause_name!("read"), 1);
let err = MachineError::syntax_error(h, e);
let err = reader.machine_st.error_form(err, stub);
-
+
return Err(err);
}
};
} else {
false
};
-
+
return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::PartialString => {
}
fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize,
- code_dirs: CodeDirs)
+ indices: MachineCodeIndices<'a>) //code_dirs: CodeDirs)
-> CallResult
{
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
},
ClauseType::BuiltIn(built_in) => {
machine_st.setup_built_in_call(built_in.clone());
- self.call_builtin(machine_st, &built_in, code_dirs)?;
+ self.call_builtin(machine_st, &built_in, indices)?;
},
ClauseType::Inlined(inlined) =>
machine_st.execute_inlined(&inlined),
ClauseType::Op(..) | ClauseType::Named(..) =>
- if let Some(idx) = code_dirs.get_code_index((name.clone(), arity), user) {
- self.context_call(machine_st, name, arity, idx, code_dirs)?;
+ if let Some(idx) = indices.get_code_index((name.clone(), arity), user) {
+ self.context_call(machine_st, name, arity, idx, indices)?;
} else {
let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
impl CallPolicy for CWILCallPolicy {
fn context_call<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName,
- arity: usize, idx: CodeIndex, code_dirs: CodeDirs)
+ arity: usize, idx: CodeIndex, indices: MachineCodeIndices<'a>)
-> CallResult
{
- self.prev_policy.context_call(machine_st, name, arity, idx, code_dirs)?;
+ self.prev_policy.context_call(machine_st, name, arity, idx, indices)?;
self.increment(machine_st)
}
}
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
- code_dirs: CodeDirs)
+ indices: MachineCodeIndices<'a>)
-> CallResult
{
- self.prev_policy.call_builtin(machine_st, ct, code_dirs)?;
+ self.prev_policy.call_builtin(machine_st, ct, indices)?;
self.increment(machine_st)
}
- fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize,
- code_dirs: CodeDirs)
+ fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, indices: MachineCodeIndices<'a>)
-> CallResult
{
- self.prev_policy.call_n(machine_st, arity, code_dirs)?;
+ self.prev_policy.call_n(machine_st, arity, indices)?;
self.increment(machine_st)
}
}
use prolog::copier::*;
use prolog::heap_iter::*;
use prolog::heap_print::*;
+use prolog::machine::MachineCodeIndices;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_state::*;
use prolog::num::{Integer, Signed, ToPrimitive, Zero};
self.p += 1;
}
- fn handle_call_clause<'a>(&mut self, code_dirs: CodeDirs<'a>,
+ fn handle_call_clause<'a>(&mut self, indices: MachineCodeIndices<'a>,
call_policy: &mut Box<CallPolicy>,
cut_policy: &mut Box<CutPolicy>,
ct: &ClauseType,
match ct {
&ClauseType::BuiltIn(ref ct) =>
- try_or_fail!(self, call_policy.call_builtin(self, ct, code_dirs)),
+ try_or_fail!(self, call_policy.call_builtin(self, ct, indices)),
&ClauseType::CallN =>
- try_or_fail!(self, call_policy.call_n(self, arity, code_dirs)),
+ try_or_fail!(self, call_policy.call_n(self, arity, indices)),
&ClauseType::Inlined(ref ct) =>
self.execute_inlined(ct),
&ClauseType::Named(ref name, ref idx) | &ClauseType::Op(ref name, _, ref idx) =>
try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
- code_dirs)),
+ indices)),
&ClauseType::System(ref ct) =>
- try_or_fail!(self, self.system_call(ct, code_dirs, call_policy, cut_policy))
+ try_or_fail!(self, self.system_call(ct, indices, call_policy, cut_policy))
};
}
- pub(super) fn execute_ctrl_instr<'a>(&mut self, code_dirs: CodeDirs<'a>,
+ pub(super) fn execute_ctrl_instr<'a>(&mut self, indices: MachineCodeIndices<'a>,
call_policy: &mut Box<CallPolicy>,
cut_policy: &mut Box<CutPolicy>,
instr: &ControlInstruction)
&ControlInstruction::Allocate(num_cells) =>
self.allocate(num_cells),
&ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) =>
- self.handle_call_clause(code_dirs, call_policy, cut_policy, ct, arity, lco,
+ self.handle_call_clause(indices, call_policy, cut_policy, ct, arity, lco,
use_default_cp),
&ControlInstruction::Deallocate => self.deallocate(),
&ControlInstruction::JmpBy(arity, offset, _, lco) => {
pub struct MachineCodeIndices<'a> {
pub(super) code_dir: &'a mut CodeDir,
pub(super) op_dir: &'a mut OpDir,
+ pub(super) modules: &'a mut ModuleDir
}
impl<'a> MachineCodeIndices<'a> {
ct => ct
}
}
+
+ #[inline]
+ pub(super) fn to_code_dirs(self) -> CodeDirs<'a> {
+ CodeDirs { code_dir: self.code_dir,
+ op_dir: self.op_dir,
+ modules: self.modules }
+ }
}
pub struct Machine {
cut_policy: Box::new(DefaultCutPolicy {}),
code: Code::new(),
code_dir: CodeDir::new(),
- term_dir: TermDir::new(),
op_dir: default_op_dir(),
+ term_dir: TermDir::new(),
modules: HashMap::new(),
cached_query: None
};
- let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir());
+ let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
+ &mut HashMap::new());
+
compile_listing(&mut wam, BUILTINS, indices);
compile_user_module(&mut wam, LISTS);
if let Some(mut module) = self.modules.remove(&name) {
let result = {
- let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir);
+ let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
+ &mut self.modules);
indices.use_qualified_module(&mut module, &exports)
};
if let Some(mut module) = self.modules.remove(&name) {
let result = {
- let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir);
+ let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
+ &mut self.modules);
indices.use_module(&mut module)
};
Line::Cut(ref cut_instr) =>
self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
Line::Control(ref control_instr) => {
- let code_dirs = CodeDirs::new(&self.code_dir, &self.op_dir,
- &self.modules);
- self.ms.execute_ctrl_instr(code_dirs, &mut self.call_policy,
+ let indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
+ &mut self.modules);
+// let code_dirs = CodeDirs::new(&self.code_dir, &self.op_dir,
+// &self.modules);
+ self.ms.execute_ctrl_instr(indices, &mut self.call_policy,
&mut self.cut_policy, control_instr)
},
Line::Fact(ref fact) => {
use prolog_parser::ast::*;
use prolog::instructions::*;
+use prolog::machine::MachineCodeIndices;
use prolog::machine::machine_errors::*;
use prolog::machine::machine_state::*;
use prolog::num::{ToPrimitive, Zero};
use prolog::num::bigint::{BigInt};
+//use prolog::term_writer::*;
use std::rc::Rc;
Ok(())
}
+ #[inline]
fn install_new_block(&mut self, r: RegType) -> usize {
self.block = self.b;
self.block
}
+ #[inline]
fn set_p(&mut self) {
if self.last_call {
self.p = CodePtr::Local(self.cp.clone());
}
pub(super) fn system_call<'a>(&mut self, ct: &SystemClauseType,
- code_dirs: CodeDirs<'a>,
+ indices: MachineCodeIndices<'a>,
call_policy: &mut Box<CallPolicy>,
cut_policy: &mut Box<CutPolicy>,)
-> CallResult
let prev_block = self.block;
if cut_policy.downcast_ref::<SCCCutPolicy>().is_err() {
- let (r_c_w_h, r_c_wo_h) = code_dirs.get_cleaner_sites();
+ let (r_c_w_h, r_c_wo_h) = indices.to_code_dirs().get_cleaner_sites();
*cut_policy = Box::new(SCCCutPolicy::new(r_c_w_h, r_c_wo_h));
}
return Err(err);
},
&SystemClauseType::Succeed => {},
- &SystemClauseType::UnwindStack => self.unwind_stack()
+ &SystemClauseType::UnwindStack => self.unwind_stack(),
+ &SystemClauseType::CompileAndRunQuery => {}
+/* let addr = self[temp_v!(1)].clone();
+
+ match term_write(&self, addr) {
+ Err(e) => machine_error
+ Ok(term) =>
+ }*/
};
self.set_p();
}
macro_rules! machine_code_indices {
- ($code_dir:expr, $op_dir:expr) => ( //, $modules:expr) => (
- MachineCodeIndices { code_dir: $code_dir, op_dir: $op_dir } //, modules: $modules }
+ ($code_dir:expr, $op_dir:expr, $modules:expr) => ( //, $modules:expr) => (
+ MachineCodeIndices { code_dir: $code_dir, op_dir: $op_dir,
+ modules: $modules} //, modules: $modules }
)
}
extern crate prolog_parser;
#[macro_use] pub mod instructions;
-pub mod and_stack;
-#[macro_use] pub mod macros;
-#[macro_use] pub mod allocator;
-pub mod toplevel;
+mod and_stack;
+#[macro_use] mod macros;
+#[macro_use] mod allocator;
+mod toplevel;
pub mod machine;
pub mod compile;
-pub mod arithmetic;
-pub mod codegen;
-pub mod copier;
-pub mod debray_allocator;
-pub mod fixtures;
-pub mod heap_iter;
-pub mod indexing;
+mod arithmetic;
+mod codegen;
+mod copier;
+mod debray_allocator;
+mod fixtures;
+mod heap_iter;
+mod indexing;
pub mod io;
-pub mod iterators;
-pub mod or_stack;
+mod iterators;
+mod or_stack;
pub mod heap_print;
-pub mod targets;
-pub mod read;
+mod targets;
+mod read;
--- /dev/null
+use prolog_parser::ast::*;
+
+use prolog::heap_iter::*;
+use prolog::instructions::HeapCellValue;
+use prolog::machine::machine_state::MachineState;
+
+pub fn term_write(machine_st: &'a MachineState, addr: Addr) -> Result<Term, ParserError> {
+ let pre_order_iter = HCPreOrderIterator::new(machine_st, addr);
+ let post_order_iter = HCPostOrderIterator::new(pre_order_iter);
+ let acyclic_post_order_iter = HCAcyclicIterator::new(post_order_iter);
+
+ let mut stack = vec![];
+
+ for value in acyclic_post_order_iter {
+ match value {
+ HeapCellValue::NamedStr(arity, name, fixity)
+ if stack.len() >= arity => {
+ let subterms: Vec<_> = stack[stack.len() - arity ..].drain().collect();
+ stack.push(Box::new(Term::Clause(Cell::default(), name, subterms, fixity)));
+ },
+ HeapCellValue::Addr(Addr::Con(constant)) =>
+ stack.push(Box::new(Term::Constant(Cell::default(), constant))),
+ HeapCellValue::Addr(Addr::Lis(_))
+ if stack.len() >= 2 => {
+ let subterms: Vec<_> = stack[stack.len() - 2 ..].drain().collect();
+ stack.push(Box::new(Term::Cons(Cell::default(), subterms[0], subterms[1])));
+ },
+ HeapCellValue::Addr(Addr::HeapCell(h)) =>
+ stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}", h))))),
+ HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
+ stack.push(Box::new(Term::Var(Cell::default(), Rc::new(format!("_{}_{}", sc, fr))))),
+ _ => return Err(ParserError::IncompleteReduction)
+ }
+ }
+
+ if let Some(term) = stack.pop() {
+ if stack.is_empty() {
+ return Ok(term);
+ }
+ }
+
+ Err(ParserError::IncompleteReduction)
+}
}
}
- fn pre_query_term(&mut self, idx: &mut MachineCodeIndices, term: Term)
- -> Result<QueryTerm, ParserError>
+ fn pre_query_term(&mut self, idx: &mut MachineCodeIndices, term: Term) -> Result<QueryTerm, ParserError>
{
match term {
Term::Clause(r, name, mut subterms, fixity) =>