From: Mark Thom Date: Thu, 8 Mar 2018 07:29:56 +0000 (-0700) Subject: add queues, fix debray allocator bug. X-Git-Tag: v0.8.110~534 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=179e425fb6409c57a81b87e1debfaaeb52d22765;p=scryer-prolog.git add queues, fix debray allocator bug. --- diff --git a/src/main.rs b/src/main.rs index ad9e8df7..e08e5301 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(); diff --git a/src/prolog/allocator.rs b/src/prolog/allocator.rs index 36b9cceb..0a9595a9 100644 --- a/src/prolog/allocator.rs +++ b/src/prolog/allocator.rs @@ -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>); fn advance_arg(&mut self); diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 72abc742..6cae3266 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -543,6 +543,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator 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 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); diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 1bdc5a9e..47c48d9c 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -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(&mut self, lvl: Level, term_loc: GenContext, cell: &Cell, target: &mut Vec) where Target: CompilationTarget<'a> @@ -336,8 +334,17 @@ impl<'a> Allocator<'a> for DebrayAllocator self.bindings } + fn reset_at_head(&mut self, args: &Vec>) { + 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 index 00000000..1cc1e6c8 --- /dev/null +++ b/src/prolog/lib/queues.pl @@ -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).