* `(=..)/2`
* `(->)/2`
* `(;)/2`
+* `acyclic_term/2`
* `append/3`
* `arg/3`
* `atom/1`
#[derive(Clone)]
pub enum ClauseType {
+ AcyclicTerm,
Arg,
CallN,
CallWithInferenceLimit,
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"),
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,
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
- }
+ })
}
}
}
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))
}
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::*;
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;
-> 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;