From b642bd2cfd0922d45a42cdf9808ea06498d3ba62 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 2 May 2020 18:46:29 -0600 Subject: [PATCH] add term_attributed_variables/2 (#422) --- src/prolog/clause_types.rs | 3 +++ src/prolog/heap_iter.rs | 8 ++++++ src/prolog/lib/atts.pl | 14 +++++++---- src/prolog/machine/attributed_variables.rs | 29 ++++++++++++++++++++++ src/prolog/machine/system_calls.rs | 8 +++++- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 83e144eb..d05c8559 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -255,6 +255,7 @@ pub enum SystemClauseType { SkipMaxList, Sleep, Succeed, + TermAttributedVariables, TermVariables, TruncateLiftedHeapTo, UnifyWithOccursCheck, @@ -410,6 +411,7 @@ impl SystemClauseType { &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), &SystemClauseType::Sleep => clause_name!("$sleep"), &SystemClauseType::Succeed => clause_name!("$succeed"), + &SystemClauseType::TermAttributedVariables => clause_name!("$term_attributed_variables"), &SystemClauseType::TermVariables => clause_name!("$term_variables"), &SystemClauseType::TruncateLiftedHeapTo => clause_name!("$truncate_lh_to"), &SystemClauseType::UnifyWithOccursCheck => clause_name!("$unify_with_occurs_check"), @@ -538,6 +540,7 @@ impl SystemClauseType { ("$sleep", 1) => Some(SystemClauseType::Sleep), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset), + ("$term_attributed_variables", 2) => Some(SystemClauseType::TermAttributedVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), ("$unwind_environments", 0) => Some(SystemClauseType::UnwindEnvironments), diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index c30918fb..de398ccb 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -254,6 +254,14 @@ impl<'a> Deref for HCAcyclicIterator<'a> { } } +impl<'b, 'a: 'b> MutStackHCIterator<'b> for HCAcyclicIterator<'a> { + type MutStack = &'b mut Vec; + + fn stack(&'b mut self) -> Self::MutStack { + self.iter.stack() + } +} + impl<'a> Iterator for HCAcyclicIterator<'a> { type Item = Addr; diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index 7160ab24..fbf440d0 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -1,9 +1,10 @@ :- module(atts, [op(1199, fx, attribute), call_residue_vars/2, - '$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2, - '$put_attr'/2, '$absent_from_list'/2, - '$get_from_list'/3, '$add_to_list'/3, '$del_attr'/3, - '$del_attr_step'/3, '$del_attr_buried'/4, - '$default_attr_list'/4]). + term_attributed_variables/2, + '$absent_attr'/2, '$copy_attr_list'/2, '$get_attr'/2, + '$put_attr'/2, '$absent_from_list'/2, + '$get_from_list'/3, '$add_to_list'/3, '$del_attr'/3, + '$del_attr_step'/3, '$del_attr_buried'/4, + '$default_attr_list'/4]). :- use_module(library(dcgs)). :- use_module(library(terms)). @@ -159,3 +160,6 @@ call_residue_vars(Goal, Vars) :- '$get_attr_var_queue_delim'(B), call(Goal), '$get_attr_var_queue_beyond'(B, Vars). + +term_attributed_variables(Term, Vars) :- + '$term_attributed_variables'(Term, Vars). diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index d853a5f8..6595ba53 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -1,5 +1,8 @@ +use crate::prolog::heap_iter::*; use crate::prolog::machine::*; +use indexmap::IndexSet; + use std::cmp::Ordering; use std::vec::IntoIter; @@ -137,4 +140,30 @@ impl MachineState { self.b0 = self.b; self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); } + + pub(super) + fn attr_vars_of_term(&self, addr: Addr) -> IndexSet { + let mut seen_vars = IndexSet::new(); + let mut iter = self.acyclic_pre_order_iter(addr); + + while let Some(addr) = iter.next() { + if let HeapCellValue::Addr(Addr::AttrVar(h)) = self.heap.index_addr(&addr).as_ref() { + seen_vars.insert(addr); + + let mut l = h + 1; + let mut list_elements = vec![]; + + while let Addr::Lis(elem) = self.store(self.deref(Addr::HeapCell(l))) { + list_elements.push(self.heap[elem].as_addr(elem)); + l = elem + 1; + } + + for element in list_elements.into_iter().rev() { + iter.stack().push(element); + } + } + } + + seen_vars + } } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index a976423f..549ee50d 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -4,11 +4,11 @@ use prolog_parser::tabled_rc::*; use crate::prolog::clause_types::*; use crate::prolog::forms::*; +use crate::prolog::heap_print::*; use crate::prolog::instructions::*; use crate::prolog::machine::code_repo::CodeRepo; use crate::prolog::machine::copier::*; use crate::prolog::machine::code_walker::*; -use crate::prolog::heap_print::*; use crate::prolog::machine::machine_errors::*; use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_state::*; @@ -3368,6 +3368,12 @@ impl MachineState { } &SystemClauseType::Succeed => { } + &SystemClauseType::TermAttributedVariables => { + let seen_vars = self.attr_vars_of_term(self[temp_v!(1)]); + let outcome = Addr::HeapCell(self.heap.to_list(seen_vars.into_iter())); + + self.unify(self[temp_v!(2)], outcome); + } &SystemClauseType::TermVariables => { let a1 = self[temp_v!(1)]; let mut seen_vars = IndexSet::new(); -- 2.54.0