From: Mark Thom Date: Wed, 9 Oct 2019 20:11:31 +0000 (-0600) Subject: copy terms to global variable blackboard, fix attribute_goals//1 X-Git-Tag: v0.8.110~12 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=f898b98b069ae366132056293360f9cb1c1eea7d;p=scryer-prolog.git copy terms to global variable blackboard, fix attribute_goals//1 --- diff --git a/Cargo.toml b/Cargo.toml index b4cd90df..e1f0ef68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.104" +version = "0.8.105" authors = ["Mark Thom "] build = "build.rs" repository = "https://github.com/mthom/scryer-prolog" diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index 2e355d56..eba35d2f 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -13,8 +13,10 @@ of a particular module, as a list of terms of the form Module:put_atts(V, ListOfAtts). */ '$default_attr_list'(Module, V) --> - { Module:get_atts(V, Attributes) }, - '$default_attr_list'(Attributes, Module, V). + ( { Module:get_atts(V, Attributes) } -> + '$default_attr_list'(Attributes, Module, V) + ; [] + ). '$default_attr_list'([PG | PGs], Module, AttrVar) --> ( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)] diff --git a/src/prolog/lib/non_iso.pl b/src/prolog/lib/non_iso.pl index 9d4367fb..14accf43 100644 --- a/src/prolog/lib/non_iso.pl +++ b/src/prolog/lib/non_iso.pl @@ -12,7 +12,9 @@ forall(Generate, Test) :- %% (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_b_put(Key, NewValue) :- diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index f2d3083b..4ed2d502 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -1070,14 +1070,19 @@ pub fn compile_special_form( wam: &mut Machine, src: ParsingStream, listing_src: ClauseName, -) -> Result { +) -> Result { let mut indices = default_index_store!(wam.indices.atom_tbl.clone()); setup_indices(wam, clause_name!("builtins"), &mut indices)?; let mut compiler = ListingCompiler::new(&wam.code_repo, true, listing_src); 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] diff --git a/src/prolog/machine/copier.rs b/src/prolog/machine/copier.rs index 4fd58f63..577f9992 100644 --- a/src/prolog/machine/copier.rs +++ b/src/prolog/machine/copier.rs @@ -15,7 +15,7 @@ pub(crate) trait CopierTarget: IndexMut { pub(crate) fn copy_term(target: T, addr: Addr) { let mut copy_term_state = CopyTermState::new(target); - copy_term_state.copy_term_impl(addr); + copy_term_state.copy_term_impl(addr); } struct CopyTermState { diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index e311a50d..a18ea6ec 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -4,6 +4,7 @@ use prolog_parser::tabled_rc::*; use prolog::clause_types::*; use prolog::fixtures::*; use prolog::forms::*; +use prolog::machine::Ball; use indexmap::IndexMap; @@ -454,7 +455,7 @@ pub type InSituCodeDir = IndexMap; // key type: module name, predicate indicator. pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>; -pub type GlobalVarDir = IndexMap; +pub type GlobalVarDir = IndexMap; pub struct IndexStore { pub(super) atom_tbl: TabledData, diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index a6e1da20..05ced12a 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -21,7 +21,7 @@ use std::io::{stdout, Write}; use std::mem; use std::ops::{Index, IndexMut}; -pub(super) struct Ball { +pub struct Ball { pub(super) boundary: usize, // ball.0 pub(super) stub: MachineStub, // ball.1 } @@ -48,6 +48,22 @@ impl Ball { 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> { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index e7abc19b..e20a2d9d 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -173,7 +173,7 @@ impl MachineState { } _ => { 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))); } } @@ -201,7 +201,8 @@ impl MachineState { self.heap[h] = HeapCellValue::Addr(t1); 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 => {} } } @@ -2091,26 +2092,6 @@ impl MachineState { 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 { let mut seen = IndexSet::new(); let mut fail = false; @@ -2264,7 +2245,8 @@ impl MachineState { } // 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); while let Some((v1, v2)) = iter.next() { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 35c1d6e2..d5ae71ec 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -179,18 +179,16 @@ impl Machine { match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes()), verify_attrs_src) { - Ok(code) => { - self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len(); - self.code_repo.code.extend(code.into_iter()); + Ok(p) => { + self.machine_st.attr_var_init.verify_attrs_loc = p; } Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"), } match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes()), project_attrs_src) { - Ok(code) => { - self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len(); - self.code_repo.code.extend(code.into_iter()); + Ok(p) => { + self.machine_st.attr_var_init.project_attrs_loc = p; } 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.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); return; diff --git a/src/prolog/machine/project_attributes.pl b/src/prolog/machine/project_attributes.pl index 2e77a311..084d60b8 100644 --- a/src/prolog/machine/project_attributes.pl +++ b/src/prolog/machine/project_attributes.pl @@ -15,16 +15,20 @@ enqueue_goals(Goals0) :- enqueue_goals(Goals). enqueue_goals(_). -'$print_exception'(E) :- - write_term('caught: ', [quoted(false)]), - writeq(E), - nl. +'$print_project_attributes_exception'(Module, E) :- + ( E = error(evaluation_error((Module:project_attributes)/2), project_attributes/2) -> + true + ; write_term('caught: ', [quoted(false)]), + writeq(E), + nl + ). call_project_attributes([], _, _). call_project_attributes([Module|Modules], QueryVars, AttrVars) :- ( catch(Module:project_attributes(QueryVars, AttrVars), - E, %error(evaluation_error((Module:project_attributes)/2), project_attributes/2), - '$print_exception'(E)) -> true + E, + '$print_project_attributes_exception'(Module, E)) + -> true ; true ), call_project_attributes(Modules, QueryVars, AttrVars). @@ -35,12 +39,25 @@ call_attribute_goals([Module | Modules], AttrVars) :- enqueue_goals(Goals), 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([AttrVar|AttrVars], Module, Goals) :- - ( catch(Module:attribute_goals(AttrVar, Goals, RGoals), - E, %error(evaluation_error((Module:attribute_goals)/3), attribute_goals/3), - ('$print_exception'(E), atts:'$default_attr_list'(Module, AttrVar, Goals, RGoals))) -> true - ; true + ( catch(( Module:attribute_goals(AttrVar, Goals, RGoals0), + atts:'$default_attr_list'(Module, AttrVar, RGoals0, RGoals) + ), + 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). diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 91afb248..ca2ac0d5 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -840,8 +840,14 @@ impl MachineState { let addr = self[temp_v!(2)].clone(); - match indices.global_variables.get(&key).cloned() { - Some(sought_addr) => self.unify(addr, sought_addr), + match indices.global_variables.get(&key) { + 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, }; } @@ -1671,7 +1677,7 @@ impl MachineState { let h = self.heap.h; 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); } else { self.fail = true; @@ -1759,9 +1765,16 @@ impl MachineState { _ => unreachable!(), }; - let value = self[temp_v!(2)].clone(); - - indices.global_variables.insert(key, value); + let value = self[temp_v!(2)].clone(); + let mut ball = Ball::new(); + + 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::TermVariables => { diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index 28153115..12d153cc 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -713,25 +713,9 @@ impl RelationWorker { let mut query_terms = vec![]; let mut work_queue = VecDeque::from(terms); let mut machine_st = MachineState::new(); - - while let Some(term) = work_queue.pop_front() { - 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); - } - } + while let Some(term) = work_queue.pop_front() { + let term = *term; let op_dir = op_dir(&indices.index_src); let mut expanded_terms = indices.term_stream.expand_goals( @@ -739,14 +723,29 @@ impl RelationWorker { op_dir.as_ref(), VecDeque::from(vec![term]) )?; - + while let Some(term) = expanded_terms.pop() { 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; + 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 { mark_cut_variable(&mut term); } @@ -754,7 +753,7 @@ impl RelationWorker { query_terms.push(self.pre_query_term(indices, term)?); } } - + Ok(query_terms) }