]> Repositorios git - scryer-prolog.git/commitdiff
add term variables
authorMark Thom <[email protected]>
Tue, 25 Sep 2018 05:33:47 +0000 (23:33 -0600)
committerMark Thom <[email protected]>
Tue, 25 Sep 2018 05:33:47 +0000 (23:33 -0600)
README.md
src/prolog/instructions.rs
src/prolog/lib/numbervars.pl [deleted file]
src/prolog/lib/terms.pl [new file with mode: 0644]
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs

index fa953ddc6f5692dda100ecf5030bfc1de4340c7c..e182968912fc7980133a3b6a60617380aa2855e0 100644 (file)
--- 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`
index b8267a5ca29a5c0239ff3251a6def3f4703896f4..eff385ab0043cb2605132fb04be1f8de46c5b83b 100644 (file)
@@ -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 (file)
index 9c6fbd9..0000000
+++ /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 (file)
index 0000000..7c16f02
--- /dev/null
@@ -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).
index af3f0aec06ec437e9b30ac394836ffbeda2a008a..8b71383d3e945ffb5f459ff0164e6cfe786f7f26 100644 (file)
@@ -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
     }
index f94800e2f63ad17ced9018d7923c4d5872155efe..639f078d21586f6374aa3f13e35af5859cc8fe91 100644 (file)
@@ -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()
         };