add acyclic term

This commit is contained in:
Mark Thom
2018-03-28 21:17:46 -06:00
parent eb694cbba7
commit 80b59bae83
4 changed files with 46 additions and 12 deletions

View File

@@ -673,6 +673,7 @@ pub struct Rule {
#[derive(Clone)]
pub enum ClauseType {
AcyclicTerm,
Arg,
CallN,
CallWithInferenceLimit,
@@ -773,7 +774,8 @@ impl ClauseType {
pub fn name(&self) -> ClauseName {
match self {
&ClauseType::Arg => clause_name!("arg"),
&ClauseType::AcyclicTerm => clause_name!("acyclic_term"),
&ClauseType::Arg => clause_name!("arg"),
&ClauseType::CallN => clause_name!("call"),
&ClauseType::CallWithInferenceLimit => clause_name!("call_with_inference_limit"),
&ClauseType::Catch => clause_name!("catch"),
@@ -798,6 +800,7 @@ impl ClauseType {
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
match (name.as_str(), arity) {
("acyclic_term", 1) => ClauseType::AcyclicTerm,
("arg", 3) => ClauseType::Arg,
("call", _) => ClauseType::CallN,
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,

View File

@@ -59,18 +59,16 @@ impl<'a> Iterator for HeapCellPreOrderIterator<'a> {
type Item = HeapCellValue;
fn next(&mut self) -> Option<Self::Item> {
if let Some(a) = self.state_stack.pop() {
self.state_stack.pop().map(|a| {
match self.follow(a) {
Addr::HeapCell(h) => Some(self.machine_st.heap[h].clone()),
Addr::StackCell(fr, sc) => {
let heap_val = HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone());
Some(heap_val)
},
da => Some(HeapCellValue::Addr(da))
Addr::HeapCell(h) =>
self.machine_st.heap[h].clone(),
Addr::StackCell(fr, sc) =>
HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone()),
da =>
HeapCellValue::Addr(da)
}
} else {
None
}
})
}
}
@@ -119,6 +117,10 @@ impl<'a> Iterator for HeapCellPostOrderIterator<'a> {
}
impl MachineState {
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HeapCellPreOrderIterator<'a> {
HeapCellPreOrderIterator::new(self, a)
}
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HeapCellPostOrderIterator<'a> {
HeapCellPostOrderIterator::new(HeapCellPreOrderIterator::new(self, a))
}

View File

@@ -1,6 +1,7 @@
use prolog::and_stack::*;
use prolog::ast::*;
use prolog::copier::*;
use prolog::heap_iter::*;
use prolog::num::{BigInt, BigUint, Zero, One};
use prolog::or_stack::*;
use prolog::heap_print::*;
@@ -9,7 +10,7 @@ use prolog::tabled_rc::*;
use downcast::Any;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::mem::swap;
use std::ops::{Index, IndexMut};
use std::rc::Rc;
@@ -395,6 +396,33 @@ pub(crate) trait CallPolicy: Any {
-> CallResult
{
match ct {
&ClauseType::AcyclicTerm => {
let addr = machine_st[temp_v!(1)].clone();
let mut seen = HashSet::new();
let mut fail = false;
{
let mut iter = machine_st.pre_order_iter(addr);
loop {
if let Some(addr) = iter.stack().last() {
if !seen.contains(addr) {
seen.insert(addr.clone());
} else {
fail = true;
break;
}
}
if iter.next().is_none() {
break;
}
}
}
machine_st.fail = fail;
return_from_clause!(lco, machine_st)
},
&ClauseType::Arg => {
if !lco {
machine_st.cp = machine_st.p.clone() + 1;