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"
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)",
[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"
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
#[macro_use] extern crate lazy_static;
+#[macro_use] extern crate downcast;
extern crate termion;
mod prolog;
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)),
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!(),
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]
}
}
use prolog::or_stack::*;
use prolog::tabled_rc::*;
+use downcast::Any;
use std::ops::{Index, IndexMut};
pub(super) struct DuplicateTerm<'a> {
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.
+ }
+ }
}
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]
}
}
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() {
}
}
- fn tidy_trail(&mut self) {
+ pub(super) fn tidy_trail(&mut self) {
if self.b == 0 {
return;
}
_ => 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) => {
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 => {
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) => {
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;
},
}
}
- 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;
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),
}
}
#[macro_use]
mod machine_state_impl;
+use prolog::machine::machine_state::*;
+
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::mem::swap;
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,
Machine {
- ms: machine_state::MachineState::new(atom_tbl),
+ ms: MachineState::new(atom_tbl),
+ cut_policy: Box::new(DefaultCutPolicy {}),
code,
code_dir,
op_dir,
&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() {
self.ms.execute_fact_instr(&fact_instr);
}
-
+
self.ms.p += 1;
},
&Line::Indexing(ref indexing_instr) =>
}
pub fn reset(&mut self) {
+ self.cut_policy = Box::new(DefaultCutPolicy {});
self.ms.reset();
}