transition to prolog

This commit is contained in:
Mark Thom
2017-03-10 23:50:26 -07:00
parent 743602778f
commit fcb3cc1287
15 changed files with 5540 additions and 23 deletions

View File

@@ -1,13 +1,13 @@
extern crate termion;
mod l3;
mod prolog;
use l3::io::*;
use l3::machine::*;
use prolog::io::*;
use prolog::machine::*;
#[cfg(test)]
mod tests {
use super::*;
use l3::ast::*;
use prolog::ast::*;
fn submit(wam: &mut Machine, buffer: &str) -> EvalResult {
let result = eval(wam, buffer);
@@ -174,13 +174,59 @@ mod tests {
assert_eq!(submit(&mut wam, "?- p(X, Y, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(f(X)), h(f(X)), Y).").failed_query(), true);
}
#[test]
fn test_queries_on_lists() {
let mut wam = Machine::new();
submit(&mut wam, "p([Z, W]).");
assert_eq!(submit(&mut wam, "?- p([Z, Z]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), true);
submit(&mut wam, "p([Z, Z]).");
assert_eq!(submit(&mut wam, "?- p([Z, Z]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), true);
submit(&mut wam, "p([Z]).");
assert_eq!(submit(&mut wam, "?- p([Z, Z]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), false);
submit(&mut wam, "member(X, [X|Xs]).
member(X, [Y|Xs]) :- member(X, Xs).");
assert_eq!(submit(&mut wam, "?- member(a, [c, [X, Y]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member(c, [a, [X, Y]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member(a, [a, [X, Y]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member(a, [X, Y, Z]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [X, Y]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, d], [foo, x], [d, f]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
}
}
fn l3_repl() {
fn prolog_repl() {
let mut wam = Machine::new();
loop {
print!("l3> ");
print!("prolog> ");
let buffer = read();
@@ -199,5 +245,5 @@ fn l3_repl() {
}
fn main() {
l3_repl();
prolog_repl();
}

80
src/prolog/and_stack.rs Normal file
View File

@@ -0,0 +1,80 @@
use prolog::ast::*;
use std::ops::{Index, IndexMut};
use std::vec::Vec;
pub struct Frame {
pub global_index: usize,
pub e: usize,
pub cp: CodePtr,
perms: Vec<Addr>
}
impl Frame {
fn new(global_index: usize, e: usize, cp: CodePtr, n: usize) -> Self {
Frame {
global_index: global_index,
e: e,
cp: cp,
perms: vec![Addr::HeapCell(0); n]
}
}
}
pub struct AndStack(Vec<Frame>);
impl AndStack {
pub fn new() -> Self {
AndStack(Vec::new())
}
pub fn push(&mut self, global_index: usize, e: usize, cp: CodePtr, n: usize) {
self.0.push(Frame::new(global_index, e, cp, n));
}
pub fn top(&self) -> Option<&Frame> {
self.0.last()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn clear(&mut self) {
self.0.clear()
}
// drop the last n frames.
pub fn drop_frames(&mut self, n: usize) {
let len = self.0.len();
self.0.truncate(len - n);
}
}
impl Index<usize> for AndStack {
type Output = Frame;
fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}
impl IndexMut<usize> for AndStack {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.index_mut(index)
}
}
impl Index<usize> for Frame {
type Output = Addr;
fn index(&self, index: usize) -> &Self::Output {
self.perms.index(index - 1)
}
}
impl IndexMut<usize> for Frame {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.perms.index_mut(index - 1)
}
}

342
src/prolog/ast.rs Normal file
View File

@@ -0,0 +1,342 @@
use std::cell::Cell;
use std::collections::HashMap;
use std::ops::{Add, AddAssign};
use std::vec::Vec;
pub type Var = String;
pub type Atom = String;
pub enum PredicateClause {
Fact(Term),
Rule(Rule)
}
impl PredicateClause {
pub fn name(&self) -> &Atom {
match self {
&PredicateClause::Fact(ref t) => t.name().unwrap(),
&PredicateClause::Rule(ref rule) => rule.head.0.name().unwrap()
}
}
pub fn arity(&self) -> usize {
match self {
&PredicateClause::Fact(ref t) => t.arity(),
&PredicateClause::Rule(ref rule) => rule.head.0.arity()
}
}
}
pub enum TopLevel {
Fact(Term),
Predicate(Vec<PredicateClause>),
Query(Term),
Rule(Rule)
}
#[derive(Clone, Copy)]
pub enum Level {
Deep, Shallow
}
#[derive(Clone, Copy)]
pub enum RegType {
Perm(usize),
Temp(usize)
}
impl Default for RegType {
fn default() -> Self {
RegType::Temp(0)
}
}
impl RegType {
pub fn reg_num(self) -> usize {
match self {
RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num
}
}
pub fn is_perm(self) -> bool {
match self {
RegType::Perm(_) => true,
_ => false
}
}
}
#[derive(Clone, Copy)]
pub enum VarReg {
ArgAndNorm(RegType, usize),
Norm(RegType)
}
impl VarReg {
pub fn norm(self) -> RegType {
match self {
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
}
}
pub fn root_register(self) -> usize {
match self {
VarReg::ArgAndNorm(_, root) => root,
VarReg::Norm(root) => root.reg_num()
}
}
}
impl Default for VarReg {
fn default() -> Self {
VarReg::Norm(RegType::default())
}
}
#[derive(Clone, PartialEq)]
pub enum Constant {
Atom(Atom),
EmptyList
}
pub enum Term {
AnonVar,
Clause(Cell<RegType>, Atom, Vec<Box<Term>>),
Cons(Cell<RegType>, Box<Term>, Box<Term>),
Constant(Cell<RegType>, Constant),
Var(Cell<VarReg>, Var)
}
pub struct Rule {
pub head: (Term, Term),
pub clauses: Vec<Term>
}
pub enum TermRef<'a> {
AnonVar(Level),
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(Level, &'a Cell<RegType>, &'a Atom, &'a Vec<Box<Term>>),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
pub enum FactInstruction {
GetConstant(Level, Constant, RegType),
GetList(Level, RegType),
GetStructure(Level, Atom, usize, RegType),
GetValue(RegType, usize),
GetVariable(RegType, usize),
UnifyConstant(Constant),
UnifyVariable(RegType),
UnifyValue(RegType)
}
pub enum QueryInstruction {
PutConstant(Level, Constant, RegType),
PutList(Level, RegType),
PutStructure(Level, Atom, usize, RegType),
PutValue(RegType, usize),
PutVariable(RegType, usize),
SetConstant(Constant),
SetVariable(RegType),
SetValue(RegType)
}
pub enum ChoiceInstruction {
RetryMeElse(usize),
TrustMe,
TryMeElse(usize)
}
pub enum ControlInstruction {
Allocate(usize),
Call(Atom, usize),
Deallocate,
Proceed
}
pub type CompiledFact = Vec<FactInstruction>;
pub type CompiledQuery = Vec<QueryInstruction>;
pub enum Line {
Choice(ChoiceInstruction),
Control(ControlInstruction),
Fact(CompiledFact),
Query(CompiledQuery)
}
pub enum LineOrCodeOffset<'a> {
Instruction(&'a Line),
Offset(usize)
}
impl<'a> From<&'a Line> for LineOrCodeOffset<'a> {
fn from(line: &'a Line) -> Self {
LineOrCodeOffset::Instruction(line)
}
}
pub type Code = Vec<Line>;
#[derive(Clone, PartialEq)]
pub enum Addr {
Con(Constant),
Lis(usize),
HeapCell(usize),
StackCell(usize, usize),
Str(usize)
}
impl Addr {
pub fn is_ref(&self) -> bool {
match self {
&Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
_ => false
}
}
pub fn as_ref(&self) -> Option<Ref> {
match self {
&Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)),
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
_ => None
}
}
}
impl From<Ref> for Addr {
fn from(r: Ref) -> Self {
match r {
Ref::HeapCell(hc) => Addr::HeapCell(hc),
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc)
}
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum Ref {
HeapCell(usize),
StackCell(usize, usize)
}
#[derive(Clone, PartialEq)]
pub enum HeapCellValue {
Con(Constant),
Lis(usize),
NamedStr(usize, Atom),
Ref(Ref),
Str(usize)
}
impl From<Addr> for HeapCellValue {
fn from(addr: Addr) -> HeapCellValue {
match addr {
Addr::Con(constant) =>
HeapCellValue::Con(constant),
Addr::HeapCell(hc) =>
HeapCellValue::Ref(Ref::HeapCell(hc)),
Addr::Lis(a) =>
HeapCellValue::Lis(a),
Addr::StackCell(fr, sc) =>
HeapCellValue::Ref(Ref::StackCell(fr, sc)),
Addr::Str(hc) =>
HeapCellValue::Str(hc)
}
}
}
impl HeapCellValue {
pub fn as_addr(&self, focus: usize) -> Addr {
match self {
&HeapCellValue::Con(ref c) => Addr::Con(c.clone()),
&HeapCellValue::Lis(a) => Addr::Lis(a),
&HeapCellValue::Ref(r) => Addr::from(r),
&HeapCellValue::Str(s) => Addr::Str(s),
&HeapCellValue::NamedStr(_, _) => Addr::Str(focus)
}
}
}
#[derive(Clone, Copy)]
pub enum CodePtr {
DirEntry(usize),
TopLevel
}
impl Default for CodePtr {
fn default() -> Self {
CodePtr::TopLevel
}
}
impl Add<usize> for CodePtr {
type Output = CodePtr;
fn add(self, rhs: usize) -> Self::Output {
match self {
CodePtr::DirEntry(p) => CodePtr::DirEntry(p + rhs),
CodePtr::TopLevel => CodePtr::TopLevel
}
}
}
impl AddAssign<usize> for CodePtr {
fn add_assign(&mut self, rhs: usize) {
match self {
&mut CodePtr::DirEntry(ref mut p) => *p += rhs,
_ => {}
}
}
}
pub type Heap = Vec<HeapCellValue>;
pub type Registers = Vec<Addr>;
impl Term {
pub fn subterms(&self) -> usize {
match self {
&Term::Clause(_, _, ref terms) => terms.len(),
_ => 1
}
}
pub fn name(&self) -> Option<&Atom> {
match self {
&Term::Constant(_, Constant::Atom(ref atom))
| &Term::Var(_, ref atom)
| &Term::Clause(_, ref atom, _) => Some(atom),
_ => None
}
}
pub fn arity(&self) -> usize {
match self {
&Term::Clause(_, _, ref child_terms) => child_terms.len(),
_ => 0
}
}
}
pub type HeapVarDict = HashMap<Var, Addr>;
pub enum EvalResult {
EntryFailure,
EntrySuccess,
InitialQuerySuccess(HeapVarDict),
QueryFailure,
SubsequentQuerySuccess,
}
impl EvalResult {
#[allow(dead_code)]
pub fn failed_query(&self) -> bool {
if let &EvalResult::QueryFailure = self {
true
} else {
false
}
}
}

546
src/prolog/codegen.rs Normal file
View File

@@ -0,0 +1,546 @@
use prolog::ast::*;
use prolog::iterators::{FactIterator, QueryIterator};
use std::cell::Cell;
use std::cmp::max;
use std::collections::HashMap;
use std::vec::Vec;
trait CompilationTarget<'a> {
type Iterator : Iterator<Item=TermRef<'a>>;
fn iter(&'a Term) -> Self::Iterator;
fn to_structure(Level, Atom, usize, RegType) -> Self;
fn to_constant(Level, Constant, RegType) -> Self;
fn to_list(Level, RegType) -> Self;
fn constant_subterm(Constant) -> Self;
fn argument_to_variable(RegType, usize) -> Self;
fn argument_to_value(RegType, usize) -> Self;
fn subterm_to_variable(RegType) -> Self;
fn subterm_to_value(RegType) -> Self;
fn clause_arg_to_instr(RegType) -> Self;
}
impl<'a> CompilationTarget<'a> for FactInstruction {
type Iterator = FactIterator<'a>;
fn iter(term: &'a Term) -> Self::Iterator {
term.breadth_first_iter()
}
fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
FactInstruction::GetStructure(lvl, atom, arity, reg)
}
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
FactInstruction::GetConstant(lvl, constant, reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
FactInstruction::GetList(lvl, reg)
}
fn constant_subterm(constant: Constant) -> Self {
FactInstruction::UnifyConstant(constant)
}
fn argument_to_variable(arg: RegType, val: usize) -> Self {
FactInstruction::GetVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self {
FactInstruction::GetValue(arg, val)
}
fn subterm_to_variable(val: RegType) -> Self {
FactInstruction::UnifyVariable(val)
}
fn subterm_to_value(val: RegType) -> Self {
FactInstruction::UnifyValue(val)
}
fn clause_arg_to_instr(val: RegType) -> Self {
FactInstruction::UnifyVariable(val)
}
}
impl<'a> CompilationTarget<'a> for QueryInstruction {
type Iterator = QueryIterator<'a>;
fn iter(term: &'a Term) -> Self::Iterator {
term.post_order_iter()
}
fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
QueryInstruction::PutStructure(lvl, atom, arity, reg)
}
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
QueryInstruction::PutConstant(lvl, constant, reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
QueryInstruction::PutList(lvl, reg)
}
fn constant_subterm(constant: Constant) -> Self {
QueryInstruction::SetConstant(constant)
}
fn argument_to_variable(arg: RegType, val: usize) -> Self {
QueryInstruction::PutVariable(arg, val)
}
fn argument_to_value(arg: RegType, val: usize) -> Self {
QueryInstruction::PutValue(arg, val)
}
fn subterm_to_variable(val: RegType) -> Self {
QueryInstruction::SetVariable(val)
}
fn subterm_to_value(val: RegType) -> Self {
QueryInstruction::SetValue(val)
}
fn clause_arg_to_instr(val: RegType) -> Self {
QueryInstruction::SetValue(val)
}
}
struct TermMarker<'a> {
bindings: HashMap<&'a Var, VarReg>,
arg_c: usize,
perm_c: usize,
temp_c: usize
}
impl<'a> TermMarker<'a> {
fn new() -> TermMarker<'a> {
TermMarker { bindings: HashMap::new(),
arg_c: 1,
perm_c: 1,
temp_c: 1 }
}
fn reset(&mut self) {
self.bindings.clear();
self.perm_c = 1;
}
fn contains_var(&self, var: &'a Var) -> bool {
self.bindings.contains_key(var)
}
fn get(&self, var: &'a Var) -> VarReg {
*self.bindings.get(var).unwrap()
}
fn insert(&mut self, var: &'a Var, r: VarReg) {
self.bindings.insert(var, r);
}
fn mark_non_var(&mut self, lvl: Level, cell: &Cell<RegType>) {
let reg_type = cell.get();
if reg_type.reg_num() == 0 {
match lvl {
Level::Deep if reg_type.is_perm() => {
let perm = self.perm_c;
self.perm_c += 1;
cell.set(RegType::Perm(perm));
},
Level::Deep => {
let temp = self.temp_c;
self.temp_c += 1;
cell.set(RegType::Temp(temp));
},
Level::Shallow if reg_type.is_perm() => {
let arg = self.arg_c;
self.arg_c += 1;
cell.set(RegType::Perm(arg));
},
Level::Shallow => {
let arg = self.arg_c;
self.arg_c += 1;
cell.set(RegType::Temp(arg));
}
};
}
}
fn mark_old_var(&mut self, lvl: Level, var: &'a Var) -> VarReg
{
let reg = self.get(var);
match lvl {
Level::Deep => VarReg::Norm(reg.norm()),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(reg.norm(), self.arg_c);
self.arg_c += 1;
self.insert(var, reg);
reg
}
}
}
fn mark_new_var(&mut self, lvl: Level, var: &'a Var, reg: RegType) -> VarReg
{
let inner_reg = if reg.is_perm() {
let perm = self.perm_c;
self.perm_c += 1;
RegType::Perm(perm)
} else {
let temp = self.temp_c;
self.temp_c += 1;
RegType::Temp(temp)
};
let reg = match lvl {
Level::Deep => VarReg::Norm(inner_reg),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(inner_reg, self.arg_c);
self.arg_c += 1;
reg
}
};
self.insert(var, reg);
reg
}
fn mark_anon_var(&mut self, lvl: Level) -> VarReg {
let inner_reg = {
let temp = self.temp_c;
self.temp_c += 1;
RegType::Temp(temp)
};
match lvl {
Level::Deep => VarReg::Norm(inner_reg),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(inner_reg, self.arg_c);
self.arg_c += 1;
reg
}
}
}
fn advance_at_head(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_c = max(term.subterms(), self.temp_c) + 1;
}
fn advance(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_c = term.subterms() + 1;
}
}
#[derive(Copy, Clone)]
enum TermStatus {
New, Old, Recurrent
}
pub struct CodeGenerator<'a> {
marker: TermMarker<'a>
}
type VariableFixture<'a> = (TermStatus, Vec<&'a Cell<VarReg>>);
type VariableFixtures<'a> = HashMap<&'a Var, VariableFixture<'a>>;
impl<'a> CodeGenerator<'a> {
pub fn new() -> Self {
CodeGenerator { marker: TermMarker::new() }
}
pub fn vars(&self) -> &HashMap<&Var, VarReg> {
&self.marker.bindings
}
fn to_structure<Target>(&mut self,
lvl: Level,
cell: &'a Cell<RegType>,
name: &'a Atom,
arity: usize)
-> Target
where Target: CompilationTarget<'a>
{
self.marker.mark_non_var(lvl, cell);
Target::to_structure(lvl, name.clone(), arity, cell.get())
}
fn to_constant<Target>(&mut self,
lvl: Level,
cell: &'a Cell<RegType>,
constant: &'a Constant)
-> Target
where Target: CompilationTarget<'a>
{
self.marker.mark_non_var(lvl, cell);
Target::to_constant(lvl, constant.clone(), cell.get())
}
fn to_list<Target>(&mut self, lvl: Level, cell: &'a Cell<RegType>) -> Target
where Target: CompilationTarget<'a>
{
self.marker.mark_non_var(lvl, cell);
Target::to_list(lvl, cell.get())
}
fn constant_subterm<Target>(&mut self,
cell: &'a Cell<RegType>,
constant: &'a Constant)
-> Target
where Target: CompilationTarget<'a>
{
self.marker.mark_non_var(Level::Deep, cell);
Target::constant_subterm(constant.clone())
}
fn anon_var_term<Target>(&mut self, lvl: Level) -> Target
where Target: CompilationTarget<'a>
{
let reg = self.marker.mark_anon_var(lvl);
match reg {
VarReg::ArgAndNorm(arg, norm) =>
Target::argument_to_variable(arg, norm),
VarReg::Norm(norm) =>
Target::subterm_to_variable(norm)
}
}
fn var_term<Target>(&mut self,
lvl: Level,
cell: &'a Cell<VarReg>,
var: &'a Var)
-> Target
where Target: CompilationTarget<'a>
{
if !self.marker.contains_var(var) {
let reg = self.marker.mark_new_var(lvl, var, cell.get().norm());
cell.set(reg);
match reg {
VarReg::ArgAndNorm(arg, norm) =>
Target::argument_to_variable(arg, norm),
VarReg::Norm(norm) =>
Target::subterm_to_variable(norm)
}
} else {
let reg = self.marker.mark_old_var(lvl, var);
cell.set(reg);
match reg {
VarReg::ArgAndNorm(arg, norm) =>
Target::argument_to_value(arg, norm),
VarReg::Norm(norm) =>
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())
}
fn subterm_to_instr<Target>(&mut self, subterm: &'a Term) -> Target
where Target: CompilationTarget<'a>
{
match subterm {
&Term::AnonVar =>
self.anon_var_term(Level::Deep),
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _) =>
self.non_var_subterm(cell),
&Term::Constant(ref cell, ref constant) =>
self.constant_subterm(cell, constant),
&Term::Var(ref cell, ref var) =>
self.var_term(Level::Deep, cell, var)
}
}
fn compile_target<Target>(&mut self, term: &'a Term) -> Vec<Target>
where Target: CompilationTarget<'a>
{
let iter = Target::iter(term);
let mut target = Vec::new();
for term in iter {
match term {
TermRef::Clause(lvl, cell, atom, terms) => {
target.push(self.to_structure(lvl, cell, atom, terms.len()));
for subterm in terms {
target.push(self.subterm_to_instr(subterm.as_ref()));
}
},
TermRef::Cons(lvl, cell, head, tail) => {
target.push(self.to_list(lvl, cell));
target.push(self.subterm_to_instr(head));
target.push(self.subterm_to_instr(tail));
},
TermRef::Constant(lvl @ Level::Shallow, cell, constant) =>
target.push(self.to_constant(lvl, cell, constant)),
TermRef::AnonVar(lvl @ Level::Shallow) =>
target.push(self.anon_var_term(lvl)),
TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
target.push(self.var_term(lvl, cell, var)),
_ => {}
};
}
target
}
fn mark_vars_in_term<Iter>(iter: Iter, vs: &mut VariableFixtures<'a>)
where Iter : Iterator<Item=TermRef<'a>>
{
for term in iter {
if let TermRef::Var(_, reg_cell, var) = term {
let mut status = vs.entry(var)
.or_insert((TermStatus::New, Vec::new()));
status.1.push(reg_cell);
match status.0 {
TermStatus::Old => status.0 = TermStatus::Recurrent,
_ => {}
};
}
}
for &mut (ref mut term_status, ref mut cb) in vs.values_mut() {
match *term_status {
TermStatus::New => *term_status = TermStatus::Old,
TermStatus::Recurrent => {
for cell_reg in cb.drain(0..) {
cell_reg.set(VarReg::Norm(RegType::Perm(0)));
}
},
_ => {}
}
}
}
fn mark_perm_vars(rule: &'a Rule) -> VariableFixtures {
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let mut vfs = HashMap::new();
let iter = p0.breadth_first_iter().chain(p1.breadth_first_iter());
Self::mark_vars_in_term(iter, &mut vfs);
for term in clauses {
Self::mark_vars_in_term(term.breadth_first_iter(), &mut vfs);
}
vfs
}
fn add_conditional_call(compiled_query: &mut Code, term: &Term) {
match term {
&Term::Constant(_, Constant::Atom(ref atom)) => {
let call = ControlInstruction::Call(atom.clone(), 0);
compiled_query.push(Line::Control(call));
},
&Term::Clause(_, ref atom, ref terms) => {
let call = ControlInstruction::Call(atom.clone(), terms.len());
compiled_query.push(Line::Control(call));
},
_ => {}
}
}
pub fn compile_rule(&mut self, rule: &'a Rule) -> Code {
let vfs = Self::mark_perm_vars(&rule);
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let mut perm_vars = 0;
for &(term_status, _) in vfs.values() {
if let TermStatus::Recurrent = term_status {
perm_vars += 1;
}
}
let mut body = Vec::new();
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
self.marker.advance(p0);
body.push(Line::Fact(self.compile_target(p0)));
self.marker.advance_at_head(p1);
body.push(Line::Query(self.compile_target(p1)));
Self::add_conditional_call(&mut body, p1);
body = clauses.iter()
.map(|ref term| self.compile_query(term))
.fold(body, |mut body, ref mut cqs| {
body.append(cqs);
body
});
body.push(Line::Control(ControlInstruction::Deallocate));
body
}
pub fn compile_fact(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);
let mut compiled_fact = vec![Line::Fact(self.compile_target(term))];
let proceed = Line::Control(ControlInstruction::Proceed);
compiled_fact.push(proceed);
compiled_fact
}
pub fn compile_query(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);
let mut compiled_query = vec![Line::Query(self.compile_target(term))];
Self::add_conditional_call(&mut compiled_query, term);
compiled_query
}
pub fn compile_predicate(&mut self, clauses: &'a Vec<PredicateClause>) -> Code
{
let mut code = Vec::new();
for (i, clause) in clauses.iter().enumerate() {
self.marker.reset();
let mut clause_code = match clause {
&PredicateClause::Fact(ref fact) =>
self.compile_fact(fact),
&PredicateClause::Rule(ref rule) =>
self.compile_rule(rule)
};
let choice = match i {
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
_ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
_ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
};
code.push(Line::Choice(choice));
code.append(&mut clause_code);
}
code
}
}

184
src/prolog/heapview.rs Normal file
View File

@@ -0,0 +1,184 @@
use prolog::and_stack::*;
use prolog::ast::*;
use std::vec::Vec;
#[derive(Clone, Copy)]
pub enum TToken {
Bar,
Comma,
LRBracket,
LSBracket(usize),
Nothing,
RRBracket,
RSBracket
}
impl TToken {
pub fn as_str(self) -> &'static str {
match self {
TToken::Bar => " | ",
TToken::Comma => ", ",
TToken::LRBracket => "(",
TToken::LSBracket(_) => "[",
TToken::Nothing => "",
TToken::RRBracket => ")",
TToken::RSBracket => "]"
}
}
}
#[derive(Clone, Copy)]
enum CellRef<'a> {
View(CellView<'a>),
Redirect(usize),
TToken(TToken)
}
#[derive(Clone, Copy)]
pub enum CellView<'a> {
Con(&'a Constant),
HeapVar(usize),
StackVar(usize, usize),
Str(usize, &'a Atom),
TToken(TToken),
}
pub struct HeapCellViewer<'a> {
and_stack: &'a AndStack,
heap: &'a Heap,
state_stack: Vec<CellRef<'a>>
}
impl<'a> HeapCellViewer<'a> {
fn cell_ref_from_addr(&self, mut focus: &'a Addr) -> CellRef<'a> {
loop {
match focus {
&Addr::Con(ref c) =>
return CellRef::View(CellView::Con(c)),
&Addr::Lis(hc) | &Addr::HeapCell(hc) | &Addr::Str(hc) =>
return CellRef::Redirect(hc),
&Addr::StackCell(fr, sc) => {
match &self.and_stack[fr][sc] {
&Addr::StackCell(fr1, sc1) => {
if fr1 == fr && sc1 == sc {
return CellRef::View(CellView::StackVar(fr, sc));
}
},
_ => focus = &self.and_stack[fr][sc]
}
}
}
}
}
pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self
{
let mut viewer = HeapCellViewer {
heap: heap,
and_stack: and_stack,
state_stack: vec![]
};
let cell_ref = viewer.cell_ref_from_addr(addr);
let view = viewer.follow(cell_ref);
viewer.state_stack.push(CellRef::View(view));
viewer
}
pub fn remove_token(&mut self, loc: usize) {
self.state_stack[loc] = CellRef::TToken(TToken::Nothing);
}
pub fn peek(&mut self) -> Option<CellView<'a>> {
let len = self.state_stack.len();
if len > 0 {
let last_elt = self.state_stack.pop().unwrap();
let cell_view = self.follow(last_elt);
self.state_stack.truncate(len - 1);
self.state_stack.push(last_elt);
Some(cell_view)
} else {
None
}
}
fn from_heap(&mut self, mut focus: usize) -> CellView<'a> {
loop {
match &self.heap[focus] {
&HeapCellValue::Con(ref c) =>
return CellView::Con(c),
&HeapCellValue::Lis(a) => {
self.state_stack.push(CellRef::TToken(TToken::RSBracket));
self.state_stack.push(CellRef::Redirect(a + 1));
self.state_stack.push(CellRef::TToken(TToken::Bar));
self.state_stack.push(CellRef::Redirect(a));
let len = self.state_stack.len() - 4;
return CellView::TToken(TToken::LSBracket(len));
},
&HeapCellValue::NamedStr(arity, ref name) => {
self.state_stack.push(CellRef::TToken(TToken::RRBracket));
for i in (2 .. arity + 1).rev() {
self.state_stack.push(CellRef::Redirect(focus + i));
self.state_stack.push(CellRef::TToken(TToken::Comma));
}
self.state_stack.push(CellRef::Redirect(focus + 1));
self.state_stack.push(CellRef::TToken(TToken::LRBracket));
return CellView::Str(arity, name);
},
&HeapCellValue::Ref(Ref::HeapCell(hc)) => {
if focus == hc {
return CellView::HeapVar(hc);
} else {
focus = hc;
}
},
&HeapCellValue::Ref(Ref::StackCell(fr, sc)) => {
match self.cell_ref_from_addr(&self.and_stack[fr][sc]) {
CellRef::View(cell_view) => return cell_view,
CellRef::Redirect(hc) => focus = hc,
CellRef::TToken(token) => return CellView::TToken(token)
};
},
&HeapCellValue::Str(cell_num) =>
focus = cell_num,
}
}
}
fn follow(&mut self, cell_ref: CellRef<'a>) -> CellView<'a>
{
match cell_ref {
CellRef::Redirect(hc) =>
self.from_heap(hc),
CellRef::View(cell_view) =>
cell_view,
CellRef::TToken(term_token) =>
CellView::TToken(term_token)
}
}
}
impl<'a> Iterator for HeapCellViewer<'a> {
type Item = CellView<'a>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(cell_ref) = self.state_stack.pop() {
Some(self.follow(cell_ref))
} else {
None
}
}
}

290
src/prolog/io.rs Normal file
View File

@@ -0,0 +1,290 @@
use prolog::ast::*;
use prolog::codegen::*;
use prolog::prolog_parser::*;
use prolog::machine::*;
use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;
use std::io::{Write, stdin, stdout};
use std::fmt;
impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Constant::Atom(ref atom) =>
write!(f, "{}", atom),
&Constant::EmptyList =>
write!(f, "[]")
}
}
}
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
write!(f, "get_constant {}, A{}", constant, r.reg_num()),
&FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
write!(f, "get_constant {}, {}", constant, r),
&FactInstruction::GetList(Level::Shallow, ref r) =>
write!(f, "get_list A{}", r.reg_num()),
&FactInstruction::GetList(Level::Deep, ref r) =>
write!(f, "get_list {}", r),
&FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
write!(f, "get_structure {}/{}, {}", name, arity, r),
&FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
&FactInstruction::GetValue(ref x, ref a) =>
write!(f, "get_value {}, A{}", x, a),
&FactInstruction::GetVariable(ref x, ref a) =>
write!(f, "get_variable {}, A{}", x, a),
&FactInstruction::UnifyConstant(ref constant) =>
write!(f, "unify_constant {}", constant),
&FactInstruction::UnifyVariable(ref r) =>
write!(f, "unify_variable {}", r),
&FactInstruction::UnifyValue(ref r) =>
write!(f, "unify_value {}", r)
}
}
}
impl fmt::Display for QueryInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
write!(f, "put_constant {}, A{}", constant, r.reg_num()),
&QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
write!(f, "put_constant {}, {}", constant, r),
&QueryInstruction::PutList(Level::Shallow, ref r) =>
write!(f, "put_list A{}", r.reg_num()),
&QueryInstruction::PutList(Level::Deep, ref r) =>
write!(f, "put_list {}", r),
&QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
write!(f, "put_structure {}/{}, {}", name, arity, r),
&QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
&QueryInstruction::PutValue(ref x, ref a) =>
write!(f, "put_value {}, A{}", x, a),
&QueryInstruction::PutVariable(ref x, ref a) =>
write!(f, "put_variable {}, A{}", x, a),
&QueryInstruction::SetConstant(ref constant) =>
write!(f, "set_constant {}", constant),
&QueryInstruction::SetVariable(ref r) =>
write!(f, "set_variable {}", r),
&QueryInstruction::SetValue(ref r) =>
write!(f, "set_value {}", r)
}
}
}
impl fmt::Display for ControlInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ControlInstruction::Allocate(num_cells) =>
write!(f, "allocate {}", num_cells),
&ControlInstruction::Call(ref name, ref arity) =>
write!(f, "call {}/{}", name, arity),
&ControlInstruction::Deallocate =>
write!(f, "deallocate"),
&ControlInstruction::Proceed =>
write!(f, "proceed")
}
}
}
impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ChoiceInstruction::TryMeElse(offset) =>
write!(f, "try_me_else {}", offset),
&ChoiceInstruction::RetryMeElse(offset) =>
write!(f, "retry_me_else {}", offset),
&ChoiceInstruction::TrustMe =>
write!(f, "trust_me")
}
}
}
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Level::Shallow => write!(f, "A"),
&Level::Deep => write!(f, "X")
}
}
}
impl fmt::Display for VarReg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
&VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
&VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
write!(f, "Y{} A{}", reg, arg),
&VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
write!(f, "X{} A{}", reg, arg)
}
}
}
impl fmt::Display for RegType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&RegType::Perm(val) => write!(f, "Y{}", val),
&RegType::Temp(val) => write!(f, "X{}", val)
}
}
}
fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
let name = predicate.first().unwrap().name();
let arity = predicate.first().unwrap().arity();
for clause in predicate.iter().skip(1) {
if !(name == clause.name() && arity == clause.arity()) {
return false;
}
}
true
}
#[allow(dead_code)]
pub fn print_code(code: &Code) {
for clause in code {
match clause {
&Line::Fact(ref fact) =>
for fact_instr in fact {
println!("{}", fact_instr);
},
&Line::Choice(ref choice) =>
println!("{}", choice),
&Line::Control(ref control) =>
println!("{}", control),
&Line::Query(ref query) =>
for query_instr in query {
println!("{}", query_instr);
}
}
}
}
pub fn read() -> String {
let _ = stdout().flush();
let mut buffer = String::new();
let mut result = String::new();
let stdin = stdin();
stdin.read_line(&mut buffer).unwrap();
if &*buffer.trim() == ":{" {
buffer.clear();
stdin.read_line(&mut buffer).unwrap();
while &*buffer.trim() != "}:" {
result += buffer.as_str();
buffer.clear();
stdin.read_line(&mut buffer).unwrap();
}
} else {
result = buffer;
}
result
}
pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
{
let result = parse_TopLevel(buffer);
let mut cg = CodeGenerator::new();
match &result {
&Ok(TopLevel::Predicate(ref clauses)) => {
if is_consistent(clauses) {
let compiled_pred = cg.compile_predicate(clauses);
wam.add_predicate(clauses, compiled_pred);
EvalResult::EntrySuccess
} else {
let msg = r"Error: predicate is inconsistent.
Each predicate must have the same name and arity.";
println!("{}", msg);
EvalResult::EntryFailure
}
},
&Ok(TopLevel::Fact(ref fact)) => {
let compiled_fact = cg.compile_fact(&fact);
wam.add_fact(fact, compiled_fact);
EvalResult::EntrySuccess
},
&Ok(TopLevel::Rule(ref rule)) => {
let compiled_rule = cg.compile_rule(&rule);
wam.add_rule(rule, compiled_rule);
EvalResult::EntrySuccess
},
&Ok(TopLevel::Query(ref query)) => {
let compiled_query = cg.compile_query(&query);
wam.run_query(compiled_query, &cg)
},
&Err(_) => {
println!("Grammatical error of some kind!");
EvalResult::EntryFailure
}
}
}
pub fn print(wam: &mut Machine, result: EvalResult) {
match result {
EvalResult::InitialQuerySuccess(heap_locs) => {
println!("yes");
if heap_locs.is_empty() {
return;
}
'outer: loop {
let mut result = EvalResult::QueryFailure;
let bindings = wam.heap_view(&heap_locs);
let stdin = stdin();
let mut stdout = stdout().into_raw_mode().unwrap();
write!(stdout, "{}\n\r", bindings).unwrap();
stdout.flush().unwrap();
if !wam.or_stack_is_empty() {
write!(stdout, "Press ; to continue or . to abort.\n\r").unwrap();
stdout.flush().unwrap();
for c in stdin.keys() {
match c.unwrap() {
Key::Char(';') => {
result = wam.continue_query();
break;
},
Key::Char('.') =>
break 'outer,
_ => {}
}
};
if let &EvalResult::QueryFailure = &result {
write!(stdout, "no\n\r").unwrap();
stdout.flush().unwrap();
break;
}
} else {
break;
}
}
},
EvalResult::QueryFailure => println!("no"),
_ => {}
};
}

