slight polishing up, bug fixes

This commit is contained in:
Mark Thom
2017-02-02 16:09:18 -07:00
parent 23fc50417f
commit 648b7d09fe
4 changed files with 93 additions and 72 deletions

View File

@@ -31,7 +31,7 @@ pub enum Reg {
Norm(usize) Norm(usize)
} }
impl Reg { impl Reg {
pub fn has_arg(&self) -> bool { pub fn has_arg(&self) -> bool {
match self { match self {
&Reg::ArgAndNorm(_, _) => true, &Reg::ArgAndNorm(_, _) => true,
@@ -87,6 +87,17 @@ pub enum Addr {
RegNum(usize) RegNum(usize)
} }
#[derive(Clone)]
pub enum HeapCellValue {
NamedStr(usize, Atom),
Ref(usize),
Str(usize),
}
pub type Heap = Vec<HeapCellValue>;
pub type Registers = Vec<HeapCellValue>;
impl Term { impl Term {
pub fn subterms(&self) -> usize { pub fn subterms(&self) -> usize {
match self { match self {
@@ -98,11 +109,11 @@ impl Term {
pub fn name(&self) -> &Atom { pub fn name(&self) -> &Atom {
match self { match self {
&Term::Atom(_, ref atom) &Term::Atom(_, ref atom)
| &Term::Var(_, ref atom) | &Term::Var(_, ref atom)
| &Term::Clause(_, ref atom, _) => atom | &Term::Clause(_, ref atom, _) => atom
} }
} }
pub fn arity(&self) -> usize { pub fn arity(&self) -> usize {
match self { match self {
&Term::Atom(_, _) | &Term::Var(_, _) => 0, &Term::Atom(_, _) | &Term::Var(_, _) => 0,

View File

@@ -255,8 +255,7 @@ fn var_term<'a, Target>(tm: &mut TermMarker<'a>,
} }
} }
fn subterm_to_instr<'a, Target>(tm: &mut TermMarker<'a>, fn subterm_to_instr<'a, Target>(tm: &mut TermMarker<'a>, subterm: &'a Term)
subterm: &'a Term)
-> Target -> Target
where Target: CompilationTarget<'a> where Target: CompilationTarget<'a>
{ {
@@ -274,7 +273,7 @@ fn compile_target<'a, Target>(term: &'a Term) -> Vec<Target>
let iter = Target::iter(term); let iter = Target::iter(term);
let mut target = Vec::<Target>::new(); let mut target = Vec::<Target>::new();
let mut marker = TermMarker::new(term); let mut marker = TermMarker::new(term);
for term in iter { for term in iter {
match term { match term {
TermRef::Atom(lvl, term, atom) => TermRef::Atom(lvl, term, atom) =>
@@ -302,7 +301,7 @@ pub fn compile_fact(term: &Term) -> CompiledFact {
compiled_fact compiled_fact
} }
pub fn compile_query(term: &Term) -> CompiledQuery { pub fn compile_query<'a>(term: &'a Term) -> CompiledQuery {
let mut compiled_query = compile_target(term); let mut compiled_query = compile_target(term);
if let &Term::Clause(_, ref atom, ref terms) = term { if let &Term::Clause(_, ref atom, ref terms) = term {

View File

@@ -1,34 +1,25 @@
use l1::ast::{Addr, Atom, CompiledFact, FactInstruction, QueryInstruction}; use l1::ast::{Addr, Atom, CompiledFact, CompiledQuery,
FactInstruction, Heap, HeapCellValue, QueryInstruction,
Registers};
use std::collections::HashMap; use std::collections::HashMap;
use std::vec::Vec; use std::vec::Vec;
#[derive(Clone)]
enum HeapCell {
NamedStr(usize, Atom),
Ref(usize),
Str(usize),
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum MachineMode { enum MachineMode {
Read, Read,
Write Write
} }
type Heap = Vec<HeapCell>;
type Registers = Vec<HeapCell>;
pub struct Machine { pub struct Machine {
h : usize, h : usize,
s : usize, s : usize,
p : usize, p : usize,
pub fail : bool, code : CompiledFact,
code_dir : HashMap<(Atom, usize), usize>,
fail : bool,
heap : Heap, heap : Heap,
mode : MachineMode, mode : MachineMode,
pub code_dir : HashMap<(Atom, usize), usize>,
pub code : CompiledFact,
registers : Registers registers : Registers
} }
@@ -37,15 +28,27 @@ impl Machine {
Machine { h : 0, Machine { h : 0,
s : 0, s : 0,
p : 0, p : 0,
code : Vec::new(),
code_dir : HashMap::new(),
fail : false, fail : false,
heap : Vec::with_capacity(256), heap : Vec::with_capacity(256),
mode : MachineMode::Write, mode : MachineMode::Write,
code_dir : HashMap::new(), registers : vec![HeapCellValue::Ref(0); 32] }
code : Vec::new(),
registers : vec![HeapCell::Ref(0); 32] }
} }
fn lookup(&self, a: Addr) -> &HeapCell { pub fn add_fact(&mut self, mut fact: CompiledFact, name: Atom, arity: usize)
{
let index = self.code.len();
self.code.append(&mut fact);
self.code_dir.insert((name, arity), index);
}
pub fn failed(&self) -> bool {
self.fail
}
fn lookup(&self, a: Addr) -> &HeapCellValue {
match a { match a {
Addr::HeapCell(hc) => &self.heap[hc], Addr::HeapCell(hc) => &self.heap[hc],
Addr::RegNum(reg) => &self.registers[reg] Addr::RegNum(reg) => &self.registers[reg]
@@ -56,12 +59,15 @@ impl Machine {
let mut a = a; let mut a = a;
loop { loop {
if let &HeapCell::Ref(value) = self.lookup(a) { if let &HeapCellValue::Ref(value) = self.lookup(a) {
if let Addr::HeapCell(av) = a { if let Addr::HeapCell(av) = a {
if value != av { if value != av {
a = Addr::HeapCell(value); a = Addr::HeapCell(value);
continue; continue;
} }
} else {
a = Addr::HeapCell(value);
continue;
} }
} }
@@ -69,21 +75,21 @@ impl Machine {
}; };
} }
fn is_unbound(hc: &HeapCell, index: usize) -> bool { fn is_unbound(hc: &HeapCellValue, index: usize) -> bool {
match hc { match hc {
&HeapCell::Ref(r) => r == index, &HeapCellValue::Ref(r) => r == index,
_ => false _ => false
} }
} }
//TODO: try to compress this function. currently it is dog shit. //TODO: try to compress this function.
fn bind(&mut self, a: Addr, val: usize) { fn bind(&mut self, a: Addr, val: usize) {
let mut a = a; let mut a = a;
loop { loop {
match a { match a {
Addr::RegNum(reg) => { Addr::RegNum(reg) => {
if let HeapCell::Ref(hc) = self.registers[reg] { if let HeapCellValue::Ref(hc) = self.registers[reg] {
a = Addr::HeapCell(hc); a = Addr::HeapCell(hc);
} else if Machine::is_unbound(&self.heap[val], val) { } else if Machine::is_unbound(&self.heap[val], val) {
self.heap[val] = self.registers[reg].clone(); self.heap[val] = self.registers[reg].clone();
@@ -91,18 +97,18 @@ impl Machine {
} else { } else {
self.fail = true; self.fail = true;
break; break;
} }
}, },
Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[hc], hc) => { Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[hc], hc) => {
self.heap[hc] = HeapCell::Ref(val); self.heap[hc] = HeapCellValue::Ref(val);
break; break;
}, },
Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[val], val) => { Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[val], val) => {
self.heap[val] = HeapCell::Ref(hc); self.heap[val] = HeapCellValue::Ref(hc);
break; break;
}, },
_ => { _ => {
self.fail = true; self.fail = true;
break; break;
} }
}; };
@@ -110,7 +116,7 @@ impl Machine {
} }
fn unify(&mut self, a1: Addr, a2: Addr) { fn unify(&mut self, a1: Addr, a2: Addr) {
let mut pdl : Vec<Addr> = vec![a1, a2]; let mut pdl = vec![a1, a2];
self.fail = false; self.fail = false;
@@ -120,16 +126,16 @@ impl Machine {
if d1 != d2 { if d1 != d2 {
match (self.lookup(d1), self.lookup(d2)) { match (self.lookup(d1), self.lookup(d2)) {
(&HeapCell::Ref(hc), _) => (&HeapCellValue::Ref(hc), _) =>
self.bind(d2, hc), self.bind(d2, hc),
(_, &HeapCell::Ref(hc)) => (_, &HeapCellValue::Ref(hc)) =>
self.bind(d1, hc), self.bind(d1, hc),
(&HeapCell::Str(a1), &HeapCell::Str(a2)) => { (&HeapCellValue::Str(a1), &HeapCellValue::Str(a2)) => {
let r1 = &self.heap[a1]; let r1 = &self.heap[a1];
let r2 = &self.heap[a2]; let r2 = &self.heap[a2];
if let &HeapCell::NamedStr(n1, ref f1) = r1 { if let &HeapCellValue::NamedStr(n1, ref f1) = r1 {
if let &HeapCell::NamedStr(n2, ref f2) = r2 { if let &HeapCellValue::NamedStr(n2, ref f2) = r2 {
if n1 == n2 && *f1 == *f2 { if n1 == n2 && *f1 == *f2 {
for i in 1 .. n1 { for i in 1 .. n1 {
pdl.push(Addr::HeapCell(a1 + i)); pdl.push(Addr::HeapCell(a1 + i));
@@ -162,12 +168,23 @@ impl Machine {
} }
} }
pub fn execute_query_instr<'a, 'b: 'a>(&'a mut self, instr: &'b QueryInstruction) { pub fn execute_query(&mut self, query: &CompiledQuery) {
for instr in query {
self.execute_query_instr(instr);
if self.fail {
break;
}
}
}
fn execute_query_instr<'a, 'b: 'a>(&'a mut self, instr: &'b QueryInstruction) {
match instr { match instr {
&QueryInstruction::Call(ref name, arity) => { &QueryInstruction::Call(ref name, arity) => {
// why is Option<&T> not Deref?!?!? // why is Option<&T> not Deref?!?!?
let compiled_fact_index = let compiled_fact_index =
self.code_dir.get(&(name.clone(), arity)).map(|index| *index); self.code_dir.get(&(name.clone(), arity))
.map(|index| *index);
match compiled_fact_index { match compiled_fact_index {
Some(compiled_fact_index) => { Some(compiled_fact_index) => {
@@ -178,8 +195,8 @@ impl Machine {
}; };
} }
&QueryInstruction::PutStructure(_, ref name, arity, reg) => { &QueryInstruction::PutStructure(_, ref name, arity, reg) => {
self.heap.push(HeapCell::Str(self.h + 1)); self.heap.push(HeapCellValue::Str(self.h + 1));
self.heap.push(HeapCell::NamedStr(arity, name.clone())); self.heap.push(HeapCellValue::NamedStr(arity, name.clone()));
self.registers[reg] = self.heap[self.h].clone(); self.registers[reg] = self.heap[self.h].clone();
@@ -188,7 +205,7 @@ impl Machine {
&QueryInstruction::PutValue(arg, norm) => &QueryInstruction::PutValue(arg, norm) =>
self.registers[arg] = self.registers[norm].clone(), self.registers[arg] = self.registers[norm].clone(),
&QueryInstruction::PutVariable(arg, norm) => { &QueryInstruction::PutVariable(arg, norm) => {
self.heap.push(HeapCell::Ref(self.h)); self.heap.push(HeapCellValue::Ref(self.h));
self.registers[norm] = self.heap[self.h].clone(); self.registers[norm] = self.heap[self.h].clone();
self.registers[arg] = self.heap[self.h].clone(); self.registers[arg] = self.heap[self.h].clone();
@@ -196,7 +213,7 @@ impl Machine {
self.h += 1; self.h += 1;
}, },
&QueryInstruction::SetVariable(reg) => { &QueryInstruction::SetVariable(reg) => {
self.heap.push(HeapCell::Ref(self.h)); self.heap.push(HeapCellValue::Ref(self.h));
self.registers[reg] = self.heap[self.h].clone(); self.registers[reg] = self.heap[self.h].clone();
self.h += 1; self.h += 1;
@@ -215,10 +232,10 @@ impl Machine {
let addr = self.deref(Addr::RegNum(reg)); let addr = self.deref(Addr::RegNum(reg));
match self.lookup(addr) { match self.lookup(addr) {
&HeapCell::Str(a) => { &HeapCellValue::Str(a) => {
let result = &self.heap[a]; let result = &self.heap[a];
if let &HeapCell::NamedStr(named_arity, ref named_str) = result { if let &HeapCellValue::NamedStr(named_arity, ref named_str) = result {
if arity == named_arity && *name == *named_str { if arity == named_arity && *name == *named_str {
self.s = a + 1; self.s = a + 1;
self.mode = MachineMode::Read; self.mode = MachineMode::Read;
@@ -227,13 +244,13 @@ impl Machine {
} }
} }
}, },
&HeapCell::Ref(r) => { &HeapCellValue::Ref(r) => {
self.heap.push(HeapCell::Str(self.h + 1)); self.heap.push(HeapCellValue::Str(self.h + 1));
self.heap.push(HeapCell::NamedStr(arity, name)); self.heap.push(HeapCellValue::NamedStr(arity, name));
let h = self.h; let h = self.h;
self.bind(Addr::HeapCell(r), h); self.bind(Addr::HeapCell(r), h);
self.h += 2; self.h += 2;
self.mode = MachineMode::Write; self.mode = MachineMode::Write;
@@ -251,7 +268,7 @@ impl Machine {
match self.mode { match self.mode {
MachineMode::Read => self.registers[reg] = self.heap[self.s].clone(), MachineMode::Read => self.registers[reg] = self.heap[self.s].clone(),
MachineMode::Write => { MachineMode::Write => {
self.heap.push(HeapCell::Ref(self.h)); self.heap.push(HeapCellValue::Ref(self.h));
self.registers[reg] = self.heap[self.h].clone(); self.registers[reg] = self.heap[self.h].clone();
self.h += 1; self.h += 1;
} }
@@ -285,6 +302,6 @@ impl Machine {
self.fail = false; self.fail = false;
self.heap = Vec::with_capacity(256); self.heap = Vec::with_capacity(256);
self.mode = MachineMode::Write; self.mode = MachineMode::Write;
self.registers = vec![HeapCell::Ref(0); 32]; self.registers = vec![HeapCellValue::Ref(0); 32];
} }
} }

View File

@@ -27,29 +27,23 @@ fn l1_repl() {
match result { match result {
Ok(TopLevel::Fact(fact)) => { Ok(TopLevel::Fact(fact)) => {
let mut compiled_fact = compile_fact(&fact); let name = fact.name().to_owned();
let index = ms.code.len(); let arity = fact.arity();
let fact = compile_fact(&fact);
ms.code.append(&mut compiled_fact); ms.add_fact(fact, name, arity);
ms.code_dir.insert((fact.name().clone(), fact.arity()), index);
}, },
Ok(TopLevel::Query(query)) => { Ok(TopLevel::Query(query)) => {
let compiled_query = compile_query(&query); let compiled_query = compile_query(&query);
for instruction in &compiled_query { ms.execute_query(&compiled_query);
ms.execute_query_instr(instruction);
if ms.failed() {
if ms.fail {
break;
}
}
if ms.fail {
println!("no"); println!("no");
} else { } else {
println!("yes"); println!("yes");
} }
ms.reset_machine_state(); ms.reset_machine_state();
}, },
Err(_) => println!("Grammatical error of some kind!"), Err(_) => println!("Grammatical error of some kind!"),