add acyclic term
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user