]> Repositorios git - scryer-prolog.git/commitdiff
add queues, fix debray allocator bug.
authorMark Thom <[email protected]>
Thu, 8 Mar 2018 07:29:56 +0000 (00:29 -0700)
committerMark Thom <[email protected]>
Thu, 8 Mar 2018 07:29:56 +0000 (00:29 -0700)
src/main.rs
src/prolog/allocator.rs
src/prolog/codegen.rs
src/prolog/debray_allocator.rs
src/prolog/lib/queues.pl [new file with mode: 0644]

index ad9e8df70facb891ac4b8c9700fd8ca8911dfd2a..e08e5301ea350ddf5c23dae1bef0367d26b99b3c 100644 (file)
@@ -14,6 +14,7 @@ mod tests;
 
 pub static LISTS: &str   = include_str!("./prolog/lib/lists.pl");
 pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
+pub static QUEUES: &str = include_str!("./prolog/lib/queues.pl");
 
 fn parse_and_compile_line(wam: &mut Machine, buffer: &str)
 {
@@ -39,6 +40,7 @@ fn prolog_repl() {
 
     load_init_str(&mut wam, LISTS);
     load_init_str(&mut wam, CONTROL);
+    load_init_str(&mut wam, QUEUES);
 
     loop {
         print!("prolog> ");
@@ -49,7 +51,7 @@ fn prolog_repl() {
                 match compile_listing(&mut wam, batch.as_str()) {
                     EvalSession::Error(e) => println!("{}", e),
                     _ => {}
-                },                
+                },
             Input::Quit => break,
             Input::Clear => {
                 wam.clear();
index 36b9cceb75a722b1f4764cd7abb109c796b350cc..0a9595a957b89914dfaabad252eb6eb58a249dc6 100644 (file)
@@ -19,6 +19,7 @@ pub trait Allocator<'a>
     fn reset(&mut self);
     fn reset_contents(&mut self) {}
     fn reset_arg(&mut self, usize);
+    fn reset_at_head(&mut self, &Vec<Box<Term>>);
     
     fn advance_arg(&mut self);
 
index 72abc742a65a5815458e369fc602122afbeef473..6cae3266f937d1d1474640571e52cf1e4cbf4329 100644 (file)
@@ -543,6 +543,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
         let mut code = Vec::new();
 
         self.marker.reset_arg(args.len());
+        self.marker.reset_at_head(args);
         self.compile_seq_prelude(&conjunct_info, &mut code);
 
         let iter = FactIterator::from_rule_head_clause(args);
@@ -607,13 +608,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
         vs.mark_vars_in_chunk(term.post_order_iter(), term.arity(), GenContext::Head);
 
         vs.populate_restricting_sets();
-
         self.marker.drain_var_data(vs);
-        self.marker.reset_arg(term.arity());
-
+        
         let mut code = Vec::new();
 
-        if let &Term::Clause(..) = term {
+        if let &Term::Clause(_, _, ref args, _) = term {
+            self.marker.reset_arg(args.len());
+            self.marker.reset_at_head(args);
+            
             let iter = FactInstruction::iter(term);
             let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
 
index 1bdc5a9e5a9e6dc79f9ecc2b709755c9e40909c1..47c48d9c53bd2e7b043fde3a164b9e04c846591b 100644 (file)
@@ -123,15 +123,13 @@ impl DebrayAllocator {
                 if r != k {
                     let r = RegType::Temp(r);
 
-                    if r.reg_num() != k {
-                        target.push(Target::move_to_register(r, k));
-
-                        self.contents.remove(&k);
-                        self.contents.insert(r.reg_num(), var.clone());
-
-                        self.record_register(var, r);
-                        self.in_use.insert(r.reg_num());
-                    }
+                    target.push(Target::move_to_register(r, k));
+                    
+                    self.contents.remove(&k);
+                    self.contents.insert(r.reg_num(), var.clone());
+                    
+                    self.record_register(var, r);
+                    self.in_use.insert(r.reg_num());
                 }
             },
             _ => {}
@@ -218,7 +216,7 @@ impl<'a> Allocator<'a> for DebrayAllocator
             }
         };
     }
-    
+
     fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
                             cell: &Cell<RegType>, target: &mut Vec<Target>)
         where Target: CompilationTarget<'a>
@@ -336,8 +334,17 @@ impl<'a> Allocator<'a> for DebrayAllocator
         self.bindings
     }
 
+    fn reset_at_head(&mut self, args: &Vec<Box<Term>>) {
+        for (idx, arg) in args.iter().enumerate() {
+            if let &Term::Var(_, ref var) = arg.as_ref() {
+                self.contents.insert(idx + 1, var.clone());
+                self.in_use.insert(idx + 1);
+            }
+        }
+    }
+    
     fn reset_arg(&mut self, arity: usize) {
         self.arg_c   = 1;
-        self.temp_lb = arity + 1;
+        self.temp_lb = arity + 1;        
     }
 }
diff --git a/src/prolog/lib/queues.pl b/src/prolog/lib/queues.pl
new file mode 100644 (file)
index 0000000..1cc1e6c
--- /dev/null
@@ -0,0 +1,58 @@
+:- module(queues, [queue/1, queue/2, queue_head/3, queue_head_list/3,
+                  queue_last/3, queue_last_list/3, list_queue/2,
+                  queue_length/2]).
+
+/* true when Queue is a queue with no elements. */
+queue(q(0,B,B)).
+
+/* true when Queue is a queue with one element. */
+queue(X, q(s(0), [X|B], B)).
+
+/* true when Queue0 and Queue1 have the same elements except that
+ * Queue0 has in addition X at the front.  Use it for enqueuing and
+ * dequeuing both.
+*/
+queue_head(X, q(N, F, B), q(s(N), [X|F], B)).
+
+/* true when append(List, Queue1, Queue0) would be true if only Queue1
+ * and Queue0 were lists instead of queues.
+*/
+queue_head_list([], Queue, Queue).
+queue_head_list([X|Xs], Queue, Queue0) :-
+    queue_head(X, Queue1, Queue0),
+    queue_head_list(Xs, Queue, Queue1).
+
+/* true when Queue0 and Queue1 have the same elements except that
+ * Queue0 has in addition to X at the end.
+*/
+queue_last(X, q(N, F, [X|B]), q(s(N), F, B)).
+
+/* true when append(Queue1, List, Queue0) would be true if only Queue1
+ * and Queue0 were lists instead of queues.
+*/
+queue_last_list([], Queue, Queue).
+queue_last_list([X|Xs], Queue1, Queue) :-
+    queue_last(X, Queue1, Queue2),
+    queue_last_list(Xs, Queue2, Queue).
+
+/* true when List is a list and Queue is a queue and they represent
+ * the same sequence.
+*/
+list_queue(List, q(Count, Front, Back)) :-
+    list_queue(List, Count, Front, Back).
+
+list_queue([], 0, B, B).
+list_queue([X|Xs], s(N), [X|F], B) :-
+    list_queue(Xs, N, F, B).
+
+/* is true when Length is (a binary length representing) the number of
+ * elements in (the queue represented by) Queue. This version cannot
+ * be used to generate a Queue, only to determine the Length.
+*/
+queue_length(q(Count, F, B), Length) :-
+    queue_length(Count, F, B, 0, Length).
+
+queue_length(0, B, B, Length, Length).
+queue_length(s(N), [_|Front], Back, L0, Length) :-
+    L1 is L0 + 1,
+    queue_length(N, Front, Back, L1, Length).