start enabling the dynamic database
This commit is contained in:
@@ -25,6 +25,13 @@ impl MachineError {
|
||||
functor!("/", 2, [name, heap_integer!(arity)], (400, YFX))
|
||||
}
|
||||
|
||||
pub(super) fn static_modification_error(perm_error: PermissionError, culprit: Addr) -> Self {
|
||||
let stub = functor!("permission_error", 3, [heap_atom!(perm_error.as_str()),
|
||||
heap_atom!("static_procedure"),
|
||||
HeapCellValue::Addr(culprit)]);
|
||||
MachineError { stub, from: ErrorProvenance::Received }
|
||||
}
|
||||
|
||||
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
||||
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
|
||||
MachineError { stub, from: ErrorProvenance::Received }
|
||||
@@ -153,6 +160,19 @@ impl ValidType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum PermissionError {
|
||||
Modify
|
||||
}
|
||||
|
||||
impl PermissionError {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
PermissionError::Modify => "modify"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum DomainError {
|
||||
NotLessThanZero
|
||||
|
||||
@@ -231,6 +231,7 @@ impl MachineState {
|
||||
self.p = dir_entry!(p);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn execute_at_index(&mut self, arity: usize, p: usize)
|
||||
{
|
||||
self.num_of_args = arity;
|
||||
|
||||
@@ -2208,7 +2208,7 @@ impl MachineState {
|
||||
try_or_fail!(self, call_policy.compile_hook(self, hook)),
|
||||
&ClauseType::Inlined(ref ct) =>
|
||||
self.execute_inlined(ct),
|
||||
&ClauseType::Named(ref name, ref idx) | &ClauseType::Op(OpDecl(.., ref name), ref idx) =>
|
||||
&ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(OpDecl(.., ref name), ref idx) =>
|
||||
try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
|
||||
indices)),
|
||||
&ClauseType::System(ref ct) =>
|
||||
|
||||
@@ -23,11 +23,27 @@ use std::mem;
|
||||
use std::ops::Index;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type InSituCodeDir = HashMap<PredicateKey, usize>;
|
||||
//pub type DynamicPredicateClauses = VecDeque<(PredicateClause, VecDeque<TopLevel>)>;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct DynamicPredicateInfo {
|
||||
pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value.
|
||||
// clauses: DynamicPredicateClauses
|
||||
}
|
||||
|
||||
impl Default for DynamicPredicateInfo {
|
||||
fn default() -> Self {
|
||||
DynamicPredicateInfo { clauses_subsection_p: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub type InSituCodeDir = HashMap<PredicateKey, usize>;
|
||||
pub type DynamicCodeDir = HashMap<PredicateKey, DynamicPredicateInfo>;
|
||||
|
||||
pub struct IndexStore {
|
||||
pub(super) atom_tbl: TabledData<Atom>,
|
||||
pub(super) code_dir: CodeDir,
|
||||
pub(super) dynamic_code_dir: DynamicCodeDir,
|
||||
pub(super) in_situ_code_dir: InSituCodeDir,
|
||||
pub(super) op_dir: OpDir,
|
||||
pub(super) modules: ModuleDir,
|
||||
@@ -48,6 +64,24 @@ impl<'a, T> RefOrOwned<'a, T> {
|
||||
}
|
||||
|
||||
impl IndexStore {
|
||||
pub fn predicate_exists(&self, name: ClauseName, arity: usize,
|
||||
op_spec: Option<(usize, Specifier)>)
|
||||
-> bool
|
||||
{
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) =>
|
||||
self.code_dir.contains_key(&(name, arity)),
|
||||
ClauseType::Op(op_decl, ..) =>
|
||||
self.code_dir.contains_key(&(op_decl.name(), op_decl.arity())),
|
||||
_ => true
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option<DynamicPredicateInfo> {
|
||||
self.dynamic_code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
|
||||
self.modules.remove(&name)
|
||||
@@ -63,6 +97,7 @@ impl IndexStore {
|
||||
IndexStore {
|
||||
atom_tbl: TabledData::new(Rc::new("user".to_string())),
|
||||
code_dir: CodeDir::new(),
|
||||
dynamic_code_dir: DynamicCodeDir::new(),
|
||||
in_situ_code_dir: InSituCodeDir::new(),
|
||||
op_dir: default_op_dir(),
|
||||
modules: ModuleDir::new(),
|
||||
@@ -204,7 +239,8 @@ impl CodeRepo {
|
||||
},
|
||||
&CodePtr::VerifyAttrInterrupt(p) =>
|
||||
Some(RefOrOwned::Borrowed(&self.code[p])),
|
||||
|
||||
&CodePtr::DynamicTransaction(..) =>
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,11 +431,11 @@ impl Machine {
|
||||
// ensure we don't try to overwrite an existing predicate from a different module.
|
||||
if !existing_idx.is_undefined() && !idx.is_undefined() {
|
||||
// allow the overwriting of user-level predicates by all other predicates.
|
||||
if existing_idx.module_name().as_str() == "user" {
|
||||
if existing_idx.module_name() == key.0.owning_module() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if existing_idx.module_name().as_str() != idx.module_name().as_str() {
|
||||
if existing_idx.module_name() != idx.module_name() {
|
||||
let err_str = format!("{}/{} from module {}", key.0, key.1,
|
||||
existing_idx.module_name().as_str());
|
||||
return Err(SessionError::CannotOverwriteImport(err_str));
|
||||
@@ -464,8 +500,7 @@ impl Machine {
|
||||
let mut heap_locs = HashMap::new();
|
||||
|
||||
self.code_repo.cached_query = code;
|
||||
self.machine_st.run_query(&mut self.indices, &mut self.policies, &mut self.code_repo,
|
||||
&alloc_locs, &mut heap_locs);
|
||||
self.run_query(&alloc_locs, &mut heap_locs);
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.fail(&heap_locs)
|
||||
@@ -474,6 +509,67 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
||||
heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
&VarData::Perm(p) if p > 0 =>
|
||||
if !heap_locs.contains_key(var) {
|
||||
let e = self.machine_st.e;
|
||||
let r = var_data.as_reg_type().reg_num();
|
||||
let addr = self.machine_st.and_stack[e][r].clone();
|
||||
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
},
|
||||
&VarData::Temp(cn, _, _) if cn == chunk_num => {
|
||||
let r = var_data.as_reg_type();
|
||||
|
||||
if r.reg_num() != 0 {
|
||||
let addr = self.machine_st[r].clone();
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query());
|
||||
|
||||
while self.machine_st.p < end_ptr {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.machine_st.p {
|
||||
match &self.code_repo[LocalCodePtr::TopLevel(cn, p)] {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.record_var_places(cn, alloc_locs, heap_locs);
|
||||
cn += 1;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.machine_st.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo);
|
||||
|
||||
match self.machine_st.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
CodePtr::DynamicTransaction(trans_type, p) => {},
|
||||
// self.dynamic_transaction(trans_type, p),
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn continue_query(&mut self, alloc_l: &AllocVarDict, heap_l: &mut HeapVarDict) -> EvalSession
|
||||
{
|
||||
if !self.or_stack_is_empty() {
|
||||
@@ -484,8 +580,7 @@ impl Machine {
|
||||
return EvalSession::from(SessionError::QueryFailure);
|
||||
}
|
||||
|
||||
self.machine_st.run_query(&mut self.indices, &mut self.policies, &mut self.code_repo,
|
||||
alloc_l, heap_l);
|
||||
self.run_query(alloc_l, heap_l);
|
||||
|
||||
if self.machine_st.fail {
|
||||
self.fail(&heap_l)
|
||||
@@ -601,73 +696,12 @@ impl MachineState {
|
||||
self.fail = true,
|
||||
CodePtr::Local(LocalCodePtr::InSituDirEntry(p))
|
||||
if p < code_repo.in_situ_code.len() => {},
|
||||
CodePtr::Local(_) =>
|
||||
CodePtr::Local(_) | CodePtr::DynamicTransaction(..) =>
|
||||
break,
|
||||
CodePtr::VerifyAttrInterrupt(p) =>
|
||||
self.verify_attr_interrupt(p),
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
||||
heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
&VarData::Perm(p) if p > 0 =>
|
||||
if !heap_locs.contains_key(var) {
|
||||
let e = self.e;
|
||||
let r = var_data.as_reg_type().reg_num(); // crashes here.
|
||||
let addr = self.and_stack[e][r].clone();
|
||||
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
},
|
||||
&VarData::Temp(cn, _, _) if cn == chunk_num => {
|
||||
let r = var_data.as_reg_type();
|
||||
|
||||
if r.reg_num() != 0 {
|
||||
let addr = self[r].clone();
|
||||
heap_locs.insert(var.clone(), addr);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn run_query(&mut self, indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies, code_repo: &mut CodeRepo,
|
||||
alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
let end_ptr = top_level_code_ptr!(0, code_repo.size_of_cached_query());
|
||||
|
||||
while self.p < end_ptr {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.p {
|
||||
match &code_repo[LocalCodePtr::TopLevel(cn, p)] {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.record_var_places(cn, alloc_locs, heap_locs);
|
||||
cn += 1;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.query_stepper(indices, policies, code_repo);
|
||||
|
||||
match self.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +244,21 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&SystemClauseType::HeadIsDynamic => {
|
||||
let head = self[temp_v!(1)].clone();
|
||||
|
||||
self.fail = !match self.store(self.deref(head)) {
|
||||
Addr::Str(s) =>
|
||||
match self.heap[s].clone() {
|
||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||
indices.get_clause_subsection(name, arity).is_some(),
|
||||
_ => unreachable!()
|
||||
},
|
||||
Addr::Con(Constant::Atom(name, _)) =>
|
||||
indices.get_clause_subsection(name, 0).is_some(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
},
|
||||
&SystemClauseType::CopyToLiftedHeap =>
|
||||
// now, stagger everything down by the length of the heap + lh offset.
|
||||
match self.store(self.deref(self[temp_v!(1)].clone())) {
|
||||
@@ -562,6 +577,26 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&SystemClauseType::NoSuchPredicate => {
|
||||
let head = self[temp_v!(1)].clone();
|
||||
|
||||
self.fail = match self.store(self.deref(head)) {
|
||||
Addr::Str(s) =>
|
||||
match self.heap[s].clone() {
|
||||
HeapCellValue::NamedStr(arity, name, op_spec) =>
|
||||
indices.predicate_exists(name, arity, op_spec),
|
||||
_ => unreachable!()
|
||||
},
|
||||
Addr::Con(Constant::Atom(name, op_spec)) =>
|
||||
indices.predicate_exists(name, 0, op_spec),
|
||||
head => {
|
||||
let err = MachineError::type_error(ValidType::Callable, head);
|
||||
let stub = MachineError::functor_stub(clause_name!("clause"), 2);
|
||||
|
||||
return Err(self.error_form(err, stub));
|
||||
}
|
||||
};
|
||||
},
|
||||
&SystemClauseType::RedoAttrVarBindings => {
|
||||
let mut bindings = mem::replace(&mut self.attr_var_init.bindings, vec![]);
|
||||
|
||||
@@ -727,6 +762,30 @@ impl MachineState {
|
||||
|
||||
self.unify(a1, a2);
|
||||
},
|
||||
&SystemClauseType::GetClause => {
|
||||
let head = self[temp_v!(1)].clone();
|
||||
let body = self[temp_v!(2)].clone();
|
||||
|
||||
let subsection = match self.store(self.deref(head)) {
|
||||
Addr::Str(s) =>
|
||||
match self.heap[s].clone() {
|
||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||
indices.get_clause_subsection(name, arity),
|
||||
_ => unreachable!()
|
||||
},
|
||||
Addr::Con(Constant::Atom(name, _)) =>
|
||||
indices.get_clause_subsection(name, 0),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
match subsection {
|
||||
Some(dynamic_predicate_info) => {
|
||||
self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
|
||||
return Ok(());
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
&SystemClauseType::GetCutPoint => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
let a2 = Addr::Con(Constant::Usize(self.b0));
|
||||
|
||||
@@ -288,11 +288,16 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
fn print_with_locs(&self, target: usize, max_var_length: usize, var_dict: &HeapVarDict)
|
||||
-> PrinterOutputter
|
||||
pub(super)
|
||||
fn print_with_locs(&self, addr: Addr, var_dict: &HeapVarDict) -> PrinterOutputter
|
||||
{
|
||||
let output = PrinterOutputter::new();
|
||||
let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
|
||||
let mut printer = HCPrinter::from_heap_locs(&self, output, var_dict);
|
||||
let mut max_var_length = 0;
|
||||
|
||||
for var in var_dict.keys() {
|
||||
max_var_length = std::cmp::max(var.len(), max_var_length);
|
||||
}
|
||||
|
||||
printer.quoted = true;
|
||||
printer.numbervars = true;
|
||||
@@ -302,10 +307,12 @@ impl MachineState {
|
||||
// style variable names will be longer than the keys of the var_dict, and therefore
|
||||
// not equal to any of them.
|
||||
printer.numbervars_offset = pow(BigInt::from(10), max_var_length) * 26;
|
||||
|
||||
printer.see_all_locs();
|
||||
|
||||
printer.print(Addr::HeapCell(target))
|
||||
let mut output = printer.print(addr);
|
||||
|
||||
output.push_char('.');
|
||||
output
|
||||
}
|
||||
|
||||
fn try_expand_term(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
@@ -322,16 +329,15 @@ impl MachineState {
|
||||
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
|
||||
|
||||
code_repo.cached_query = code;
|
||||
self.run_query(indices, policies, code_repo, &AllocVarDict::new(), &mut HeapVarDict::new());
|
||||
self.query_stepper(indices, policies, code_repo);
|
||||
|
||||
if self.fail {
|
||||
self.reset();
|
||||
None
|
||||
} else {
|
||||
let &TermWriteResult { heap_loc: _, max_var_length, ref var_dict } = &term_write_result;
|
||||
let mut output = self.print_with_locs(h, max_var_length, var_dict);
|
||||
let &TermWriteResult { heap_loc: _, ref var_dict } = &term_write_result;
|
||||
let output = self.print_with_locs(Addr::HeapCell(h), var_dict);
|
||||
|
||||
output.push_char('.');
|
||||
self.reset();
|
||||
Some(output.result())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user