209
src/prolog/iterators.rs Normal file
View File

@@ -0,0 +1,209 @@
use prolog::ast::*;
use std::cell::Cell;
use std::collections::VecDeque;
use std::vec::Vec;
enum IteratorState<'a> {
AnonVar(Level),
Clause(Level, usize, &'a Cell<RegType>, &'a Atom, &'a Vec<Box<Term>>),
Constant(Level, &'a Cell<RegType>, &'a Constant),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
RootClause(usize, &'a Vec<Box<Term>>),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
impl<'a> IteratorState<'a> {
fn to_state(lvl: Level, term: &'a Term) -> IteratorState<'a> {
match term {
&Term::AnonVar =>
IteratorState::AnonVar(lvl),
&Term::Clause(ref cell, ref atom, ref child_terms) =>
IteratorState::Clause(lvl, 0, cell, atom, child_terms),
&Term::Cons(ref cell, ref head, ref tail) =>
IteratorState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()),
&Term::Constant(ref cell, ref constant) =>
IteratorState::Constant(lvl, cell, constant),
&Term::Var(ref cell, ref var) =>
IteratorState::Var(lvl, cell, var)
}
}
}
pub struct QueryIterator<'a> {
state_stack: Vec<IteratorState<'a>>
}
impl<'a> QueryIterator<'a> {
fn push_clause(&mut self,
lvl: Level,
child_num: usize,
cell: &'a Cell<RegType>,
name: &'a Atom,
child_terms: &'a Vec<Box<Term>>)
{
self.state_stack.push(IteratorState::Clause(lvl,
child_num,
cell,
name,
child_terms));
}
fn push_root_clause(&mut self,
child_num: usize,
child_terms: &'a Vec<Box<Term>>)
{
self.state_stack.push(IteratorState::RootClause(child_num, child_terms));
}
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(IteratorState::to_state(lvl, term));
}
fn push_final_cons(&mut self,
lvl: Level,
cell: &'a Cell<RegType>,
head: &'a Term,
tail: &'a Term)
{
self.state_stack.push(IteratorState::FinalCons(lvl, cell, head, tail));
}
fn new(term: &'a Term) -> QueryIterator<'a> {
let state = match term {
&Term::AnonVar =>
IteratorState::AnonVar(Level::Shallow),
&Term::Clause(_, _, ref terms) =>
IteratorState::RootClause(0, terms),
&Term::Cons(ref cell, ref head, ref tail) =>
IteratorState::InitialCons(Level::Shallow, cell, head.as_ref(), tail.as_ref()),
&Term::Constant(ref cell, ref constant) =>
IteratorState::Constant(Level::Shallow, cell, constant),
&Term::Var(ref cell, ref var) =>
IteratorState::Var(Level::Shallow, cell, var)
};
QueryIterator { state_stack: vec![state] }
}
}
impl<'a> Iterator for QueryIterator<'a> {
type Item = TermRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() {
match iter_state {
IteratorState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
IteratorState::Clause(lvl, child_num, cell, atom, child_terms) => {
if child_num == child_terms.len() {
return Some(TermRef::Clause(lvl, cell, atom, child_terms));
} else {
self.push_clause(lvl, child_num + 1, cell, atom, child_terms);
self.push_subterm(Level::Deep, child_terms[child_num].as_ref());
}
},
IteratorState::InitialCons(lvl, cell, head, tail) => {
self.push_final_cons(lvl, cell, head, tail);
self.push_subterm(Level::Deep, head);
self.push_subterm(Level::Deep, tail);
},
IteratorState::FinalCons(lvl, cell, head, tail) =>
return Some(TermRef::Cons(lvl, cell, head, tail)),
IteratorState::Constant(lvl, cell, constant) =>
return Some(TermRef::Constant(lvl, cell, constant)),
IteratorState::RootClause(child_num, child_terms) => {
if child_num == child_terms.len() {
return None;
} else {
self.push_root_clause(child_num + 1, child_terms);
self.push_subterm(Level::Shallow, child_terms[child_num].as_ref());
}
},
IteratorState::Var(lvl, cell, var) =>
return Some(TermRef::Var(lvl, cell, var))
};
}
None
}
}
pub struct FactIterator<'a> {
state_queue: VecDeque<IteratorState<'a>>,
}
impl<'a> FactIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_queue.push_back(IteratorState::to_state(lvl, term));
}
fn new(term: &'a Term) -> FactIterator<'a> {
let states = match term {
&Term::AnonVar =>
vec![IteratorState::AnonVar(Level::Shallow)],
&Term::Clause(_, _, ref terms) =>
vec![IteratorState::RootClause(0, terms)],
&Term::Cons(ref cell, ref head, ref tail) =>
vec![IteratorState::InitialCons(Level::Shallow,
cell,
head.as_ref(),
tail.as_ref())],
&Term::Constant(ref cell, ref constant) =>
vec![IteratorState::Constant(Level::Shallow, cell, constant)],
&Term::Var(ref cell, ref var) =>
vec![IteratorState::Var(Level::Shallow, cell, var)]
};
FactIterator { state_queue: VecDeque::from(states) }
}
}
impl<'a> Iterator for FactIterator<'a> {
type Item = TermRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(state) = self.state_queue.pop_front() {
match state {
IteratorState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
IteratorState::Clause(lvl, _, cell, atom, child_terms) => {
for child_term in child_terms {
self.push_subterm(Level::Deep, child_term);
}
return Some(TermRef::Clause(lvl, cell, atom, child_terms));
},
IteratorState::InitialCons(lvl, cell, head, tail) => {
self.push_subterm(Level::Deep, head);
self.push_subterm(Level::Deep, tail);
return Some(TermRef::Cons(lvl, cell, head, tail));
},
IteratorState::Constant(lvl, cell, constant) =>
return Some(TermRef::Constant(lvl, cell, constant)),
IteratorState::RootClause(_, child_terms) => {
for child_term in child_terms {
self.push_subterm(Level::Shallow, child_term);
}
},
IteratorState::Var(lvl, cell, var) =>
return Some(TermRef::Var(lvl, cell, var)),
_ => {}
}
}
None
}
}
impl Term {
pub fn post_order_iter(&self) -> QueryIterator {
QueryIterator::new(self)
}
pub fn breadth_first_iter(&self) -> FactIterator {
FactIterator::new(self)
}
}

