]> Repositorios git - scryer-prolog.git/commitdiff
defer cut actions to cut policy trait objects.
authorMark Thom <[email protected]>
Wed, 7 Feb 2018 06:41:31 +0000 (23:41 -0700)
committerMark Thom <[email protected]>
Wed, 7 Feb 2018 06:41:31 +0000 (23:41 -0700)
Cargo.lock
Cargo.toml
src/main.rs
src/prolog/builtins.rs
src/prolog/heap_iter.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs

index ddb719f8afde5f2f486ebaf477a3ab21dfbba559..27072053033c2eea1a58270959fd665bee49078e 100644 (file)
@@ -11,6 +11,11 @@ name = "bitflags"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "downcast"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "fuchsia-zircon"
 version = "0.2.1"
@@ -173,6 +178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "rusty-wam"
 version = "0.7.5"
 dependencies = [
+ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -228,6 +234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [metadata]
 "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6d87c251688702a52991eaebd07c13eabba9cc0b7f8c31ef94dc881be706e8"
 "checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
 "checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
index 08e048a785cb5b936bd1883c5febcef0abc47910..b29cd2302f3ca10b0568d1c3212aa95fb39159ca 100644 (file)
@@ -8,6 +8,7 @@ lazy_static = "0.2"
 num = "0.1"
 regex = "0.2.1"
 ordered-float = "0.5.0"
+downcast = "0.9.1"
 
 [dependencies.termion]
 version = "1.4.0"
\ No newline at end of file
index 0e71c49ca3d6f5c408bf19b372c45de308d5a425..62cde4baaca9d820eeb5dc32f21dd9f365c92237 100644 (file)
@@ -1,4 +1,5 @@
 #[macro_use] extern crate lazy_static;
+#[macro_use] extern crate downcast;
 extern crate termion;
 
 mod prolog;
index 5d2c89bd94b5a5e6f5048187c91c8c42789bac6c..c6f1be05b6962e20d585958b5ffcc6260d0c1705 100644 (file)
@@ -506,7 +506,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          deallocate!(),
          goto_execute!(340, 0), // goto run_cleaners_with_handling/0, 340.
          trust_me!(),
-         proceed!(),
+         proceed!(), // goto_execute!(380, 0), // goto restore_cut_points/0, 380.
          try_me_else!(10), // run_cleaners_without_handling/1, 352.
          allocate!(2),
          get_level!(perm_v!(1)),
@@ -518,7 +518,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          deallocate!(),
          goto_execute!(352, 0), // goto run_cleaners_without_handling/0, 352.
          trust_me!(),
-         proceed!(),
+         proceed!(), // goto_execute!(380, 0), // goto restore_cut_points/0, 380.
          allocate!(1), // sgc_on_success/2, 364.
          fact![get_var_in_fact!(perm_v!(1), 2)],
          reset_block!(),
index a2fd7a428533fe0934038b47f2242d9077afa5c4..57a9a00966368f3b1d1318011e51affefb305758 100644 (file)
@@ -4,16 +4,15 @@ use prolog::machine::machine_state::MachineState;
 use std::vec::Vec;
 
 pub struct HeapCellPreOrderIterator<'a> {
-    machine_st  : &'a MachineState,
-    state_stack : Vec<Addr>
+    machine_st: &'a MachineState,
+    state_stack: Vec<Addr>
 }
 
 impl<'a> HeapCellPreOrderIterator<'a> {
     pub fn new(machine_st: &'a MachineState, a: Addr) -> Self
     {
         HeapCellPreOrderIterator {
-            machine_st,
-            state_stack: vec![a]
+            machine_st, state_stack: vec![a]
         }
     }
 
index 0bc19e57d5f38b1bb6c4b2e561e9fccbc2ef08c8..6bcdecfcb987e32200794add0096a11a10996c52 100644 (file)
@@ -4,6 +4,7 @@ use prolog::copier::*;
 use prolog::or_stack::*;
 use prolog::tabled_rc::*;
 
+use downcast::Any;
 use std::ops::{Index, IndexMut};
 
 pub(super) struct DuplicateTerm<'a> {
@@ -173,5 +174,81 @@ pub struct MachineState {
     pub(super) block: usize, // an offset into the OR stack.
     pub(super) ball: (usize, Vec<HeapCellValue>), // heap boundary, and a term copy
     pub(super) interms: Vec<Number>, // intermediate numbers.
-    pub(super) sgc_cps: Vec<(Addr, usize, usize)>, // locations of cleaners/cut points, prev. block
+}
+
+pub(crate) trait CutPolicy: Any {
+    fn cut(&mut self, &mut MachineState, RegType);
+}
+
+// from the downcast crate.
+downcast!(CutPolicy);
+
+pub(crate) struct DefaultCutPolicy {}
+
+impl CutPolicy for DefaultCutPolicy {
+    fn cut(&mut self, machine_st: &mut MachineState, r: RegType) {
+        let b = machine_st.b;
+
+        if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() {
+            if b > b0 {
+                machine_st.b = b0;
+                machine_st.tidy_trail();
+                machine_st.or_stack.truncate(machine_st.b);
+            }
+        } else {
+            machine_st.fail = true;
+            return;
+        }
+
+        machine_st.p += 1;        
+    }
+}
+
+pub(crate) struct SetupCallCleanupCutPolicy {
+    // locations of cleaners, cut points, the previous block
+    cont_pts: Vec<(Addr, usize, usize)> 
+}
+
+impl SetupCallCleanupCutPolicy {
+    pub(crate) fn new() -> Self {
+        SetupCallCleanupCutPolicy { cont_pts: vec![] }
+    }
+    
+    pub(crate) fn out_of_cont_pts(&self) -> bool {
+        self.cont_pts.is_empty()
+    }
+
+    pub(crate) fn push_cont_pt(&mut self, addr: Addr, b: usize, block: usize) {
+        self.cont_pts.push((addr, b, block));
+    }
+
+    pub(crate) fn pop_cont_pt(&mut self) -> Option<(Addr, usize, usize)> {
+        self.cont_pts.pop()
+    }
+}
+
+impl CutPolicy for SetupCallCleanupCutPolicy {
+    fn cut(&mut self, machine_st: &mut MachineState, r: RegType) {
+        let b = machine_st.b;
+
+        if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() {
+            if b > b0 {
+                machine_st.b = b0;
+                machine_st.tidy_trail();
+                machine_st.or_stack.truncate(machine_st.b);
+            }
+        } else {
+            machine_st.fail = true;
+            return;
+        }
+
+        machine_st.p += 1;
+        
+        if !self.out_of_cont_pts() {
+            machine_st.cp = machine_st.p;
+            machine_st.num_of_args = 0;
+            machine_st.b0 = machine_st.b;
+            machine_st.p  = CodePtr::DirEntry(352); // goto_call run_cleaners_without_handling/0.
+        }
+    }
 }
index 57c1f094d09ea81525bc4e71c1097dc852231238..a60d7f230a86aafd34917081e6dbe9215898966f 100644 (file)
@@ -28,27 +28,27 @@ macro_rules! try_or_fail {
 
 impl MachineState {
     pub(super) fn new(atom_tbl: TabledData<Atom>) -> MachineState {
-        MachineState { atom_tbl,
-                       s: 0,
-                       p: CodePtr::default(),
-                       b: 0,
-                       b0: 0,
-                       e: 0,
-                       num_of_args: 0,
-                       cp: CodePtr::default(),
-                       fail: false,
-                       heap: Heap::with_capacity(256),
-                       mode: MachineMode::Write,
-                       and_stack: AndStack::new(),
-                       or_stack: OrStack::new(),
-                       registers: vec![Addr::HeapCell(0); 64],
-                       trail: Vec::new(),
-                       tr: 0,
-                       hb: 0,
-                       block: 0,
-                       ball: (0, Vec::new()),
-                       interms: vec![Number::default(); 256],
-                       sgc_cps: vec![]
+        MachineState {
+            atom_tbl,
+            s: 0,
+            p: CodePtr::default(),
+            b: 0,
+            b0: 0,
+            e: 0,
+            num_of_args: 0,
+            cp: CodePtr::default(),
+            fail: false,
+            heap: Heap::with_capacity(256),
+            mode: MachineMode::Write,
+            and_stack: AndStack::new(),
+            or_stack: OrStack::new(),
+            registers: vec![Addr::HeapCell(0); 64],
+            trail: Vec::new(),
+            tr: 0,
+            hb: 0,
+            block: 0,
+            ball: (0, Vec::new()),
+            interms: vec![Number::default(); 256]
         }
     }
 
@@ -158,11 +158,11 @@ impl MachineState {
 
     fn trail(&mut self, r: Ref) {
         match r {
-            Ref::HeapCell(hc) => 
+            Ref::HeapCell(hc) =>
                 if hc < self.hb {
                     self.trail.push(r);
                     self.tr += 1;
-                },            
+                },
             Ref::StackCell(fr, _) => {
                 let fr_gi = self.and_stack[fr].global_index;
                 let b_gi  = if !self.or_stack.is_empty() {
@@ -195,7 +195,7 @@ impl MachineState {
         }
     }
 
-    fn tidy_trail(&mut self) {
+    pub(super) fn tidy_trail(&mut self) {
         if self.b == 0 {
             return;
         }
@@ -1123,8 +1123,10 @@ impl MachineState {
             _ => self.fail = true
         };
     }
-    
-    pub(super) fn execute_built_in_instr(&mut self, code_dir: &CodeDir, instr: &BuiltInInstruction)
+
+    pub(super) fn execute_built_in_instr(&mut self, code_dir: &CodeDir,
+                                         cut_policy: &mut Box<CutPolicy>,
+                                         instr: &BuiltInInstruction)
     {
         match instr {
             &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => {
@@ -1202,7 +1204,17 @@ impl MachineState {
                 let b = self.b;
                 let block = self.block;
 
-                self.sgc_cps.push((addr, b, block));
+                if !cut_policy.is::<SetupCallCleanupCutPolicy>() {
+                    *cut_policy = Box::new(SetupCallCleanupCutPolicy::new());
+                }
+
+                match cut_policy.downcast_mut::<SetupCallCleanupCutPolicy>().ok()
+                {
+                    Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block),
+                    None => panic!("install_cleaner: should have installed \\
+SetupCallCleanupCutPolicy.")
+                };
+
                 self.p += 1;
             },
             &BuiltInInstruction::SetBall => {
@@ -1435,7 +1447,8 @@ impl MachineState {
         self.unify(Addr::HeapCell(old_h), a2);
     }
 
-    pub(super) fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
+    pub(super) fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, cut_policy: &mut Box<CutPolicy>,
+                                     instr: &ControlInstruction)
     {
         match instr {
             &ControlInstruction::Allocate(num_cells) => {
@@ -1561,23 +1574,28 @@ impl MachineState {
                     self.p = self.cp;
                     val
                 }),
-            &ControlInstruction::GetCleanerCall => {                
+            &ControlInstruction::GetCleanerCall => {
                 let dest = self[temp_v!(1)].clone();
                 
-                if let Some((cleaner_addr, b_cutoff, prev_block)) = self.sgc_cps.pop() {
-                    self.p += 1;
-                    
-                    if self.b <= b_cutoff + 1 {
-                        self.block = prev_block;
+                match cut_policy.downcast_mut::<SetupCallCleanupCutPolicy>().ok() {
+                    Some(sgc_policy) =>
+                        if let Some((addr, b_cutoff, prev_block)) = sgc_policy.pop_cont_pt()
+                        {
+                            self.p += 1;
                         
-                        if let Some(r) = dest.as_var() {
-                            self.bind(r, cleaner_addr);
-                            return;
-                        }
-                    } else {
-                        self.sgc_cps.push((cleaner_addr, b_cutoff, prev_block));                        
-                    }
-                }
+                            if self.b <= b_cutoff + 1 {
+                                self.block = prev_block;
+                                
+                                if let Some(r) = dest.as_var() {
+                                    self.bind(r, addr);
+                                    return;
+                                }
+                            } else {                                
+                                sgc_policy.push_cont_pt(addr, b_cutoff, prev_block);
+                            }
+                        },
+                    None => panic!("expected SetupCallCleanupCutPolicy trait object.")
+                };
 
                 self.fail = true;
             },
@@ -1796,7 +1814,9 @@ impl MachineState {
         }
     }
 
-    pub(super) fn execute_cut_instr(&mut self, instr: &CutInstruction) {
+    pub(super) fn execute_cut_instr(&mut self, instr: &CutInstruction,
+                                    cut_policy: &mut Box<CutPolicy>)
+    {
         match instr {
             &CutInstruction::NeckCut => {
                 let b  = self.b;
@@ -1816,29 +1836,8 @@ impl MachineState {
                 self[r] = Addr::Con(Constant::Usize(b0));
                 self.p += 1;
             },
-            &CutInstruction::Cut(r) => {
-                let b = self.b;
-
-                if let Addr::Con(Constant::Usize(b0)) = self[r].clone() {
-                    if b > b0 {
-                        self.b = b0;
-                        self.tidy_trail();
-                        self.or_stack.truncate(self.b);
-                    }
-                } else {
-                    self.fail = true;
-                    return;
-                }
-
-                self.p += 1;
-                
-                if !self.sgc_cps.is_empty() {
-                    self.cp = self.p;
-                    self.num_of_args = 0;
-                    self.b0 = self.b;
-                    self.p  = CodePtr::DirEntry(352); // goto_call run_cleaners_without_handling/0.
-                }
-            }
+            &CutInstruction::Cut(r) =>
+                cut_policy.cut(self, r),
         }
     }
 
index 7b9a3bc751c6bc16871153658cb744c55dd969fd..e3a44b808ead710c99e7cfb3da5c3a3c08eb8f41 100644 (file)
@@ -9,6 +9,8 @@ pub(crate) mod machine_state;
 #[macro_use]
 mod machine_state_impl;
 
+use prolog::machine::machine_state::*;
+
 use std::cell::RefCell;
 use std::collections::{HashMap, HashSet};
 use std::mem::swap;
@@ -16,7 +18,8 @@ use std::ops::Index;
 use std::rc::Rc;
 
 pub struct Machine {
-    ms: machine_state::MachineState,
+    ms: MachineState,
+    cut_policy: Box<CutPolicy>,
     code: Code,
     code_dir: CodeDir,
     op_dir: OpDir,
@@ -46,7 +49,8 @@ impl Machine {
         
         
         Machine {
-            ms: machine_state::MachineState::new(atom_tbl),
+            ms: MachineState::new(atom_tbl),
+            cut_policy: Box::new(DefaultCutPolicy {}),
             code,
             code_dir,
             op_dir,
@@ -102,13 +106,13 @@ impl Machine {
             &Line::Arithmetic(ref arith_instr) =>
                 self.ms.execute_arith_instr(arith_instr),
             &Line::BuiltIn(ref built_in_instr) =>
-                self.ms.execute_built_in_instr(&self.code_dir, built_in_instr),
+                self.ms.execute_built_in_instr(&self.code_dir, &mut self.cut_policy, built_in_instr),
             &Line::Choice(ref choice_instr) =>
                 self.ms.execute_choice_instr(choice_instr),
             &Line::Cut(ref cut_instr) =>
-                self.ms.execute_cut_instr(cut_instr),
+                self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
             &Line::Control(ref control_instr) =>
-                self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
+                self.ms.execute_ctrl_instr(&self.code_dir, &mut self.cut_policy, control_instr),
             &Line::Fact(ref fact) => {
                 for fact_instr in fact {
                     if self.failed() {
@@ -117,7 +121,7 @@ impl Machine {
 
                     self.ms.execute_fact_instr(&fact_instr);
                 }
-
                 self.ms.p += 1;
             },
             &Line::Indexing(ref indexing_instr) =>
@@ -341,6 +345,7 @@ impl Machine {
     }
 
     pub fn reset(&mut self) {
+        self.cut_policy = Box::new(DefaultCutPolicy {});
         self.ms.reset();
     }