add findall/3
This commit is contained in:
@@ -7,7 +7,6 @@ type Trail = Vec<(Ref, HeapCellValue)>;
|
|||||||
|
|
||||||
pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
|
pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
|
||||||
{
|
{
|
||||||
fn source(&self) -> usize;
|
|
||||||
fn threshold(&self) -> usize;
|
fn threshold(&self) -> usize;
|
||||||
fn push(&mut self, HeapCellValue);
|
fn push(&mut self, HeapCellValue);
|
||||||
fn store(&self, Addr) -> Addr;
|
fn store(&self, Addr) -> Addr;
|
||||||
@@ -33,7 +32,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
fn new(target: T) -> Self {
|
fn new(target: T) -> Self {
|
||||||
CopyTermState {
|
CopyTermState {
|
||||||
trail: vec![],
|
trail: vec![],
|
||||||
scan: target.source(),
|
scan: 0,
|
||||||
old_h: target.threshold(),
|
old_h: target.threshold(),
|
||||||
target
|
target
|
||||||
}
|
}
|
||||||
@@ -168,6 +167,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_term_impl(&mut self, addr: Addr) {
|
fn copy_term_impl(&mut self, addr: Addr) {
|
||||||
|
self.scan = self.target.threshold();
|
||||||
self.target.push(HeapCellValue::Addr(addr));
|
self.target.push(HeapCellValue::Addr(addr));
|
||||||
|
|
||||||
while self.scan < self.target.threshold() {
|
while self.scan < self.target.threshold() {
|
||||||
|
|||||||
71
src/prolog/heap.rs
Normal file
71
src/prolog/heap.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
|
use prolog::instructions::*;
|
||||||
|
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
|
pub struct Heap {
|
||||||
|
heap: Vec<HeapCellValue>,
|
||||||
|
pub h: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Heap {
|
||||||
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
|
Heap { heap: Vec::with_capacity(cap),
|
||||||
|
h: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, val: HeapCellValue) {
|
||||||
|
self.heap.push(val);
|
||||||
|
self.h += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate(&mut self, h: usize) {
|
||||||
|
self.h = h;
|
||||||
|
self.heap.truncate(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.heap.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, vals: Vec<HeapCellValue>) {
|
||||||
|
let n = vals.len();
|
||||||
|
|
||||||
|
self.heap.extend(vals.into_iter());
|
||||||
|
self.h += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.heap.clear();
|
||||||
|
self.h = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_list<Iter: Iterator<Item=Addr>>(&mut self, values: Iter) -> usize {
|
||||||
|
let head_addr = self.h;
|
||||||
|
|
||||||
|
for value in values {
|
||||||
|
let h = self.h;
|
||||||
|
|
||||||
|
self.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
||||||
|
self.push(HeapCellValue::Addr(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
||||||
|
head_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for Heap {
|
||||||
|
type Output = HeapCellValue;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.heap[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<usize> for Heap {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
&mut self.heap[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ use prolog_parser::tabled_rc::*;
|
|||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{BTreeSet, HashMap, VecDeque};
|
use std::collections::{BTreeSet, HashMap, VecDeque};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::ops::{Add, AddAssign, Index, IndexMut, Sub};
|
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
@@ -238,6 +238,7 @@ pub struct Module {
|
|||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum SystemClauseType {
|
pub enum SystemClauseType {
|
||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
|
CopyToLiftedHeap,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
DeleteHeadAttribute,
|
DeleteHeadAttribute,
|
||||||
DynamicModuleResolution,
|
DynamicModuleResolution,
|
||||||
@@ -245,13 +246,16 @@ pub enum SystemClauseType {
|
|||||||
EnqueueAttributedVar,
|
EnqueueAttributedVar,
|
||||||
ExpandGoal,
|
ExpandGoal,
|
||||||
ExpandTerm,
|
ExpandTerm,
|
||||||
|
TruncateIfNoLiftedHeapGrowth,
|
||||||
GetAttributedVariableList,
|
GetAttributedVariableList,
|
||||||
GetAttrVarQueueDelimiter,
|
GetAttrVarQueueDelimiter,
|
||||||
GetAttrVarQueueBeyond,
|
GetAttrVarQueueBeyond,
|
||||||
GetBValue,
|
GetBValue,
|
||||||
|
GetLiftedHeapFromOffset,
|
||||||
GetSCCCleaner,
|
GetSCCCleaner,
|
||||||
InstallSCCCleaner,
|
InstallSCCCleaner,
|
||||||
InstallInferenceCounter,
|
InstallInferenceCounter,
|
||||||
|
LiftedHeapLength,
|
||||||
ModuleOf,
|
ModuleOf,
|
||||||
RedoAttrVarBindings,
|
RedoAttrVarBindings,
|
||||||
RemoveCallPolicyCheck,
|
RemoveCallPolicyCheck,
|
||||||
@@ -282,8 +286,9 @@ pub enum SystemClauseType {
|
|||||||
|
|
||||||
impl SystemClauseType {
|
impl SystemClauseType {
|
||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
||||||
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
||||||
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
|
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
|
||||||
@@ -291,14 +296,17 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
&SystemClauseType::EnqueueAttributedVar => clause_name!("$enqueue_attr_var"),
|
||||||
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
||||||
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
||||||
|
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"),
|
||||||
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
|
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
|
||||||
&SystemClauseType::GetAttrVarQueueDelimiter => clause_name!("$get_attr_var_queue_delim"),
|
&SystemClauseType::GetAttrVarQueueDelimiter => clause_name!("$get_attr_var_queue_delim"),
|
||||||
&SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"),
|
&SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"),
|
||||||
|
&SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"),
|
||||||
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
||||||
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
||||||
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
||||||
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
||||||
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"),
|
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"),
|
||||||
|
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
|
||||||
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
||||||
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
|
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
|
||||||
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
|
&SystemClauseType::RemoveCallPolicyCheck => clause_name!("$remove_call_policy_check"),
|
||||||
@@ -328,8 +336,9 @@ impl SystemClauseType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
|
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
||||||
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
||||||
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
||||||
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
|
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
|
||||||
@@ -337,12 +346,15 @@ impl SystemClauseType {
|
|||||||
("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
|
("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
|
||||||
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
|
("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth),
|
||||||
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
||||||
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
||||||
|
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
||||||
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
|
("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
|
||||||
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
|
("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
|
||||||
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
|
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
|
||||||
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
||||||
|
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
||||||
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
||||||
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
|
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
|
||||||
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
||||||
@@ -834,6 +846,12 @@ impl Sub<usize> for Addr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SubAssign<usize> for Addr {
|
||||||
|
fn sub_assign(&mut self, rhs: usize) {
|
||||||
|
*self = self.clone() - rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Ref> for Addr {
|
impl From<Ref> for Addr {
|
||||||
fn from(r: Ref) -> Self {
|
fn from(r: Ref) -> Self {
|
||||||
match r {
|
match r {
|
||||||
@@ -1067,71 +1085,6 @@ impl AddAssign<usize> for CodePtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Heap {
|
|
||||||
heap: Vec<HeapCellValue>,
|
|
||||||
pub h: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Heap {
|
|
||||||
pub fn with_capacity(cap: usize) -> Self {
|
|
||||||
Heap { heap: Vec::with_capacity(cap), h: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, val: HeapCellValue) {
|
|
||||||
self.heap.push(val);
|
|
||||||
self.h += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn truncate(&mut self, h: usize) {
|
|
||||||
self.h = h;
|
|
||||||
self.heap.truncate(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.heap.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn append(&mut self, vals: Vec<HeapCellValue>) {
|
|
||||||
let n = vals.len();
|
|
||||||
|
|
||||||
self.heap.extend(vals.into_iter());
|
|
||||||
self.h += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.heap.clear();
|
|
||||||
self.h = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_list<Iter: Iterator<Item=Addr>>(&mut self, values: Iter) -> usize {
|
|
||||||
let head_addr = self.h;
|
|
||||||
|
|
||||||
for value in values {
|
|
||||||
let h = self.h;
|
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
|
||||||
self.push(HeapCellValue::Addr(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
|
||||||
head_addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Index<usize> for Heap {
|
|
||||||
type Output = HeapCellValue;
|
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
|
||||||
&self.heap[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IndexMut<usize> for Heap {
|
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
|
||||||
&mut self.heap[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Registers = Vec<Addr>;
|
pub type Registers = Vec<Addr>;
|
||||||
|
|
||||||
pub enum TermIterState<'a> {
|
pub enum TermIterState<'a> {
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
(=..)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2,
|
(=..)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2,
|
||||||
(=@=)/2, (\=@=)/2, (:)/2, call_with_inference_limit/3,
|
(=@=)/2, (\=@=)/2, (:)/2, call_with_inference_limit/3,
|
||||||
catch/3, current_prolog_flag/2, expand_goal/2, expand_term/2,
|
catch/3, current_prolog_flag/2, expand_goal/2, expand_term/2,
|
||||||
set_prolog_flag/2, setup_call_cleanup/3, term_variables/2,
|
findall/3, set_prolog_flag/2, setup_call_cleanup/3,
|
||||||
throw/1, true/0, false/0, write/1, write_canonical/1,
|
term_variables/2, throw/1, true/0, false/0, write/1,
|
||||||
writeq/1, write_term/2]).
|
write_canonical/1, writeq/1, write_term/2]).
|
||||||
|
|
||||||
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
|
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
|
||||||
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
|
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
|
||||||
@@ -351,3 +351,20 @@ handle_ball(C, C, R) :- !, '$erase_ball', call(R).
|
|||||||
handle_ball(_, _, _) :- '$unwind_stack'.
|
handle_ball(_, _, _) :- '$unwind_stack'.
|
||||||
|
|
||||||
throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'.
|
throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'.
|
||||||
|
|
||||||
|
:- non_counted_backtracking '$iterate_find_all'/4.
|
||||||
|
'$iterate_find_all'(Template, Goal, _, LhOffset) :-
|
||||||
|
call(Goal),
|
||||||
|
'$copy_to_lh'(LhOffset, Template),
|
||||||
|
'$fail'.
|
||||||
|
'$iterate_find_all'(_, _, Solutions, LhOffset) :-
|
||||||
|
'$truncate_if_no_lh_growth'(LhOffset),
|
||||||
|
'$get_lh_from_offset'(LhOffset, Solutions).
|
||||||
|
|
||||||
|
findall(Template, Goal, Solutions) :-
|
||||||
|
'$skip_max_list'(_, -1, Solutions, R),
|
||||||
|
( nonvar(R), R \== [], throw(error(type_error(list, Solutions), findall/3))
|
||||||
|
; true
|
||||||
|
),
|
||||||
|
'$lh_length'(LhLength),
|
||||||
|
'$call_with_default_policy'('$iterate_find_all'(Template, Goal, Solutions, LhLength)).
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use prolog_parser::string_list::*;
|
|||||||
use prolog::instructions::*;
|
use prolog::instructions::*;
|
||||||
use prolog::and_stack::*;
|
use prolog::and_stack::*;
|
||||||
use prolog::copier::*;
|
use prolog::copier::*;
|
||||||
|
use prolog::heap::*;
|
||||||
use prolog::machine::{AttrVarInitializer, IndexStore};
|
use prolog::machine::{AttrVarInitializer, IndexStore};
|
||||||
use prolog::machine::machine_errors::*;
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::num::{BigInt, BigUint, Zero, One};
|
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.
|
// the ordinary, heap term copier, used by duplicate_term.
|
||||||
impl<'a> CopierTarget for CopyTerm<'a> {
|
impl<'a> CopierTarget for CopyTerm<'a> {
|
||||||
fn source(&self) -> usize {
|
|
||||||
self.state.heap.h
|
|
||||||
}
|
|
||||||
|
|
||||||
fn threshold(&self) -> usize {
|
fn threshold(&self) -> usize {
|
||||||
self.state.heap.h
|
self.state.heap.h
|
||||||
}
|
}
|
||||||
@@ -85,14 +82,17 @@ impl<'a> CopierTarget for CopyTerm<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct CopyBallTerm<'a> {
|
pub(super) struct CopyBallTerm<'a> {
|
||||||
state: &'a mut MachineState,
|
and_stack: &'a mut AndStack,
|
||||||
heap_boundary: usize
|
heap: &'a mut Heap,
|
||||||
|
heap_boundary: usize,
|
||||||
|
stub: &'a mut MachineStub,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CopyBallTerm<'a> {
|
impl<'a> CopyBallTerm<'a> {
|
||||||
pub(super) fn new(state: &'a mut MachineState) -> Self {
|
pub(super) fn new(and_stack: &'a mut AndStack, heap: &'a mut Heap, stub: &'a mut MachineStub) -> Self
|
||||||
let hb = state.heap.len();
|
{
|
||||||
CopyBallTerm { state, heap_boundary: hb }
|
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 {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
if index < self.heap_boundary {
|
if index < self.heap_boundary {
|
||||||
&self.state.heap[index]
|
&self.heap[index]
|
||||||
} else {
|
} else {
|
||||||
let index = index - self.heap_boundary;
|
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> {
|
impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
if index < self.heap_boundary {
|
if index < self.heap_boundary {
|
||||||
&mut self.state.heap[index]
|
&mut self.heap[index]
|
||||||
} else {
|
} else {
|
||||||
let index = index - self.heap_boundary;
|
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.
|
// the ordinary, heap term copier, used by duplicate_term.
|
||||||
impl<'a> CopierTarget for CopyBallTerm<'a> {
|
impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||||
fn source(&self) -> usize {
|
|
||||||
self.heap_boundary
|
|
||||||
}
|
|
||||||
|
|
||||||
fn threshold(&self) -> usize {
|
fn threshold(&self) -> usize {
|
||||||
self.heap_boundary + self.state.ball.stub.len()
|
self.heap_boundary + self.stub.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, hcv: HeapCellValue) {
|
fn push(&mut self, value: HeapCellValue) {
|
||||||
self.state.ball.stub.push(hcv);
|
self.stub.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store(&self, addr: Addr) -> Addr {
|
fn store(&self, addr: Addr) -> Addr {
|
||||||
match addr {
|
match addr {
|
||||||
Addr::HeapCell(hc) if hc < self.heap_boundary =>
|
Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary =>
|
||||||
self.state.heap[hc].as_addr(hc),
|
self.heap[h].as_addr(h),
|
||||||
Addr::HeapCell(hc) => {
|
Addr::HeapCell(h) | Addr::AttrVar(h) => {
|
||||||
let index = hc - self.heap_boundary;
|
let index = h - self.heap_boundary;
|
||||||
self.state.ball.stub[index].as_addr(hc)
|
self.stub[index].as_addr(h)
|
||||||
},
|
},
|
||||||
Addr::StackCell(fr, sc) =>
|
Addr::StackCell(fr, sc) =>
|
||||||
self.state.and_stack[fr][sc].clone(),
|
self.and_stack[fr][sc].clone(),
|
||||||
addr => addr
|
addr => addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,7 +158,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn stack(&mut self) -> &mut AndStack {
|
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) hb: usize,
|
||||||
pub(super) block: usize, // an offset into the OR stack.
|
pub(super) block: usize, // an offset into the OR stack.
|
||||||
pub(super) ball: Ball,
|
pub(super) ball: Ball,
|
||||||
|
pub(super) lifted_heap: Vec<HeapCellValue>,
|
||||||
pub(super) interms: Vec<Number>, // intermediate numbers.
|
pub(super) interms: Vec<Number>, // intermediate numbers.
|
||||||
pub(super) last_call: bool,
|
pub(super) last_call: bool,
|
||||||
pub(crate) flags: MachineFlags
|
pub(crate) flags: MachineFlags
|
||||||
@@ -626,7 +623,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
&BuiltInClauseType::CopyTerm => {
|
&BuiltInClauseType::CopyTerm => {
|
||||||
machine_st.duplicate_term();
|
machine_st.copy_term();
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
return_from_clause!(machine_st.last_call, machine_st)
|
||||||
},
|
},
|
||||||
&BuiltInClauseType::Eq => {
|
&BuiltInClauseType::Eq => {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use prolog_parser::string_list::StringList;
|
|||||||
use prolog::instructions::*;
|
use prolog::instructions::*;
|
||||||
use prolog::and_stack::*;
|
use prolog::and_stack::*;
|
||||||
use prolog::copier::*;
|
use prolog::copier::*;
|
||||||
|
use prolog::heap::*;
|
||||||
use prolog::heap_iter::*;
|
use prolog::heap_iter::*;
|
||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
use prolog::machine::{AttrVarInitializer, IndexStore};
|
use prolog::machine::{AttrVarInitializer, IndexStore};
|
||||||
@@ -42,7 +43,7 @@ impl MachineState {
|
|||||||
cp: LocalCodePtr::default(),
|
cp: LocalCodePtr::default(),
|
||||||
attr_var_init: AttrVarInitializer::new(0, 0),
|
attr_var_init: AttrVarInitializer::new(0, 0),
|
||||||
fail: false,
|
fail: false,
|
||||||
heap: Heap::with_capacity(256),
|
heap: Heap::with_capacity(1024),
|
||||||
mode: MachineMode::Write,
|
mode: MachineMode::Write,
|
||||||
and_stack: AndStack::new(),
|
and_stack: AndStack::new(),
|
||||||
or_stack: OrStack::new(),
|
or_stack: OrStack::new(),
|
||||||
@@ -54,6 +55,7 @@ impl MachineState {
|
|||||||
hb: 0,
|
hb: 0,
|
||||||
block: 0,
|
block: 0,
|
||||||
ball: Ball::new(),
|
ball: Ball::new(),
|
||||||
|
lifted_heap: Vec::with_capacity(1024),
|
||||||
interms: vec![Number::default(); 256],
|
interms: vec![Number::default(); 256],
|
||||||
last_call: false,
|
last_call: false,
|
||||||
flags: MachineFlags::default()
|
flags: MachineFlags::default()
|
||||||
@@ -1348,7 +1350,7 @@ impl MachineState {
|
|||||||
pub(super) fn set_ball(&mut self) {
|
pub(super) fn set_ball(&mut self) {
|
||||||
let addr = self[temp_v!(1)].clone();
|
let addr = self[temp_v!(1)].clone();
|
||||||
self.ball.boundary = self.heap.h;
|
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>
|
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();
|
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 {
|
self.heap.push(match heap_value {
|
||||||
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff),
|
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff),
|
||||||
_ => heap_value
|
_ => 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 old_h = self.heap.h;
|
||||||
|
|
||||||
let a1 = self[temp_v!(1)].clone();
|
let a1 = self[temp_v!(1)].clone();
|
||||||
@@ -2380,5 +2384,6 @@ impl MachineState {
|
|||||||
self.block = 0;
|
self.block = 0;
|
||||||
|
|
||||||
self.ball.reset();
|
self.ball.reset();
|
||||||
|
self.lifted_heap.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ impl Machine {
|
|||||||
{
|
{
|
||||||
if self.machine_st.ball.stub.len() > 0 {
|
if self.machine_st.ball.stub.len() > 0 {
|
||||||
let h = self.machine_st.heap.h;
|
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),
|
let error_str = self.machine_st.print_exception(Addr::HeapCell(h),
|
||||||
&heap_locs,
|
&heap_locs,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use prolog_parser::ast::*;
|
use prolog_parser::ast::*;
|
||||||
|
|
||||||
|
use prolog::copier::*;
|
||||||
use prolog::heap_iter::*;
|
use prolog::heap_iter::*;
|
||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
use prolog::instructions::*;
|
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,
|
indices: &IndexStore,
|
||||||
call_policy: &mut Box<CallPolicy>,
|
call_policy: &mut Box<CallPolicy>,
|
||||||
cut_policy: &mut Box<CutPolicy>)
|
cut_policy: &mut Box<CutPolicy>)
|
||||||
-> CallResult
|
-> CallResult
|
||||||
{
|
{
|
||||||
match ct {
|
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 => {
|
&SystemClauseType::CheckCutPoint => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
@@ -205,6 +227,27 @@ impl MachineState {
|
|||||||
_ => self.fail = true
|
_ => 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 => {
|
&SystemClauseType::DeleteAttribute => {
|
||||||
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
|
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
@@ -282,6 +325,18 @@ impl MachineState {
|
|||||||
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
||||||
return Ok(());
|
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 => {
|
&SystemClauseType::GetAttributedVariableList => {
|
||||||
let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
|
let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
let mut attr_var_list = match attr_var {
|
let mut attr_var_list = match attr_var {
|
||||||
@@ -317,15 +372,43 @@ impl MachineState {
|
|||||||
match self.store(self.deref(addr)) {
|
match self.store(self.deref(addr)) {
|
||||||
Addr::Con(Constant::Usize(b)) => {
|
Addr::Con(Constant::Usize(b)) => {
|
||||||
let iter = self.gather_attr_vars_created_since(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();
|
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
|
_ => 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 => {
|
&SystemClauseType::GetDoubleQuotes => {
|
||||||
let a1 = self[temp_v!(1)].clone();
|
let a1 = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
@@ -574,7 +657,7 @@ impl MachineState {
|
|||||||
let h = self.heap.h;
|
let h = self.heap.h;
|
||||||
|
|
||||||
if self.ball.stub.len() > 0 {
|
if self.ball.stub.len() > 0 {
|
||||||
self.copy_and_align_ball_to_heap();
|
self.copy_and_align_ball_to_heap(0);
|
||||||
} else {
|
} else {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ extern crate ordered_float;
|
|||||||
extern crate prolog_parser;
|
extern crate prolog_parser;
|
||||||
|
|
||||||
#[macro_use] pub mod instructions;
|
#[macro_use] pub mod instructions;
|
||||||
|
pub mod heap;
|
||||||
mod and_stack;
|
mod and_stack;
|
||||||
#[macro_use] mod macros;
|
#[macro_use] mod macros;
|
||||||
#[macro_use] mod allocator;
|
#[macro_use] mod allocator;
|
||||||
|
|||||||
14
src/tests.rs
14
src/tests.rs
@@ -1711,6 +1711,20 @@ fn test_queries_on_builtins()
|
|||||||
[["X = f(((a,b),c))"]]);
|
[["X = f(((a,b),c))"]]);
|
||||||
assert_prolog_success!(&mut wam, "?- X = f(((a,b),(c, d))).",
|
assert_prolog_success!(&mut wam, "?- X = f(((a,b),(c, d))).",
|
||||||
[["X = f(((a,b),c,d))"]]);
|
[["X = f(((a,b),c,d))"]]);
|
||||||
|
|
||||||
|
assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), S).",
|
||||||
|
[["S = [1, 2]", "X = _0"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- findall(X+Y, (X = 1), S).",
|
||||||
|
[["S = [1+_18]", "X = _1", "Y = _2"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- findall(X, false, S).",
|
||||||
|
[["S = []", "X = _0"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 1), S).",
|
||||||
|
[["S = [1, 1]", "X = _0"]]);
|
||||||
|
assert_prolog_failure!(&mut wam, "?- findall(X, (X = 2 ; X = 1), [1, 2]).");
|
||||||
|
assert_prolog_success!(&mut wam, "?- findall(X, (X = 1 ; X = 2), [X, Y]).",
|
||||||
|
[["X = 1", "Y = 2"]]);
|
||||||
|
assert_prolog_success!(&mut wam, "?- catch(findall(X, 4, S), error(type_error(callable, 4), _), true).",
|
||||||
|
[["S = _3", "X = _1"]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user