add queues, fix debray allocator bug.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
58
src/prolog/lib/queues.pl
Normal 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).
|
||||
Reference in New Issue
Block a user