784
src/prolog/machine.rs Normal file
View File

@@ -0,0 +1,784 @@
use prolog::ast::*;
use prolog::codegen::*;
use prolog::heapview::*;
use prolog::and_stack::*;
use prolog::or_stack::*;
use std::collections::HashMap;
use std::ops::{Index, IndexMut};
use std::vec::Vec;
#[derive(Clone, Copy)]
enum MachineMode {
Read,
Write
}
struct MachineState {
h: usize,
s: usize,
p: CodePtr,
b: usize,
e: usize,
num_of_args: usize,
cp: CodePtr,
fail: bool,
heap: Heap,
mode: MachineMode,
and_stack: AndStack,
or_stack: OrStack,
registers: Registers,
trail: Vec<Ref>,
tr: usize,
hb: usize
}
type CodeDir = HashMap<(Atom, usize), usize>;
pub struct Machine {
ms: MachineState,
code: Code,
code_dir: CodeDir
}
impl Index<RegType> for MachineState {
type Output = Addr;
fn index(&self, reg: RegType) -> &Self::Output {
match reg {
RegType::Temp(temp) => &self.registers[temp],
RegType::Perm(perm) => {
let e = self.e;
&self.and_stack[e][perm]
}
}
}
}
impl IndexMut<RegType> for MachineState {
fn index_mut(&mut self, reg: RegType) -> &mut Self::Output {
match reg {
RegType::Temp(temp) => &mut self.registers[temp],
RegType::Perm(perm) => {
let e = self.e;
&mut self.and_stack[e][perm]
}
}
}
}
impl Machine {
pub fn new() -> Self {
Machine {
ms: MachineState::new(),
code: Vec::new(),
code_dir: HashMap::new()
}
}
pub fn failed(&self) -> bool {
self.ms.fail
}
pub fn add_fact(&mut self, fact: &Term, mut code: Code) {
if fact.name().is_some() {
let p = self.code.len();
let name = fact.name().unwrap().clone();
let arity = fact.arity();
self.code.append(&mut code);
self.code_dir.insert((name, arity), p);
}
}
pub fn add_rule(&mut self, rule: &Rule, mut code: Code) {
if rule.head.0.name().is_some() {
let p = self.code.len();
let name = rule.head.0.name().unwrap().clone();
let arity = rule.head.0.arity();
self.code.append(&mut code);
self.code_dir.insert((name, arity), p);
}
}
pub fn add_predicate(&mut self, pred: &Vec<PredicateClause>, mut code: Code)
{
let p = self.code.len();
let name = pred.first().unwrap().name().clone();
let arity = pred.first().unwrap().arity();
self.code.append(&mut code);
self.code_dir.insert((name, arity), p);
}
fn execute_instr<'a>(&mut self, instr_src: LineOrCodeOffset<'a>) -> bool
{
let mut instr = match instr_src {
LineOrCodeOffset::Instruction(instr) => instr,
LineOrCodeOffset::Offset(p) => &self.code[p]
};
loop {
match instr {
&Line::Choice(ref choice_instr) =>
self.ms.execute_choice_instr(choice_instr),
&Line::Fact(ref fact) => {
for fact_instr in fact {
if self.failed() {
break;
}
self.ms.execute_fact_instr(&fact_instr);
}
self.ms.p += 1;
},
&Line::Query(ref query) => {
for query_instr in query {
if self.failed() {
break;
}
self.ms.execute_query_instr(&query_instr);
}
self.ms.p += 1;
},
&Line::Control(ref control_instr) =>
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
}
if self.failed() {
let p = self.ms
.or_stack
.top()
.map(|fr| fr.bp)
.unwrap_or_default();
if let CodePtr::TopLevel = p {
return false;
} else {
self.ms.fail = false;
self.ms.p = p;
}
}
match self.ms.p {
CodePtr::DirEntry(p) if p < self.code.len() =>
instr = &self.code[p],
_ => break
}
}
true
}
pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
let mut result = String::new();
for (var, addr) in var_dir {
let mut viewer = HeapCellViewer::new(&self.ms.heap,
&self.ms.and_stack,
addr);
if result != "" {
result += "\n\r";
}
result += var.as_str();
result += " = ";
while let Some(view) = viewer.next() {
match view {
CellView::Con(&Constant::EmptyList) =>
result += "[]",
CellView::Con(&Constant::Atom(ref atom)) =>
result += atom.as_str(),
CellView::HeapVar(cell_num) => {
result += "_";
result += cell_num.to_string().as_str();
},
CellView::StackVar(fr, sc) => {
result += "_";
result += fr.to_string().as_str();
result += "_";
result += sc.to_string().as_str();
},
CellView::Str(_, ref name) =>
result += name.as_str(),
CellView::TToken(TToken::Bar) => {
match viewer.peek() {
Some(CellView::Con(&Constant::EmptyList)) => {
viewer.next();
},
Some(CellView::TToken(TToken::LSBracket(loc))) => {
result += ", ";
viewer.next();
viewer.remove_token(loc);
},
_ => result += " | "
};
},
CellView::TToken(token) =>
result += token.as_str()
};
}
}
result
}
pub fn run_query(&mut self, code: Code, cg: &CodeGenerator) -> EvalResult
{
let mut succeeded = true;
let mut heap_locs = HashMap::new();
for instr in code.iter().take(1) {
succeeded = self.execute_instr(LineOrCodeOffset::from(instr));
}
if succeeded {
for (var, vr) in cg.vars() {
let addr = self.ms.registers[vr.root_register()].clone();
heap_locs.insert((*var).clone(), addr);
}
for instr in code.iter().skip(1) {
succeeded = self.execute_instr(LineOrCodeOffset::from(instr));
if !succeeded {
break;
}
}
}
if succeeded {
EvalResult::InitialQuerySuccess(heap_locs)
} else {
EvalResult::QueryFailure
}
}
pub fn or_stack_is_empty(&self) -> bool {
self.ms.or_stack.is_empty()
}
pub fn continue_query(&mut self) -> EvalResult
{
if !self.or_stack_is_empty() {
let b = self.ms.b;
self.ms.p = self.ms.or_stack[b].bp;
let succeeded = if let CodePtr::DirEntry(p) = self.ms.p {
self.execute_instr(LineOrCodeOffset::Offset(p))
} else {
false
};
if succeeded {
EvalResult::SubsequentQuerySuccess
} else {
EvalResult::QueryFailure
}
} else {
EvalResult::QueryFailure
}
}
pub fn reset(&mut self) {
self.ms.reset();
}
}
impl MachineState {
fn new() -> MachineState {
MachineState { h: 0,
s: 0,
p: CodePtr::TopLevel,
b: 0,
e: 0,
num_of_args: 0,
cp: CodePtr::TopLevel,
fail: false,
heap: Vec::with_capacity(256),
mode: MachineMode::Write,
and_stack: AndStack::new(),
or_stack: OrStack::new(),
registers: vec![Addr::HeapCell(0); 64],
trail: Vec::new(),
tr: 0,
hb: 0
}
}
fn num_frames(&self) -> usize {
self.and_stack.len() + self.or_stack.len()
}
fn store(&self, a: Addr) -> Addr {
match a {
Addr::HeapCell(r) => self.heap[r].as_addr(r),
Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),
addr => addr
}
}
fn deref(&self, a: Addr) -> Addr {
let mut a = a;
loop {
let value = self.store(a.clone());
if value.is_ref() && value != a {
a = value;
continue;
}
return a;
};
}
fn bind(&mut self, r1: Ref, a2: Addr) {
let t2 = self.store(a2);
match r1 {
Ref::StackCell(fr, sc) =>
self.and_stack[fr][sc] = t2,
Ref::HeapCell(hc) =>
self.heap[hc] = HeapCellValue::from(t2)
};
self.trail(r1);
}
fn unify(&mut self, a1: Addr, a2: Addr) {
let mut pdl = vec![a1, a2];
self.fail = false;
while !(pdl.is_empty() || self.fail) {
let d1 = self.deref(pdl.pop().unwrap());
let d2 = self.deref(pdl.pop().unwrap());
if d1 != d2 {
match (self.store(d1.clone()), self.store(d2.clone())) {
(Addr::HeapCell(hc), _) =>
self.bind(Ref::HeapCell(hc), d2),
(_, Addr::HeapCell(hc)) =>
self.bind(Ref::HeapCell(hc), d1),
(Addr::StackCell(fr, sc), _) =>
self.bind(Ref::StackCell(fr, sc), d2),
(_, Addr::StackCell(fr, sc)) =>
self.bind(Ref::StackCell(fr, sc), d1),
(Addr::Lis(a1), Addr::Lis(a2)) => {
pdl.push(Addr::HeapCell(a1));
pdl.push(Addr::HeapCell(a2));
pdl.push(Addr::HeapCell(a1 + 1));
pdl.push(Addr::HeapCell(a2 + 1));
},
(Addr::Con(c1), Addr::Con(c2)) => {
if c1 != c2 {
self.fail = true;
}
},
(Addr::Str(a1), Addr::Str(a2)) => {
let r1 = &self.heap[a1];
let r2 = &self.heap[a2];
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 + 1 {
pdl.push(Addr::HeapCell(a1 + i));
pdl.push(Addr::HeapCell(a2 + i));
}
continue;
}
}
}
self.fail = true;
},
_ => self.fail = true
};
}
}
}
fn trail(&mut self, r: Ref) {
match r {
Ref::HeapCell(hc) => {
if hc < self.hb {
self.trail.push(r);
self.tr += 1;
}
},
Ref::StackCell(fr, _) => {
let fr_gi = self.and_stack[fr].global_index;
let b_gi = if !self.or_stack.is_empty() {
self.or_stack[self.b].global_index
} else {
0
};
if fr_gi < b_gi {
self.trail.push(r);
self.tr += 1;
}
}
}
}
fn unwind_trail(&mut self, a1: usize, a2: usize) {
for i in a1 .. a2 {
match self.trail[i] {
Ref::HeapCell(r) =>
self.heap[r] = HeapCellValue::Ref(Ref::HeapCell(r)),
Ref::StackCell(fr, sc) =>
self.and_stack[fr][sc] = Addr::StackCell(fr, sc)
}
}
}
fn execute_fact_instr(&mut self, instr: &FactInstruction) {
match instr {
&FactInstruction::GetConstant(_, ref constant, reg) => {
let addr = self.deref(self[reg].clone());
match self.store(addr) {
Addr::HeapCell(hc) => {
self.heap[hc] = HeapCellValue::Con(constant.clone());
self.trail(Ref::HeapCell(hc));
},
Addr::StackCell(fr, sc) => {
self.and_stack[fr][sc] = Addr::Con(constant.clone());
self.trail(Ref::StackCell(fr, sc));
},
Addr::Con(c) => {
if c != *constant {
self.fail = true;
}
},
_ => self.fail = true
};
},
&FactInstruction::GetList(_, reg) => {
let addr = self.deref(self[reg].clone());
match self.store(addr.clone()) {
Addr::HeapCell(hc) => {
let h = self.h;
self.heap.push(HeapCellValue::Lis(h+1));
self.bind(Ref::HeapCell(hc), Addr::HeapCell(h));
self.h += 1;
self.mode = MachineMode::Write;
},
Addr::StackCell(fr, sc) => {
let h = self.h;
self.heap.push(HeapCellValue::Lis(h+1));
self.bind(Ref::StackCell(fr, sc), Addr::HeapCell(h));
self.h += 1;
self.mode = MachineMode::Write;
},
Addr::Lis(a) => {
self.s = a;
self.mode = MachineMode::Read;
},
_ => self.fail = true
};
},
&FactInstruction::GetStructure(_, ref name, arity, reg) => {
let addr = self.deref(self[reg].clone());
match self.store(addr.clone()) {
Addr::Str(a) => {
let result = &self.heap[a];
if let &HeapCellValue::NamedStr(narity, ref str) = result {
if narity == arity && *name == *str {
self.s = a + 1;
self.mode = MachineMode::Read;
} else {
self.fail = true;
}
}
},
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
self.heap.push(HeapCellValue::Str(self.h + 1));
self.heap.push(HeapCellValue::NamedStr(arity, name.clone()));
let h = self.h;
self.bind(addr.as_ref().unwrap(), Addr::HeapCell(h));
self.h += 2;
self.mode = MachineMode::Write;
},
_ => self.fail = true
};
},
&FactInstruction::GetVariable(norm, arg) =>
self[norm] = self.registers[arg].clone(),
&FactInstruction::GetValue(norm, arg) => {
let norm_addr = self[norm].clone();
let reg_addr = self.registers[arg].clone();
self.unify(norm_addr, reg_addr);
},
&FactInstruction::UnifyConstant(ref c) => {
match self.mode {
MachineMode::Read => {
let addr = self.deref(Addr::HeapCell(self.s));
match self.store(addr) {
Addr::HeapCell(hc) =>
self.heap[hc] = HeapCellValue::Con(c.clone()),
Addr::StackCell(fr, sc) =>
self.and_stack[fr][sc] = Addr::Con(c.clone()),
Addr::Con(c1) => {
if c1 != *c {
self.fail = true;
}
},
_ => self.fail = true
};
},
MachineMode::Write => {
self.heap.push(HeapCellValue::Con(c.clone()));
self.h += 1;
}
};
},
&FactInstruction::UnifyVariable(reg) => {
match self.mode {
MachineMode::Read =>
self[reg] = self.heap[self.s].as_addr(self.s),
MachineMode::Write => {
let h = self.h;
self.heap.push(HeapCellValue::Ref(Ref::HeapCell(h)));
self[reg] = Addr::HeapCell(self.h);
self.h += 1;
}
};
self.s += 1;
},
&FactInstruction::UnifyValue(reg) => {
let s = self.s;
match self.mode {
MachineMode::Read => {
let reg_addr = self[reg].clone();
self.unify(reg_addr, Addr::HeapCell(s));
},
MachineMode::Write => {
let heap_val = self.store(self[reg].clone());
self.heap.push(HeapCellValue::from(heap_val));
self.h += 1;
}
};
self.s += 1;
}
};
}
fn execute_query_instr(&mut self, instr: &QueryInstruction) {
match instr {
&QueryInstruction::PutConstant(_, ref constant, reg) =>
self[reg] = Addr::Con(constant.clone()),
&QueryInstruction::PutList(_, reg) =>
self[reg] = Addr::Lis(self.h),
&QueryInstruction::PutStructure(_, ref name, arity, reg) => {
self.heap.push(HeapCellValue::NamedStr(arity, name.clone()));
self[reg] = Addr::Str(self.h);
self.h += 1;
},
&QueryInstruction::PutValue(norm, arg) =>
self.registers[arg] = self[norm].clone(),
&QueryInstruction::PutVariable(norm, arg) => {
let h = self.h;
self.heap.push(HeapCellValue::Ref(Ref::HeapCell(h)));
self[norm] = Addr::HeapCell(h);
self.registers[arg] = Addr::HeapCell(h);
self.h += 1;
},
&QueryInstruction::SetConstant(ref constant) => {
self.heap.push(HeapCellValue::Con(constant.clone()));
self.h += 1;
},
&QueryInstruction::SetVariable(reg) => {
let h = self.h;
self.heap.push(HeapCellValue::Ref(Ref::HeapCell(h)));
self[reg] = Addr::HeapCell(h);
self.h += 1;
},
&QueryInstruction::SetValue(reg) => {
let heap_val = self[reg].clone();
self.heap.push(HeapCellValue::from(heap_val));
self.h += 1;
},
}
}
fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
{
match instr {
&ControlInstruction::Allocate(num_cells) => {
let num_frames = self.num_frames();
self.and_stack.push(num_frames + 1, self.e, self.cp, num_cells);
self.e = self.and_stack.len() - 1;
self.p += 1;
},
&ControlInstruction::Call(ref name, arity) => {
let compiled_tl_index = code_dir.get(&(name.clone(), arity))
.map(|index| *index);
match compiled_tl_index {
Some(compiled_tl_index) => {
self.cp = self.p + 1;
self.num_of_args = arity;
self.p = CodePtr::DirEntry(compiled_tl_index);
},
None => self.fail = true
};
},
&ControlInstruction::Deallocate => {
let e = self.e;
let num_frame_e = self.and_stack.top().unwrap().global_index;
let num_frame_b = self.or_stack
.top()
.map(|fr| fr.global_index)
.unwrap_or(0);
self.p = self.and_stack[e].cp;
self.e = self.and_stack[e].e;
if num_frame_e > num_frame_b {
let top_e = self.and_stack.top().unwrap().e;
self.and_stack.drop_frames(top_e - self.e + 1);
}
},
&ControlInstruction::Proceed =>
self.p = self.cp,
};
}
fn execute_choice_instr(&mut self, instr: &ChoiceInstruction)
{
match instr {
&ChoiceInstruction::TryMeElse(offset) => {
let n = self.num_of_args;
let num_frames = self.num_frames();
self.or_stack.push(num_frames + 1,
self.e,
self.cp,
self.b,
self.p + offset,
self.tr,
self.h,
self.num_of_args);
self.b = self.or_stack.len() - 1;
let b = self.b;
for i in 1 .. n + 1 {
self.or_stack[b][i] = self.registers[i].clone();
}
self.hb = self.h;
self.p += 1;
},
&ChoiceInstruction::RetryMeElse(offset) => {
let b = self.b;
let n = self.or_stack[b].num_args();
for i in 1 .. n + 1 {
self.registers[i] = self.or_stack[b][i].clone();
}
self.e = self.or_stack[b].e;
self.cp = self.or_stack[b].cp;
self.or_stack[b].bp = self.p + offset;
let old_tr = self.or_stack[b].tr;
let curr_tr = self.tr;
self.unwind_trail(old_tr, curr_tr);
self.tr = self.or_stack[b].tr;
self.trail.truncate(self.tr);
self.heap.truncate(self.or_stack[b].h);
self.h = self.or_stack[b].h;
self.hb = self.h;
self.p += 1;
},
&ChoiceInstruction::TrustMe => {
let b = self.b;
let n = self.or_stack[b].num_args();
for i in 1 .. n + 1 {
self.registers[i] = self.or_stack[b][i].clone();
}
self.e = self.or_stack[b].e;
self.cp = self.or_stack[b].cp;
let old_tr = self.or_stack[b].tr;
let curr_tr = self.tr;
self.unwind_trail(old_tr, curr_tr);
self.tr = self.or_stack[b].tr;
self.trail.truncate(self.tr);
self.h = self.or_stack[b].h;
self.heap.truncate(self.h);
self.b = self.or_stack[b].b;
self.or_stack.pop();
self.hb = self.h;
self.p += 1;
}
}
}
fn reset(&mut self) {
self.h = 0;
self.hb = 0;
self.e = 0;
self.b = 0;
self.s = 0;
self.tr = 0;
self.p = CodePtr::TopLevel;
self.cp = CodePtr::TopLevel;
self.num_of_args = 0;
self.fail = false;
self.trail.clear();
self.heap.clear();
self.mode = MachineMode::Write;
self.and_stack.clear();
self.or_stack.clear();
self.registers = vec![Addr::HeapCell(0); 64];
}
}

