add queues, fix debray allocator bug.

This commit is contained in:
Mark Thom
2018-03-08 00:29:56 -07:00
parent 10db0f58dd
commit 179e425fb6
5 changed files with 86 additions and 16 deletions

View 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();

View 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);

View 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);

View 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;
}
}

58
src/prolog/lib/queues.pl Normal file
View File

@@ -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).