From: Mark Thom Date: Wed, 13 Feb 2019 21:18:41 +0000 (-0700) Subject: prepare to add project_attributes/2 and attribute_goals/2 X-Git-Tag: v0.8.110~258 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=f616b4ddfdd207d6a734b96712c1d0880bf4706e;p=scryer-prolog.git prepare to add project_attributes/2 and attribute_goals/2 --- diff --git a/README.md b/README.md index eeb48f3e..620dfecd 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ The following predicates are built-in to rusty-wam. * `compound/1` * `copy_term/2` * `cyclic_term/1` +* `dif/2` * `expand_goal/2` * `expand_term/2` * `false/0` diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 46a86114..0f092411 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -176,7 +176,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator }; } - fn compile_target(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool) -> Vec + fn compile_target(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool) + -> Vec where Target: CompilationTarget<'a>, Iter: Iterator> { let mut target = Vec::new(); @@ -489,6 +490,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator }) } + #[inline] + fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell) + { + let r = self.marker.get(Rc::new(String::from("!"))); + cell.set(VarReg::Norm(r)); + code.push(set_cp!(cell.get().norm())); + } + fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>, code: &mut Code, is_exposed: bool) -> Result<(), ParserError> @@ -518,7 +527,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(get_level_and_unify!(cell.get().norm())); }, &QueryTerm::UnblockedCut(ref cell) => - code.push(set_cp!(cell.get().norm())), + self.compile_unblocked_cut(code, cell), &QueryTerm::BlockedCut => code.push(if chunk_num == 0 { Line::Cut(CutInstruction::NeckCut) diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index a95bf480..adfefc73 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -175,14 +175,14 @@ impl DebrayAllocator { let mut final_index = 0; for index in self.temp_lb .. { - if !self.in_use.contains(&index) { + if !self.in_use.contains(&index) { final_index = index; break; } } + self.in_use.insert(final_index); self.temp_lb = final_index + 1; - final_index } @@ -245,7 +245,10 @@ impl<'a> Allocator<'a> for DebrayAllocator RegType::Temp(k) }, _ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()), - _ => r + _ => { + self.in_use.insert(r.reg_num()); + r + } }; cell.set(r); diff --git a/src/prolog/fixtures.rs b/src/prolog/fixtures.rs index 34d3c4a6..3394ea95 100644 --- a/src/prolog/fixtures.rs +++ b/src/prolog/fixtures.rs @@ -124,11 +124,10 @@ impl<'a> VariableFixtures<'a> status.1.push(cell); match status.0 { - VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => { + VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => if let Level::Shallow = lvl { self.record_temp_info(tvd, arg_c, term_loc); - } - }, + }, _ => status.0 = VarStatus::Perm(chunk_num) }; diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index deb04f98..a39cd1db 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -950,7 +950,7 @@ pub enum LocalCodePtr { UserTermExpansion(usize) } -impl LocalCodePtr { +impl LocalCodePtr { pub fn assign_if_local(&mut self, cp: CodePtr) { match cp { CodePtr::Local(local) => *self = local, diff --git a/src/prolog/lib/dif.pl b/src/prolog/lib/dif.pl new file mode 100644 index 00000000..fadf9fea --- /dev/null +++ b/src/prolog/lib/dif.pl @@ -0,0 +1,57 @@ +[:- module(dif, [dif/2]). + +:- use_module(library(atts)). +:- use_module(library(control), [(\=)/2]). + +:- attribute dif/2. + +dif_set_variables([], _, _). +dif_set_variables([Var|Vars], X, Y) :- + put_atts(Var, dif(X, Y)), + dif_set_variables(Vars, X, Y). + +verify_dif_attrs([dif(X, Y) | Attrs], Var, [X \== Y | Goals]) :- + ( get_atts(Var, +dif(X, Y)) -> true + ; put_atts(Var, +dif(X, Y)) + ), + verify_dif_attrs(Attrs, Var, Goals). +verify_dif_attrs([_ | Attrs], Var, Goals) :- + verify_dif_attrs(Attrs, Var, Goals). +verify_dif_attrs([], _, []). + +verify_dif_attrs_no_var([dif(X, Y) | Attrs], [X \== Y | Goals]) :- + verify_dif_attrs_no_var(Attrs, Goals). +verify_dif_attrs_no_var([_ | Attrs], Goals) :- + verify_dif_attrs_no_var(Attrs, Goals). +verify_dif_attrs_no_var([], []). + +verify_attributes(Var, Value, Goals) :- + ( get_atts(Var, Attrs) -> + ( var(Value) -> verify_dif_attrs(Attrs, Value, Goals) + ; verify_dif_attrs_no_var(Attrs, Goals) + ) + ). + +% Probably the world's worst dif/2 implementation. I'm open to +% suggestions for improvement. + +dif(X, Y) :- ( X \= Y -> true + ; term_variables(X, XVars), term_variables(Y, YVars), + ( XVars == [], YVars == [] -> false + ; dif_set_variables(XVars, X, Y), + dif_set_variables(YVars, X, Y) + ) + ). + +gather_dif_goals(Attrs, Goal, Goal) :- + var(Attrs), !. +gather_dif_goals([dif(X, Y)|Attrs], OldGoal, Goal) :- + ( var(OldGoal), !, gather_dif_goals(Attrs, dif(X, Y), Goal) + ; !, gather_dif_goals(Attrs, (dif(X, Y), OldGoal), Goal) + ). +gather_dif_goals([_|Attrs], OldGoal, Goal) :- + gather_dif_goals(Attrs, OldGoal, Goal). + +attribute_goals(X, Goal) :- + '$get_attr_list'(X, Attrs), + gather_dif_goals(Attrs, _, Goal). diff --git a/src/prolog/machine/attributed_variables.pl b/src/prolog/machine/attributed_variables.pl index 9bfa7b27..90c04136 100644 --- a/src/prolog/machine/attributed_variables.pl +++ b/src/prolog/machine/attributed_variables.pl @@ -18,7 +18,7 @@ gather_modules([Attr|Attrs], [Module|Modules]) :- verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :- catch(Module:verify_attributes(Var, Value, Goals), - error(evaluation_error((M:verify_attributes)/3), verify_attrs/3), + error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3), Goals = []), verify_attrs(Modules, Var, Value, ListOfGoalLists). verify_attrs([], _, _, []). diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index 940d3413..75ec9db2 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -1,21 +1,24 @@ use prolog::machine::*; -pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl"); +pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl"); +pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl"); pub(super) type Bindings = Vec<(usize, Addr)>; pub(super) struct AttrVarInitializer { pub(super) bindings: Bindings, pub(super) cp: LocalCodePtr, - pub(super) verify_attrs_loc: usize + pub(super) verify_attrs_loc: usize, + pub(super) project_attrs_loc: usize } impl AttrVarInitializer { - pub(super) fn new(p: usize) -> Self { + pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self { AttrVarInitializer { bindings: vec![], cp: LocalCodePtr::default(), - verify_attrs_loc: p, + verify_attrs_loc, + project_attrs_loc } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 6bea1cc2..4299c565 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -40,7 +40,7 @@ impl MachineState { e: 0, num_of_args: 0, cp: LocalCodePtr::default(), - attr_var_init: AttrVarInitializer::new(0), + attr_var_init: AttrVarInitializer::new(0, 0), fail: false, heap: Heap::with_capacity(256), mode: MachineMode::Write, diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index e0245a99..aa693685 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -319,6 +319,7 @@ static ERROR: &str = include_str!("../lib/error.pl"); static TERMS: &str = include_str!("../lib/terms.pl"); static DCGS: &str = include_str!("../lib/dcgs.pl"); static ATTS: &str = include_str!("../lib/atts.pl"); +static DIF: &str = include_str!("../lib/dif.pl"); impl Machine { fn compile_special_forms(&mut self) { @@ -327,10 +328,29 @@ impl Machine { self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len(); self.code_repo.code.extend(code.into_iter()); }, - Err(_) => panic!("Machine::compile_special_forms() failed") + Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS") + } + + match compile_special_form(self, PROJECT_ATTRS.as_bytes()) { + Ok(code) => { + self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len(); + self.code_repo.code.extend(code.into_iter()); + }, + Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS") } } + fn compile_libraries(&mut self) { + compile_user_module(self, LISTS.as_bytes()); + compile_user_module(self, CONTROL.as_bytes()); + compile_user_module(self, QUEUES.as_bytes()); + compile_user_module(self, ERROR.as_bytes()); + compile_user_module(self, TERMS.as_bytes()); + compile_user_module(self, DCGS.as_bytes()); + compile_user_module(self, ATTS.as_bytes()); + compile_user_module(self, DIF.as_bytes()); + } + pub fn new() -> Self { let mut wam = Machine { machine_st: MachineState::new(), @@ -344,15 +364,9 @@ impl Machine { compile_listing(&mut wam, BUILTINS.as_bytes(), default_index_store!(atom_tbl.clone())); - compile_user_module(&mut wam, LISTS.as_bytes()); - compile_user_module(&mut wam, CONTROL.as_bytes()); - compile_user_module(&mut wam, QUEUES.as_bytes()); - compile_user_module(&mut wam, ERROR.as_bytes()); - compile_user_module(&mut wam, TERMS.as_bytes()); - compile_user_module(&mut wam, DCGS.as_bytes()); - compile_user_module(&mut wam, ATTS.as_bytes()); - + wam.compile_libraries(); wam.compile_special_forms(); + wam } @@ -608,7 +622,7 @@ impl MachineState { for i in 1 .. rs + 1 { self.and_stack[e][i] = self[RegType::Temp(i)].clone(); } - + self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0)); self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args)); diff --git a/src/prolog/machine/project_attributes.pl b/src/prolog/machine/project_attributes.pl new file mode 100644 index 00000000..d876e5b5 --- /dev/null +++ b/src/prolog/machine/project_attributes.pl @@ -0,0 +1,46 @@ +:- use_module(library(dcgs)). + +driver(QueryVars, AttrVars) :- + phrase(gather_modules(AttrVars), Modules0), + sort(Modules0, Modules), + call_project_attributes(Modules, QueryVars, AttrVars), + call_attribute_goals(QueryVars), + call_attribute_goals(AttrVars). + +call_project_attributes([], _, _). +call_project_attributes([Module|Modules], QueryVars, AttrVars) :- + ( catch(Module:project_attributes(QueryVars, AttrVars), + error(evaluation_error((Module:project_attributes/2), project_attributes/2)), + true) -> true + ; true + ), + call_project_attributes(Modules, QueryVars, AttrVars). + +call_attribute_goals([]). +call_attribute_goals([AttrVar | AttrVars]) :- + ( '$get_attr_list'(AttrVar, Ls) -> call_goals(Ls, AttrVar) + ; true + ), + call_attribute_goals(AttrVars). + +call_goals(Ls, _) :- var(Ls), !. +call_goals([Attr|Attrs], X) :- + '$module_of'(Module, Attr), + ( catch(Module:attribute_goals(X, Goal), + error(evaluation_error((Module:attribute_goals/2), attribute_goals/2)), + writeq(Goal)) -> true + ; true + ), + call_goals(Attrs, X). + +gather_modules([]) --> []. +gather_modules([AttrVar|AttrVars]) --> + { '$get_attr_list'(AttrVar, Attrs) }, + gather_modules_for_attrs(Attrs), + gather_modules(AttrVars). + +gather_modules_for_attrs(Attrs) --> { var(Attrs), ! }. +gather_modules_for_attrs([Attr|Attrs]) --> + { '$module_of'(Module, Attr) }, + [Module], + gather_modules_for_attrs(Attrs). diff --git a/src/prolog/targets.rs b/src/prolog/targets.rs index 094e0f40..5af37f57 100644 --- a/src/prolog/targets.rs +++ b/src/prolog/targets.rs @@ -104,8 +104,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { post_order_iter(term) } - fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self - { + fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self { QueryInstruction::PutStructure(ct, arity, r) } diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 7730241a..5853268d 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -349,7 +349,7 @@ fn mark_cut_variables(terms: &mut Vec) -> bool { let mut found_cut_var = false; for item in terms.iter_mut() { - found_cut_var = mark_cut_variable(item); + found_cut_var = mark_cut_variable(item) || found_cut_var; } found_cut_var @@ -437,22 +437,16 @@ impl RelationWorker { fn fabricate_disjunct(&self, body_term: Term) -> (JumpStub, VecDeque) { - let mut cut_var_found = false; - - let mut vars = self.compute_head(&body_term); + let vars = self.compute_head(&body_term); let clauses: Vec<_> = unfold_by_str(body_term, ";").into_iter() .map(|term| { let mut subterms = unfold_by_str(term, ","); - cut_var_found = mark_cut_variables(&mut subterms); + mark_cut_variables(&mut subterms); let term = subterms.pop().unwrap(); fold_by_str(subterms.into_iter(), term, clause_name!(",")) }).collect(); - if cut_var_found { - vars.push(Term::Var(Cell::default(), rc_atom!("!"))); - } - let results = clauses.into_iter() .map(|clause| self.fabricate_rule_body(&vars, clause)) .collect(); diff --git a/src/prolog/write.rs b/src/prolog/write.rs index 98f4ddb4..239feb4f 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -134,6 +134,8 @@ impl fmt::Display for CompareTermQT { impl fmt::Display for ClauseType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + &ClauseType::System(SystemClauseType::SetCutPoint(r)) => + write!(f, "$set_cp({})", r), &ClauseType::Named(ref name, ref idx) | &ClauseType::Op(OpDecl(.., ref name), ref idx) => { let idx = idx.0.borrow();