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 LISTS: &str = include_str!("./prolog/lib/lists.pl");
|
||||||
pub static CONTROL: &str = include_str!("./prolog/lib/control.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)
|
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, LISTS);
|
||||||
load_init_str(&mut wam, CONTROL);
|
load_init_str(&mut wam, CONTROL);
|
||||||
|
load_init_str(&mut wam, QUEUES);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
print!("prolog> ");
|
print!("prolog> ");
|
||||||
@@ -49,7 +51,7 @@ fn prolog_repl() {
|
|||||||
match compile_listing(&mut wam, batch.as_str()) {
|
match compile_listing(&mut wam, batch.as_str()) {
|
||||||
EvalSession::Error(e) => println!("{}", e),
|
EvalSession::Error(e) => println!("{}", e),
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Input::Quit => break,
|
Input::Quit => break,
|
||||||
Input::Clear => {
|
Input::Clear => {
|
||||||
wam.clear();
|
wam.clear();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub trait Allocator<'a>
|
|||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
fn reset_contents(&mut self) {}
|
fn reset_contents(&mut self) {}
|
||||||
fn reset_arg(&mut self, usize);
|
fn reset_arg(&mut self, usize);
|
||||||
|
fn reset_at_head(&mut self, &Vec<Box<Term>>);
|
||||||
|
|
||||||
fn advance_arg(&mut self);
|
fn advance_arg(&mut self);
|
||||||
|
|
||||||
|
|||||||
@@ -543,6 +543,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
self.marker.reset_arg(args.len());
|
self.marker.reset_arg(args.len());
|
||||||
|
self.marker.reset_at_head(args);
|
||||||
self.compile_seq_prelude(&conjunct_info, &mut code);
|
self.compile_seq_prelude(&conjunct_info, &mut code);
|
||||||
|
|
||||||
let iter = FactIterator::from_rule_head_clause(args);
|
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.mark_vars_in_chunk(term.post_order_iter(), term.arity(), GenContext::Head);
|
||||||
|
|
||||||
vs.populate_restricting_sets();
|
vs.populate_restricting_sets();
|
||||||
|
|
||||||
self.marker.drain_var_data(vs);
|
self.marker.drain_var_data(vs);
|
||||||
self.marker.reset_arg(term.arity());
|
|
||||||
|
|
||||||
let mut code = Vec::new();
|
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 iter = FactInstruction::iter(term);
|
||||||
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
|
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
|
||||||
|
|
||||||
|
|||||||
@@ -123,15 +123,13 @@ impl DebrayAllocator {
|
|||||||
if r != k {
|
if r != k {
|
||||||
let r = RegType::Temp(r);
|
let r = RegType::Temp(r);
|
||||||
|
|
||||||
if r.reg_num() != k {
|
target.push(Target::move_to_register(r, k));
|
||||||
target.push(Target::move_to_register(r, k));
|
|
||||||
|
self.contents.remove(&k);
|
||||||
self.contents.remove(&k);
|
self.contents.insert(r.reg_num(), var.clone());
|
||||||
self.contents.insert(r.reg_num(), var.clone());
|
|
||||||
|
self.record_register(var, r);
|
||||||
self.record_register(var, r);
|
self.in_use.insert(r.reg_num());
|
||||||
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,
|
fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
|
||||||
cell: &Cell<RegType>, target: &mut Vec<Target>)
|
cell: &Cell<RegType>, target: &mut Vec<Target>)
|
||||||
where Target: CompilationTarget<'a>
|
where Target: CompilationTarget<'a>
|
||||||
@@ -336,8 +334,17 @@ impl<'a> Allocator<'a> for DebrayAllocator
|
|||||||
self.bindings
|
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) {
|
fn reset_arg(&mut self, arity: usize) {
|
||||||
self.arg_c = 1;
|
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