add cyclic_term
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
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::*;
|
||||
@@ -10,7 +9,7 @@ use prolog::tabled_rc::*;
|
||||
use downcast::Any;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::mem::swap;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::rc::Rc;
|
||||
@@ -397,30 +396,8 @@ pub(crate) trait CallPolicy: Any {
|
||||
{
|
||||
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;
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Arg => {
|
||||
@@ -476,6 +453,11 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::CyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Display => {
|
||||
let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
|
||||
DisplayFormatter {},
|
||||
|
||||
@@ -11,7 +11,7 @@ use prolog::or_stack::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::cmp::{max, Ordering};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::rc::Rc;
|
||||
|
||||
macro_rules! try_or_fail {
|
||||
@@ -1001,6 +1001,30 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_cyclic_term(&self, addr: Addr) -> bool {
|
||||
let mut seen = HashSet::new();
|
||||
let mut fail = false;
|
||||
|
||||
let mut iter = self.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;
|
||||
}
|
||||
}
|
||||
|
||||
fail
|
||||
}
|
||||
|
||||
fn try_get_arg(&mut self) -> Result<(), Vec<HeapCellValue>>
|
||||
{
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
@@ -25,8 +25,9 @@ pub struct Machine {
|
||||
call_policy: Box<CallPolicy>,
|
||||
cut_policy: Box<CutPolicy>,
|
||||
code: Code,
|
||||
code_dir: CodeDir,
|
||||
code_dir: CodeDir,
|
||||
pub op_dir: OpDir,
|
||||
term_dir: TermDir,
|
||||
modules: HashMap<ClauseName, Module>,
|
||||
cached_query: Option<Code>
|
||||
}
|
||||
@@ -68,6 +69,7 @@ impl Machine {
|
||||
cut_policy: Box::new(DefaultCutPolicy {}),
|
||||
code,
|
||||
code_dir,
|
||||
term_dir: TermDir::new(),
|
||||
op_dir,
|
||||
modules: HashMap::new(),
|
||||
cached_query: None
|
||||
@@ -173,7 +175,8 @@ impl Machine {
|
||||
self.code.extend(code.into_iter());
|
||||
}
|
||||
|
||||
pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession
|
||||
pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code, pred: Predicate)
|
||||
-> EvalSession
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
Some(&(_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
@@ -184,8 +187,9 @@ impl Machine {
|
||||
let offset = self.code.len();
|
||||
|
||||
self.code.extend(code.into_iter());
|
||||
self.term_dir.insert((name.clone(), arity), pred);
|
||||
self.code_dir.insert((name, arity), (offset, clause_name!("user")));
|
||||
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user