add assertz/1 and asserta/1
This commit is contained in:
92
src/prolog/machine/dynamic_database.rs
Normal file
92
src/prolog/machine/dynamic_database.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use prolog::compile::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::machine::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::num::ToPrimitive;
|
||||
|
||||
impl Machine {
|
||||
fn get_dynamic_predicate_key(&self) -> PredicateKey {
|
||||
let name = self.machine_st[temp_v!(3)].clone();
|
||||
let arity = self.machine_st[temp_v!(4)].clone();
|
||||
|
||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||
Addr::Con(Constant::Number(Number::Integer(arity))) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
(name, arity)
|
||||
}
|
||||
|
||||
fn print_new_dynamic_clause(&self, addrs: VecDeque<Addr>) -> String
|
||||
{
|
||||
let mut output = PrinterOutputter::new();
|
||||
let (name, arity) = self.get_dynamic_predicate_key();
|
||||
|
||||
output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity)
|
||||
.as_str());
|
||||
|
||||
for addr in addrs {
|
||||
let mut printer = HCPrinter::new(&self.machine_st, output);
|
||||
printer.quoted = true;
|
||||
|
||||
output = printer.print(addr);
|
||||
output.append(". ");
|
||||
}
|
||||
|
||||
output.result()
|
||||
}
|
||||
|
||||
fn handle_eval_result_from_dynamic_compile(&mut self, result: EvalSession)
|
||||
{
|
||||
if let EvalSession::Error(e) = result {
|
||||
println!("{}\r", e);
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace)
|
||||
{
|
||||
let stub = MachineError::functor_stub(place.predicate_name(), 1);
|
||||
|
||||
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
||||
Ok(addrs) => {
|
||||
let mut addrs = VecDeque::from(addrs);
|
||||
let added_clause = self.machine_st[temp_v!(1)].clone();
|
||||
|
||||
place.push_to_queue(&mut addrs, added_clause);
|
||||
self.print_new_dynamic_clause(addrs)
|
||||
},
|
||||
Err(err) =>
|
||||
return self.machine_st.throw_exception(err)
|
||||
};
|
||||
|
||||
let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
|
||||
|
||||
let result = compile_user_module(self, pred_str.as_bytes());
|
||||
self.machine_st = machine_st;
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(result);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn dynamic_transaction(&mut self, trans_type: DynamicTransactionType, p: LocalCodePtr)
|
||||
{
|
||||
match trans_type {
|
||||
DynamicTransactionType::Abolish => {},
|
||||
DynamicTransactionType::Assert(place) =>
|
||||
self.recompile_dynamic_predicate(place),
|
||||
DynamicTransactionType::Retract(idx) => {}
|
||||
}
|
||||
|
||||
self.machine_st.p = CodePtr::Local(p);
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,6 @@ 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 }
|
||||
@@ -160,19 +153,6 @@ 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
|
||||
|
||||
@@ -8,6 +8,7 @@ use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
|
||||
mod attributed_variables;
|
||||
mod dynamic_database;
|
||||
mod machine_errors;
|
||||
pub(super) mod machine_state;
|
||||
pub(super) mod term_expansion;
|
||||
@@ -69,19 +70,19 @@ impl IndexStore {
|
||||
-> bool
|
||||
{
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) =>
|
||||
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)
|
||||
@@ -557,8 +558,23 @@ impl Machine {
|
||||
|
||||
match self.machine_st.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
CodePtr::DynamicTransaction(trans_type, p) => {},
|
||||
// self.dynamic_transaction(trans_type, p),
|
||||
CodePtr::DynamicTransaction(trans_type, p) => {
|
||||
// self.code_repo.cached_query is about to be overwritten by the term expander,
|
||||
// so hold onto it locally and restore it after the compiler has finished.
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
self.dynamic_transaction(trans_type, p);
|
||||
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
}
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
break;
|
||||
}
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
},
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
|
||||
@@ -230,6 +230,20 @@ impl MachineState {
|
||||
-> CallResult
|
||||
{
|
||||
match ct {
|
||||
&SystemClauseType::AssertDynamicPredicateToFront => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::AssertDynamicPredicateToBack => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Back);
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::LiftedHeapLength => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len()));
|
||||
@@ -260,7 +274,6 @@ impl MachineState {
|
||||
};
|
||||
},
|
||||
&SystemClauseType::CopyToLiftedHeap =>
|
||||
// now, stagger everything down by the length of the heap + lh offset.
|
||||
match self.store(self.deref(self[temp_v!(1)].clone())) {
|
||||
Addr::Con(Constant::Usize(lh_offset)) => {
|
||||
let copy_target = self[temp_v!(2)].clone();
|
||||
@@ -304,10 +317,10 @@ impl MachineState {
|
||||
self.heap[h+1] = HeapCellValue::Addr(Addr::HeapCell(l+1));
|
||||
self.trail(TrailRef::AttrVarLink(h+1, Addr::Lis(l)));
|
||||
},
|
||||
_ => {}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
_ => unreachable!()
|
||||
}
|
||||
},
|
||||
&SystemClauseType::DynamicModuleResolution => {
|
||||
@@ -764,7 +777,6 @@ impl MachineState {
|
||||
},
|
||||
&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) =>
|
||||
|
||||
Reference in New Issue
Block a user