From: Mark Thom Date: Tue, 25 Sep 2018 05:33:47 +0000 (-0600) Subject: add term variables X-Git-Tag: v0.8.110~362 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=4cf1aa0d8f2b1efe5d64bdc016dcac785d57b46e;p=scryer-prolog.git add term variables --- diff --git a/README.md b/README.md index fa953ddc..e1829689 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Extend rusty-wam to include the following, among other features: * Default representation of strings as list of chars, using a packed internal representation (_done_). - A representation of 'partial strings' as difference lists - of characters (_in progress_). + of characters (_done_). * `term_expansion/2` and `goal_expansion/2` (_in progress_). * Definite Clause Grammars. * Attributed variables using the SICStus Prolog interface and @@ -153,6 +153,7 @@ The following predicates are built-in to rusty-wam. * `member/2` * `memberchk/2` * `nonvar/1` +* `numbervars/{2,3}` * `once/1` * `partial_string/2` * `rational/1` @@ -163,6 +164,7 @@ The following predicates are built-in to rusty-wam. * `setup_call_cleanup/3` * `sort/2` * `string/1` +* `term_variables/2` * `throw/1` * `true/0` * `var/1` diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index b8267a5c..eff385ab 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -238,6 +238,7 @@ pub enum SystemClauseType { SetDoubleQuotes, SkipMaxList, Succeed, + TermVariables, UnwindStack } @@ -275,6 +276,7 @@ impl SystemClauseType { &SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"), &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), &SystemClauseType::Succeed => clause_name!("$succeed"), + &SystemClauseType::TermVariables => clause_name!("$term_variables"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), } } @@ -308,6 +310,7 @@ impl SystemClauseType { ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), + ("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), _ => None } diff --git a/src/prolog/lib/numbervars.pl b/src/prolog/lib/numbervars.pl deleted file mode 100644 index 9c6fbd95..00000000 --- a/src/prolog/lib/numbervars.pl +++ /dev/null @@ -1,29 +0,0 @@ -:- module(numbervars, [numbervars/2, numbervars/3]). - -numbervars(Term, NewTerm) :- duplicate_term(Term, NewTerm), numbervars(Term, NewTerm, 0, _). - -numbervars(Term, NewTerm, N) :- - ( integer(N), N >= 0 -> duplicate_term(Term, NewTerm), numbervars(Term, NewTerm, N, _) - ; integer(N) -> throw(error(domain_error(not_less_than_zero, N), numbervars/3)) - ; throw(error(type_error(integer, N), numbervars/3)) - ). - -numbervars(Term, NewTerm, N1, N2) :- - var(Term), !, NewTerm = '$VAR'(N1), N2 is N1 + 1. -numbervars(Term, NewTerm, N1, N2) :- compound(Term), !, - Term =.. [Name | Args], - NewTerm =.. [Name | NewArgs], - fold_numbervars(Args, NewArgs, N1, N2). -numbervars(_, _, N, N). - -marked_already(Term, NewTerm) :- - var(Term), nonvar(NewTerm), NewTerm = '$VAR'(_). -marked_already(Term, NewTerm) :- - atomic(Term). - -fold_numbervars([HeadTerm | Terms], [NewHeadTerm | NewTerms], N1, Nn) :- - ( marked_already(HeadTerm, NewHeadTerm) -> N1 = N2 - ; numbervars(HeadTerm, NewHeadTerm, N1, N2) - ), - fold_numbervars(Terms, NewTerms, N2, Nn). -fold_numbervars([], [], N, N). diff --git a/src/prolog/lib/terms.pl b/src/prolog/lib/terms.pl new file mode 100644 index 00000000..7c16f021 --- /dev/null +++ b/src/prolog/lib/terms.pl @@ -0,0 +1,19 @@ +:- module(terms, [term_variables/2, numbervars/2, numbervars/3]). + +term_variables(Term, Vars) :- '$term_variables'(Term, Vars). + +numbervars(Term, N) :- + integer(N), + term_variables(Term, Vars), + numberlist(Vars, N, N1). + +numbervars(Term, N0, N) :- + integer(N0), + integer(N), + term_variables(Term, Vars), + numberlist(Vars, N0, N). + +numberlist([], N,N). +numberlist(['$VAR'(N0)|Vars], N0,N) :- + N1 is N0+1, + numberlist(Vars, N1,N). diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index af3f0aec..8b71383d 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -120,7 +120,7 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> { static LISTS: &str = include_str!("../lib/lists.pl"); static CONTROL: &str = include_str!("../lib/control.pl"); static QUEUES: &str = include_str!("../lib/queues.pl"); -static NUMVARS: &str = include_str!("../lib/numbervars.pl"); +static TERMS: &str = include_str!("../lib/terms.pl"); impl Machine { pub fn new() -> Self { @@ -144,7 +144,7 @@ impl Machine { compile_user_module(&mut wam, LISTS.as_bytes()); compile_user_module(&mut wam, CONTROL.as_bytes()); compile_user_module(&mut wam, QUEUES.as_bytes()); - compile_user_module(&mut wam, NUMVARS.as_bytes()); + compile_user_module(&mut wam, TERMS.as_bytes()); wam } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index f94800e2..639f078d 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1,13 +1,14 @@ use prolog_parser::ast::*; +use prolog::heap_iter::*; use prolog::instructions::*; use prolog::machine::MachineCodeIndices; use prolog::machine::machine_errors::*; use prolog::machine::machine_state::*; use prolog::num::{ToPrimitive, Zero}; use prolog::num::bigint::{BigInt}; -//use prolog::term_writer::*; +use std::collections::HashSet; use std::rc::Rc; struct BrentAlgState { @@ -435,6 +436,47 @@ impl MachineState { return Err(err); }, &SystemClauseType::Succeed => {}, + &SystemClauseType::TermVariables => { + let a1 = self[temp_v!(1)].clone(); + let mut vars = Vec::new(); + + { + let iter = HCPreOrderIterator::new(self, a1); + + for item in iter { + match item { + HeapCellValue::Addr(Addr::HeapCell(h)) => + vars.push(Ref::HeapCell(h)), + HeapCellValue::Addr(Addr::StackCell(fr, sc)) => + vars.push(Ref::StackCell(fr, sc)), + _ => {} + } + } + } + + let mut h = self.heap.h; + let outcome = Addr::HeapCell(h); + + let mut seen_vars = HashSet::new(); + + for r in vars { + if seen_vars.contains(&r) { + continue; + } + + self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1))); + self.heap.push(HeapCellValue::Addr(r.as_addr())); + + h += 2; + + seen_vars.insert(r); + } + + self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList))); + + let a2 = self[temp_v!(2)].clone(); + self.unify(a2, outcome); + }, &SystemClauseType::UnwindStack => self.unwind_stack() };