9
src/prolog/mod.rs Normal file
View File

@@ -0,0 +1,9 @@
pub mod and_stack;
pub mod ast;
pub mod codegen;
pub mod heapview;
pub mod io;
pub mod iterators;
pub mod prolog_parser;
pub mod machine;
pub mod or_stack;

112
src/prolog/or_stack.rs Normal file
View File

@@ -0,0 +1,112 @@
use prolog::ast::*;
use std::ops::{Index, IndexMut};
use std::vec::Vec;
pub struct Frame {
pub global_index: usize,
pub e: usize,
pub cp: CodePtr,
pub b: usize,
pub bp: CodePtr,
pub tr: usize,
pub h: usize,
args: Vec<Addr>
}
impl Frame {
fn new(global_index: usize,
e: usize,
cp: CodePtr,
b: usize,
bp: CodePtr,
tr: usize,
h: usize,
n: usize)
-> Self
{
Frame {
global_index: global_index,
e: e,
cp: cp,
b: b,
bp: bp,
tr: tr,
h: h,
args: vec![Addr::HeapCell(0); n]
}
}
pub fn num_args(&self) -> usize {
self.args.len()
}
}
pub struct OrStack(Vec<Frame>);
impl OrStack {
pub fn new() -> Self {
OrStack(Vec::new())
}
pub fn push(&mut self,
global_index: usize,
e: usize,
cp: CodePtr,
b: usize,
bp: CodePtr,
tr: usize,
h: usize,
n: usize)
{
self.0.push(Frame::new(global_index, e, cp, b, bp, tr, h, n));
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn clear(&mut self) {
self.0.clear()
}
pub fn top(&self) -> Option<&Frame> {
self.0.last()
}
pub fn pop(&mut self) {
self.0.pop();
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Index<usize> for OrStack {
type Output = Frame;
fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
}
}
impl IndexMut<usize> for OrStack {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.index_mut(index)
}
}
impl Index<usize> for Frame {
type Output = Addr;
fn index(&self, index: usize) -> &Self::Output {
self.args.index(index - 1)
}
}
impl IndexMut<usize> for Frame {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.args.index_mut(index - 1)
}
}

