From: Mark Thom Date: Thu, 2 Feb 2017 23:09:18 +0000 (-0700) Subject: slight polishing up, bug fixes X-Git-Tag: v0.8.110~779 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=648b7d09fe2926a7e0af5c40ce96cc4100878d10;p=scryer-prolog.git slight polishing up, bug fixes --- diff --git a/src/l1/ast.rs b/src/l1/ast.rs index 74c50915..25493f5b 100644 --- a/src/l1/ast.rs +++ b/src/l1/ast.rs @@ -31,7 +31,7 @@ pub enum Reg { Norm(usize) } -impl Reg { +impl Reg { pub fn has_arg(&self) -> bool { match self { &Reg::ArgAndNorm(_, _) => true, @@ -87,6 +87,17 @@ pub enum Addr { RegNum(usize) } +#[derive(Clone)] +pub enum HeapCellValue { + NamedStr(usize, Atom), + Ref(usize), + Str(usize), +} + +pub type Heap = Vec; + +pub type Registers = Vec; + impl Term { pub fn subterms(&self) -> usize { match self { @@ -98,11 +109,11 @@ impl Term { pub fn name(&self) -> &Atom { match self { &Term::Atom(_, ref atom) - | &Term::Var(_, ref atom) + | &Term::Var(_, ref atom) | &Term::Clause(_, ref atom, _) => atom } } - + pub fn arity(&self) -> usize { match self { &Term::Atom(_, _) | &Term::Var(_, _) => 0, diff --git a/src/l1/codegen.rs b/src/l1/codegen.rs index 6579ef0b..a62dc407 100644 --- a/src/l1/codegen.rs +++ b/src/l1/codegen.rs @@ -255,8 +255,7 @@ fn var_term<'a, Target>(tm: &mut TermMarker<'a>, } } -fn subterm_to_instr<'a, Target>(tm: &mut TermMarker<'a>, - subterm: &'a Term) +fn subterm_to_instr<'a, Target>(tm: &mut TermMarker<'a>, subterm: &'a Term) -> Target where Target: CompilationTarget<'a> { @@ -274,7 +273,7 @@ fn compile_target<'a, Target>(term: &'a Term) -> Vec let iter = Target::iter(term); let mut target = Vec::::new(); let mut marker = TermMarker::new(term); - + for term in iter { match term { TermRef::Atom(lvl, term, atom) => @@ -302,7 +301,7 @@ pub fn compile_fact(term: &Term) -> CompiledFact { 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); if let &Term::Clause(_, ref atom, ref terms) = term { diff --git a/src/l1/machine.rs b/src/l1/machine.rs index 3ef4d2bc..c1bdd375 100644 --- a/src/l1/machine.rs +++ b/src/l1/machine.rs @@ -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::vec::Vec; -#[derive(Clone)] -enum HeapCell { - NamedStr(usize, Atom), - Ref(usize), - Str(usize), -} - #[derive(Clone, Copy)] enum MachineMode { Read, Write } -type Heap = Vec; - -type Registers = Vec; - pub struct Machine { h : usize, s : usize, p : usize, - pub fail : bool, + code : CompiledFact, + code_dir : HashMap<(Atom, usize), usize>, + fail : bool, heap : Heap, mode : MachineMode, - pub code_dir : HashMap<(Atom, usize), usize>, - pub code : CompiledFact, registers : Registers } @@ -37,15 +28,27 @@ impl Machine { Machine { h : 0, s : 0, p : 0, + code : Vec::new(), + code_dir : HashMap::new(), fail : false, heap : Vec::with_capacity(256), mode : MachineMode::Write, - code_dir : HashMap::new(), - code : Vec::new(), - registers : vec![HeapCell::Ref(0); 32] } + registers : vec![HeapCellValue::Ref(0); 32] } + } + + 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); } - fn lookup(&self, a: Addr) -> &HeapCell { + pub fn failed(&self) -> bool { + self.fail + } + + fn lookup(&self, a: Addr) -> &HeapCellValue { match a { Addr::HeapCell(hc) => &self.heap[hc], Addr::RegNum(reg) => &self.registers[reg] @@ -56,12 +59,15 @@ impl Machine { let mut a = a; loop { - if let &HeapCell::Ref(value) = self.lookup(a) { + if let &HeapCellValue::Ref(value) = self.lookup(a) { if let Addr::HeapCell(av) = a { if value != av { a = Addr::HeapCell(value); 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 { - &HeapCell::Ref(r) => r == index, + &HeapCellValue::Ref(r) => r == index, _ => 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) { let mut a = a; - + loop { match a { Addr::RegNum(reg) => { - if let HeapCell::Ref(hc) = self.registers[reg] { + if let HeapCellValue::Ref(hc) = self.registers[reg] { a = Addr::HeapCell(hc); } else if Machine::is_unbound(&self.heap[val], val) { self.heap[val] = self.registers[reg].clone(); @@ -91,18 +97,18 @@ impl Machine { } else { self.fail = true; break; - } + } }, Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[hc], hc) => { - self.heap[hc] = HeapCell::Ref(val); + self.heap[hc] = HeapCellValue::Ref(val); break; }, - Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[val], val) => { - self.heap[val] = HeapCell::Ref(hc); + Addr::HeapCell(hc) if Machine::is_unbound(&self.heap[val], val) => { + self.heap[val] = HeapCellValue::Ref(hc); break; }, _ => { - self.fail = true; + self.fail = true; break; } }; @@ -110,7 +116,7 @@ impl Machine { } fn unify(&mut self, a1: Addr, a2: Addr) { - let mut pdl : Vec = vec![a1, a2]; + let mut pdl = vec![a1, a2]; self.fail = false; @@ -120,16 +126,16 @@ impl Machine { if d1 != d2 { match (self.lookup(d1), self.lookup(d2)) { - (&HeapCell::Ref(hc), _) => + (&HeapCellValue::Ref(hc), _) => self.bind(d2, hc), - (_, &HeapCell::Ref(hc)) => + (_, &HeapCellValue::Ref(hc)) => self.bind(d1, hc), - (&HeapCell::Str(a1), &HeapCell::Str(a2)) => { + (&HeapCellValue::Str(a1), &HeapCellValue::Str(a2)) => { let r1 = &self.heap[a1]; let r2 = &self.heap[a2]; - if let &HeapCell::NamedStr(n1, ref f1) = r1 { - if let &HeapCell::NamedStr(n2, ref f2) = r2 { + if let &HeapCellValue::NamedStr(n1, ref f1) = r1 { + if let &HeapCellValue::NamedStr(n2, ref f2) = r2 { if n1 == n2 && *f1 == *f2 { for i in 1 .. n1 { 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 { &QueryInstruction::Call(ref name, arity) => { // why is Option<&T> not Deref?!?!? 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 { Some(compiled_fact_index) => { @@ -178,8 +195,8 @@ impl Machine { }; } &QueryInstruction::PutStructure(_, ref name, arity, reg) => { - self.heap.push(HeapCell::Str(self.h + 1)); - self.heap.push(HeapCell::NamedStr(arity, name.clone())); + self.heap.push(HeapCellValue::Str(self.h + 1)); + self.heap.push(HeapCellValue::NamedStr(arity, name.clone())); self.registers[reg] = self.heap[self.h].clone(); @@ -188,7 +205,7 @@ impl Machine { &QueryInstruction::PutValue(arg, norm) => self.registers[arg] = self.registers[norm].clone(), &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[arg] = self.heap[self.h].clone(); @@ -196,7 +213,7 @@ impl Machine { self.h += 1; }, &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.h += 1; @@ -215,10 +232,10 @@ impl Machine { let addr = self.deref(Addr::RegNum(reg)); match self.lookup(addr) { - &HeapCell::Str(a) => { + &HeapCellValue::Str(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 { self.s = a + 1; self.mode = MachineMode::Read; @@ -227,13 +244,13 @@ impl Machine { } } }, - &HeapCell::Ref(r) => { - self.heap.push(HeapCell::Str(self.h + 1)); - self.heap.push(HeapCell::NamedStr(arity, name)); + &HeapCellValue::Ref(r) => { + self.heap.push(HeapCellValue::Str(self.h + 1)); + self.heap.push(HeapCellValue::NamedStr(arity, name)); let h = self.h; - self.bind(Addr::HeapCell(r), h); + self.bind(Addr::HeapCell(r), h); self.h += 2; self.mode = MachineMode::Write; @@ -251,7 +268,7 @@ impl Machine { match self.mode { MachineMode::Read => self.registers[reg] = self.heap[self.s].clone(), 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.h += 1; } @@ -285,6 +302,6 @@ impl Machine { self.fail = false; self.heap = Vec::with_capacity(256); self.mode = MachineMode::Write; - self.registers = vec![HeapCell::Ref(0); 32]; + self.registers = vec![HeapCellValue::Ref(0); 32]; } } diff --git a/src/main.rs b/src/main.rs index 00878d92..e3fa6578 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,29 +27,23 @@ fn l1_repl() { match result { Ok(TopLevel::Fact(fact)) => { - let mut compiled_fact = compile_fact(&fact); - let index = ms.code.len(); + let name = fact.name().to_owned(); + let arity = fact.arity(); + let fact = compile_fact(&fact); - ms.code.append(&mut compiled_fact); - ms.code_dir.insert((fact.name().clone(), fact.arity()), index); + ms.add_fact(fact, name, arity); }, Ok(TopLevel::Query(query)) => { let compiled_query = compile_query(&query); - for instruction in &compiled_query { - ms.execute_query_instr(instruction); - - if ms.fail { - break; - } - } - - if ms.fail { + ms.execute_query(&compiled_query); + + if ms.failed() { println!("no"); } else { println!("yes"); - } - + } + ms.reset_machine_state(); }, Err(_) => println!("Grammatical error of some kind!"),