transition to debray allocation

This commit is contained in:
Mark Thom
2017-04-30 13:53:15 -06:00
parent 1bdc539c25
commit 316e5c5c1a
11 changed files with 440 additions and 100 deletions

2
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
[root] [root]
name = "rusty-wam" name = "rusty-wam"
version = "0.5.7" version = "0.6.0"
dependencies = [ dependencies = [
"lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rusty-wam" name = "rusty-wam"
version = "0.5.7" version = "0.6.0"
authors = ["Mark Thom"] authors = ["Mark Thom"]
build = "build.rs" build = "build.rs"

View File

@@ -10,14 +10,9 @@ pure Prolog.
Prolog is implemented as a simple REPL. It is without without meta- or Prolog is implemented as a simple REPL. It is without without meta- or
extra-logical operators, or side effects of any kind, with the lone extra-logical operators, or side effects of any kind, with the lone
exception of cut. In terms of the tutorial pacing, the work has exception of cut. In terms of the tutorial pacing, the work covers in
progressed to the end of section 5.11, skipping past 5.4. Atoms and some form all of the WAM book, including lists, cuts, Debray
lists are the only two data types currently supported. allocation, and indexing.
While proper environment trimming code is emitted by the code
generator, it has no effect on the bytecode WAM, which lacks
fine-grained control over the alignment and allocation of stack
frames.
## Tutorial ## Tutorial
To enter a multi-clause predicate, the brackets ":{" and "}:" are used To enter a multi-clause predicate, the brackets ":{" and "}:" are used

View File

@@ -9,7 +9,7 @@ pub type Atom = String;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum GenContext { pub enum GenContext {
Head, Mid(usize), Last(usize) // Mid/Last: chunk_num Head, Mid(usize), Last(usize) // Mid & Last: chunk_num
} }
pub enum PredicateClause { pub enum PredicateClause {
@@ -70,7 +70,7 @@ impl RegType {
RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num
} }
} }
pub fn is_perm(self) -> bool { pub fn is_perm(self) -> bool {
match self { match self {
RegType::Perm(_) => true, RegType::Perm(_) => true,
@@ -91,7 +91,7 @@ impl VarReg {
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
} }
} }
pub fn is_temp(self) -> bool { pub fn is_temp(self) -> bool {
!self.norm().is_perm() !self.norm().is_perm()
} }
@@ -242,6 +242,7 @@ pub enum FactInstruction {
} }
pub enum QueryInstruction { pub enum QueryInstruction {
GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType), PutConstant(Level, Constant, RegType),
PutList(Level, RegType), PutList(Level, RegType),
PutStructure(Level, Atom, usize, RegType), PutStructure(Level, Atom, usize, RegType),
@@ -433,13 +434,6 @@ impl Term {
} }
} }
pub fn subterms(&self) -> usize {
match self {
&Term::Clause(_, _, ref terms) => terms.len(),
_ => 1
}
}
pub fn name(&self) -> Option<&Atom> { pub fn name(&self) -> Option<&Atom> {
match self { match self {
&Term::Constant(_, Constant::Atom(ref atom)) &Term::Constant(_, Constant::Atom(ref atom))

View File

@@ -1,8 +1,8 @@
use prolog::ast::*; use prolog::ast::*;
use prolog::debray_allocator::*;
use prolog::fixtures::*; use prolog::fixtures::*;
use prolog::indexing::*; use prolog::indexing::*;
use prolog::iterators::*; use prolog::iterators::*;
use prolog::naive_allocator::*;
use prolog::targets::*; use prolog::targets::*;
use std::cell::Cell; use std::cell::Cell;
@@ -69,30 +69,39 @@ impl<'a> CodeGenerator<'a> {
fn to_structure<Target>(&mut self, fn to_structure<Target>(&mut self,
lvl: Level, lvl: Level,
cell: &'a Cell<RegType>, cell: &'a Cell<RegType>,
term_loc: GenContext,
name: &'a Atom, name: &'a Atom,
arity: usize) arity: usize,
target: &mut Vec<Target>)
-> Target -> Target
where Target: CompilationTarget<'a> where Target: CompilationTarget<'a>
{ {
self.marker.mark_non_var(lvl, cell); self.marker.mark_non_var(lvl, term_loc, cell, target);
Target::to_structure(lvl, name.clone(), arity, cell.get()) Target::to_structure(lvl, name.clone(), arity, cell.get())
} }
fn to_constant<Target>(&mut self, fn to_constant<Target>(&mut self,
lvl: Level, lvl: Level,
cell: &'a Cell<RegType>, cell: &'a Cell<RegType>,
constant: &'a Constant) term_loc: GenContext,
constant: &'a Constant,
target: &mut Vec<Target>)
-> Target -> Target
where Target: CompilationTarget<'a> where Target: CompilationTarget<'a>
{ {
self.marker.mark_non_var(lvl, cell); self.marker.mark_non_var(lvl, term_loc, cell, target);
Target::to_constant(lvl, constant.clone(), cell.get()) Target::to_constant(lvl, constant.clone(), cell.get())
} }
fn to_list<Target>(&mut self, lvl: Level, cell: &'a Cell<RegType>) -> Target fn to_list<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &'a Cell<RegType>,
target: &mut Vec<Target>)
-> Target
where Target: CompilationTarget<'a> where Target: CompilationTarget<'a>
{ {
self.marker.mark_non_var(lvl, cell); self.marker.mark_non_var(lvl, term_loc, cell, target);
Target::to_list(lvl, cell.get()) Target::to_list(lvl, cell.get())
} }
@@ -102,56 +111,15 @@ impl<'a> CodeGenerator<'a> {
Target::constant_subterm(constant.clone()) Target::constant_subterm(constant.clone())
} }
fn anon_var_term<Target>(&mut self, lvl: Level, target: &mut Vec<Target>) fn non_var_subterm<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &'a Cell<RegType>,
target: &mut Vec<Target>)
-> Target
where Target: CompilationTarget<'a> where Target: CompilationTarget<'a>
{ {
let reg = self.marker.mark_anon_var(lvl); self.marker.mark_non_var(lvl, term_loc, cell, target);
let instr = match reg {
VarReg::ArgAndNorm(arg, norm) =>
Target::argument_to_variable(arg, norm),
VarReg::Norm(norm) =>
Target::subterm_to_variable(norm)
};
target.push(instr);
}
fn var_term<Target>(&mut self,
lvl: Level,
cell: &'a Cell<VarReg>,
var: &'a Var,
_: GenContext,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
if !self.marker.marked_var(var) {
let reg = self.marker.mark_new_var(lvl, var, cell.get().norm());
cell.set(reg);
match reg {
VarReg::ArgAndNorm(arg, norm) => // if arg.reg_num() != norm =>
target.push(Target::argument_to_variable(arg, norm)),
VarReg::Norm(norm) =>
target.push(Target::subterm_to_variable(norm)),
};
} else {
let reg = self.marker.mark_old_var(lvl, var);
cell.set(reg);
match reg {
VarReg::ArgAndNorm(arg, norm) => // if arg.reg_num() != norm =>
target.push(Target::argument_to_value(arg, norm)),
VarReg::Norm(norm) =>
target.push(Target::subterm_to_value(norm)),
};
}
}
fn non_var_subterm<Target>(&mut self, cell: &'a Cell<RegType>) -> Target
where Target: CompilationTarget<'a>
{
self.marker.mark_non_var(Level::Deep, cell);
Target::clause_arg_to_instr(cell.get()) Target::clause_arg_to_instr(cell.get())
} }
@@ -163,13 +131,15 @@ impl<'a> CodeGenerator<'a> {
{ {
match subterm { match subterm {
&Term::AnonVar => &Term::AnonVar =>
self.anon_var_term(Level::Deep, target), self.marker.mark_anon_var(Level::Deep, target),
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _) => &Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _) => {
target.push(self.non_var_subterm(cell)), let instr = self.non_var_subterm(Level::Deep, term_loc, cell, target);
target.push(instr);
},
&Term::Constant(_, ref constant) => &Term::Constant(_, ref constant) =>
target.push(self.constant_subterm(constant)), target.push(self.constant_subterm(constant)),
&Term::Var(ref cell, ref var) => &Term::Var(ref cell, ref var) =>
self.var_term(Level::Deep, cell, var, term_loc, target) self.marker.mark_var(var, Level::Deep, cell, term_loc, target)
}; };
} }
@@ -186,7 +156,14 @@ impl<'a> CodeGenerator<'a> {
for term in iter { for term in iter {
match term { match term {
TermRef::Clause(lvl, cell, atom, terms) => { TermRef::Clause(lvl, cell, atom, terms) => {
target.push(self.to_structure(lvl, cell, atom, terms.len())); let str_instr = self.to_structure(lvl,
cell,
term_loc,
atom,
terms.len(),
&mut target);
target.push(str_instr);
if !has_exposed_vars { if !has_exposed_vars {
if self.all_singleton_vars(terms) { if self.all_singleton_vars(terms) {
@@ -200,21 +177,24 @@ impl<'a> CodeGenerator<'a> {
} }
}, },
TermRef::Cons(lvl, cell, head, tail) => { TermRef::Cons(lvl, cell, head, tail) => {
target.push(self.to_list(lvl, cell)); let list_instr = self.to_list(lvl, term_loc, cell, &mut target);
target.push(list_instr);
self.subterm_to_instr(head, term_loc, &mut target); self.subterm_to_instr(head, term_loc, &mut target);
self.subterm_to_instr(tail, term_loc, &mut target); self.subterm_to_instr(tail, term_loc, &mut target);
}, },
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
target.push(self.to_constant(lvl, cell, constant)), let const_instr = self.to_constant(lvl, cell, term_loc, constant, &mut target);
target.push(const_instr);
},
TermRef::AnonVar(lvl @ Level::Shallow) => TermRef::AnonVar(lvl @ Level::Shallow) =>
if has_exposed_vars { if has_exposed_vars {
self.anon_var_term(lvl, &mut target); self.marker.mark_anon_var(lvl, &mut target);
} else { } else {
self.marker.advance_arg(); self.marker.advance_arg();
}, },
TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) => TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
self.var_term(lvl, cell, var, term_loc, &mut target), self.marker.mark_var(var, lvl, cell, term_loc, &mut target),
_ => {} _ => {}
}; };
} }
@@ -332,7 +312,7 @@ impl<'a> CodeGenerator<'a> {
body.push(Line::Cut(CutInstruction::NeckCut(term))); body.push(Line::Cut(CutInstruction::NeckCut(term)));
}, },
&TermOrCut::Term(ref p1) => { &TermOrCut::Term(ref p1) => {
self.marker.advance_at_head(p1); self.marker.advance(p1);
if p1.is_clause() { if p1.is_clause() {
let term_loc = if p1.is_callable() { let term_loc = if p1.is_callable() {

View File

@@ -0,0 +1,355 @@
use prolog::ast::*;
use prolog::fixtures::*;
use prolog::targets::*;
use std::cell::Cell;
use std::collections::{BTreeSet, HashMap};
pub struct TermMarker<'a> {
pub bindings: HashMap<&'a Var, VarData>,
arg_c: usize,
temp_lb: usize,
contents: HashMap<usize, &'a Var>,
in_use: BTreeSet<usize>,
}
impl<'a> TermMarker<'a> {
pub fn new() -> TermMarker<'a> {
TermMarker {
arg_c: 1,
temp_lb: 1,
bindings: HashMap::new(),
contents: HashMap::new(),
in_use: BTreeSet::new()
}
}
fn occurs_shallowly_in_head(&self, var: &'a Var, term_loc: GenContext, r: usize) -> bool
{
match (term_loc, self.bindings.get(var).unwrap()) {
(GenContext::Head, &VarData::Temp(_, _, ref tvd)) =>
tvd.use_set.contains(&(GenContext::Head, r)),
_ => false
}
}
pub fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a>
{
let mut perm_vs = VariableFixtures::new();
for (var, (var_status, cells)) in vs.into_iter() {
match var_status {
VarStatus::Temp(chunk_num, tvd) => {
self.bindings.insert(var, VarData::Temp(chunk_num, 0, tvd));
},
VarStatus::Perm(_) => {
self.bindings.insert(var, VarData::Perm(0));
perm_vs.insert(var, (var_status, cells));
}
};
}
perm_vs
}
fn alloc_with_cr(&self, var: &'a Var) -> usize
{
match self.bindings.get(var) {
Some(&VarData::Temp(_, _, ref tvd)) => {
for &(_, reg) in tvd.use_set.iter() {
if !self.in_use.contains(&reg) {
return reg;
}
}
let mut result = 0;
for reg in self.temp_lb .. {
if !self.in_use.contains(&reg) {
if !tvd.no_use_set.contains(&reg) {
result = reg;
break;
}
}
}
result
},
_ => 0
}
}
fn alloc_with_ca(&self, var: &'a Var) -> usize
{
match self.bindings.get(var) {
Some(&VarData::Temp(_, _, ref tvd)) => {
for &(_, reg) in tvd.use_set.iter() {
if !self.in_use.contains(&reg) {
return reg;
}
}
let mut result = 0;
for reg in self.temp_lb .. {
if !self.in_use.contains(&reg) {
if !tvd.no_use_set.contains(&reg) {
if !tvd.conflict_set.contains(&reg) {
result = reg;
break;
}
}
}
}
result
},
_ => 0
}
}
fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(&'a Var, usize)>
{
// we want to allocate a register to the k^{th} parameter, par_k.
// par_k may not be a temporary variable.
let k = self.arg_c;
match self.contents.get(&k) {
Some(t_var) => {
// suppose this branch fires. then t_var is a
// temp. var. belonging to the current chunk.
// consider its use set. T == par_k iff
// (GenContext::Last(_), k) is in t_var.use_set.
let tvd = self.bindings.get(t_var).unwrap();
if let &VarData::Temp(_, _, ref tvd) = tvd {
if !tvd.use_set.contains(&(GenContext::Last(chunk_num), k)) {
return Some((t_var, self.alloc_with_ca(t_var)));
}
}
None
},
_ => None
}
}
fn evacuate_arg<Target>(&mut self, chunk_num: usize, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
match self.alloc_in_last_goal_hint(chunk_num) {
Some((var, r)) => {
let k = self.arg_c;
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);
self.record_register(var, r);
self.in_use.insert(r.reg_num());
}
}
},
_ => {}
};
}
fn alloc_reg_to_var<Target>(&mut self,
var: &'a Var,
lvl: Level,
term_loc: GenContext,
target: &mut Vec<Target>)
-> usize
where Target: CompilationTarget<'a>
{
match term_loc {
GenContext::Head =>
if let Level::Shallow = lvl {
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
},
GenContext::Mid(_) =>
self.alloc_with_ca(var),
GenContext::Last(chunk_num) =>
if let Level::Shallow = lvl {
self.evacuate_arg(chunk_num, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
}
}
}
fn get(&self, var: &'a Var) -> RegType {
self.bindings.get(var).unwrap().as_reg_type()
}
fn in_place(&self, var: &'a Var, term_loc: GenContext, r: RegType, k: usize) -> bool
{
match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => match self.bindings.get(var).unwrap() {
&VarData::Temp(_, o, _) if r.reg_num() == k => o == k,
_ => false
}
}
}
// delete after anon_vars are handled by means of *_void stuff.
pub fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = RegType::Temp(self.alloc_reg_to_non_var());
match lvl {
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
target.push(Target::argument_to_variable(r, k));
},
Level::Deep =>
target.push(Target::subterm_to_variable(r))
};
}
fn alloc_reg_to_non_var(&mut self) -> usize
{
let mut final_index = 0;
for index in self.temp_lb .. {
if !self.in_use.contains(&index) {
final_index = index;
break;
}
}
self.temp_lb = final_index + 1;
final_index
}
pub fn mark_non_var<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = cell.get();
if r.reg_num() == 0 {
let r = match lvl {
Level::Shallow => {
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
self.evacuate_arg(chunk_num, target);
}
self.arg_c += 1;
RegType::Temp(k)
},
_ => RegType::Temp(self.alloc_reg_to_non_var())
};
cell.set(r);
}
}
pub fn mark_var<Target>(&mut self,
var: &'a Var,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let (r, is_new_var) = match self.get(var) {
RegType::Temp(0) => {
// here, r is temporary *and* unassigned.
let o = self.alloc_reg_to_var(var, lvl, term_loc, target);
cell.set(VarReg::Norm(RegType::Temp(o)));
(RegType::Temp(o), true)
},
RegType::Perm(0) => {
let pr = cell.get().norm();
self.record_register(var, pr);
(pr, true)
},
r => (r, false)
};
match lvl {
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
cell.set(VarReg::ArgAndNorm(r, k));
if !self.in_place(var, term_loc, r, k) {
if is_new_var {
target.push(Target::argument_to_variable(r, k));
} else {
target.push(Target::argument_to_value(r, k));
}
}
},
Level::Deep if is_new_var =>
if self.occurs_shallowly_in_head(var, term_loc, r.reg_num()) {
target.push(Target::subterm_to_value(r));
} else {
target.push(Target::subterm_to_variable(r));
},
Level::Deep =>
target.push(Target::subterm_to_value(r))
};
if !r.is_perm() {
let o = r.reg_num();
self.contents.insert(o, var);
self.record_register(var, r);
self.in_use.insert(o);
}
}
pub fn contains_var(&self, var: &'a Var) -> bool {
self.bindings.contains_key(var)
}
fn record_register(&mut self, var: &'a Var, r: RegType) {
match self.bindings.get_mut(var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
&mut VarData::Perm(ref mut s) => *s = r.reg_num()
}
}
pub fn advance_arg(&mut self) {
self.arg_c += 1;
}
pub fn advance(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_lb = term.arity() + 1;
}
pub fn reset(&mut self) {
self.bindings.clear();
self.contents.clear();
self.in_use.clear();
}
pub fn reset_contents(&mut self) {
self.contents.clear();
self.in_use.clear();
}
}

View File

@@ -10,14 +10,9 @@ pub type OccurrenceSet = BTreeSet<(GenContext, usize)>;
pub struct TempVarData { pub struct TempVarData {
last_term_arity: usize, last_term_arity: usize,
use_set: OccurrenceSet, pub use_set: OccurrenceSet,
no_use_set: BTreeSet<usize>, pub no_use_set: BTreeSet<usize>,
conflict_set: BTreeSet<usize> pub conflict_set: BTreeSet<usize>
}
// labeled with chunk_num and temp offset (unassigned if 0).
pub enum VarData {
Perm(usize), Temp(usize, usize, TempVarData)
} }
// labeled with chunk numbers. // labeled with chunk numbers.
@@ -25,6 +20,12 @@ pub enum VarStatus {
Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _)
} }
// Perm: 0 initially, a stack register once processed.
// Temp: labeled with chunk_num and temp offset (unassigned if 0), arg (0 if unassigned).
pub enum VarData {
Perm(usize), Temp(usize, usize, TempVarData)
}
impl VarData { impl VarData {
pub fn as_reg_type(&self) -> RegType { pub fn as_reg_type(&self) -> RegType {
match self { match self {

View File

@@ -57,6 +57,8 @@ impl fmt::Display for FactInstruction {
impl fmt::Display for QueryInstruction { impl fmt::Display for QueryInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&QueryInstruction::GetVariable(ref x, ref a) =>
write!(f, "get_variable {}, A{}", x, a),
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) => &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
write!(f, "put_constant {}, A{}", constant, r.reg_num()), write!(f, "put_constant {}, A{}", constant, r.reg_num()),
&QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) => &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>

View File

@@ -111,7 +111,7 @@ impl Machine {
self.code_dir.insert((name, arity), p); self.code_dir.insert((name, arity), p);
} }
fn execute_instr<'b>(&mut self, instr_src: LineOrCodeOffset<'b>) -> bool fn execute_instr<'a>(&mut self, instr_src: LineOrCodeOffset<'a>) -> bool
{ {
let mut instr = match instr_src { let mut instr = match instr_src {
LineOrCodeOffset::Instruction(instr) => instr, LineOrCodeOffset::Instruction(instr) => instr,
@@ -251,9 +251,10 @@ impl Machine {
} }
if succeeded { if succeeded {
for (var, var_status) in cg.vars() { for (var, var_data) in cg.vars() {
let r = var_status.as_reg_type().reg_num(); let r = var_data.as_reg_type();
let addr = self.ms.registers[r].clone();
let addr = self.ms[r].clone();
heap_locs.insert((*var).clone(), addr); heap_locs.insert((*var).clone(), addr);
} }
@@ -536,7 +537,6 @@ impl MachineState {
_ => self.fail = true _ => self.fail = true
}; };
}, },
&FactInstruction::GetList(_, reg) => { &FactInstruction::GetList(_, reg) => {
let addr = self.deref(self[reg].clone()); let addr = self.deref(self[reg].clone());
@@ -782,6 +782,8 @@ impl MachineState {
fn execute_query_instr(&mut self, instr: &QueryInstruction) { fn execute_query_instr(&mut self, instr: &QueryInstruction) {
match instr { match instr {
&QueryInstruction::GetVariable(norm, arg) =>
self[norm] = self.registers[arg].clone(),
&QueryInstruction::PutConstant(_, ref constant, reg) => &QueryInstruction::PutConstant(_, ref constant, reg) =>
self[reg] = Addr::Con(constant.clone()), self[reg] = Addr::Con(constant.clone()),
&QueryInstruction::PutList(_, reg) => &QueryInstruction::PutList(_, reg) =>
@@ -813,6 +815,7 @@ impl MachineState {
match norm { match norm {
RegType::Perm(n) => { RegType::Perm(n) => {
let e = self.e; let e = self.e;
self[norm] = Addr::StackCell(e, n); self[norm] = Addr::StackCell(e, n);
self.registers[arg] = self[norm].clone(); self.registers[arg] = self[norm].clone();
}, },

View File

@@ -1,12 +1,12 @@
pub mod and_stack; pub mod and_stack;
pub mod ast; pub mod ast;
pub mod codegen; pub mod codegen;
pub mod debray_allocator;
pub mod fixtures; pub mod fixtures;
pub mod heapview; pub mod heapview;
pub mod indexing; pub mod indexing;
pub mod io; pub mod io;
pub mod iterators; pub mod iterators;
pub mod naive_allocator;
pub mod prolog_parser; pub mod prolog_parser;
pub mod machine; pub mod machine;
pub mod or_stack; pub mod or_stack;

View File

@@ -16,6 +16,8 @@ pub trait CompilationTarget<'a> {
fn argument_to_variable(RegType, usize) -> Self; fn argument_to_variable(RegType, usize) -> Self;
fn argument_to_value(RegType, usize) -> Self; fn argument_to_value(RegType, usize) -> Self;
fn move_to_register(RegType, usize) -> Self;
fn subterm_to_variable(RegType) -> Self; fn subterm_to_variable(RegType) -> Self;
fn subterm_to_value(RegType) -> Self; fn subterm_to_value(RegType) -> Self;
@@ -53,6 +55,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
FactInstruction::GetVariable(arg, val) FactInstruction::GetVariable(arg, val)
} }
fn move_to_register(arg: RegType, val: usize) -> Self {
FactInstruction::GetVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self { fn argument_to_value(arg: RegType, val: usize) -> Self {
FactInstruction::GetValue(arg, val) FactInstruction::GetValue(arg, val)
} }
@@ -100,6 +106,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
fn argument_to_variable(arg: RegType, val: usize) -> Self { fn argument_to_variable(arg: RegType, val: usize) -> Self {
QueryInstruction::PutVariable(arg, val) QueryInstruction::PutVariable(arg, val)
} }
fn move_to_register(arg: RegType, val: usize) -> Self {
QueryInstruction::GetVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self { fn argument_to_value(arg: RegType, val: usize) -> Self {
QueryInstruction::PutValue(arg, val) QueryInstruction::PutValue(arg, val)