transition to the operator precedence parser.
This commit is contained in:
@@ -1,13 +1,22 @@
|
||||
use prolog::num::bigint::BigInt;
|
||||
|
||||
use prolog::ordered_float::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::iter::*;
|
||||
use std::fmt;
|
||||
use std::io::Error as IOError;
|
||||
use std::num::{ParseFloatError};
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::str::Utf8Error;
|
||||
use std::vec::Vec;
|
||||
|
||||
pub type Atom = String;
|
||||
|
||||
pub type Var = String;
|
||||
|
||||
pub type Atom = String;
|
||||
pub const LEXER_BUF_SIZE: usize = 4096;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum GenContext {
|
||||
@@ -58,38 +67,6 @@ pub enum TopLevel {
|
||||
Rule(Rule)
|
||||
}
|
||||
|
||||
impl TopLevel {
|
||||
pub fn query_iter_mut<'a>(&'a mut self) -> Box<Iterator<Item=&'a mut QueryTerm> + 'a>
|
||||
{
|
||||
let mut iter: Box<Iterator<Item=&'a mut QueryTerm> + 'a> = Box::new(empty());
|
||||
|
||||
match self {
|
||||
&mut TopLevel::Rule(Rule { head: (_, ref mut head), ref mut clauses }) => {
|
||||
iter = Box::new(once(head));
|
||||
iter = Box::new(iter.chain(clauses.iter_mut()));
|
||||
},
|
||||
&mut TopLevel::Query(ref mut clauses) =>
|
||||
iter = Box::new(iter.chain(clauses.iter_mut())),
|
||||
&mut TopLevel::Predicate(ref mut pred_clauses) =>
|
||||
for pred_clause in pred_clauses.iter_mut() {
|
||||
match pred_clause {
|
||||
&mut PredicateClause::Rule(Rule { head: (_, ref mut head),
|
||||
ref mut clauses })
|
||||
=>
|
||||
{
|
||||
iter = Box::new(iter.chain(once(head)));
|
||||
iter = Box::new(iter.chain(clauses.iter_mut()));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Level {
|
||||
Deep, Shallow
|
||||
@@ -142,13 +119,142 @@ impl Default for VarReg {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||
pub type Specifier = u32;
|
||||
|
||||
pub const XFX: u32 = 0x0001;
|
||||
pub const XFY: u32 = 0x0002;
|
||||
pub const YFX: u32 = 0x0004;
|
||||
pub const XF: u32 = 0x0010;
|
||||
pub const YF: u32 = 0x0020;
|
||||
pub const FX: u32 = 0x0040;
|
||||
pub const FY: u32 = 0x0080;
|
||||
pub const DELIMITER: u32 = 0x0100;
|
||||
pub const TERM: u32 = 0x1000;
|
||||
pub const LTERM: u32 = 0x3000;
|
||||
|
||||
macro_rules! is_term {
|
||||
($x:expr) => ( ($x & TERM) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_lterm {
|
||||
($x:expr) => ( ($x & LTERM) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_op {
|
||||
($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_infix {
|
||||
($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_xfx {
|
||||
($x:expr) => ( ($x & XFX) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_xfy {
|
||||
($x:expr) => ( ($x & XFY) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_yfx {
|
||||
($x:expr) => ( ($x & YFX) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_yf {
|
||||
($x:expr) => ( ($x & YF) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_xf {
|
||||
($x:expr) => ( ($x & XF) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_fx {
|
||||
($x:expr) => ( ($x & FX) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! is_fy {
|
||||
($x:expr) => ( ($x & FY) != 0 )
|
||||
}
|
||||
|
||||
macro_rules! prefix {
|
||||
($x:expr) => ($x & (FX | FY))
|
||||
}
|
||||
|
||||
/* 'TokenTooLong' is hard to detect reliably if we don't process the
|
||||
input one character at a time. It would be easy to detect if the regex
|
||||
library supported matching on iterator inputs, but it currently does
|
||||
not. This is fine, mostly; the typical Prolog program will not contain
|
||||
tokens exceeding 4096 chars in length. */
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParserError
|
||||
{
|
||||
CommaArityMismatch,
|
||||
UnexpectedEOF,
|
||||
FailedMatch(String),
|
||||
IO(IOError),
|
||||
InadmissibleFact,
|
||||
InadmissibleQueryTerm,
|
||||
IncompleteReduction,
|
||||
InconsistentPredicate,
|
||||
ParseBigInt,
|
||||
ParseFloat(ParseFloatError),
|
||||
// TokenTooLong,
|
||||
Utf8Conversion(Utf8Error)
|
||||
}
|
||||
|
||||
impl From<IOError> for ParserError {
|
||||
fn from(err: IOError) -> ParserError {
|
||||
ParserError::IO(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Utf8Error> for ParserError {
|
||||
fn from(err: Utf8Error) -> ParserError {
|
||||
ParserError::Utf8Conversion(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseFloatError> for ParserError {
|
||||
fn from(err: ParseFloatError) -> ParserError {
|
||||
ParserError::ParseFloat(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub enum Fixity {
|
||||
In, Post, Pre
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub enum Constant {
|
||||
Atom(Atom),
|
||||
BlockNum(usize),
|
||||
Float(OrderedFloat<f64>),
|
||||
Integer(BigInt),
|
||||
String(String),
|
||||
Usize(usize),
|
||||
EmptyList
|
||||
}
|
||||
|
||||
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, "[]"),
|
||||
&Constant::Float(fl) =>
|
||||
write!(f, "{}", fl),
|
||||
&Constant::Integer(ref i) =>
|
||||
write!(f, "{}", i),
|
||||
&Constant::String(ref s) =>
|
||||
write!(f, "{}", s),
|
||||
&Constant::Usize(integer) =>
|
||||
write!(f, "u{}", integer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Term {
|
||||
AnonVar,
|
||||
Clause(Cell<RegType>, Atom, Vec<Box<Term>>),
|
||||
@@ -193,7 +299,7 @@ pub enum ClauseType<'a> {
|
||||
Catch,
|
||||
Deep(Level, &'a Cell<RegType>, &'a Atom),
|
||||
Root,
|
||||
Throw
|
||||
Throw,
|
||||
}
|
||||
|
||||
impl<'a> ClauseType<'a> {
|
||||
@@ -201,7 +307,7 @@ impl<'a> ClauseType<'a> {
|
||||
match self {
|
||||
ClauseType::CallN | ClauseType::Catch | ClauseType::Throw => Level::Shallow,
|
||||
ClauseType::Deep(_, _, _) => Level::Deep,
|
||||
ClauseType::Root => Level::Shallow
|
||||
ClauseType::Root => Level::Shallow,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,8 +408,8 @@ pub enum BuiltInInstruction {
|
||||
IsAtomic,
|
||||
IsVar,
|
||||
ResetBlock,
|
||||
SetBall,
|
||||
Unify,
|
||||
SetBall,
|
||||
Unify,
|
||||
UnwindStack
|
||||
}
|
||||
|
||||
@@ -568,7 +674,7 @@ impl Term {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
&Term::Clause(_, _, ref child_terms) => child_terms.len(),
|
||||
|
||||
@@ -10,9 +10,13 @@ pub enum PredicateKeyType {
|
||||
User
|
||||
}
|
||||
|
||||
pub type OpDirKey = (Atom, Fixity);
|
||||
// name and fixity -> operator type and precedence.
|
||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
|
||||
|
||||
fn get_builtins() -> Code {
|
||||
|
||||
fn get_builtins() -> Code {
|
||||
vec![internal_call_n!(), // callN/N, 0.
|
||||
is_atomic!(), // atomic/1, 1.
|
||||
proceed!(),
|
||||
@@ -78,7 +82,7 @@ fn get_builtins() -> Code {
|
||||
reset_block!(),
|
||||
proceed!(),
|
||||
trust_me!(), // 53.
|
||||
allocate!(0),
|
||||
allocate!(0),
|
||||
query![get_var_in_query!(temp_v!(3), 1),
|
||||
put_value!(temp_v!(2), 1)],
|
||||
reset_block!(),
|
||||
@@ -86,7 +90,7 @@ fn get_builtins() -> Code {
|
||||
goto!(61, 0),
|
||||
set_ball!(), // throw/1, 59.
|
||||
unwind_stack!(),
|
||||
fail!(), // false/0, 61.
|
||||
fail!(), // false/0, 61.
|
||||
try_me_else!(7), // not/1, 62.
|
||||
allocate!(1),
|
||||
get_level!(),
|
||||
@@ -100,10 +104,16 @@ fn get_builtins() -> Code {
|
||||
proceed!()]
|
||||
}
|
||||
|
||||
pub fn build_code_dir() -> (Code, CodeDir) {
|
||||
pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
||||
{
|
||||
let mut code_dir = HashMap::new();
|
||||
let mut op_dir = HashMap::new();
|
||||
|
||||
let builtin_code = get_builtins();
|
||||
|
||||
|
||||
op_dir.insert((String::from(":-"), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((String::from("?-"), Fixity::Pre), (FX, 1200));
|
||||
|
||||
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
|
||||
// (an extra register is needed for the predicate name)
|
||||
for arity in 0 .. 63 {
|
||||
@@ -118,5 +128,5 @@ pub fn build_code_dir() -> (Code, CodeDir) {
|
||||
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59));
|
||||
|
||||
(builtin_code, code_dir)
|
||||
(builtin_code, code_dir, op_dir)
|
||||
}
|
||||
|
||||
132
src/prolog/io.rs
132
src/prolog/io.rs
@@ -2,7 +2,6 @@ use prolog::ast::*;
|
||||
use prolog::codegen::*;
|
||||
use prolog::debray_allocator::*;
|
||||
use prolog::machine::*;
|
||||
use prolog::prolog_parser::*;
|
||||
|
||||
use termion::raw::IntoRawMode;
|
||||
use termion::input::TermRead;
|
||||
@@ -10,20 +9,6 @@ use termion::event::Key;
|
||||
|
||||
use std::io::{Write, stdin, stdout};
|
||||
use std::fmt;
|
||||
use std::mem::swap;
|
||||
|
||||
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, "[]"),
|
||||
&Constant::BlockNum(integer) =>
|
||||
write!(f, "u{}", integer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FactInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
@@ -209,110 +194,6 @@ impl fmt::Display for RegType {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Wait until constexprs are supported in stable before trying to
|
||||
// switch to this.
|
||||
|
||||
struct ClauseRewriter { field: fn(&mut Vec<Box<Term>>) -> QueryTerm }
|
||||
|
||||
impl Clone for ClauseRewriter {
|
||||
fn clone(&self) -> Self {
|
||||
ClauseRewriter { field: self.field }
|
||||
}
|
||||
}
|
||||
|
||||
struct ClauseRewriters {
|
||||
rewriter_map: HashMap<&'static str, ClauseRewriter>
|
||||
}
|
||||
|
||||
impl ClauseRewriters {
|
||||
fn new() -> Self {
|
||||
let mut rewriter_map =
|
||||
[("call", ClauseRewriter { field: rewrite_call_N })]//,
|
||||
//("catch", rewrite_catch),
|
||||
//("throw", rewrite_throw)]
|
||||
.iter().cloned().collect();
|
||||
|
||||
ClauseRewriters { rewriter_map: rewriter_map }
|
||||
}
|
||||
|
||||
fn get(&self, name: &str) -> Option<&ClauseRewriter> {
|
||||
self.rewriter_map.get(name)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
fn rewrite_call_n(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
let mut new_terms = Vec::with_capacity(0);
|
||||
swap(&mut new_terms, terms);
|
||||
|
||||
QueryTerm::CallN(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_catch(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
let mut new_terms = Vec::with_capacity(0);
|
||||
swap(&mut new_terms, terms);
|
||||
|
||||
QueryTerm::Catch(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_throw(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
let mut new_terms = Vec::with_capacity(0);
|
||||
swap(&mut new_terms, terms);
|
||||
|
||||
QueryTerm::Throw(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_clause(name: &Atom, terms: &mut Vec<Box<Term>>) -> Option<QueryTerm>
|
||||
{
|
||||
if name == "call" {
|
||||
Some(rewrite_call_n(terms))
|
||||
} else if name == "catch" && terms.len() == 3 {
|
||||
Some(rewrite_catch(terms))
|
||||
} else if name == "throw" && terms.len() == 1 {
|
||||
Some(rewrite_throw(terms))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_code(input: &str) -> Option<TopLevel>
|
||||
{
|
||||
match parse_TopLevel(input) {
|
||||
Ok(mut tl) => {
|
||||
for query in tl.query_iter_mut() {
|
||||
let new_query = match query {
|
||||
&mut QueryTerm::Term(Term::Clause(_, ref name, ref mut cts)) =>
|
||||
rewrite_clause(name, cts),
|
||||
&mut QueryTerm::Term(Term::Var(_, _)) =>
|
||||
Some(QueryTerm::CallN(Vec::new())),
|
||||
_ => None
|
||||
};
|
||||
|
||||
if let Some(mut new_query) = new_query {
|
||||
swap(&mut new_query, query);
|
||||
}
|
||||
}
|
||||
|
||||
Some(tl)
|
||||
},
|
||||
Err(_) => None
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -371,16 +252,9 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
|
||||
match tl {
|
||||
&TopLevel::Predicate(ref clauses) => {
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||
|
||||
if is_consistent(clauses) {
|
||||
let compiled_pred = cg.compile_predicate(clauses);
|
||||
wam.add_predicate(clauses, compiled_pred)
|
||||
} else {
|
||||
let msg = r"Error: predicate is inconsistent.
|
||||
Each predicate must have the same name and arity.";
|
||||
|
||||
EvalSession::EntryFailure(String::from(msg))
|
||||
}
|
||||
let compiled_pred = cg.compile_predicate(clauses);
|
||||
|
||||
wam.add_predicate(clauses, compiled_pred)
|
||||
},
|
||||
&TopLevel::Fact(ref fact) => {
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||
|
||||
@@ -53,15 +53,12 @@ impl<'a> QueryIterator<'a> {
|
||||
fn from_term(term: &'a Term) -> Self {
|
||||
let state = match term {
|
||||
&Term::AnonVar =>
|
||||
//IteratorState::AnonVar(Level::Shallow),
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Clause(_, _, ref terms) =>
|
||||
IteratorState::Clause(0, ClauseType::Root, terms),
|
||||
&Term::Cons(_, _, _) =>
|
||||
//IteratorState::InitialCons(Level::Shallow, cell, head.as_ref(), tail.as_ref()),
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Constant(_, _) =>
|
||||
//IteratorState::Constant(Level::Shallow, cell, constant),
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
IteratorState::Var(Level::Shallow, cell, var)
|
||||
|
||||
@@ -36,7 +36,7 @@ struct MachineState {
|
||||
tr: usize,
|
||||
hb: usize,
|
||||
block: usize, // an offset into the OR stack.
|
||||
ball: (usize, Heap) // heap boundary, and a term copy
|
||||
ball: (usize, Heap) // heap boundary, and a term copy
|
||||
}
|
||||
|
||||
struct DuplicateTerm<'a> {
|
||||
@@ -158,6 +158,7 @@ pub struct Machine {
|
||||
ms: MachineState,
|
||||
code: Code,
|
||||
code_dir: CodeDir,
|
||||
op_dir: OpDir,
|
||||
cached_query: Option<Code>
|
||||
}
|
||||
|
||||
@@ -205,12 +206,13 @@ impl Index<CodePtr> for Machine {
|
||||
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let (code, code_dir) = build_code_dir();
|
||||
let (code, code_dir, op_dir) = build_code_dir();
|
||||
|
||||
Machine {
|
||||
ms: MachineState::new(),
|
||||
code: code,
|
||||
code_dir: code_dir,
|
||||
op_dir: op_dir,
|
||||
cached_query: None
|
||||
}
|
||||
}
|
||||
@@ -484,12 +486,8 @@ impl Machine {
|
||||
|
||||
while let Some(view) = viewer.next() {
|
||||
match view {
|
||||
CellView::Con(&Constant::BlockNum(integer)) =>
|
||||
result += integer.to_string().as_str(),
|
||||
CellView::Con(&Constant::EmptyList) =>
|
||||
result += "[]",
|
||||
CellView::Con(&Constant::Atom(ref atom)) =>
|
||||
result += atom.as_str(),
|
||||
CellView::Con(ref r) =>
|
||||
result += format!("{}", r).as_str(),
|
||||
CellView::HeapVar(cell_num) => {
|
||||
result += "_";
|
||||
result += cell_num.to_string().as_str();
|
||||
@@ -552,6 +550,10 @@ impl Machine {
|
||||
pub fn reset(&mut self) {
|
||||
self.ms.reset();
|
||||
}
|
||||
|
||||
pub fn op_dir(&self) -> &OpDir {
|
||||
&self.op_dir
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
@@ -1163,11 +1165,11 @@ impl MachineState {
|
||||
|
||||
fn throw_exception(&mut self, mut hcv: Vec<HeapCellValue>) {
|
||||
let h = self.h;
|
||||
|
||||
|
||||
self.registers[1] = Addr::HeapCell(h);
|
||||
self.h += hcv.len();
|
||||
|
||||
self.heap.append(&mut hcv);
|
||||
|
||||
self.heap.append(&mut hcv);
|
||||
self.goto_throw();
|
||||
}
|
||||
|
||||
@@ -1256,7 +1258,7 @@ impl MachineState {
|
||||
self.p += 1;
|
||||
},
|
||||
&BuiltInInstruction::GetCurrentBlock => {
|
||||
let c = Constant::BlockNum(self.block);
|
||||
let c = Constant::Usize(self.block);
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
self.write_constant_to_var(addr, &c);
|
||||
@@ -1297,10 +1299,9 @@ impl MachineState {
|
||||
},
|
||||
&BuiltInInstruction::SetBall => {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.0 = self.h;
|
||||
|
||||
{
|
||||
self.ball.0 = self.h;
|
||||
|
||||
let mut duplicator = DuplicateBallTerm::new(self);
|
||||
duplicator.duplicate_term(addr);
|
||||
}
|
||||
@@ -1311,7 +1312,7 @@ impl MachineState {
|
||||
let nb = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match nb {
|
||||
Addr::Con(Constant::BlockNum(nb)) => {
|
||||
Addr::Con(Constant::Usize(nb)) => {
|
||||
let b = self.b - 1;
|
||||
|
||||
if nb > 0 && self.or_stack[b].b == nb {
|
||||
@@ -1325,7 +1326,7 @@ impl MachineState {
|
||||
},
|
||||
&BuiltInInstruction::InstallNewBlock => {
|
||||
self.block = self.b;
|
||||
let c = Constant::BlockNum(self.block);
|
||||
let c = Constant::Usize(self.block);
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
|
||||
self.write_constant_to_var(addr, &c);
|
||||
@@ -1335,7 +1336,7 @@ impl MachineState {
|
||||
let addr = self.deref(self[temp_v!(1)].clone());
|
||||
|
||||
match self.store(addr) {
|
||||
Addr::Con(Constant::BlockNum(b)) => {
|
||||
Addr::Con(Constant::Usize(b)) => {
|
||||
self.block = b;
|
||||
self.p += 1;
|
||||
},
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
extern crate num;
|
||||
extern crate ordered_float;
|
||||
|
||||
pub mod allocator;
|
||||
pub mod and_stack;
|
||||
#[macro_use]
|
||||
pub mod ast;
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod builtins;
|
||||
pub mod codegen;
|
||||
pub mod copier;
|
||||
pub mod debray_allocator;
|
||||
@@ -9,12 +16,7 @@ pub mod heapview;
|
||||
pub mod indexing;
|
||||
pub mod io;
|
||||
pub mod iterators;
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod naive_allocator;
|
||||
pub mod prolog_parser;
|
||||
pub mod machine;
|
||||
pub mod or_stack;
|
||||
pub mod parser;
|
||||
pub mod targets;
|
||||
|
||||
pub mod builtins;
|
||||
|
||||
1
src/prolog/parser
Submodule
1
src/prolog/parser
Submodule
Submodule src/prolog/parser added at de2a1a7364
@@ -1,93 +0,0 @@
|
||||
use prolog::ast::*;
|
||||
//use prolog::prolog_parser_utils::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
grammar;
|
||||
|
||||
pub TopLevel: TopLevel = {
|
||||
"?-" <q:Query> "." => TopLevel::Query(q),
|
||||
<Predicate> => TopLevel::Predicate(<>),
|
||||
<Rule> "." => TopLevel::Rule(<>),
|
||||
<Term> "." => TopLevel::Fact(<>)
|
||||
};
|
||||
|
||||
Atom : Atom = {
|
||||
r"[a-z][A-Za-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(<>)
|
||||
};
|
||||
|
||||
Query : Vec<QueryTerm> = {
|
||||
<tcs: (<QueryTerm> ",")*> <tc: QueryTerm> => {
|
||||
let mut tcs = tcs;
|
||||
tcs.push(tc);
|
||||
tcs
|
||||
}
|
||||
};
|
||||
|
||||
Rule : Rule = {
|
||||
<c:Clause> ":-" <h:QueryTerm> <cs: ("," <QueryTerm>)*> =>
|
||||
Rule { head: (c, h), clauses: cs },
|
||||
<a:Atom> ":-" <h:QueryTerm> <cs: ("," <QueryTerm>)*> =>
|
||||
Rule { head: (Term::Constant(Cell::default(), Constant::Atom(a)), h),
|
||||
clauses: cs }
|
||||
};
|
||||
|
||||
QueryTerm : QueryTerm = {
|
||||
"!" => QueryTerm::Cut,
|
||||
<Var> => QueryTerm::CallN(vec![Box::new(Term::Var(Cell::default(), <>))]),
|
||||
<Clause> => QueryTerm::Term(<>),
|
||||
<Atom> => QueryTerm::Term(Term::Constant(Cell::default(), Constant::Atom(<>)))
|
||||
};
|
||||
|
||||
Term : Term = {
|
||||
<Clause> => <>,
|
||||
<Atom> => Term::Constant(Cell::default(), Constant::Atom(<>)),
|
||||
<List> => <>,
|
||||
<Var> => Term::Var(Cell::default(), <>),
|
||||
"_" => Term::AnonVar
|
||||
};
|
||||
|
||||
Var : Var = {
|
||||
r"[A-Z][A-Za-z0-9_]*" => <>.trim().to_string()
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user