add findall/3
This commit is contained in:
@@ -4,6 +4,7 @@ use prolog_parser::string_list::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::and_stack::*;
|
||||
use prolog::copier::*;
|
||||
use prolog::heap::*;
|
||||
use prolog::machine::{AttrVarInitializer, IndexStore};
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::num::{BigInt, BigUint, Zero, One};
|
||||
@@ -59,10 +60,6 @@ impl<'a> IndexMut<usize> for CopyTerm<'a> {
|
||||
|
||||
// the ordinary, heap term copier, used by duplicate_term.
|
||||
impl<'a> CopierTarget for CopyTerm<'a> {
|
||||
fn source(&self) -> usize {
|
||||
self.state.heap.h
|
||||
}
|
||||
|
||||
fn threshold(&self) -> usize {
|
||||
self.state.heap.h
|
||||
}
|
||||
@@ -85,14 +82,17 @@ impl<'a> CopierTarget for CopyTerm<'a> {
|
||||
}
|
||||
|
||||
pub(super) struct CopyBallTerm<'a> {
|
||||
state: &'a mut MachineState,
|
||||
heap_boundary: usize
|
||||
and_stack: &'a mut AndStack,
|
||||
heap: &'a mut Heap,
|
||||
heap_boundary: usize,
|
||||
stub: &'a mut MachineStub,
|
||||
}
|
||||
|
||||
impl<'a> CopyBallTerm<'a> {
|
||||
pub(super) fn new(state: &'a mut MachineState) -> Self {
|
||||
let hb = state.heap.len();
|
||||
CopyBallTerm { state, heap_boundary: hb }
|
||||
pub(super) fn new(and_stack: &'a mut AndStack, heap: &'a mut Heap, stub: &'a mut MachineStub) -> Self
|
||||
{
|
||||
let hb = heap.len();
|
||||
CopyBallTerm { and_stack, heap, heap_boundary: hb, stub }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,10 +101,10 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
if index < self.heap_boundary {
|
||||
&self.state.heap[index]
|
||||
&self.heap[index]
|
||||
} else {
|
||||
let index = index - self.heap_boundary;
|
||||
&self.state.ball.stub[index]
|
||||
&self.stub[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,38 +112,34 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
|
||||
impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
if index < self.heap_boundary {
|
||||
&mut self.state.heap[index]
|
||||
&mut self.heap[index]
|
||||
} else {
|
||||
let index = index - self.heap_boundary;
|
||||
&mut self.state.ball.stub[index]
|
||||
&mut self.stub[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the ordinary, heap term copier, used by duplicate_term.
|
||||
impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
fn source(&self) -> usize {
|
||||
self.heap_boundary
|
||||
}
|
||||
|
||||
fn threshold(&self) -> usize {
|
||||
self.heap_boundary + self.state.ball.stub.len()
|
||||
self.heap_boundary + self.stub.len()
|
||||
}
|
||||
|
||||
fn push(&mut self, hcv: HeapCellValue) {
|
||||
self.state.ball.stub.push(hcv);
|
||||
fn push(&mut self, value: HeapCellValue) {
|
||||
self.stub.push(value);
|
||||
}
|
||||
|
||||
fn store(&self, addr: Addr) -> Addr {
|
||||
match addr {
|
||||
Addr::HeapCell(hc) if hc < self.heap_boundary =>
|
||||
self.state.heap[hc].as_addr(hc),
|
||||
Addr::HeapCell(hc) => {
|
||||
let index = hc - self.heap_boundary;
|
||||
self.state.ball.stub[index].as_addr(hc)
|
||||
Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary =>
|
||||
self.heap[h].as_addr(h),
|
||||
Addr::HeapCell(h) | Addr::AttrVar(h) => {
|
||||
let index = h - self.heap_boundary;
|
||||
self.stub[index].as_addr(h)
|
||||
},
|
||||
Addr::StackCell(fr, sc) =>
|
||||
self.state.and_stack[fr][sc].clone(),
|
||||
self.and_stack[fr][sc].clone(),
|
||||
addr => addr
|
||||
}
|
||||
}
|
||||
@@ -162,7 +158,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
}
|
||||
|
||||
fn stack(&mut self) -> &mut AndStack {
|
||||
&mut self.state.and_stack
|
||||
self.and_stack
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +216,7 @@ pub struct MachineState {
|
||||
pub(super) hb: usize,
|
||||
pub(super) block: usize, // an offset into the OR stack.
|
||||
pub(super) ball: Ball,
|
||||
pub(super) lifted_heap: Vec<HeapCellValue>,
|
||||
pub(super) interms: Vec<Number>, // intermediate numbers.
|
||||
pub(super) last_call: bool,
|
||||
pub(crate) flags: MachineFlags
|
||||
@@ -626,7 +623,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
},
|
||||
&BuiltInClauseType::CopyTerm => {
|
||||
machine_st.duplicate_term();
|
||||
machine_st.copy_term();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
&BuiltInClauseType::Eq => {
|
||||
|
||||
@@ -4,6 +4,7 @@ use prolog_parser::string_list::StringList;
|
||||
use prolog::instructions::*;
|
||||
use prolog::and_stack::*;
|
||||
use prolog::copier::*;
|
||||
use prolog::heap::*;
|
||||
use prolog::heap_iter::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::machine::{AttrVarInitializer, IndexStore};
|
||||
@@ -42,7 +43,7 @@ impl MachineState {
|
||||
cp: LocalCodePtr::default(),
|
||||
attr_var_init: AttrVarInitializer::new(0, 0),
|
||||
fail: false,
|
||||
heap: Heap::with_capacity(256),
|
||||
heap: Heap::with_capacity(1024),
|
||||
mode: MachineMode::Write,
|
||||
and_stack: AndStack::new(),
|
||||
or_stack: OrStack::new(),
|
||||
@@ -54,6 +55,7 @@ impl MachineState {
|
||||
hb: 0,
|
||||
block: 0,
|
||||
ball: Ball::new(),
|
||||
lifted_heap: Vec::with_capacity(1024),
|
||||
interms: vec![Number::default(); 256],
|
||||
last_call: false,
|
||||
flags: MachineFlags::default()
|
||||
@@ -1348,7 +1350,7 @@ impl MachineState {
|
||||
pub(super) fn set_ball(&mut self) {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.boundary = self.heap.h;
|
||||
copy_term(CopyBallTerm::new(self), addr);
|
||||
copy_term(CopyBallTerm::new(&mut self.and_stack, &mut self.heap, &mut self.ball.stub), addr);
|
||||
}
|
||||
|
||||
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey>
|
||||
@@ -1416,10 +1418,12 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn copy_and_align_ball_to_heap(&mut self) -> usize {
|
||||
pub(super) fn copy_and_align_ball_to_heap(&mut self, from: usize) -> usize {
|
||||
let diff = self.heap_ball_boundary_diff();
|
||||
|
||||
for heap_value in self.ball.stub.iter().cloned() {
|
||||
for index in from .. self.ball.stub.len() {
|
||||
let heap_value = self.ball.stub[index].clone();
|
||||
|
||||
self.heap.push(match heap_value {
|
||||
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff),
|
||||
_ => heap_value
|
||||
@@ -2021,7 +2025,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn duplicate_term(&mut self) {
|
||||
pub(super) fn copy_term(&mut self) {
|
||||
let old_h = self.heap.h;
|
||||
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
@@ -2380,5 +2384,6 @@ impl MachineState {
|
||||
self.block = 0;
|
||||
|
||||
self.ball.reset();
|
||||
self.lifted_heap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ impl Machine {
|
||||
{
|
||||
if self.machine_st.ball.stub.len() > 0 {
|
||||
let h = self.machine_st.heap.h;
|
||||
self.machine_st.copy_and_align_ball_to_heap();
|
||||
self.machine_st.copy_and_align_ball_to_heap(0);
|
||||
|
||||
let error_str = self.machine_st.print_exception(Addr::HeapCell(h),
|
||||
&heap_locs,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use prolog::copier::*;
|
||||
use prolog::heap_iter::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
@@ -190,13 +191,34 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn system_call(&mut self, ct: &SystemClauseType,
|
||||
fn copy_findall_solution(&mut self, lh_offset: usize, copy_target: Addr) -> usize
|
||||
{
|
||||
let threshold = self.lifted_heap.len() - lh_offset;
|
||||
let mut copy_ball_term = CopyBallTerm::new(&mut self.and_stack, &mut self.heap,
|
||||
&mut self.lifted_heap);
|
||||
|
||||
copy_ball_term.push(HeapCellValue::Addr(Addr::Lis(threshold + 1)));
|
||||
copy_ball_term.push(HeapCellValue::Addr(Addr::HeapCell(threshold + 3)));
|
||||
copy_ball_term.push(HeapCellValue::Addr(Addr::HeapCell(threshold + 2)));
|
||||
|
||||
copy_term(copy_ball_term, copy_target);
|
||||
threshold + lh_offset + 2
|
||||
}
|
||||
|
||||
pub(super) fn system_call(&mut self,
|
||||
ct: &SystemClauseType,
|
||||
indices: &IndexStore,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>)
|
||||
-> CallResult
|
||||
{
|
||||
match ct {
|
||||
&SystemClauseType::LiftedHeapLength => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len()));
|
||||
|
||||
self.unify(a1, lh_len);
|
||||
},
|
||||
&SystemClauseType::CheckCutPoint => {
|
||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
@@ -205,6 +227,27 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&SystemClauseType::CopyToLiftedHeap =>
|
||||
// now, stagger everything down by the length of the heap + lh offset.
|
||||
match self.store(self.deref(self[temp_v!(1)].clone())) {
|
||||
Addr::Con(Constant::Usize(lh_offset)) => {
|
||||
let copy_target = self[temp_v!(2)].clone();
|
||||
|
||||
let old_threshold = self.copy_findall_solution(lh_offset, copy_target);
|
||||
let new_threshold = self.lifted_heap.len() - lh_offset;
|
||||
|
||||
self.lifted_heap[old_threshold] = HeapCellValue::Addr(Addr::HeapCell(new_threshold));
|
||||
|
||||
for index in old_threshold + 1 .. self.lifted_heap.len() {
|
||||
match &mut self.lifted_heap[index] {
|
||||
&mut HeapCellValue::Addr(ref mut addr) =>
|
||||
*addr -= self.heap.len() + lh_offset,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => self.fail = true
|
||||
},
|
||||
&SystemClauseType::DeleteAttribute => {
|
||||
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
@@ -282,6 +325,18 @@ impl MachineState {
|
||||
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::TruncateIfNoLiftedHeapGrowth =>
|
||||
match self.store(self.deref(self[temp_v!(1)].clone())) {
|
||||
Addr::Con(Constant::Usize(lh_offset)) => {
|
||||
if lh_offset >= self.lifted_heap.len() {
|
||||
self.lifted_heap.truncate(lh_offset);
|
||||
} else {
|
||||
self.lifted_heap.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
||||
}
|
||||
},
|
||||
_ =>
|
||||
self.fail = true
|
||||
},
|
||||
&SystemClauseType::GetAttributedVariableList => {
|
||||
let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let mut attr_var_list = match attr_var {
|
||||
@@ -317,15 +372,43 @@ impl MachineState {
|
||||
match self.store(self.deref(addr)) {
|
||||
Addr::Con(Constant::Usize(b)) => {
|
||||
let iter = self.gather_attr_vars_created_since(b);
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
let list_addr = self[temp_v!(2)].clone();
|
||||
|
||||
self.unify(var_list_addr, list_addr);
|
||||
|
||||
self.unify(var_list_addr, list_addr);
|
||||
},
|
||||
_ => self.fail = true
|
||||
}
|
||||
},
|
||||
&SystemClauseType::GetLiftedHeapFromOffset => {
|
||||
let lh_offset = self[temp_v!(1)].clone();
|
||||
|
||||
match self.store(self.deref(lh_offset)) {
|
||||
Addr::Con(Constant::Usize(lh_offset)) =>
|
||||
if lh_offset >= self.lifted_heap.len() {
|
||||
let solutions = self[temp_v!(2)].clone();
|
||||
self.unify(solutions, Addr::Con(Constant::EmptyList));
|
||||
} else {
|
||||
let h = self.heap.h;
|
||||
|
||||
for index in lh_offset .. self.lifted_heap.len() {
|
||||
match self.lifted_heap[index].clone() {
|
||||
HeapCellValue::Addr(addr) =>
|
||||
self.heap.push(HeapCellValue::Addr(addr + h)),
|
||||
value =>
|
||||
self.heap.push(value)
|
||||
}
|
||||
}
|
||||
|
||||
self.lifted_heap.truncate(lh_offset);
|
||||
|
||||
let solutions = self[temp_v!(2)].clone();
|
||||
self.unify(Addr::HeapCell(h), solutions);
|
||||
},
|
||||
_ => self.fail = true
|
||||
}
|
||||
},
|
||||
&SystemClauseType::GetDoubleQuotes => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
|
||||
@@ -574,7 +657,7 @@ impl MachineState {
|
||||
let h = self.heap.h;
|
||||
|
||||
if self.ball.stub.len() > 0 {
|
||||
self.copy_and_align_ball_to_heap();
|
||||
self.copy_and_align_ball_to_heap(0);
|
||||
} else {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
|
||||
Reference in New Issue
Block a user