From: Mark Thom Date: Wed, 7 Feb 2018 06:41:31 +0000 (-0700) Subject: defer cut actions to cut policy trait objects. X-Git-Tag: v0.8.110~578 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=1bf9c0d205819efa9881110d3da6dcd0037d84cd;p=scryer-prolog.git defer cut actions to cut policy trait objects. --- diff --git a/Cargo.lock b/Cargo.lock index ddb719f8..27072053 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 08e048a7..b29cd230 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/main.rs b/src/main.rs index 0e71c49c..62cde4ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #[macro_use] extern crate lazy_static; +#[macro_use] extern crate downcast; extern crate termion; mod prolog; diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 5d2c89bd..c6f1be05 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -506,7 +506,7 @@ fn get_builtins(atom_tbl: TabledData) -> 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) -> 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!(), diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index a2fd7a42..57a9a009 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -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 + machine_st: &'a MachineState, + state_stack: Vec } 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] } } diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 0bc19e57..6bcdecfc 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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), // heap boundary, and a term copy pub(super) interms: Vec, // 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. + } + } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 57c1f094..a60d7f23 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -28,27 +28,27 @@ macro_rules! try_or_fail { impl MachineState { pub(super) fn new(atom_tbl: TabledData) -> 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, + 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::() { + *cut_policy = Box::new(SetupCallCleanupCutPolicy::new()); + } + + match cut_policy.downcast_mut::().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, + 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::().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) + { 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), } } diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 7b9a3bc7..e3a44b80 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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, 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(); }