]> Repositorios git - scryer-prolog.git/commitdiff
prepare to add project_attributes/2 and attribute_goals/2
authorMark Thom <[email protected]>
Wed, 13 Feb 2019 21:18:41 +0000 (14:18 -0700)
committerMark Thom <[email protected]>
Wed, 13 Feb 2019 21:18:41 +0000 (14:18 -0700)
14 files changed:
README.md
src/prolog/codegen.rs
src/prolog/debray_allocator.rs
src/prolog/fixtures.rs
src/prolog/instructions.rs
src/prolog/lib/dif.pl [new file with mode: 0644]
src/prolog/machine/attributed_variables.pl
src/prolog/machine/attributed_variables.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/project_attributes.pl [new file with mode: 0644]
src/prolog/targets.rs
src/prolog/toplevel.rs
src/prolog/write.rs

index eeb48f3e51a4487ad381c716466183d2ace5dc24..620dfecdc5bed9e07445fecbae00a7239fb3f3da 100644 (file)
--- 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`
index 46a86114af9d5f9686e9b46a3077596e2e23b479..0f092411f36161c9f5904e12aa1a7f662576945e 100644 (file)
@@ -176,7 +176,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
         };
     }
 
-    fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool) -> Vec<Target>
+    fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
+                                    -> Vec<Target>
         where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
     {
         let mut target = Vec::new();
@@ -489,6 +490,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
         })
     }
 
+    #[inline]
+    fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>)
+    {
+        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<TermMarker>
                         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)
index a95bf480b67a44e2ffad0552fe0f24d96774ff23..adfefc73c43cfe579be16453daf72675a0107370 100644 (file)
@@ -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);
index 34d3c4a6a9d780cb52e87c9803c9d05638df8efb..3394ea952f82c4c91168c71170905285d432b1dd 100644 (file)
@@ -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)
                 };
 
index deb04f98048cf98a3423725a446bdba9a98504c2..a39cd1db7eb1209d5d85ccff733804545cd7b71d 100644 (file)
@@ -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 (file)
index 0000000..fadf9fe
--- /dev/null
@@ -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).
index 9bfa7b2731ff685d384a516a7125ac72b7bdc980..90c041362ddffcda485945be30c216a4e721883f 100644 (file)
@@ -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([], _, _, []).
index 940d34133ba827e4f96cb02eb07dccd6f63b5a73..75ec9db258492c7f4a84ee258b24f072d15949ae 100644 (file)
@@ -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
         }
     }
 
index 6bea1cc245e2d41d0f9178bd8680f33047979233..4299c5656ba51e28eb736c625ee6dc2cc7205777 100644 (file)
@@ -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,
index e0245a9977cf0c6177f62833519040a4a2ae8627..aa69368593bbb8040f15d81af4e578986122385c 100644 (file)
@@ -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 (file)
index 0000000..d876e5b
--- /dev/null
@@ -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).
index 094e0f4063108ec30e603cd080e7f79ec72d46f1..5af37f57052b5f5a5dab1e77a4898a01ce476f85 100644 (file)
@@ -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)
     }
 
index 7730241aebe0d5622879bfcc2461da45204ce2e1..5853268d4a42ae65ae16f11d36af2d6c8281f7c1 100644 (file)
@@ -349,7 +349,7 @@ fn mark_cut_variables(terms: &mut Vec<Term>) -> 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<Term>)
     {
-        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();
index 98f4ddb41f1eeb6b4be76fd05f29ecc2877c3e76..239feb4f2bd50acc0f4fe26e437eeac5b6d183a6 100644 (file)
@@ -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();