add acyclic term
This commit is contained in:
@@ -122,6 +122,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `(=..)/2`
|
* `(=..)/2`
|
||||||
* `(->)/2`
|
* `(->)/2`
|
||||||
* `(;)/2`
|
* `(;)/2`
|
||||||
|
* `acyclic_term/2`
|
||||||
* `append/3`
|
* `append/3`
|
||||||
* `arg/3`
|
* `arg/3`
|
||||||
* `atom/1`
|
* `atom/1`
|
||||||
|
|||||||
@@ -673,6 +673,7 @@ pub struct Rule {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ClauseType {
|
pub enum ClauseType {
|
||||||
|
AcyclicTerm,
|
||||||
Arg,
|
Arg,
|
||||||
CallN,
|
CallN,
|
||||||
CallWithInferenceLimit,
|
CallWithInferenceLimit,
|
||||||
@@ -773,6 +774,7 @@ impl ClauseType {
|
|||||||
|
|
||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
|
&ClauseType::AcyclicTerm => clause_name!("acyclic_term"),
|
||||||
&ClauseType::Arg => clause_name!("arg"),
|
&ClauseType::Arg => clause_name!("arg"),
|
||||||
&ClauseType::CallN => clause_name!("call"),
|
&ClauseType::CallN => clause_name!("call"),
|
||||||
&ClauseType::CallWithInferenceLimit => clause_name!("call_with_inference_limit"),
|
&ClauseType::CallWithInferenceLimit => clause_name!("call_with_inference_limit"),
|
||||||
@@ -798,6 +800,7 @@ impl ClauseType {
|
|||||||
|
|
||||||
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
|
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
|
||||||
match (name.as_str(), arity) {
|
match (name.as_str(), arity) {
|
||||||
|
("acyclic_term", 1) => ClauseType::AcyclicTerm,
|
||||||
("arg", 3) => ClauseType::Arg,
|
("arg", 3) => ClauseType::Arg,
|
||||||
("call", _) => ClauseType::CallN,
|
("call", _) => ClauseType::CallN,
|
||||||
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
|
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
|
||||||
|
|||||||
@@ -59,18 +59,16 @@ impl<'a> Iterator for HeapCellPreOrderIterator<'a> {
|
|||||||
type Item = HeapCellValue;
|
type Item = HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
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) {
|
match self.follow(a) {
|
||||||
Addr::HeapCell(h) => Some(self.machine_st.heap[h].clone()),
|
Addr::HeapCell(h) =>
|
||||||
Addr::StackCell(fr, sc) => {
|
self.machine_st.heap[h].clone(),
|
||||||
let heap_val = HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone());
|
Addr::StackCell(fr, sc) =>
|
||||||
Some(heap_val)
|
HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone()),
|
||||||
},
|
da =>
|
||||||
da => Some(HeapCellValue::Addr(da))
|
HeapCellValue::Addr(da)
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +117,10 @@ impl<'a> Iterator for HeapCellPostOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
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> {
|
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HeapCellPostOrderIterator<'a> {
|
||||||
HeapCellPostOrderIterator::new(HeapCellPreOrderIterator::new(self, a))
|
HeapCellPostOrderIterator::new(HeapCellPreOrderIterator::new(self, a))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use prolog::and_stack::*;
|
use prolog::and_stack::*;
|
||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
use prolog::copier::*;
|
use prolog::copier::*;
|
||||||
|
use prolog::heap_iter::*;
|
||||||
use prolog::num::{BigInt, BigUint, Zero, One};
|
use prolog::num::{BigInt, BigUint, Zero, One};
|
||||||
use prolog::or_stack::*;
|
use prolog::or_stack::*;
|
||||||
use prolog::heap_print::*;
|
use prolog::heap_print::*;
|
||||||
@@ -9,7 +10,7 @@ use prolog::tabled_rc::*;
|
|||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -395,6 +396,33 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
-> CallResult
|
-> CallResult
|
||||||
{
|
{
|
||||||
match ct {
|
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 => {
|
&ClauseType::Arg => {
|
||||||
if !lco {
|
if !lco {
|
||||||
machine_st.cp = machine_st.p.clone() + 1;
|
machine_st.cp = machine_st.p.clone() + 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user