View File

@@ -0,0 +1,77 @@
use prolog::ast::*;
use std::cell::Cell;
grammar;
pub TopLevel: TopLevel = {
"?-" <t:Term> "." => TopLevel::Query(t),
<Predicate> => TopLevel::Predicate(<>),
<Rule> "." => TopLevel::Rule(<>),
<Term> "." => TopLevel::Fact(<>)
};
Atom : Atom = {
r"[a-z][a-z0-9_]*" => <>.trim().to_string(),
};
BoxedTerm : Box<Term> = {
<t:Term> => Box::new(t)
};
Clause : Term = {
<a:Atom> "(" <ts: (<BoxedTerm> ",")*> <t:BoxedTerm> ")" => {
let mut ts = ts;
ts.push(t);
Term::Clause(Cell::default(), a, ts)
}
};
List : Term = {
"[]" => Term::Constant(Cell::default(), Constant::EmptyList),
"[" <ListInternals> "]" => <>
};
ListInternals : Term = {
<t:BoxedTerm> => Term::Cons(Cell::default(),
t,
Box::new(Term::Constant(Cell::default(),
Constant::EmptyList))),
<t:BoxedTerm> "," <li: ListInternals> => Term::Cons(Cell::default(),
t,
Box::new(li)),
<t1:BoxedTerm> "|" <t2:BoxedTerm> => Term::Cons(Cell::default(), t1, t2)
};
Predicate : Vec<PredicateClause> = {
<pcs: (<PredicateClause>)+> <pc: PredicateClause> => {
let mut pcs = pcs;
pcs.push(pc);
pcs
}
};
PredicateClause : PredicateClause = {
<Rule> "." => PredicateClause::Rule(<>),
<Term> "." => PredicateClause::Fact(<>)
};
Rule : Rule = {
<c:Clause> ":-" <h:Term> <cs: ("," <Term>)*> =>
Rule { head: (c, h), clauses: cs },
<a:Atom> ":-" <h:Term> <cs: ("," <Term>)*> =>
Rule { head: (Term::Constant(Cell::default(), Constant::Atom(a)), h),
clauses: cs }
};
Term : Term = {
<Atom> => Term::Constant(Cell::default(), Constant::Atom(<>)),
<Clause> => <>,
<List> => <>,
<Var> => Term::Var(Cell::default(), <>),
"_" => Term::AnonVar
};
Var : Var = {
r"[A-Z][a-z0-9_]*" => <>.trim().to_string()
};

2815
src/prolog/prolog_parser.rs Normal file

File diff suppressed because it is too large Load Diff