copy terms to global variable blackboard, fix attribute_goals//1
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.104"
|
version = "0.8.105"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
of a particular module, as a list of terms of the form
|
of a particular module, as a list of terms of the form
|
||||||
Module:put_atts(V, ListOfAtts). */
|
Module:put_atts(V, ListOfAtts). */
|
||||||
'$default_attr_list'(Module, V) -->
|
'$default_attr_list'(Module, V) -->
|
||||||
{ Module:get_atts(V, Attributes) },
|
( { Module:get_atts(V, Attributes) } ->
|
||||||
'$default_attr_list'(Attributes, Module, V).
|
'$default_attr_list'(Attributes, Module, V)
|
||||||
|
; []
|
||||||
|
).
|
||||||
|
|
||||||
'$default_attr_list'([PG | PGs], Module, AttrVar) -->
|
'$default_attr_list'([PG | PGs], Module, AttrVar) -->
|
||||||
( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)]
|
( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)]
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ forall(Generate, Test) :-
|
|||||||
|
|
||||||
%% (non-)backtrackable global variables.
|
%% (non-)backtrackable global variables.
|
||||||
|
|
||||||
bb_put(Key, Value) :- atom(Key), !, '$store_global_var'(Key, Value).
|
bb_put(Key, Value) :- atom(Key),
|
||||||
|
!,
|
||||||
|
'$store_global_var'(Key, Value).
|
||||||
bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)).
|
bb_put(Key, _) :- throw(error(type_error(atom, Key), bb_put/2)).
|
||||||
|
|
||||||
bb_b_put(Key, NewValue) :-
|
bb_b_put(Key, NewValue) :-
|
||||||
|
|||||||
@@ -1070,14 +1070,19 @@ pub fn compile_special_form<R: Read>(
|
|||||||
wam: &mut Machine,
|
wam: &mut Machine,
|
||||||
src: ParsingStream<R>,
|
src: ParsingStream<R>,
|
||||||
listing_src: ClauseName,
|
listing_src: ClauseName,
|
||||||
) -> Result<Code, SessionError> {
|
) -> Result<usize, SessionError> {
|
||||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||||
|
|
||||||
let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src);
|
let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src);
|
||||||
let results = compiler.gather_items(wam, src, &mut indices)?;
|
let results = compiler.gather_items(wam, src, &mut indices)?;
|
||||||
|
|
||||||
compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)
|
let code = compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?;
|
||||||
|
let p = wam.code_repo.code.len();
|
||||||
|
|
||||||
|
add_toplevel_code(wam, code, indices);
|
||||||
|
|
||||||
|
Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
|||||||
|
|
||||||
pub(crate) fn copy_term<T: CopierTarget>(target: T, addr: Addr) {
|
pub(crate) fn copy_term<T: CopierTarget>(target: T, addr: Addr) {
|
||||||
let mut copy_term_state = CopyTermState::new(target);
|
let mut copy_term_state = CopyTermState::new(target);
|
||||||
copy_term_state.copy_term_impl(addr);
|
copy_term_state.copy_term_impl(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CopyTermState<T: CopierTarget> {
|
struct CopyTermState<T: CopierTarget> {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use prolog_parser::tabled_rc::*;
|
|||||||
use prolog::clause_types::*;
|
use prolog::clause_types::*;
|
||||||
use prolog::fixtures::*;
|
use prolog::fixtures::*;
|
||||||
use prolog::forms::*;
|
use prolog::forms::*;
|
||||||
|
use prolog::machine::Ball;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
@@ -454,7 +455,7 @@ pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
|||||||
// key type: module name, predicate indicator.
|
// key type: module name, predicate indicator.
|
||||||
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
||||||
|
|
||||||
pub type GlobalVarDir = IndexMap<ClauseName, Addr>;
|
pub type GlobalVarDir = IndexMap<ClauseName, Ball>;
|
||||||
|
|
||||||
pub struct IndexStore {
|
pub struct IndexStore {
|
||||||
pub(super) atom_tbl: TabledData<Atom>,
|
pub(super) atom_tbl: TabledData<Atom>,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use std::io::{stdout, Write};
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
pub(super) struct Ball {
|
pub struct Ball {
|
||||||
pub(super) boundary: usize, // ball.0
|
pub(super) boundary: usize, // ball.0
|
||||||
pub(super) stub: MachineStub, // ball.1
|
pub(super) stub: MachineStub, // ball.1
|
||||||
}
|
}
|
||||||
@@ -48,6 +48,22 @@ impl Ball {
|
|||||||
stub: mem::replace(&mut self.stub, vec![]),
|
stub: mem::replace(&mut self.stub, vec![]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn copy_and_align(&self, h: usize) -> MachineStub {
|
||||||
|
let diff = self.boundary as i64 - h as i64;
|
||||||
|
let mut stub = vec![];
|
||||||
|
|
||||||
|
for index in 0..self.stub.len() {
|
||||||
|
let heap_value = self.stub[index].clone();
|
||||||
|
|
||||||
|
stub.push(match heap_value {
|
||||||
|
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff),
|
||||||
|
_ => heap_value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
stub
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct CopyTerm<'a> {
|
pub(super) struct CopyTerm<'a> {
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.push_attr_var_binding(h, addr.clone());
|
self.push_attr_var_binding(h, addr.clone());
|
||||||
self.heap[h] = HeapCellValue::Addr(addr);
|
self.heap[h] = HeapCellValue::Addr(addr);
|
||||||
self.trail(TrailRef::Ref(Ref::AttrVar(h)));
|
self.trail(TrailRef::Ref(Ref::AttrVar(h)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,8 @@ impl MachineState {
|
|||||||
self.heap[h] = HeapCellValue::Addr(t1);
|
self.heap[h] = HeapCellValue::Addr(t1);
|
||||||
self.trail(TrailRef::Ref(Ref::HeapCell(h)));
|
self.trail(TrailRef::Ref(Ref::HeapCell(h)));
|
||||||
}
|
}
|
||||||
Some(Ref::AttrVar(h)) => return self.bind_attr_var(h, t1),
|
Some(Ref::AttrVar(h)) =>
|
||||||
|
self.bind_attr_var(h, t1),
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2091,26 +2092,6 @@ impl MachineState {
|
|||||||
self.fail = true;
|
self.fail = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn heap_ball_boundary_diff(&self) -> i64 {
|
|
||||||
self.ball.boundary as i64 - self.heap.h as i64
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn copy_and_align_ball(&self) -> MachineStub {
|
|
||||||
let diff = self.heap_ball_boundary_diff();
|
|
||||||
let mut stub = vec![];
|
|
||||||
|
|
||||||
for index in 0..self.ball.stub.len() {
|
|
||||||
let heap_value = self.ball.stub[index].clone();
|
|
||||||
|
|
||||||
stub.push(match heap_value {
|
|
||||||
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff),
|
|
||||||
_ => heap_value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
stub
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool {
|
pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool {
|
||||||
let mut seen = IndexSet::new();
|
let mut seen = IndexSet::new();
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
@@ -2264,7 +2245,8 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true on failure.
|
// returns true on failure.
|
||||||
pub(super) fn eq_test(&self, a1: Addr, a2: Addr) -> bool {
|
pub(super)
|
||||||
|
fn eq_test(&self, a1: Addr, a2: Addr) -> bool {
|
||||||
let mut iter = self.zipped_acyclic_pre_order_iter(a1, a2);
|
let mut iter = self.zipped_acyclic_pre_order_iter(a1, a2);
|
||||||
|
|
||||||
while let Some((v1, v2)) = iter.next() {
|
while let Some((v1, v2)) = iter.next() {
|
||||||
|
|||||||
@@ -179,18 +179,16 @@ impl Machine {
|
|||||||
|
|
||||||
match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes()), verify_attrs_src)
|
match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes()), verify_attrs_src)
|
||||||
{
|
{
|
||||||
Ok(code) => {
|
Ok(p) => {
|
||||||
self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len();
|
self.machine_st.attr_var_init.verify_attrs_loc = p;
|
||||||
self.code_repo.code.extend(code.into_iter());
|
|
||||||
}
|
}
|
||||||
Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
|
Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
|
||||||
}
|
}
|
||||||
|
|
||||||
match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes()), project_attrs_src)
|
match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes()), project_attrs_src)
|
||||||
{
|
{
|
||||||
Ok(code) => {
|
Ok(p) => {
|
||||||
self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len();
|
self.machine_st.attr_var_init.project_attrs_loc = p;
|
||||||
self.code_repo.code.extend(code.into_iter());
|
|
||||||
}
|
}
|
||||||
Err(e) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS: {}", e),
|
Err(e) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS: {}", e),
|
||||||
}
|
}
|
||||||
@@ -602,7 +600,9 @@ impl Machine {
|
|||||||
self.machine_st.absorb_snapshot(snapshot);
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
self.machine_st.ball = ball;
|
self.machine_st.ball = ball;
|
||||||
|
|
||||||
let stub = self.machine_st.copy_and_align_ball();
|
let h = self.machine_st.heap.h;
|
||||||
|
let stub = self.machine_st.ball.copy_and_align(h);
|
||||||
|
|
||||||
self.machine_st.throw_exception(stub);
|
self.machine_st.throw_exception(stub);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -15,16 +15,20 @@ enqueue_goals(Goals0) :-
|
|||||||
enqueue_goals(Goals).
|
enqueue_goals(Goals).
|
||||||
enqueue_goals(_).
|
enqueue_goals(_).
|
||||||
|
|
||||||
'$print_exception'(E) :-
|
'$print_project_attributes_exception'(Module, E) :-
|
||||||
write_term('caught: ', [quoted(false)]),
|
( E = error(evaluation_error((Module:project_attributes)/2), project_attributes/2) ->
|
||||||
writeq(E),
|
true
|
||||||
nl.
|
; write_term('caught: ', [quoted(false)]),
|
||||||
|
writeq(E),
|
||||||
|
nl
|
||||||
|
).
|
||||||
|
|
||||||
call_project_attributes([], _, _).
|
call_project_attributes([], _, _).
|
||||||
call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
|
call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
|
||||||
( catch(Module:project_attributes(QueryVars, AttrVars),
|
( catch(Module:project_attributes(QueryVars, AttrVars),
|
||||||
E, %error(evaluation_error((Module:project_attributes)/2), project_attributes/2),
|
E,
|
||||||
'$print_exception'(E)) -> true
|
'$print_project_attributes_exception'(Module, E))
|
||||||
|
-> true
|
||||||
; true
|
; true
|
||||||
),
|
),
|
||||||
call_project_attributes(Modules, QueryVars, AttrVars).
|
call_project_attributes(Modules, QueryVars, AttrVars).
|
||||||
@@ -35,12 +39,25 @@ call_attribute_goals([Module | Modules], AttrVars) :-
|
|||||||
enqueue_goals(Goals),
|
enqueue_goals(Goals),
|
||||||
call_attribute_goals(Modules, AttrVars).
|
call_attribute_goals(Modules, AttrVars).
|
||||||
|
|
||||||
|
'$print_attribute_goals_exception'(Module, E) :-
|
||||||
|
( E = error(evaluation_error((Module:attribute_goals)/3), attribute_goals/3)
|
||||||
|
-> true
|
||||||
|
; write_term('caught: ', [quoted(false)]),
|
||||||
|
writeq(E),
|
||||||
|
nl
|
||||||
|
).
|
||||||
|
|
||||||
call_goals([], _, []).
|
call_goals([], _, []).
|
||||||
call_goals([AttrVar|AttrVars], Module, Goals) :-
|
call_goals([AttrVar|AttrVars], Module, Goals) :-
|
||||||
( catch(Module:attribute_goals(AttrVar, Goals, RGoals),
|
( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0),
|
||||||
E, %error(evaluation_error((Module:attribute_goals)/3), attribute_goals/3),
|
atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals)
|
||||||
('$print_exception'(E), atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals))) -> true
|
),
|
||||||
; true
|
E,
|
||||||
|
( '$print_attribute_goals_exception'(Module, E),
|
||||||
|
atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
||||||
|
))
|
||||||
|
-> true
|
||||||
|
; atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals)
|
||||||
),
|
),
|
||||||
call_goals(AttrVars, Module, RGoals).
|
call_goals(AttrVars, Module, RGoals).
|
||||||
|
|
||||||
|
|||||||
@@ -840,8 +840,14 @@ impl MachineState {
|
|||||||
|
|
||||||
let addr = self[temp_v!(2)].clone();
|
let addr = self[temp_v!(2)].clone();
|
||||||
|
|
||||||
match indices.global_variables.get(&key).cloned() {
|
match indices.global_variables.get(&key) {
|
||||||
Some(sought_addr) => self.unify(addr, sought_addr),
|
Some(ref ball) => {
|
||||||
|
let h = self.heap.h;
|
||||||
|
let stub = ball.copy_and_align(h);
|
||||||
|
|
||||||
|
self.heap.extend(stub.into_iter());
|
||||||
|
self.unify(addr, Addr::HeapCell(h));
|
||||||
|
}
|
||||||
None => self.fail = true,
|
None => self.fail = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1671,7 +1677,7 @@ impl MachineState {
|
|||||||
let h = self.heap.h;
|
let h = self.heap.h;
|
||||||
|
|
||||||
if self.ball.stub.len() > 0 {
|
if self.ball.stub.len() > 0 {
|
||||||
let stub = self.copy_and_align_ball();
|
let stub = self.ball.copy_and_align(h);
|
||||||
self.heap.append(stub);
|
self.heap.append(stub);
|
||||||
} else {
|
} else {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
@@ -1759,9 +1765,16 @@ impl MachineState {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = self[temp_v!(2)].clone();
|
let value = self[temp_v!(2)].clone();
|
||||||
|
let mut ball = Ball::new();
|
||||||
indices.global_variables.insert(key, value);
|
|
||||||
|
ball.boundary = self.heap.h;
|
||||||
|
copy_term(
|
||||||
|
CopyBallTerm::new(&mut self.and_stack, &mut self.heap, &mut ball.stub),
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
|
||||||
|
indices.global_variables.insert(key, ball);
|
||||||
}
|
}
|
||||||
&SystemClauseType::Succeed => {}
|
&SystemClauseType::Succeed => {}
|
||||||
&SystemClauseType::TermVariables => {
|
&SystemClauseType::TermVariables => {
|
||||||
|
|||||||
@@ -713,25 +713,9 @@ impl RelationWorker {
|
|||||||
let mut query_terms = vec![];
|
let mut query_terms = vec![];
|
||||||
let mut work_queue = VecDeque::from(terms);
|
let mut work_queue = VecDeque::from(terms);
|
||||||
let mut machine_st = MachineState::new();
|
let mut machine_st = MachineState::new();
|
||||||
|
|
||||||
while let Some(term) = work_queue.pop_front() {
|
while let Some(term) = work_queue.pop_front() {
|
||||||
let mut term = *term;
|
let term = *term;
|
||||||
|
|
||||||
if let Term::Clause(cell, name, terms, op_spec) = term {
|
|
||||||
if name.as_str() == "," {
|
|
||||||
let term = Term::Clause(cell, name, terms, op_spec);
|
|
||||||
let mut subterms = unfold_by_str(term, ",");
|
|
||||||
|
|
||||||
while let Some(subterm) = subterms.pop() {
|
|
||||||
work_queue.push_front(Box::new(subterm));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
term = Term::Clause(cell, name, terms, op_spec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let op_dir = op_dir(&indices.index_src);
|
let op_dir = op_dir(&indices.index_src);
|
||||||
|
|
||||||
let mut expanded_terms = indices.term_stream.expand_goals(
|
let mut expanded_terms = indices.term_stream.expand_goals(
|
||||||
@@ -739,14 +723,29 @@ impl RelationWorker {
|
|||||||
op_dir.as_ref(),
|
op_dir.as_ref(),
|
||||||
VecDeque::from(vec![term])
|
VecDeque::from(vec![term])
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
while let Some(term) = expanded_terms.pop() {
|
while let Some(term) = expanded_terms.pop() {
|
||||||
work_queue.push_front(Box::new(term));
|
work_queue.push_front(Box::new(term));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(term) = work_queue.pop_front() {
|
if let Some(term) = work_queue.pop_front() {
|
||||||
let mut term = *term;
|
let mut term = *term;
|
||||||
|
|
||||||
|
if let Term::Clause(cell, name, terms, op_spec) = term {
|
||||||
|
if name.as_str() == "," {
|
||||||
|
let term = Term::Clause(cell, name, terms, op_spec);
|
||||||
|
let mut subterms = unfold_by_str(term, ",");
|
||||||
|
|
||||||
|
while let Some(subterm) = subterms.pop() {
|
||||||
|
work_queue.push_front(Box::new(subterm));
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
term = Term::Clause(cell, name, terms, op_spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !blocks_cuts {
|
if !blocks_cuts {
|
||||||
mark_cut_variable(&mut term);
|
mark_cut_variable(&mut term);
|
||||||
}
|
}
|
||||||
@@ -754,7 +753,7 @@ impl RelationWorker {
|
|||||||
query_terms.push(self.pre_query_term(indices, term)?);
|
query_terms.push(self.pre_query_term(indices, term)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(query_terms)
|
Ok(query_terms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user