]> Repositorios git - scryer-prolog.git/commitdiff
add library(reif)
authorMark Thom <[email protected]>
Sat, 16 Feb 2019 23:34:38 +0000 (16:34 -0700)
committerMark Thom <[email protected]>
Sat, 16 Feb 2019 23:34:38 +0000 (16:34 -0700)
README.md
src/prolog/codegen.rs
src/prolog/instructions.rs
src/prolog/lib/reif.pl [new file with mode: 0644]
src/prolog/machine/attributed_variables.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs

index 3e3e0e4adb0e41357e222a9607c8de469a7186f1..81d915315dc1b4ea274617450a374c0017c7062a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ Extend rusty-wam to include the following, among other features:
      - [x] Support for `attribute_goals/2` and `project_attributes/2`
      - [ ] `call_residue/2` and `call_residue_vars/2`
 * `if_` and related predicates, following the developments of the
-  paper "Indexing `dif/2`".
+  paper "Indexing `dif/2`" (_in progress_).
 * All-solutions predicates (`findall/{3,4}`, `bagof/3`, `setof/3`).
 * Clause creation and destruction (`asserta/1`, `assertz/1`,
   `retract/1`, `abolish/1`) with logical update semantics.
index 24ad167679e71ff2eaf20336f63477021ae96a73..80ae682462d164d18bf978e5278b862a25f57778 100644 (file)
@@ -457,16 +457,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
 
         Ok(match terms[0].as_ref() {
             &Term::Var(ref vr, ref name) => {
-                let mut target = Vec::new();
+                let mut target = vec![];
 
                 self.marker.reset_arg(2);
                 self.marker.mark_var(name.clone(), Level::Shallow, vr,
                                      term_loc, &mut target);
 
                 if !target.is_empty() {
-                    for query_instr in target {
-                        code.push(Line::Query(query_instr));
-                    }
+                    code.extend(target.into_iter().map(Line::Query));
                 }
 
                 if use_default_call_policy {
@@ -476,9 +474,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
                 }
             },
             &Term::Constant(_, ref c @ Constant::Number(_)) => {
-                code.push(Line::Query(put_constant!(Level::Shallow,
-                                                    c.clone(),
-                                                    temp_v!(1))));
+                code.push(Line::Query(put_constant!(Level::Shallow, c.clone(), temp_v!(1))));
 
                 if use_default_call_policy {
                     code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
@@ -510,7 +506,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
             code.extend(target.into_iter().map(|query_instr| Line::Query(query_instr)));
         }
 
-        code.push(get_level_and_unify!(cell.get().norm()));        
+        code.push(get_level_and_unify!(cell.get().norm()));
     }
 
     fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>,
index a20f50d7ddc260fa232788991ac3221ba39ca17a..99a4832e92c8a5574371818004b3bfe357941515 100644 (file)
@@ -382,6 +382,7 @@ pub enum BuiltInClauseType {
     NotEq,
     PartialString,
     Read,
+    ReifySwitch,
     Sort,
 }
 
@@ -459,9 +460,10 @@ impl BuiltInClauseType {
             &BuiltInClauseType::KeySort => clause_name!("keysort"),
             &BuiltInClauseType::Nl => clause_name!("nl"),
             &BuiltInClauseType::NotEq => clause_name!("\\=="),
+            &BuiltInClauseType::PartialString => clause_name!("partial_string"),
             &BuiltInClauseType::Read => clause_name!("read"),
+            &BuiltInClauseType::ReifySwitch => clause_name!("$reify_switch"),
             &BuiltInClauseType::Sort => clause_name!("sort"),
-            &BuiltInClauseType::PartialString => clause_name!("partial_string")
         }
     }
 
@@ -480,9 +482,10 @@ impl BuiltInClauseType {
             &BuiltInClauseType::KeySort => 2,
             &BuiltInClauseType::NotEq => 2,
             &BuiltInClauseType::Nl => 0,
+            &BuiltInClauseType::PartialString => 1,
             &BuiltInClauseType::Read => 1,
+            &BuiltInClauseType::ReifySwitch => 3,
             &BuiltInClauseType::Sort => 2,
-            &BuiltInClauseType::PartialString => 1,
         }
     }
 
@@ -506,9 +509,10 @@ impl BuiltInClauseType {
             ("keysort", 2) => Some(BuiltInClauseType::KeySort),
             ("nl", 0) => Some(BuiltInClauseType::Nl),
             ("\\==", 2) => Some(BuiltInClauseType::NotEq),
-            ("sort", 2) => Some(BuiltInClauseType::Sort),
-            ("read", 1) => Some(BuiltInClauseType::Read),
             ("partial_string", 2) => Some(BuiltInClauseType::PartialString),
+            ("read", 1) => Some(BuiltInClauseType::Read),
+            ("$reify_switch", 3) => Some(BuiltInClauseType::ReifySwitch),
+            ("sort", 2) => Some(BuiltInClauseType::Sort),
             _ => None
         }
     }
diff --git a/src/prolog/lib/reif.pl b/src/prolog/lib/reif.pl
new file mode 100644 (file)
index 0000000..dc7a68a
--- /dev/null
@@ -0,0 +1,73 @@
+:- module(reif, [if_/3, (=)/3, (,)/3, (;)/3, cond_t/3, dif/3,
+                memberd_t/3, tfilter/3, tmember/2, tmember_t/3,
+                tpartition/4]).
+
+:- use_module(library(control), [(\=)/2]).
+:- use_module(library(dif)).
+
+/* in essence, '$reify_switch'(T, Then_0, Else_0) is this:
+    (  T == true -> call(Then_0)
+    ;  T == false -> call(Else_0)
+    ;  nonvar(T) -> throw(error(type_error(boolean, T), _))
+    ;  throw(error(instantiation_error, _))
+    ).
+    but without creating choice points.
+*/
+
+if_(If_1, Then_0, Else_0) :-
+    call(If_1, T),
+    '$reify_switch'(T, Then_0, Else_0).
+
+=(X, Y, T) :-
+    (  X == Y -> T = true
+    ;  X \= Y -> T = false
+    ;  T = true, X = Y
+    ;  T = false, dif(X, Y)
+    ).
+
+dif(X, Y, T) :-
+  =(X, Y, NT),
+  non(NT, T).
+
+non(true, false).
+non(false, true).
+
+tfilter(C_2, Es, Fs) :-
+   i_tfilter(Es, C_2, Fs).
+
+i_tfilter([], _, []).
+i_tfilter([E|Es], C_2, Fs0) :-
+   if_(call(C_2, E), Fs0 = [E|Fs], Fs0 = Fs),
+   i_tfilter(Es, C_2, Fs).
+
+tpartition(P_2, Xs, Ts, Fs) :-
+   i_tpartition(Xs, P_2, Ts, Fs).
+
+i_tpartition([], _P_2, [], []).
+i_tpartition([X|Xs], P_2, Ts0, Fs0) :-
+   if_( call(P_2, X)
+      , ( Ts0 = [X|Ts], Fs0 = Fs )
+      , ( Fs0 = [X|Fs], Ts0 = Ts ) ),
+   i_tpartition(Xs, P_2, Ts, Fs).
+
+','(A_1, B_1, T) :-
+    if_(A_1, call(B_1, T), T = false).
+
+';'(A_1, B_1, T) :-
+    if_(A_1, T = true, call(B_1, T)).
+
+cond_t(If_1, Then_0, T) :-
+   if_(If_1, ( Then_0, T = true ), T = false ).
+
+memberd_t(E, Xs, T) :-
+   i_memberd_t(Xs, E, T).
+
+i_memberd_t([], _, false).
+i_memberd_t([X|Xs], E, T) :-
+   if_( X = E, T = true, i_memberd_t(Xs, E, T) ).
+
+tmember(P_2, [X|Xs]) :-
+   if_( call(P_2, X), true, tmember(P_2, Xs) ).
+
+tmember_t(P_2, [X|Xs], T) :-
+   if_( call(P_2, X), T = true, tmember_t(P_2, Xs, T) ).
index 770bd36bf52cdcf0663b959f6a36ae4360cc451e..af7766972af45cae7d7ad2db390bd2048aa7db76 100644 (file)
@@ -156,12 +156,14 @@ impl MachineState {
 
     fn print_attribute_goals(&mut self, var_dict: &HeapVarDict)
     {
-        let attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
+        let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
 
         if attr_goals.is_empty() {
             return;
         }
 
+        self.term_dedup(&mut attr_goals);
+
         let mut output = PrinterOutputter::new();
 
         for goal_addr in attr_goals {
index 909ad4cb9761806bd4fd8963cc4645ba9a5b7423..4a3af940d4f215f13391499cf8d4d041213931c8 100644 (file)
@@ -114,6 +114,7 @@ impl MachineError {
 pub enum ValidType {
     Atom,
     Atomic,
+    Boolean,
 //    Byte,
     Callable,
 //    Character,
@@ -134,6 +135,7 @@ impl ValidType {
         match self {
             ValidType::Atom => "atom",
             ValidType::Atomic => "atomic",
+            ValidType::Boolean => "boolean",
 //            ValidType::Byte => "byte",
             ValidType::Callable => "callable",
 //            ValidType::Character => "character",
index ec979842072888cd83c5deeda13732200d304073..ae6847c13e634dfaecfab3b10fcf9d60f8e65d27 100644 (file)
@@ -572,6 +572,48 @@ pub(crate) trait CallPolicy: Any {
 
                 return_from_clause!(machine_st.last_call, machine_st)
             },
+            &BuiltInClauseType::ReifySwitch => {
+                let truth_value = machine_st[temp_v!(1)].clone();
+                let truth_value = machine_st.store(machine_st.deref(truth_value));
+
+                match truth_value {
+                    Addr::Con(Constant::Atom(atom, spec)) =>
+                        match atom.as_str() {
+                            "true"  => {
+                                let t_branch = machine_st[temp_v!(2)].clone();
+
+                                machine_st[temp_v!(1)] = t_branch;
+                                self.call_n(machine_st, 1, indices)
+                            },
+                            "false" => {
+                                let f_branch = machine_st[temp_v!(3)].clone();
+
+                                machine_st[temp_v!(1)] = f_branch;
+                                self.call_n(machine_st, 1, indices)
+                            }
+                            _ => {
+                                let truth_value = Addr::Con(Constant::Atom(atom, spec));
+
+                                let stub = MachineError::functor_stub(clause_name!("if_"), 3);
+                                let err  = MachineError::type_error(ValidType::Boolean, truth_value);
+
+                                Err(machine_st.error_form(err, stub))
+                            }
+                        },
+                    ref addr if addr.is_ref() => {
+                        let stub = MachineError::functor_stub(clause_name!("if_"), 3);
+                        let err = MachineError::instantiation_error();
+                        
+                        Err(machine_st.error_form(err, stub))
+                    },
+                    addr => {
+                        let stub = MachineError::functor_stub(clause_name!("if_"), 3);
+                        let err = MachineError::type_error(ValidType::Boolean, addr);
+                        
+                        Err(machine_st.error_form(err, stub))
+                    }
+                }
+            },
             &BuiltInClauseType::CopyTerm => {
                 machine_st.duplicate_term();
                 return_from_clause!(machine_st.last_call, machine_st)
index 54f27231e426ad4f28f3a88fc9d3d52a92347c44..89feda2f298646e9490fd7125446f8be40406a5d 100644 (file)
@@ -321,6 +321,7 @@ static DCGS: &str     = include_str!("../lib/dcgs.pl");
 static ATTS: &str     = include_str!("../lib/atts.pl");
 static DIF: &str      = include_str!("../lib/dif.pl");
 static FREEZE: &str   = include_str!("../lib/freeze.pl");
+static REIF: &str     = include_str!("../lib/reif.pl");
 
 impl Machine {
     fn compile_special_forms(&mut self) {
@@ -351,6 +352,7 @@ impl Machine {
         compile_user_module(self, ATTS.as_bytes());
         compile_user_module(self, DIF.as_bytes());
         compile_user_module(self, FREEZE.as_bytes());
+        compile_user_module(self, REIF.as_bytes());
     }
 
     pub fn new() -> Self {
index c3b4c9fe24f2fdfb86fce4143a9ee04560140fd6..1152c8c760fd9ddf710b0ecc0b9dc690f3b9653e 100644 (file)
@@ -409,7 +409,7 @@ impl MachineState {
                 for (h, addr) in bindings {
                     self.heap[h] = HeapCellValue::Addr(addr);
                 }
-            },
+            },            
             &SystemClauseType::RemoveCallPolicyCheck => {
                 let restore_default =
                     match call_policy.downcast_mut::<CWILCallPolicy>().ok() {