major refactor.
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -176,7 +176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rusty-wam"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
dependencies = [
|
||||
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusty-wam"
|
||||
version = "0.7.5"
|
||||
version = "0.7.6"
|
||||
authors = ["Mark Thom"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -13,15 +13,19 @@ pub type ArithCont = (Code, Option<ArithmeticTerm>);
|
||||
|
||||
impl<'a> ArithInstructionIterator<'a> {
|
||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||
self.state_stack.push(TermIterState::to_state(lvl, term));
|
||||
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
|
||||
}
|
||||
|
||||
fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
|
||||
let state = match term {
|
||||
&Term::AnonVar =>
|
||||
return Err(ArithmeticError::InvalidTerm),
|
||||
&Term::Clause(_, ref name, ref terms, _) =>
|
||||
TermIterState::Clause(0, ClauseType::Root(name), terms),
|
||||
&Term::Clause(ref cell, ref name, ref terms, fixity) =>
|
||||
match ClauseType::from(name.clone(), terms.len(), fixity) {
|
||||
ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) =>
|
||||
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)),
|
||||
_ => Err(ArithmeticError::InvalidOp)
|
||||
}?,
|
||||
&Term::Constant(ref cell, ref cons) =>
|
||||
TermIterState::Constant(Level::Shallow, cell, cons),
|
||||
&Term::Cons(_, _, _) =>
|
||||
@@ -36,7 +40,7 @@ impl<'a> ArithInstructionIterator<'a> {
|
||||
|
||||
pub enum ArithTermRef<'a> {
|
||||
Constant(&'a Constant),
|
||||
Op(&'a str, usize), // name, arity.
|
||||
Op(ClauseName, usize), // name, arity.
|
||||
Var(&'a Cell<VarReg>, &'a Var)
|
||||
}
|
||||
|
||||
@@ -48,14 +52,14 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||
match iter_state {
|
||||
TermIterState::AnonVar(_) =>
|
||||
return Some(Err(ArithmeticError::UninstantiatedVar)),
|
||||
TermIterState::Clause(child_num, ct, child_terms) => {
|
||||
let arity = child_terms.len();
|
||||
TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
|
||||
let arity = subterms.len();
|
||||
|
||||
if child_num == arity {
|
||||
return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
|
||||
} else {
|
||||
self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
|
||||
self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
|
||||
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms));
|
||||
self.push_subterm(lvl, subterms[child_num].as_ref());
|
||||
}
|
||||
},
|
||||
TermIterState::Constant(_, _, c) =>
|
||||
@@ -97,19 +101,19 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
|
||||
}
|
||||
|
||||
fn get_unary_instr(name: &str, a1: ArithmeticTerm, t: usize)
|
||||
fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match name {
|
||||
match name.as_str() {
|
||||
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
|
||||
_ => Err(ArithmeticError::InvalidOp)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_binary_instr(name: &str, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
|
||||
fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match name {
|
||||
match name.as_str() {
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
|
||||
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
||||
@@ -137,7 +141,7 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
temp
|
||||
}
|
||||
|
||||
fn instr_from_clause(&mut self, name: &str, arity: usize)
|
||||
fn instr_from_clause(&mut self, name: ClauseName, arity: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match arity {
|
||||
@@ -215,7 +219,7 @@ impl<'a> ArithmeticEvaluator<'a>
|
||||
self.interm.push(ArithmeticTerm::Reg(r));
|
||||
},
|
||||
ArithTermRef::Op(name, arity) => {
|
||||
code.push(Line::Arithmetic(self.instr_from_clause(&*name, arity)?));
|
||||
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io::Error as IOError;
|
||||
use std::num::{ParseFloatError};
|
||||
use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg};
|
||||
@@ -46,37 +47,27 @@ impl PredicateClause {
|
||||
pub fn first_arg(&self) -> Option<&Term> {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref term) => term.first_arg(),
|
||||
&PredicateClause::Rule(ref rule) =>
|
||||
if let &QueryTerm::Term(ref term) = &rule.head.0 {
|
||||
term.first_arg()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
&PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref term) => term.arity(),
|
||||
&PredicateClause::Rule(ref rule) => rule.head.0.arity()
|
||||
&PredicateClause::Rule(ref rule) => rule.head.1.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<TabledRc<Atom>> {
|
||||
pub fn name(&self) -> Option<ClauseName> {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref term) => term.name(),
|
||||
&PredicateClause::Rule(ref rule) =>
|
||||
if let &QueryTerm::Term(ref term) = &rule.head.0 {
|
||||
term.name()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
&PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Declaration {
|
||||
Op(usize, Specifier, TabledRc<Atom>)
|
||||
Op(usize, Specifier, ClauseName)
|
||||
}
|
||||
|
||||
pub enum TopLevel {
|
||||
@@ -88,7 +79,7 @@ pub enum TopLevel {
|
||||
}
|
||||
|
||||
impl TopLevel {
|
||||
pub fn name(&self) -> Option<TabledRc<Atom>> {
|
||||
pub fn name(&self) -> Option<ClauseName> {
|
||||
match self {
|
||||
&TopLevel::Declaration(_) => None,
|
||||
&TopLevel::Fact(ref term) => term.name(),
|
||||
@@ -99,15 +90,8 @@ impl TopLevel {
|
||||
None
|
||||
},
|
||||
&TopLevel::Query(_) => None,
|
||||
&TopLevel::Rule(Rule { head: (QueryTerm::Term(ref term), _), .. }) =>
|
||||
match term {
|
||||
&Term::Clause(_, ref name, ..)
|
||||
| &Term::Constant(_, Constant::Atom(ref name)) =>
|
||||
Some(name.clone()),
|
||||
_ =>
|
||||
None
|
||||
},
|
||||
_ => None
|
||||
&TopLevel::Rule(Rule { ref head, .. }) =>
|
||||
Some(head.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,14 +102,23 @@ impl TopLevel {
|
||||
&TopLevel::Predicate(ref clauses) =>
|
||||
clauses.first().map(|t| t.arity()).unwrap_or(0),
|
||||
&TopLevel::Query(_) => 0,
|
||||
&TopLevel::Rule(Rule { head: (ref qt, _), ..}) => qt.arity(),
|
||||
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Level {
|
||||
Deep, Shallow
|
||||
Deep, Root, Shallow
|
||||
}
|
||||
|
||||
impl Level {
|
||||
pub fn child_level(self) -> Level {
|
||||
match self {
|
||||
Level::Root => Level::Shallow,
|
||||
_ => Level::Deep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@@ -305,7 +298,7 @@ pub enum Fixity {
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub enum Constant {
|
||||
Atom(TabledRc<Atom>),
|
||||
Atom(ClauseName),
|
||||
Number(Number),
|
||||
String(Rc<String>),
|
||||
Usize(usize),
|
||||
@@ -332,36 +325,57 @@ impl fmt::Display for Constant {
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub enum Term {
|
||||
AnonVar,
|
||||
Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
|
||||
Clause(Cell<RegType>, ClauseName, Vec<Box<Term>>, Option<Fixity>),
|
||||
Cons(Cell<RegType>, Box<Term>, Box<Term>),
|
||||
Constant(Cell<RegType>, Constant),
|
||||
Var(Cell<VarReg>, Rc<Var>)
|
||||
}
|
||||
|
||||
pub enum InlinedQueryTerm {
|
||||
CompareNumber(CompareNumberQT, Vec<Box<Term>>),
|
||||
IsAtomic(Vec<Box<Term>>),
|
||||
IsCompound(Vec<Box<Term>>),
|
||||
IsInteger(Vec<Box<Term>>),
|
||||
IsRational(Vec<Box<Term>>),
|
||||
IsString(Vec<Box<Term>>),
|
||||
IsFloat(Vec<Box<Term>>),
|
||||
IsNonVar(Vec<Box<Term>>),
|
||||
IsVar(Vec<Box<Term>>),
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum InlinedClauseType {
|
||||
CompareNumber(CompareNumberQT),
|
||||
IsAtomic,
|
||||
IsCompound,
|
||||
IsInteger,
|
||||
IsRational,
|
||||
IsString,
|
||||
IsFloat,
|
||||
IsNonVar,
|
||||
IsVar,
|
||||
}
|
||||
|
||||
impl InlinedQueryTerm {
|
||||
pub fn arity(&self) -> usize {
|
||||
impl InlinedClauseType {
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
&InlinedQueryTerm::CompareNumber(_, _) => 2,
|
||||
&InlinedQueryTerm::IsAtomic(_) => 1,
|
||||
&InlinedQueryTerm::IsCompound(_) => 1,
|
||||
&InlinedQueryTerm::IsFloat(_) => 1,
|
||||
&InlinedQueryTerm::IsRational(_) => 1,
|
||||
&InlinedQueryTerm::IsString(_) => 1,
|
||||
&InlinedQueryTerm::IsNonVar(_) => 1,
|
||||
&InlinedQueryTerm::IsInteger(_) => 1,
|
||||
&InlinedQueryTerm::IsVar(_) => 1,
|
||||
&InlinedClauseType::CompareNumber(qt) => qt.name(),
|
||||
&InlinedClauseType::IsAtomic => "atomic",
|
||||
&InlinedClauseType::IsCompound => "compound",
|
||||
&InlinedClauseType::IsInteger => "integer",
|
||||
&InlinedClauseType::IsRational => "rational",
|
||||
&InlinedClauseType::IsString => "string",
|
||||
&InlinedClauseType::IsFloat => "float",
|
||||
&InlinedClauseType::IsNonVar => "nonvar",
|
||||
&InlinedClauseType::IsVar => "var"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(name: &str, arity: usize) -> Option<Self> {
|
||||
match (name, arity) {
|
||||
(">", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan)),
|
||||
("<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan)),
|
||||
(">=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual)),
|
||||
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
|
||||
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
|
||||
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
|
||||
("atomic", 1) => Some(InlinedClauseType::IsAtomic),
|
||||
("compound", 1) => Some(InlinedClauseType::IsCompound),
|
||||
("integer", 1) => Some(InlinedClauseType::IsInteger),
|
||||
("rational", 1) => Some(InlinedClauseType::IsRational),
|
||||
("string", 1) => Some(InlinedClauseType::IsString),
|
||||
("float", 1) => Some(InlinedClauseType::IsFloat),
|
||||
("nonvar", 1) => Some(InlinedClauseType::IsNonVar),
|
||||
("var", 1) => Some(InlinedClauseType::IsVar),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,7 +391,7 @@ pub enum CompareNumberQT {
|
||||
}
|
||||
|
||||
impl CompareNumberQT {
|
||||
fn name<'a>(self) -> &'a str {
|
||||
fn name(self) -> &'static str {
|
||||
match self {
|
||||
CompareNumberQT::GreaterThan => ">",
|
||||
CompareNumberQT::LessThan => "<",
|
||||
@@ -390,13 +404,13 @@ impl CompareNumberQT {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CompareTermQT {
|
||||
pub enum CompareTermQT {
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
Equal,
|
||||
GreaterThanOrEqual,
|
||||
GreaterThan,
|
||||
NotEqual,
|
||||
GreaterThan,
|
||||
NotEqual,
|
||||
}
|
||||
|
||||
impl CompareTermQT {
|
||||
@@ -417,118 +431,174 @@ impl CompareTermQT {
|
||||
pub type JumpStub = Vec<Term>;
|
||||
|
||||
pub enum QueryTerm {
|
||||
Arg(Vec<Box<Term>>),
|
||||
CallN(Vec<Box<Term>>),
|
||||
CallWithInferenceLimit(Vec<Box<Term>>),
|
||||
Catch(Vec<Box<Term>>),
|
||||
Compare(Vec<Box<Term>>),
|
||||
CompareTerm(CompareTermQT, Vec<Box<Term>>),
|
||||
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
|
||||
Cut,
|
||||
Display(Vec<Box<Term>>),
|
||||
DuplicateTerm(Vec<Box<Term>>),
|
||||
Eq(Vec<Box<Term>>),
|
||||
Functor(Vec<Box<Term>>),
|
||||
Ground(Vec<Box<Term>>),
|
||||
Inlined(InlinedQueryTerm),
|
||||
Is(Vec<Box<Term>>),
|
||||
Jump(JumpStub),
|
||||
NotEq(Vec<Box<Term>>),
|
||||
SetupCallCleanup(Vec<Box<Term>>),
|
||||
Term(Term),
|
||||
Throw(Vec<Box<Term>>)
|
||||
Jump(JumpStub)
|
||||
}
|
||||
|
||||
impl QueryTerm {
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
&QueryTerm::Arg(_) => 3,
|
||||
&QueryTerm::Catch(_) => 3,
|
||||
&QueryTerm::Compare(_) => 3,
|
||||
&QueryTerm::CompareTerm(..) => 2,
|
||||
&QueryTerm::Display(_) => 1,
|
||||
&QueryTerm::Throw(_) => 1,
|
||||
&QueryTerm::DuplicateTerm(_) => 2,
|
||||
&QueryTerm::Eq(_) => 2,
|
||||
&QueryTerm::Functor(_) => 3,
|
||||
&QueryTerm::Ground(_) => 1,
|
||||
&QueryTerm::Inlined(ref term) => term.arity(),
|
||||
&QueryTerm::Is(_) => 2,
|
||||
&QueryTerm::Jump(ref vars) => vars.len(),
|
||||
&QueryTerm::NotEq(_) => 2,
|
||||
&QueryTerm::CallN(ref terms) => terms.len(),
|
||||
&QueryTerm::CallWithInferenceLimit(_) => 3,
|
||||
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
|
||||
&QueryTerm::Cut => 0,
|
||||
&QueryTerm::SetupCallCleanup(_) => 3,
|
||||
&QueryTerm::Term(ref term) => term.arity(),
|
||||
&QueryTerm::Jump(ref vars) => vars.len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Rule {
|
||||
pub head: (QueryTerm, QueryTerm),
|
||||
pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
|
||||
pub clauses: Vec<QueryTerm>
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ClauseType<'a> {
|
||||
#[derive(Clone)]
|
||||
pub enum ClauseType {
|
||||
Arg,
|
||||
CallN,
|
||||
CallWithInferenceLimit,
|
||||
Catch,
|
||||
Compare,
|
||||
CompareNumber(CompareNumberQT),
|
||||
CompareTerm(CompareTermQT),
|
||||
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
|
||||
Display,
|
||||
DuplicateTerm,
|
||||
Eq,
|
||||
Functor,
|
||||
Ground,
|
||||
Inlined(InlinedClauseType),
|
||||
Is,
|
||||
NotEq,
|
||||
Root(&'a TabledRc<Atom>),
|
||||
Op(ClauseName, Fixity),
|
||||
Named(ClauseName),
|
||||
SetupCallCleanup,
|
||||
Throw,
|
||||
}
|
||||
|
||||
impl<'a> ClauseType<'a> {
|
||||
pub fn name(&self) -> &'a str {
|
||||
impl ClauseType {
|
||||
pub fn fixity(&self) -> Option<Fixity> {
|
||||
match self {
|
||||
&ClauseType::Arg => "arg",
|
||||
&ClauseType::CallN => "call",
|
||||
&ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
|
||||
&ClauseType::Catch => "catch",
|
||||
&ClauseType::Compare => "compare",
|
||||
&ClauseType::CompareNumber(qt) => qt.name(),
|
||||
&ClauseType::CompareTerm(qt) => qt.name(),
|
||||
&ClauseType::Display => "display",
|
||||
&ClauseType::Deep(_, _, name, _) => name.as_str(),
|
||||
&ClauseType::DuplicateTerm => "duplicate_term",
|
||||
&ClauseType::Eq => "==",
|
||||
&ClauseType::Functor => "functor",
|
||||
&ClauseType::Ground => "ground",
|
||||
&ClauseType::Is => "is",
|
||||
&ClauseType::NotEq => "\\==",
|
||||
&ClauseType::Root(name) => name.as_str(),
|
||||
&ClauseType::SetupCallCleanup => "setup_call_cleanup",
|
||||
&ClauseType::Throw => "throw"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn level_of_subterms(self) -> Level {
|
||||
match self {
|
||||
ClauseType::Deep(..) => Level::Deep,
|
||||
_ => Level::Shallow
|
||||
&ClauseType::Compare | &ClauseType::CompareTerm(_)
|
||||
| &ClauseType::Inlined(InlinedClauseType::CompareNumber(_))
|
||||
| &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In),
|
||||
&ClauseType::Op(_, fixity) => Some(fixity),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
pub enum ClauseName {
|
||||
BuiltIn(&'static str),
|
||||
User(TabledRc<Atom>)
|
||||
}
|
||||
|
||||
impl Hash for ClauseName {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(*self.as_str()).hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ClauseName {
|
||||
fn eq(&self, other: &ClauseName) -> bool {
|
||||
*self.as_str() == *other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ClauseName {}
|
||||
|
||||
impl Ord for ClauseName {
|
||||
fn cmp(&self, other: &ClauseName) -> Ordering {
|
||||
(*self.as_str()).cmp(other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for ClauseName {
|
||||
fn partial_cmp(&self, other: &ClauseName) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a TabledRc<Atom>> for ClauseName {
|
||||
fn from(name: &'a TabledRc<Atom>) -> ClauseName {
|
||||
ClauseName::User(name.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl ClauseName {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
&ClauseName::BuiltIn(s) => s,
|
||||
&ClauseName::User(ref name) => name.as_ref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClauseType {
|
||||
pub fn name(&self) -> ClauseName {
|
||||
match self {
|
||||
&ClauseType::Arg => ClauseName::BuiltIn("arg"),
|
||||
&ClauseType::CallN => ClauseName::BuiltIn("call"),
|
||||
&ClauseType::CallWithInferenceLimit => ClauseName::BuiltIn("call_with_inference_limit"),
|
||||
&ClauseType::Catch => ClauseName::BuiltIn("catch"),
|
||||
&ClauseType::Compare => ClauseName::BuiltIn("compare"),
|
||||
&ClauseType::CompareTerm(qt) => ClauseName::BuiltIn(qt.name()),
|
||||
&ClauseType::Display => ClauseName::BuiltIn("display"),
|
||||
&ClauseType::DuplicateTerm => ClauseName::BuiltIn("duplicate_term"),
|
||||
&ClauseType::Eq => ClauseName::BuiltIn("=="),
|
||||
&ClauseType::Functor => ClauseName::BuiltIn("functor"),
|
||||
&ClauseType::Ground => ClauseName::BuiltIn("ground"),
|
||||
&ClauseType::Inlined(inlined) => ClauseName::BuiltIn(inlined.name()),
|
||||
&ClauseType::Is => ClauseName::BuiltIn("is"),
|
||||
&ClauseType::NotEq => ClauseName::BuiltIn("\\=="),
|
||||
&ClauseType::Op(ref name, _) => name.clone(),
|
||||
&ClauseType::Named(ref name) => name.clone(),
|
||||
&ClauseType::SetupCallCleanup => ClauseName::BuiltIn("setup_call_cleanup"),
|
||||
&ClauseType::Throw => ClauseName::BuiltIn("throw")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
|
||||
match (name.as_str(), arity) {
|
||||
("arg", 3) => ClauseType::Arg,
|
||||
("call", _) => ClauseType::CallN,
|
||||
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
|
||||
("catch", 3) => ClauseType::Catch,
|
||||
("compare", 3) => ClauseType::Compare,
|
||||
("@>", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThan),
|
||||
("@<", 2) => ClauseType::CompareTerm(CompareTermQT::LessThan),
|
||||
("@>=", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual),
|
||||
("@<=", 2) => ClauseType::CompareTerm(CompareTermQT::LessThanOrEqual),
|
||||
("\\=@=", 2) => ClauseType::CompareTerm(CompareTermQT::NotEqual),
|
||||
("=@=", 2) => ClauseType::CompareTerm(CompareTermQT::Equal),
|
||||
("display", 1) => ClauseType::Display,
|
||||
("duplicate_term", 2) => ClauseType::DuplicateTerm,
|
||||
("==", 2) => ClauseType::Eq,
|
||||
("functor", 3) => ClauseType::Functor,
|
||||
("ground", 1) => ClauseType::Ground,
|
||||
("is", 2) => ClauseType::Is,
|
||||
("\\==", 2) => ClauseType::NotEq,
|
||||
("setup_call_cleanup", 3) => ClauseType::SetupCallCleanup,
|
||||
("throw", 1) => ClauseType::Throw,
|
||||
_ => if let Some(fixity) = fixity {
|
||||
ClauseType::Op(name, fixity)
|
||||
} else {
|
||||
ClauseType::Named(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InlinedClauseType> for ClauseType {
|
||||
fn from(inlined_ct: InlinedClauseType) -> Self {
|
||||
ClauseType::Inlined(inlined_ct)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TermRef<'a> {
|
||||
AnonVar(Level),
|
||||
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
Constant(Level, &'a Cell<RegType>, &'a Constant),
|
||||
Clause(ClauseType<'a>, &'a Vec<Box<Term>>),
|
||||
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
|
||||
Var(Level, &'a Cell<VarReg>, &'a Var)
|
||||
}
|
||||
|
||||
@@ -538,9 +608,8 @@ impl<'a> TermRef<'a> {
|
||||
TermRef::AnonVar(lvl)
|
||||
| TermRef::Cons(lvl, ..)
|
||||
| TermRef::Constant(lvl, ..)
|
||||
| TermRef::Var(lvl, ..) => lvl,
|
||||
TermRef::Clause(ClauseType::Deep(lvl, ..), ..) => lvl,
|
||||
_ => Level::Shallow
|
||||
| TermRef::Var(lvl, ..)
|
||||
| TermRef::Clause(lvl, ..) => lvl
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -921,7 +990,7 @@ pub enum ControlInstruction {
|
||||
Allocate(usize), // num_frames.
|
||||
ArgCall,
|
||||
ArgExecute,
|
||||
Call(TabledRc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
|
||||
Call(ClauseName, usize, usize), // name, arity, perm_vars after threshold.
|
||||
CallN(usize), // arity.
|
||||
CatchCall,
|
||||
CatchExecute,
|
||||
@@ -934,11 +1003,11 @@ pub enum ControlInstruction {
|
||||
DisplayExecute,
|
||||
Deallocate,
|
||||
DuplicateTermCall,
|
||||
DuplicateTermExecute,
|
||||
DuplicateTermExecute,
|
||||
DynamicIs,
|
||||
EqCall,
|
||||
EqExecute,
|
||||
Execute(TabledRc<Atom>, usize),
|
||||
Execute(ClauseName, usize),
|
||||
ExecuteN(usize),
|
||||
FunctorCall,
|
||||
FunctorExecute,
|
||||
@@ -949,11 +1018,11 @@ pub enum ControlInstruction {
|
||||
GroundExecute,
|
||||
JmpByCall(usize, usize), // arity, global_offset.
|
||||
JmpByExecute(usize, usize),
|
||||
IsCall(RegType, ArithmeticTerm),
|
||||
IsCall(RegType, ArithmeticTerm),
|
||||
IsExecute(RegType, ArithmeticTerm),
|
||||
NotEqCall,
|
||||
NotEqExecute,
|
||||
Proceed,
|
||||
Proceed,
|
||||
ThrowCall,
|
||||
ThrowExecute,
|
||||
}
|
||||
@@ -965,7 +1034,7 @@ impl ControlInstruction {
|
||||
&ControlInstruction::ArgExecute => true,
|
||||
&ControlInstruction::Call(_, _, _) => true,
|
||||
&ControlInstruction::CatchCall => true,
|
||||
&ControlInstruction::CatchExecute => true,
|
||||
&ControlInstruction::CatchExecute => true,
|
||||
&ControlInstruction::CompareTermCall(..) => true,
|
||||
&ControlInstruction::CompareTermExecute(..) => true,
|
||||
&ControlInstruction::DisplayCall => true,
|
||||
@@ -1003,7 +1072,7 @@ impl ControlInstruction {
|
||||
pub enum IndexingInstruction {
|
||||
SwitchOnTerm(usize, usize, usize, usize),
|
||||
SwitchOnConstant(usize, HashMap<Constant, usize>),
|
||||
SwitchOnStructure(usize, HashMap<(TabledRc<Atom>, usize), usize>)
|
||||
SwitchOnStructure(usize, HashMap<(ClauseName, usize), usize>)
|
||||
}
|
||||
|
||||
impl From<IndexingInstruction> for Line {
|
||||
@@ -1015,7 +1084,7 @@ impl From<IndexingInstruction> for Line {
|
||||
pub enum FactInstruction {
|
||||
GetConstant(Level, Constant, RegType),
|
||||
GetList(Level, RegType),
|
||||
GetStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
|
||||
GetStructure(ClauseType, usize, RegType),
|
||||
GetValue(RegType, usize),
|
||||
GetVariable(RegType, usize),
|
||||
UnifyConstant(Constant),
|
||||
@@ -1029,7 +1098,7 @@ pub enum QueryInstruction {
|
||||
GetVariable(RegType, usize),
|
||||
PutConstant(Level, Constant, RegType),
|
||||
PutList(Level, RegType),
|
||||
PutStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
|
||||
PutStructure(ClauseType, usize, RegType),
|
||||
PutUnsafeValue(usize, usize),
|
||||
PutValue(RegType, usize),
|
||||
PutVariable(RegType, usize),
|
||||
@@ -1113,7 +1182,7 @@ pub enum Ref {
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum HeapCellValue {
|
||||
Addr(Addr),
|
||||
NamedStr(usize, TabledRc<Atom>, Option<Fixity>), // arity, name, fixity if it has one.
|
||||
NamedStr(usize, ClauseName, Option<Fixity>), // arity, name, fixity if it has one.
|
||||
}
|
||||
|
||||
impl HeapCellValue {
|
||||
@@ -1233,15 +1302,7 @@ impl Term {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_callable(&self) -> bool {
|
||||
match self {
|
||||
&Term::Clause(..) | &Term::Constant(_, Constant::Atom(_)) =>
|
||||
true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<TabledRc<Atom>> {
|
||||
pub fn name(&self) -> Option<ClauseName> {
|
||||
match self {
|
||||
&Term::Constant(_, Constant::Atom(ref atom))
|
||||
| &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
|
||||
@@ -1259,20 +1320,27 @@ impl Term {
|
||||
|
||||
pub enum TermIterState<'a> {
|
||||
AnonVar(Level),
|
||||
Clause(usize, ClauseType<'a>, &'a Vec<Box<Term>>),
|
||||
Constant(Level, &'a Cell<RegType>, &'a Constant),
|
||||
Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
|
||||
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
|
||||
Var(Level, &'a Cell<VarReg>, &'a Var)
|
||||
}
|
||||
|
||||
impl<'a> TermIterState<'a> {
|
||||
pub fn to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
|
||||
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
|
||||
match term {
|
||||
&Term::AnonVar =>
|
||||
TermIterState::AnonVar(lvl),
|
||||
&Term::Clause(ref cell, ref atom, ref child_terms, fixity) =>
|
||||
TermIterState::Clause(0, ClauseType::Deep(lvl, cell, atom, fixity), child_terms),
|
||||
&Term::Clause(ref cell, ref name, ref subterms, fixity) => {
|
||||
let ct = if let Some(fixity) = fixity {
|
||||
ClauseType::Op(name.clone(), fixity)
|
||||
} else {
|
||||
ClauseType::Named(name.clone())
|
||||
};
|
||||
|
||||
TermIterState::Clause(lvl, 0, cell, ct, subterms)
|
||||
},
|
||||
&Term::Cons(ref cell, ref head, ref tail) =>
|
||||
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()),
|
||||
&Term::Constant(ref cell, ref constant) =>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::num::bigint::{BigInt};
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type PredicateKey = (TabledRc<Atom>, usize); // name, arity, type.
|
||||
pub type PredicateKey = (ClauseName, usize); // name, arity, type.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PredicateKeyType {
|
||||
@@ -13,13 +12,13 @@ pub enum PredicateKeyType {
|
||||
User
|
||||
}
|
||||
|
||||
pub type OpDirKey = (TabledRc<Atom>, Fixity);
|
||||
pub type OpDirKey = (ClauseName, 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(atom_tbl: TabledData<Atom>) -> Code {
|
||||
fn get_builtins() -> Code {
|
||||
vec![internal_call_n!(), // callN/N, 0.
|
||||
is_atomic!(temp_v!(1)), // atomic/1, 1.
|
||||
proceed!(),
|
||||
@@ -115,25 +114,25 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
retry!(7),
|
||||
trust!(10),
|
||||
try_me_else!(4),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
|
||||
get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
|
||||
fact![get_constant!(atom!("!"), temp_v!(1)),
|
||||
get_structure!(",", 2, temp_v!(2), Some(infix!())),
|
||||
unify_variable!(temp_v!(1)),
|
||||
unify_variable!(temp_v!(2))],
|
||||
set_cp!(temp_v!(3)),
|
||||
goto_execute!(83, 3),
|
||||
retry_me_else!(4),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
|
||||
get_constant!(atom!("!", atom_tbl), temp_v!(2))],
|
||||
fact![get_constant!(atom!("!"), temp_v!(1)),
|
||||
get_constant!(atom!("!"), temp_v!(2))],
|
||||
set_cp!(temp_v!(3)),
|
||||
proceed!(),
|
||||
trust_me!(),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1))],
|
||||
fact![get_constant!(atom!("!"), temp_v!(1))],
|
||||
set_cp!(temp_v!(3)),
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
execute_n!(1),
|
||||
retry_me_else!(8),
|
||||
allocate!(3),
|
||||
fact![get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
|
||||
fact![get_structure!(",", 2, temp_v!(2), Some(infix!())),
|
||||
unify_variable!(perm_v!(2)),
|
||||
unify_variable!(perm_v!(1)),
|
||||
get_var_in_fact!(perm_v!(3), 3)],
|
||||
@@ -147,7 +146,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
retry_me_else!(10),
|
||||
allocate!(2),
|
||||
get_level!(perm_v!(2)),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(2)),
|
||||
fact![get_constant!(atom!("!"), temp_v!(2)),
|
||||
get_var_in_fact!(perm_v!(1), 3)],
|
||||
neck_cut!(),
|
||||
call_n!(1),
|
||||
@@ -168,12 +167,12 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
indexed_try!(3),
|
||||
trust!(5),
|
||||
try_me_else!(3),
|
||||
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
|
||||
fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
|
||||
unify_variable!(temp_v!(1)),
|
||||
unify_variable!(temp_v!(2))],
|
||||
goto_execute!(139, 3),
|
||||
trust_me!(),
|
||||
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
|
||||
fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
|
||||
unify_void!(2)],
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
neck_cut!(),
|
||||
@@ -232,13 +231,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
goto_execute!(149, 3), // goto get_arg/3.
|
||||
trust_me!(),
|
||||
query![get_var_in_query!(temp_v!(4), 1),
|
||||
put_structure!(atom_tbl,
|
||||
Level::Shallow,
|
||||
String::from("type_error"),
|
||||
1,
|
||||
temp_v!(1),
|
||||
None),
|
||||
set_constant!(atom!("integer_expected", atom_tbl))],
|
||||
put_structure!("type_error", 1, temp_v!(1), None),
|
||||
set_constant!(atom!("integer_expected"))],
|
||||
goto_execute!(59, 1), // goto throw/1.
|
||||
try_me_else!(5), // arg_/5, 173.
|
||||
fact![get_value!(temp_v!(1), 2),
|
||||
@@ -405,13 +399,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
trust_me!(),
|
||||
fact![get_var_in_fact!(temp_v!(3), 1),
|
||||
get_var_in_fact!(temp_v!(4), 2)],
|
||||
query![put_structure!(atom_tbl,
|
||||
Level::Shallow,
|
||||
String::from("type_error"),
|
||||
2,
|
||||
temp_v!(1),
|
||||
None),
|
||||
set_constant!(atom!("integer_expected", atom_tbl)),
|
||||
query![put_structure!("type_error", 2, temp_v!(1), None),
|
||||
set_constant!(atom!("integer_expected")),
|
||||
set_value!(temp_v!(4))],
|
||||
goto_execute!(59, 1), // goto throw/1, 59.
|
||||
switch_on_term!(1,2,5,0), // length/3, 281.
|
||||
@@ -453,7 +442,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
try_me_else!(5), // 304.
|
||||
is_var!(temp_v!(1)),
|
||||
neck_cut!(),
|
||||
query![put_constant!(Level::Shallow, atom!("instantiation_error", atom_tbl),
|
||||
query![put_constant!(Level::Shallow,
|
||||
atom!("instantiation_error"),
|
||||
temp_v!(1))],
|
||||
goto_execute!(59, 1),
|
||||
trust_me!(),
|
||||
@@ -502,7 +492,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
get_cleaner_call!(),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_var!(temp_v!(4), 2),
|
||||
put_constant!(Level::Shallow, atom!("true", atom_tbl), temp_v!(3))],
|
||||
put_constant!(Level::Shallow, atom!("true"), temp_v!(3))],
|
||||
goto_call!(5, 3), // goto catch/3, 5.
|
||||
set_cp!(perm_v!(1)),
|
||||
deallocate!(),
|
||||
@@ -621,9 +611,9 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
remove_call_policy_check!(),
|
||||
fail!(),
|
||||
try_me_else!(4), // handle_ile/3, 444.
|
||||
fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
|
||||
fact![get_structure!("inference_limit_exceeded", 1, temp_v!(2), None),
|
||||
unify_value!(temp_v!(1)),
|
||||
get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
|
||||
get_constant!(atom!("inference_limit_exceeded"), temp_v!(3))],
|
||||
neck_cut!(),
|
||||
proceed!(),
|
||||
default_trust_me!(),
|
||||
@@ -648,119 +638,119 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
]
|
||||
}
|
||||
|
||||
pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
|
||||
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(atom_tbl.clone());
|
||||
let builtin_code = get_builtins();
|
||||
|
||||
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((tabled_rc!("?-", atom_tbl), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((tabled_rc!("\\+", atom_tbl), Fixity::Pre), (FY, 900));
|
||||
op_dir.insert((tabled_rc!("=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
|
||||
op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
|
||||
|
||||
// arithmetic operators.
|
||||
op_dir.insert((tabled_rc!("is", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("+", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("/\\", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("\\/", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("xor", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("//", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("/", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("div", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("*", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((tabled_rc!("rdiv", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("<<", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!(">>", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("mod", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("rem", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
|
||||
|
||||
// arithmetic comparison operators.
|
||||
op_dir.insert((tabled_rc!(">", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=\\=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=:=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!(">=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((tabled_rc!(";", atom_tbl), Fixity::In), (XFY, 1100));
|
||||
op_dir.insert((tabled_rc!("->", atom_tbl), Fixity::In), (XFY, 1050));
|
||||
op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
|
||||
op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
|
||||
|
||||
op_dir.insert((tabled_rc!("=..", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("==", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("\\==", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("@=<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("@>=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("@<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("@>", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=@=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("\\=@=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
|
||||
|
||||
// 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 {
|
||||
code_dir.insert((tabled_rc!("call", atom_tbl), arity), (PredicateKeyType::BuiltIn, 0));
|
||||
code_dir.insert((clause_name!("call"), arity), (PredicateKeyType::BuiltIn, 0));
|
||||
}
|
||||
|
||||
code_dir.insert((tabled_rc!("atomic", atom_tbl), 1), (PredicateKeyType::BuiltIn, 1));
|
||||
code_dir.insert((tabled_rc!("var", atom_tbl), 1), (PredicateKeyType::BuiltIn, 3));
|
||||
code_dir.insert((tabled_rc!("false", atom_tbl), 0), (PredicateKeyType::BuiltIn, 61));
|
||||
code_dir.insert((tabled_rc!("\\+", atom_tbl), 1), (PredicateKeyType::BuiltIn, 62));
|
||||
code_dir.insert((tabled_rc!("duplicate_term", atom_tbl), 2), (PredicateKeyType::BuiltIn, 71));
|
||||
code_dir.insert((tabled_rc!("catch", atom_tbl), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((tabled_rc!("throw", atom_tbl), 1), (PredicateKeyType::BuiltIn, 59));
|
||||
code_dir.insert((tabled_rc!("=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 73));
|
||||
code_dir.insert((tabled_rc!("true", atom_tbl), 0), (PredicateKeyType::BuiltIn, 75));
|
||||
code_dir.insert((clause_name!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
||||
code_dir.insert((clause_name!("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
||||
code_dir.insert((clause_name!("false"), 0), (PredicateKeyType::BuiltIn, 61));
|
||||
code_dir.insert((clause_name!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
|
||||
code_dir.insert((clause_name!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
|
||||
code_dir.insert((clause_name!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((clause_name!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
|
||||
code_dir.insert((clause_name!("="), 2), (PredicateKeyType::BuiltIn, 73));
|
||||
code_dir.insert((clause_name!("true"), 0), (PredicateKeyType::BuiltIn, 75));
|
||||
|
||||
code_dir.insert((tabled_rc!(",", atom_tbl), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((tabled_rc!(";", atom_tbl), 2), (PredicateKeyType::BuiltIn, 120));
|
||||
code_dir.insert((tabled_rc!("->", atom_tbl), 2), (PredicateKeyType::BuiltIn, 138));
|
||||
code_dir.insert((clause_name!(","), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((clause_name!(";"), 2), (PredicateKeyType::BuiltIn, 120));
|
||||
code_dir.insert((clause_name!("->"), 2), (PredicateKeyType::BuiltIn, 138));
|
||||
|
||||
code_dir.insert((tabled_rc!("functor", atom_tbl), 3), (PredicateKeyType::BuiltIn, 146));
|
||||
code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
|
||||
code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
|
||||
code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
|
||||
code_dir.insert((clause_name!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
|
||||
code_dir.insert((clause_name!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
|
||||
code_dir.insert((clause_name!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
|
||||
code_dir.insert((clause_name!("display"), 1), (PredicateKeyType::BuiltIn, 192));
|
||||
|
||||
code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
|
||||
code_dir.insert((tabled_rc!(">", atom_tbl), 2), (PredicateKeyType::BuiltIn, 196));
|
||||
code_dir.insert((tabled_rc!("<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 198));
|
||||
code_dir.insert((tabled_rc!(">=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 200));
|
||||
code_dir.insert((tabled_rc!("<=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 202));
|
||||
code_dir.insert((tabled_rc!("=\\=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 204));
|
||||
code_dir.insert((tabled_rc!("=:=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 206));
|
||||
code_dir.insert((tabled_rc!("=..", atom_tbl), 2), (PredicateKeyType::BuiltIn, 208));
|
||||
code_dir.insert((clause_name!("is"), 2), (PredicateKeyType::BuiltIn, 194));
|
||||
code_dir.insert((clause_name!(">"), 2), (PredicateKeyType::BuiltIn, 196));
|
||||
code_dir.insert((clause_name!("<"), 2), (PredicateKeyType::BuiltIn, 198));
|
||||
code_dir.insert((clause_name!(">="), 2), (PredicateKeyType::BuiltIn, 200));
|
||||
code_dir.insert((clause_name!("<="), 2), (PredicateKeyType::BuiltIn, 202));
|
||||
code_dir.insert((clause_name!("=\\="), 2), (PredicateKeyType::BuiltIn, 204));
|
||||
code_dir.insert((clause_name!("=:="), 2), (PredicateKeyType::BuiltIn, 206));
|
||||
code_dir.insert((clause_name!("=.."), 2), (PredicateKeyType::BuiltIn, 208));
|
||||
|
||||
code_dir.insert((tabled_rc!("length", atom_tbl), 2), (PredicateKeyType::BuiltIn, 261));
|
||||
code_dir.insert((tabled_rc!("setup_call_cleanup", atom_tbl), 3),
|
||||
code_dir.insert((clause_name!("length"), 2), (PredicateKeyType::BuiltIn, 261));
|
||||
code_dir.insert((clause_name!("setup_call_cleanup"), 3),
|
||||
(PredicateKeyType::BuiltIn, 294));
|
||||
code_dir.insert((tabled_rc!("call_with_inference_limit", atom_tbl), 3),
|
||||
code_dir.insert((clause_name!("call_with_inference_limit"), 3),
|
||||
(PredicateKeyType::BuiltIn, 393));
|
||||
code_dir.insert((tabled_rc!("_handle_inference_limit_exceeded", atom_tbl), 2),
|
||||
code_dir.insert((clause_name!("_handle_inference_limit_exceeded"), 2),
|
||||
(PredicateKeyType::BuiltIn, 421));
|
||||
|
||||
code_dir.insert((tabled_rc!("compound", atom_tbl), 1), (PredicateKeyType::BuiltIn, 372));
|
||||
code_dir.insert((tabled_rc!("rational", atom_tbl), 1), (PredicateKeyType::BuiltIn, 374));
|
||||
code_dir.insert((tabled_rc!("string", atom_tbl), 1), (PredicateKeyType::BuiltIn, 376));
|
||||
code_dir.insert((tabled_rc!("float", atom_tbl), 1), (PredicateKeyType::BuiltIn, 378));
|
||||
code_dir.insert((tabled_rc!("nonvar", atom_tbl), 1), (PredicateKeyType::BuiltIn, 380));
|
||||
code_dir.insert((clause_name!("compound"), 1), (PredicateKeyType::BuiltIn, 372));
|
||||
code_dir.insert((clause_name!("rational"), 1), (PredicateKeyType::BuiltIn, 374));
|
||||
code_dir.insert((clause_name!("string"), 1), (PredicateKeyType::BuiltIn, 376));
|
||||
code_dir.insert((clause_name!("float"), 1), (PredicateKeyType::BuiltIn, 378));
|
||||
code_dir.insert((clause_name!("nonvar"), 1), (PredicateKeyType::BuiltIn, 380));
|
||||
|
||||
code_dir.insert((tabled_rc!("ground", atom_tbl), 1), (PredicateKeyType::BuiltIn, 384));
|
||||
code_dir.insert((tabled_rc!("==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 385));
|
||||
code_dir.insert((tabled_rc!("\\==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 386));
|
||||
code_dir.insert((tabled_rc!("@>=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 387));
|
||||
code_dir.insert((tabled_rc!("@=<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 388));
|
||||
code_dir.insert((tabled_rc!("@>", atom_tbl), 2), (PredicateKeyType::BuiltIn, 389));
|
||||
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
|
||||
code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
|
||||
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
|
||||
code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
|
||||
code_dir.insert((clause_name!("ground"), 1), (PredicateKeyType::BuiltIn, 384));
|
||||
code_dir.insert((clause_name!("=="), 2), (PredicateKeyType::BuiltIn, 385));
|
||||
code_dir.insert((clause_name!("\\=="), 2), (PredicateKeyType::BuiltIn, 386));
|
||||
code_dir.insert((clause_name!("@>="), 2), (PredicateKeyType::BuiltIn, 387));
|
||||
code_dir.insert((clause_name!("@=<"), 2), (PredicateKeyType::BuiltIn, 388));
|
||||
code_dir.insert((clause_name!("@>"), 2), (PredicateKeyType::BuiltIn, 389));
|
||||
code_dir.insert((clause_name!("@<"), 2), (PredicateKeyType::BuiltIn, 390));
|
||||
code_dir.insert((clause_name!("=@="), 2), (PredicateKeyType::BuiltIn, 391));
|
||||
code_dir.insert((clause_name!("\\=@="), 2), (PredicateKeyType::BuiltIn, 392));
|
||||
code_dir.insert((clause_name!("compare"), 3), (PredicateKeyType::BuiltIn, 464));
|
||||
|
||||
(builtin_code, code_dir, op_dir)
|
||||
}
|
||||
|
||||
@@ -156,25 +156,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
};
|
||||
}
|
||||
|
||||
fn compile_clause<Target>(&mut self, ct: ClauseType<'a>, term_loc: GenContext,
|
||||
is_exposed: bool, terms: &'a Vec<Box<Term>>,
|
||||
target: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
match ct {
|
||||
ClauseType::Deep(lvl, cell, atom, fixity) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, target);
|
||||
target.push(Target::to_structure(lvl, atom.clone(), terms.len(),
|
||||
cell.get(), fixity));
|
||||
|
||||
for subterm in terms {
|
||||
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, target);
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
|
||||
-> Vec<Target>
|
||||
where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
|
||||
@@ -183,8 +164,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
|
||||
for term in iter {
|
||||
match term {
|
||||
TermRef::Clause(ct, terms) =>
|
||||
self.compile_clause(ct, term_loc, is_exposed, terms, &mut target),
|
||||
TermRef::Clause(lvl, cell, ct, terms) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
target.push(Target::to_structure(ct, terms.len(), cell.get()));
|
||||
|
||||
for subterm in terms {
|
||||
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
|
||||
}
|
||||
},
|
||||
TermRef::Cons(lvl, cell, head, tail) => {
|
||||
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
|
||||
target.push(Target::to_list(lvl, cell.get()));
|
||||
@@ -214,24 +201,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a>
|
||||
{
|
||||
let mut vs = VariableFixtures::new();
|
||||
let at_rule_head = iter.at_rule_head();
|
||||
|
||||
while let Some((chunk_num, lt_arity, terms)) = iter.next() {
|
||||
for (i, query_term) in terms.iter().enumerate() {
|
||||
let term_loc = if chunk_num == 0 && i == 0 && at_rule_head {
|
||||
GenContext::Head
|
||||
} else if i < terms.len() - 1 {
|
||||
GenContext::Mid(chunk_num)
|
||||
} else {
|
||||
GenContext::Last(chunk_num)
|
||||
};
|
||||
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
|
||||
for (i, chunked_term) in chunked_terms.iter().enumerate() {
|
||||
let term_loc = match chunked_term {
|
||||
&ChunkedTerm::HeadClause(..) => GenContext::Head,
|
||||
&ChunkedTerm::BodyTerm(_) => if i < chunked_terms.len() - 1 {
|
||||
GenContext::Mid(chunk_num)
|
||||
} else {
|
||||
GenContext::Last(chunk_num)
|
||||
}
|
||||
};
|
||||
|
||||
self.update_var_count(query_term.post_order_iter());
|
||||
vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
|
||||
self.update_var_count(chunked_term.post_order_iter());
|
||||
vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
|
||||
}
|
||||
}
|
||||
|
||||
let num_of_chunks = iter.chunk_num();
|
||||
let num_of_chunks = iter.chunk_num;
|
||||
let has_deep_cut = iter.encountered_deep_cut();
|
||||
|
||||
vs.populate_restricting_sets();
|
||||
@@ -245,51 +232,51 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
|
||||
{
|
||||
match qt {
|
||||
&QueryTerm::CallWithInferenceLimit(_) =>
|
||||
code.push(goto_call!(393, 3)),
|
||||
&QueryTerm::SetupCallCleanup(_) =>
|
||||
code.push(goto_call!(294, 3)),
|
||||
&QueryTerm::Arg(_) => {
|
||||
let call = ControlInstruction::ArgCall;
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::CallN(ref terms) => {
|
||||
let call = ControlInstruction::CallN(terms.len());
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::Catch(_) =>
|
||||
code.push(Line::Control(ControlInstruction::CatchCall)),
|
||||
&QueryTerm::Compare(_) =>
|
||||
code.push(Line::Control(ControlInstruction::CompareCall)),
|
||||
&QueryTerm::CompareTerm(qt, _) =>
|
||||
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
|
||||
&QueryTerm::Display(_) =>
|
||||
code.push(Line::Control(ControlInstruction::DisplayCall)),
|
||||
&QueryTerm::DuplicateTerm(_) =>
|
||||
code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
|
||||
&QueryTerm::Eq(_) =>
|
||||
code.push(Line::Control(ControlInstruction::EqCall)),
|
||||
&QueryTerm::Ground(_) =>
|
||||
code.push(Line::Control(ControlInstruction::GroundCall)),
|
||||
&QueryTerm::Functor(_) =>
|
||||
code.push(Line::Control(ControlInstruction::FunctorCall)),
|
||||
&QueryTerm::Inlined(_) =>
|
||||
code.push(proceed!()),
|
||||
&QueryTerm::Jump(ref vars) => {
|
||||
code.push(jmp_call!(vars.len(), 0));
|
||||
},
|
||||
&QueryTerm::NotEq(_) =>
|
||||
code.push(Line::Control(ControlInstruction::NotEqCall)),
|
||||
&QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
|
||||
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::Term(Term::Clause(_, ref atom, ref terms, _)) => {
|
||||
let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&QueryTerm::Throw(_) =>
|
||||
code.push(Line::Control(ControlInstruction::ThrowCall)),
|
||||
&QueryTerm::Clause(_, ref ct, ref terms) =>
|
||||
match ct {
|
||||
&ClauseType::CallWithInferenceLimit =>
|
||||
code.push(goto_call!(393, 3)),
|
||||
&ClauseType::SetupCallCleanup =>
|
||||
code.push(goto_call!(294, 3)),
|
||||
&ClauseType::Arg => {
|
||||
let call = ControlInstruction::ArgCall;
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&ClauseType::CallN => {
|
||||
let call = ControlInstruction::CallN(terms.len());
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&ClauseType::Catch =>
|
||||
code.push(Line::Control(ControlInstruction::CatchCall)),
|
||||
&ClauseType::Compare =>
|
||||
code.push(Line::Control(ControlInstruction::CompareCall)),
|
||||
&ClauseType::CompareTerm(qt) =>
|
||||
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
|
||||
&ClauseType::Display =>
|
||||
code.push(Line::Control(ControlInstruction::DisplayCall)),
|
||||
&ClauseType::DuplicateTerm =>
|
||||
code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
|
||||
&ClauseType::Eq =>
|
||||
code.push(Line::Control(ControlInstruction::EqCall)),
|
||||
&ClauseType::Ground =>
|
||||
code.push(Line::Control(ControlInstruction::GroundCall)),
|
||||
&ClauseType::Functor =>
|
||||
code.push(Line::Control(ControlInstruction::FunctorCall)),
|
||||
&ClauseType::Inlined(_) =>
|
||||
code.push(proceed!()),
|
||||
&ClauseType::NotEq =>
|
||||
code.push(Line::Control(ControlInstruction::NotEqCall)),
|
||||
&ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => {
|
||||
let call = ControlInstruction::Call(name.clone(), terms.len(), pvs);
|
||||
code.push(Line::Control(call));
|
||||
},
|
||||
&ClauseType::Throw =>
|
||||
code.push(Line::Control(ControlInstruction::ThrowCall)),
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -344,11 +331,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
dealloc_index
|
||||
}
|
||||
|
||||
fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
|
||||
fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec<Box<Term>>,
|
||||
term_loc: GenContext, code: &mut Code)
|
||||
-> Result<(), ParserError>
|
||||
{
|
||||
match term {
|
||||
&InlinedQueryTerm::CompareNumber(cmp, ref terms) => {
|
||||
match ct {
|
||||
InlinedClauseType::CompareNumber(cmp) => {
|
||||
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
|
||||
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
|
||||
|
||||
@@ -359,8 +347,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
at_1.unwrap_or(interm!(1)),
|
||||
at_2.unwrap_or(interm!(2))));
|
||||
},
|
||||
&InlinedQueryTerm::IsAtomic(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsAtomic =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
|
||||
code.push(fail!());
|
||||
},
|
||||
@@ -372,8 +360,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(is_atomic!(r));
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsCompound(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsCompound =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Clause(..) | &Term::Cons(..) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
@@ -385,8 +373,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(fail!());
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsRational(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsRational =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Constant(_, Constant::Number(Number::Rational(_))) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
@@ -398,8 +386,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(fail!());
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsFloat(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsFloat =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Constant(_, Constant::Number(Number::Float(_))) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
@@ -411,8 +399,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(fail!());
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsString(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsString =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Constant(_, Constant::String(_)) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
@@ -424,8 +412,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(fail!());
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsNonVar(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsNonVar =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::AnonVar => {
|
||||
code.push(fail!());
|
||||
},
|
||||
@@ -437,8 +425,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(succeed!());
|
||||
}
|
||||
},
|
||||
&InlinedQueryTerm::IsInteger(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsInteger =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Constant(_, Constant::Number(Number::Integer(_))) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
@@ -450,8 +438,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.push(fail!());
|
||||
},
|
||||
},
|
||||
&InlinedQueryTerm::IsVar(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
InlinedClauseType::IsVar =>
|
||||
match terms[0].as_ref() {
|
||||
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
|
||||
code.push(fail!());
|
||||
},
|
||||
@@ -488,14 +476,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
GenContext::Last(chunk_num)
|
||||
};
|
||||
|
||||
let term = if let &ChunkedTerm::BodyTerm(ref term) = term {
|
||||
Ok(term)
|
||||
} else {
|
||||
Err(ParserError::InadmissibleQueryTerm)
|
||||
}?;
|
||||
|
||||
match *term {
|
||||
&QueryTerm::Cut =>
|
||||
code.push(if chunk_num == 0 {
|
||||
Line::Cut(CutInstruction::NeckCut)
|
||||
} else {
|
||||
Line::Cut(CutInstruction::Cut(perm_v!(1)))
|
||||
}),
|
||||
&QueryTerm::Is(ref terms) => {
|
||||
}),
|
||||
&QueryTerm::Clause(_, ClauseType::Is, ref terms) => {
|
||||
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
|
||||
code.append(&mut acode);
|
||||
|
||||
@@ -510,7 +504,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
if !target.is_empty() {
|
||||
code.push(Line::Query(target));
|
||||
}
|
||||
|
||||
|
||||
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
|
||||
},
|
||||
&Term::Constant(_, ref c @ Constant::Number(_)) => {
|
||||
@@ -524,8 +518,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
}
|
||||
}
|
||||
},
|
||||
&QueryTerm::Inlined(ref term) =>
|
||||
try!(self.compile_inlined(term, term_loc, code)),
|
||||
&QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) =>
|
||||
try!(self.compile_inlined(ct, terms, term_loc, code)),
|
||||
_ => {
|
||||
let num_perm_vars = if chunk_num == 0 {
|
||||
conjunct_info.perm_vars()
|
||||
@@ -535,7 +529,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
|
||||
self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
self.marker.reset_contents();
|
||||
@@ -559,10 +553,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
|
||||
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
|
||||
{
|
||||
// add a proceed to bookend any trailing inlines or cuts.
|
||||
// add a proceed to bookend any trailing cuts.
|
||||
match toc {
|
||||
&QueryTerm::Inlined(_) | &QueryTerm::Cut =>
|
||||
code.push(proceed!()),
|
||||
&QueryTerm::Cut => code.push(proceed!()),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
@@ -579,42 +572,37 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
let iter = ChunkedIterator::from_rule(rule);
|
||||
let conjunct_info = self.collect_var_data(iter);
|
||||
|
||||
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
||||
let &Rule { head: (_, ref args, ref p1), ref clauses } = rule;
|
||||
let mut code = Vec::new();
|
||||
|
||||
if let &QueryTerm::Term(ref term) = p0 {
|
||||
self.marker.reset_arg(term.arity());
|
||||
self.compile_seq_prelude(&conjunct_info, &mut code);
|
||||
self.marker.reset_arg(args.len());
|
||||
self.compile_seq_prelude(&conjunct_info, &mut code);
|
||||
|
||||
if let &Term::Clause(..) = term {
|
||||
let iter = FactInstruction::iter(term);
|
||||
let fact = self.compile_target(iter, GenContext::Head, false);
|
||||
let iter = FactIterator::from_rule_head_clause(args);
|
||||
let fact = self.compile_target(iter, GenContext::Head, false);
|
||||
|
||||
if !fact.is_empty() {
|
||||
code.push(Line::Fact(fact));
|
||||
}
|
||||
}
|
||||
|
||||
let iter = ChunkedIterator::from_rule_body(p1, clauses);
|
||||
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
|
||||
|
||||
if conjunct_info.allocates() {
|
||||
let index = if let &Line::Control(_) = code.last().unwrap() {
|
||||
code.len() - 2
|
||||
} else {
|
||||
code.len() - 1
|
||||
};
|
||||
|
||||
if let &mut Line::Query(ref mut query) = &mut code[index] {
|
||||
conjunct_info.perm_vs.mark_unsafe_vars_in_rule(term, query);
|
||||
}
|
||||
}
|
||||
|
||||
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
||||
Ok(code)
|
||||
} else {
|
||||
Err(ParserError::InvalidRuleHead)
|
||||
if !fact.is_empty() {
|
||||
code.push(Line::Fact(fact));
|
||||
}
|
||||
|
||||
let iter = ChunkedIterator::from_rule_body(p1, clauses);
|
||||
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
|
||||
|
||||
if conjunct_info.allocates() {
|
||||
let index = if let &Line::Control(_) = code.last().unwrap() {
|
||||
code.len() - 2
|
||||
} else {
|
||||
code.len() - 1
|
||||
};
|
||||
|
||||
if let &mut Line::Query(ref mut query) = &mut code[index] {
|
||||
let head_iter = FactIterator::from_rule_head_clause(args);
|
||||
conjunct_info.perm_vs.mark_unsafe_vars_in_rule(head_iter, query);
|
||||
}
|
||||
}
|
||||
|
||||
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
|
||||
Ok(code)
|
||||
}
|
||||
|
||||
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
|
||||
|
||||
@@ -210,7 +210,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
|
||||
|
||||
match lvl {
|
||||
Level::Deep => target.push(Target::subterm_to_variable(r)),
|
||||
Level::Shallow => {
|
||||
Level::Root | Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
self.arg_c += 1;
|
||||
|
||||
@@ -218,12 +218,9 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn mark_non_var<Target>(&mut self,
|
||||
lvl: Level,
|
||||
term_loc: GenContext,
|
||||
cell: &Cell<RegType>,
|
||||
target: &mut Vec<Target>)
|
||||
|
||||
fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
|
||||
cell: &Cell<RegType>, target: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
let r = cell.get();
|
||||
@@ -270,7 +267,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
|
||||
};
|
||||
|
||||
match lvl {
|
||||
Level::Shallow => {
|
||||
Level::Root | Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
|
||||
if self.is_curr_arg_distinct_from(var) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::iterators::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
@@ -275,9 +276,9 @@ impl<'a> VariableFixtures<'a>
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
|
||||
fn mark_head_vars_as_safe(&self, head_iter: FactIterator<'a>, unsafe_vars: &mut HashMap<RegType, bool>)
|
||||
{
|
||||
for term_ref in head.breadth_first_iter() {
|
||||
for term_ref in head_iter {
|
||||
match term_ref {
|
||||
TermRef::Var(Level::Shallow, cell, _) => {
|
||||
unsafe_vars.remove(&cell.get().norm());
|
||||
@@ -294,12 +295,12 @@ impl<'a> VariableFixtures<'a>
|
||||
self.mark_unsafe_vars(&mut unsafe_vars, query);
|
||||
}
|
||||
|
||||
pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
|
||||
pub fn mark_unsafe_vars_in_rule(&self, head_iter: FactIterator<'a>, query: &mut CompiledQuery)
|
||||
{
|
||||
let mut unsafe_vars = HashMap::new();
|
||||
|
||||
self.record_unsafe_vars(&mut unsafe_vars);
|
||||
self.mark_head_vars_as_safe(head, &mut unsafe_vars);
|
||||
self.mark_head_vars_as_safe(head_iter, &mut unsafe_vars);
|
||||
self.mark_unsafe_vars(&mut unsafe_vars, query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::heap_iter::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TokenOrRedirect {
|
||||
Atom(TabledRc<Atom>),
|
||||
Atom(ClauseName),
|
||||
Redirect,
|
||||
Open,
|
||||
Close,
|
||||
@@ -21,7 +20,7 @@ pub enum TokenOrRedirect {
|
||||
pub trait HeapCellValueFormatter {
|
||||
// this function belongs to the display predicate formatter, which it uses
|
||||
// to format all clauses.
|
||||
fn format_struct(&self, arity: usize, name: TabledRc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
fn format_struct(&self, arity: usize, name: ClauseName, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
state_stack.push(TokenOrRedirect::Close);
|
||||
|
||||
@@ -38,7 +37,7 @@ pub trait HeapCellValueFormatter {
|
||||
|
||||
// this can be overloaded to handle special cases, falling back on the default of
|
||||
// format_struct when convenient.
|
||||
fn format_clause(&self, usize, TabledRc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
|
||||
fn format_clause(&self, usize, ClauseType, &mut Vec<TokenOrRedirect>);
|
||||
}
|
||||
|
||||
pub trait HeapCellValueOutputter {
|
||||
@@ -95,18 +94,16 @@ impl HeapCellValueOutputter for PrinterOutputter {
|
||||
pub struct DisplayFormatter {}
|
||||
|
||||
impl HeapCellValueFormatter for DisplayFormatter {
|
||||
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
|
||||
state_stack: &mut Vec<TokenOrRedirect>)
|
||||
fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
if fixity.is_some() {
|
||||
if ct.fixity().is_some() {
|
||||
let mut new_name = String::from("'");
|
||||
new_name += name.as_ref();
|
||||
new_name += ct.name().as_str();
|
||||
new_name += "'";
|
||||
|
||||
let name = TabledRc::new(new_name, name.table());
|
||||
self.format_struct(arity, name, state_stack);
|
||||
|
||||
self.format_struct(arity, ct.name(), state_stack);
|
||||
} else {
|
||||
self.format_struct(arity, name, state_stack);
|
||||
self.format_struct(arity, ct.name(), state_stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,31 +111,30 @@ impl HeapCellValueFormatter for DisplayFormatter {
|
||||
pub struct TermFormatter {}
|
||||
|
||||
impl HeapCellValueFormatter for TermFormatter {
|
||||
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
|
||||
state_stack: &mut Vec<TokenOrRedirect>)
|
||||
fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
if let Some(fixity) = fixity {
|
||||
if let Some(fixity) = ct.fixity() {
|
||||
match fixity {
|
||||
Fixity::Post => {
|
||||
state_stack.push(TokenOrRedirect::Atom(name));
|
||||
state_stack.push(TokenOrRedirect::Atom(ct.name()));
|
||||
state_stack.push(TokenOrRedirect::Space);
|
||||
state_stack.push(TokenOrRedirect::Redirect);
|
||||
},
|
||||
Fixity::Pre => {
|
||||
state_stack.push(TokenOrRedirect::Redirect);
|
||||
state_stack.push(TokenOrRedirect::Space);
|
||||
state_stack.push(TokenOrRedirect::Atom(name));
|
||||
state_stack.push(TokenOrRedirect::Atom(ct.name()));
|
||||
},
|
||||
Fixity::In => {
|
||||
state_stack.push(TokenOrRedirect::Redirect);
|
||||
state_stack.push(TokenOrRedirect::Space);
|
||||
state_stack.push(TokenOrRedirect::Atom(name));
|
||||
state_stack.push(TokenOrRedirect::Atom(ct.name()));
|
||||
state_stack.push(TokenOrRedirect::Space);
|
||||
state_stack.push(TokenOrRedirect::Redirect);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.format_struct(arity, name, state_stack);
|
||||
self.format_struct(arity, ct.name(), state_stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,8 +157,10 @@ impl<'a, Formatter: HeapCellValueFormatter, Outputter: HeapCellValueOutputter>
|
||||
|
||||
fn handle_heap_term(&mut self, heap_val: HeapCellValue) {
|
||||
match heap_val {
|
||||
HeapCellValue::NamedStr(arity, name, fixity) =>
|
||||
self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
|
||||
HeapCellValue::NamedStr(arity, name, fixity) => {
|
||||
let ct = ClauseType::from(name, arity, fixity);
|
||||
self.formatter.format_clause(arity, ct, &mut self.state_stack)
|
||||
},
|
||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
||||
if !self.at_cdr("") {
|
||||
self.outputter.append("[]");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::hash::Hash;
|
||||
@@ -12,7 +11,7 @@ enum IntIndex {
|
||||
pub struct CodeOffsets {
|
||||
pub constants: HashMap<Constant, ThirdLevelIndex>,
|
||||
pub lists: ThirdLevelIndex,
|
||||
pub structures: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>
|
||||
pub structures: HashMap<(ClauseName, usize), ThirdLevelIndex>
|
||||
}
|
||||
|
||||
impl CodeOffsets {
|
||||
@@ -145,7 +144,7 @@ impl CodeOffsets {
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_on_structure(str_ind: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>,
|
||||
fn switch_on_structure(str_ind: HashMap<(ClauseName, usize), ThirdLevelIndex>,
|
||||
prelude: &mut CodeDeque)
|
||||
-> IntIndex
|
||||
{
|
||||
|
||||
@@ -13,21 +13,21 @@ use termion::event::Key;
|
||||
use std::io::{Write, stdin, stdout};
|
||||
use std::fmt;
|
||||
|
||||
impl fmt::Display for ClauseName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
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::GetConstant(lvl, ref constant, ref r) =>
|
||||
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num()),
|
||||
&FactInstruction::GetList(lvl, ref r) =>
|
||||
write!(f, "get_list {}{}", lvl, r.reg_num()),
|
||||
&FactInstruction::GetStructure(ref ct, ref arity, ref r) =>
|
||||
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r),
|
||||
&FactInstruction::GetValue(ref x, ref a) =>
|
||||
write!(f, "get_value {}, A{}", x, a),
|
||||
&FactInstruction::GetVariable(ref x, ref a) =>
|
||||
@@ -51,18 +51,12 @@ impl fmt::Display for QueryInstruction {
|
||||
match self {
|
||||
&QueryInstruction::GetVariable(ref x, ref a) =>
|
||||
write!(f, "query:get_variable {}, A{}", x, a),
|
||||
&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::PutConstant(lvl, ref constant, ref r) =>
|
||||
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num()),
|
||||
&QueryInstruction::PutList(lvl, ref r) =>
|
||||
write!(f, "put_list {}{}", lvl, r.reg_num()),
|
||||
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) =>
|
||||
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r),
|
||||
&QueryInstruction::PutUnsafeValue(y, a) =>
|
||||
write!(f, "put_unsafe_value Y{}, A{}", y, a),
|
||||
&QueryInstruction::PutValue(ref x, ref a) =>
|
||||
@@ -382,7 +376,7 @@ impl fmt::Display for CutInstruction {
|
||||
impl fmt::Display for Level {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Level::Shallow => write!(f, "A"),
|
||||
&Level::Root | &Level::Shallow => write!(f, "A"),
|
||||
&Level::Deep => write!(f, "X")
|
||||
}
|
||||
}
|
||||
@@ -531,7 +525,7 @@ fn compile_query<'a>(terms: &'a Vec<QueryTerm>, queue: &'a Vec<TopLevel>)
|
||||
let mut code = try!(cg.compile_query(terms));
|
||||
|
||||
compile_appendix(&mut code, queue)?;
|
||||
|
||||
|
||||
Ok((code, cg.take_vars()))
|
||||
}
|
||||
|
||||
|
||||
@@ -10,21 +10,31 @@ pub struct QueryIterator<'a> {
|
||||
|
||||
impl<'a> QueryIterator<'a> {
|
||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||
self.state_stack.push(TermIterState::to_state(lvl, term));
|
||||
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
|
||||
}
|
||||
|
||||
fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
|
||||
let state_stack = terms.iter().rev()
|
||||
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
|
||||
.collect();
|
||||
|
||||
QueryIterator { state_stack }
|
||||
}
|
||||
|
||||
fn from_term(term: &'a Term) -> Self {
|
||||
let state = match term {
|
||||
&Term::AnonVar =>
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Clause(_, ref name, ref terms, _) =>
|
||||
TermIterState::Clause(0, ClauseType::Root(name), terms),
|
||||
&Term::Clause(ref r, ref name, ref terms, fixity) =>
|
||||
TermIterState::Clause(Level::Root, 0, r,
|
||||
ClauseType::from(name.clone(), terms.len(), fixity),
|
||||
terms),
|
||||
&Term::Cons(..) =>
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Constant(_, _) =>
|
||||
return QueryIterator { state_stack: vec![] },
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
TermIterState::Var(Level::Shallow, cell, var)
|
||||
TermIterState::Var(Level::Root, cell, var)
|
||||
};
|
||||
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
@@ -32,87 +42,18 @@ impl<'a> QueryIterator<'a> {
|
||||
|
||||
fn new(term: &'a QueryTerm) -> Self {
|
||||
match term {
|
||||
&QueryTerm::CallN(ref terms) => {
|
||||
let state = TermIterState::Clause(1, ClauseType::CallN, terms);
|
||||
&QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms) => {
|
||||
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::CallWithInferenceLimit(ref terms) => {
|
||||
let ct = ClauseType::CallWithInferenceLimit;
|
||||
let state = TermIterState::Clause(0, ct, terms);
|
||||
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Catch(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Catch, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::DuplicateTerm(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::DuplicateTerm, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Arg(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Arg, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::SetupCallCleanup(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::SetupCallCleanup, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Eq(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Eq, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Functor(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Functor, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Display(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Display, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Ground(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Ground, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(qt, ref terms)) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Compare(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Compare, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::CompareTerm(qt, ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Is(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Is, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsNonVar(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsFloat(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsRational(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsCompound(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsString(ref terms)) =>
|
||||
Self::from_term(terms[0].as_ref()),
|
||||
&QueryTerm::NotEq(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::NotEq, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Term(ref term) =>
|
||||
Self::from_term(term),
|
||||
&QueryTerm::Throw(ref term) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Throw, term);
|
||||
&QueryTerm::Clause(ref cell, ref ct, ref terms) => {
|
||||
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
&QueryTerm::Cut => QueryIterator { state_stack: vec![] },
|
||||
&QueryTerm::Jump(ref vars) => {
|
||||
let state_stack = vars.iter().rev().map(|t| {
|
||||
TermIterState::to_state(Level::Shallow, t)
|
||||
TermIterState::subterm_to_state(Level::Shallow, t)
|
||||
}).collect();
|
||||
|
||||
QueryIterator { state_stack }
|
||||
@@ -121,12 +62,6 @@ impl<'a> QueryIterator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl QueryTerm {
|
||||
pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
|
||||
QueryIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for QueryIterator<'a> {
|
||||
type Item = TermRef<'a>;
|
||||
|
||||
@@ -135,25 +70,30 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
match iter_state {
|
||||
TermIterState::AnonVar(lvl) =>
|
||||
return Some(TermRef::AnonVar(lvl)),
|
||||
TermIterState::Clause(child_num, ct, child_terms) => {
|
||||
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
|
||||
if child_num == child_terms.len() {
|
||||
match ct {
|
||||
ClauseType::CallN =>
|
||||
self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
|
||||
ClauseType::Deep(..) =>
|
||||
return Some(TermRef::Clause(ct, child_terms)),
|
||||
ClauseType::Named(..) | ClauseType::Op(..) =>
|
||||
return match lvl {
|
||||
Level::Root => None,
|
||||
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms))
|
||||
},
|
||||
_ =>
|
||||
return None
|
||||
};
|
||||
} else {
|
||||
self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
|
||||
self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
|
||||
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1,
|
||||
cell, ct, child_terms));
|
||||
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
|
||||
}
|
||||
},
|
||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
|
||||
self.push_subterm(Level::Deep, tail);
|
||||
self.push_subterm(Level::Deep, head);
|
||||
|
||||
self.push_subterm(lvl.child_level(), tail);
|
||||
self.push_subterm(lvl.child_level(), head);
|
||||
},
|
||||
TermIterState::FinalCons(lvl, cell, head, tail) =>
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail)),
|
||||
@@ -174,24 +114,31 @@ pub struct FactIterator<'a> {
|
||||
|
||||
impl<'a> FactIterator<'a> {
|
||||
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
|
||||
self.state_queue.push_back(TermIterState::to_state(lvl, term));
|
||||
self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
|
||||
}
|
||||
|
||||
fn new(term: &'a Term) -> FactIterator<'a> {
|
||||
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
|
||||
let state_queue = terms.iter()
|
||||
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
|
||||
.collect();
|
||||
|
||||
FactIterator { state_queue }
|
||||
}
|
||||
|
||||
fn new(term: &'a Term) -> Self {
|
||||
let states = match term {
|
||||
&Term::AnonVar =>
|
||||
vec![TermIterState::AnonVar(Level::Shallow)],
|
||||
&Term::Clause(.., ref name, ref terms, _) =>
|
||||
vec![TermIterState::Clause(0, ClauseType::Root(name), terms)],
|
||||
vec![TermIterState::AnonVar(Level::Root)],
|
||||
&Term::Clause(ref cell, ref name, ref terms, fixity) => {
|
||||
let ct = ClauseType::from(name.clone(), terms.len(), fixity);
|
||||
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
|
||||
},
|
||||
&Term::Cons(ref cell, ref head, ref tail) =>
|
||||
vec![TermIterState::InitialCons(Level::Shallow,
|
||||
cell,
|
||||
head.as_ref(),
|
||||
tail.as_ref())],
|
||||
vec![TermIterState::InitialCons(Level::Root, cell, head.as_ref(), tail.as_ref())],
|
||||
&Term::Constant(ref cell, ref constant) =>
|
||||
vec![TermIterState::Constant(Level::Shallow, cell, constant)],
|
||||
vec![TermIterState::Constant(Level::Root, cell, constant)],
|
||||
&Term::Var(ref cell, ref var) =>
|
||||
vec![TermIterState::Var(Level::Shallow, cell, var)]
|
||||
vec![TermIterState::Var(Level::Root, cell, var)]
|
||||
};
|
||||
|
||||
FactIterator { state_queue: VecDeque::from(states) }
|
||||
@@ -206,16 +153,14 @@ impl<'a> Iterator for FactIterator<'a> {
|
||||
match state {
|
||||
TermIterState::AnonVar(lvl) =>
|
||||
return Some(TermRef::AnonVar(lvl)),
|
||||
TermIterState::Clause(_, ct, child_terms) => {
|
||||
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
|
||||
for child_term in child_terms {
|
||||
self.push_subterm(ct.level_of_subterms(), child_term);
|
||||
self.push_subterm(lvl.child_level(), child_term);
|
||||
}
|
||||
|
||||
match ct {
|
||||
ClauseType::Deep(..) =>
|
||||
return Some(TermRef::Clause(ct, child_terms)),
|
||||
_ =>
|
||||
continue
|
||||
match lvl {
|
||||
Level::Root => continue,
|
||||
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
|
||||
};
|
||||
},
|
||||
TermIterState::InitialCons(lvl, cell, head, tail) => {
|
||||
@@ -246,10 +191,32 @@ impl Term {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ChunkedTerm<'a> {
|
||||
HeadClause(ClauseName, &'a Vec<Box<Term>>),
|
||||
BodyTerm(&'a QueryTerm)
|
||||
}
|
||||
|
||||
impl QueryTerm {
|
||||
pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
|
||||
QueryIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ChunkedTerm<'a> {
|
||||
pub fn post_order_iter(&self) -> QueryIterator<'a> {
|
||||
match self {
|
||||
&ChunkedTerm::BodyTerm(ref qt) =>
|
||||
QueryIterator::new(qt),
|
||||
&ChunkedTerm::HeadClause(_, terms) =>
|
||||
QueryIterator::from_rule_head_clause(terms)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChunkedIterator<'a>
|
||||
{
|
||||
term_loc: GenContext,
|
||||
iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
|
||||
pub chunk_num: usize,
|
||||
iter: Box<Iterator<Item=ChunkedTerm<'a>> + 'a>,
|
||||
deep_cut_encountered: bool
|
||||
}
|
||||
|
||||
@@ -258,19 +225,19 @@ impl<'a> ChunkedIterator<'a>
|
||||
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
|
||||
{
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Last(0),
|
||||
iter: Box::new(terms.iter()),
|
||||
chunk_num: 0,
|
||||
iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
|
||||
deep_cut_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
|
||||
{
|
||||
let inner_iter = Box::new(once(p1));
|
||||
let iter = inner_iter.chain(clauses.iter());
|
||||
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
||||
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
|
||||
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Last(0),
|
||||
chunk_num: 0,
|
||||
iter: Box::new(iter),
|
||||
deep_cut_encountered: false
|
||||
}
|
||||
@@ -278,14 +245,14 @@ impl<'a> ChunkedIterator<'a>
|
||||
|
||||
pub fn from_rule(rule: &'a Rule) -> Self
|
||||
{
|
||||
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
||||
let &Rule { head: (ref name, ref args, ref p1), ref clauses } = rule;
|
||||
|
||||
let iter = once(p0);
|
||||
let inner_iter = Box::new(once(p1));
|
||||
let iter = iter.chain(inner_iter.chain(clauses.iter()));
|
||||
let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
|
||||
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
||||
let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))));
|
||||
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Head,
|
||||
chunk_num: 0,
|
||||
iter: Box::new(iter),
|
||||
deep_cut_encountered: false,
|
||||
}
|
||||
@@ -295,15 +262,7 @@ impl<'a> ChunkedIterator<'a>
|
||||
self.deep_cut_encountered
|
||||
}
|
||||
|
||||
pub fn at_rule_head(&self) -> bool {
|
||||
self.term_loc == GenContext::Head
|
||||
}
|
||||
|
||||
pub fn chunk_num(&self) -> usize {
|
||||
self.term_loc.chunk_num()
|
||||
}
|
||||
|
||||
fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
|
||||
fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>)
|
||||
{
|
||||
let mut arity = 0;
|
||||
let mut item = Some(term);
|
||||
@@ -311,81 +270,39 @@ impl<'a> ChunkedIterator<'a>
|
||||
|
||||
while let Some(term) = item {
|
||||
match term {
|
||||
&QueryTerm::Jump(ref vars) => {
|
||||
ChunkedTerm::HeadClause(..) =>
|
||||
result.push(term),
|
||||
ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
|
||||
result.push(term);
|
||||
arity = vars.len();
|
||||
break;
|
||||
},
|
||||
&QueryTerm::CompareTerm(..) => {
|
||||
result.push(term);
|
||||
arity = 2;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Term(ref inner_term) =>
|
||||
if let GenContext::Head = self.term_loc {
|
||||
result.push(term);
|
||||
self.term_loc = GenContext::Last(0);
|
||||
} else {
|
||||
result.push(term);
|
||||
|
||||
if inner_term.is_callable() {
|
||||
arity = inner_term.arity();
|
||||
break;
|
||||
}
|
||||
},
|
||||
&QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
|
||||
result.push(term);
|
||||
arity = 3;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::CallN(ref child_terms) => {
|
||||
result.push(term);
|
||||
arity = child_terms.len() + 1;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Catch(ref child_terms)
|
||||
| &QueryTerm::Throw(ref child_terms) => {
|
||||
result.push(term);
|
||||
arity = child_terms.len();
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Ground(_) | &QueryTerm::Display(_) => {
|
||||
result.push(term);
|
||||
arity = 1;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Arg(_)
|
||||
| &QueryTerm::Functor(_)
|
||||
| &QueryTerm::CallWithInferenceLimit(_) => {
|
||||
result.push(term);
|
||||
arity = 3;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Eq(_) | &QueryTerm::NotEq(_)
|
||||
| &QueryTerm::Is(_) | &QueryTerm::DuplicateTerm(_) => {
|
||||
result.push(term);
|
||||
arity = 2;
|
||||
break;
|
||||
},
|
||||
&QueryTerm::Inlined(_) =>
|
||||
result.push(term),
|
||||
&QueryTerm::Cut => {
|
||||
ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
|
||||
result.push(term);
|
||||
|
||||
if self.term_loc.chunk_num() > 0 {
|
||||
if self.chunk_num > 0 {
|
||||
self.deep_cut_encountered = true;
|
||||
}
|
||||
},
|
||||
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
|
||||
result.push(term),
|
||||
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
|
||||
result.push(term);
|
||||
arity = subterms.len() + 1;
|
||||
break;
|
||||
},
|
||||
ChunkedTerm::BodyTerm(qt) => {
|
||||
result.push(term);
|
||||
arity = qt.arity();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
item = self.iter.next();
|
||||
}
|
||||
|
||||
let chunk_num = self.term_loc.chunk_num();
|
||||
|
||||
if let &mut GenContext::Last(ref mut chunk_num) = &mut self.term_loc {
|
||||
*chunk_num += 1;
|
||||
}
|
||||
let chunk_num = self.chunk_num;
|
||||
self.chunk_num += 1;
|
||||
|
||||
(chunk_num, arity, result)
|
||||
}
|
||||
@@ -394,7 +311,7 @@ impl<'a> ChunkedIterator<'a>
|
||||
impl<'a> Iterator for ChunkedIterator<'a>
|
||||
{
|
||||
// the chunk number, last term arity, and vector of references.
|
||||
type Item = (usize, usize, Vec<&'a QueryTerm>);
|
||||
type Item = (usize, usize, Vec<ChunkedTerm<'a>>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|term| self.take_chunk(term))
|
||||
|
||||
@@ -185,7 +185,7 @@ pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||
|
||||
pub(crate) trait CallPolicy: Any {
|
||||
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
|
||||
name: TabledRc<Atom>, arity: usize)
|
||||
name: ClauseName, arity: usize)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
|
||||
@@ -204,7 +204,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
|
||||
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
|
||||
name: TabledRc<Atom>, arity: usize)
|
||||
name: ClauseName, arity: usize)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
|
||||
@@ -351,20 +351,19 @@ pub(crate) struct DefaultCallPolicy {}
|
||||
|
||||
impl CallPolicy for DefaultCallPolicy {}
|
||||
|
||||
pub(crate) struct CallWithInferenceLimitCallPolicy {
|
||||
atom_tbl: TabledData<Atom>,
|
||||
pub(crate) struct CallWithInferenceLimitCallPolicy {
|
||||
pub(crate) prev_policy: Box<CallPolicy>,
|
||||
count: BigUint,
|
||||
limits: Vec<(BigUint, usize)>
|
||||
}
|
||||
|
||||
impl CallWithInferenceLimitCallPolicy {
|
||||
pub(crate) fn new_in_place(atom_tbl: TabledData<Atom>, policy: &mut Box<CallPolicy>)
|
||||
pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>)
|
||||
{
|
||||
let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||
swap(&mut prev_policy, policy);
|
||||
|
||||
let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
|
||||
let new_policy = CallWithInferenceLimitCallPolicy { prev_policy,
|
||||
count: BigUint::zero(),
|
||||
limits: vec![] };
|
||||
*policy = Box::new(new_policy);
|
||||
@@ -373,15 +372,13 @@ impl CallWithInferenceLimitCallPolicy {
|
||||
fn increment(&mut self) -> CallResult {
|
||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||
if self.count == *limit {
|
||||
return Err(functor!(self.atom_tbl,
|
||||
"inference_limit_exceeded",
|
||||
1,
|
||||
return Err(functor!("inference_limit_exceeded", 1,
|
||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
|
||||
} else {
|
||||
self.count += BigUint::one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -422,7 +419,7 @@ impl CallWithInferenceLimitCallPolicy {
|
||||
|
||||
impl CallPolicy for CallWithInferenceLimitCallPolicy {
|
||||
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
|
||||
name: TabledRc<Atom>, arity: usize)
|
||||
name: ClauseName, arity: usize)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.try_call(machine_st, code_dir, name, arity)?;
|
||||
@@ -430,7 +427,7 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
|
||||
}
|
||||
|
||||
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
|
||||
name: TabledRc<Atom>, arity: usize)
|
||||
name: ClauseName, arity: usize)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.try_execute(machine_st, code_dir, name, arity)?;
|
||||
|
||||
@@ -269,13 +269,7 @@ impl MachineState {
|
||||
|
||||
match item {
|
||||
Addr::Con(Constant::Number(n)) => Ok(n),
|
||||
_ => {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
Err(functor!(self.atom_tbl,
|
||||
"instantiation_error",
|
||||
1,
|
||||
[heap_atom!("(is)/2", atom_tbl)]))
|
||||
}
|
||||
_ => Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
|
||||
}
|
||||
},
|
||||
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
|
||||
@@ -292,10 +286,7 @@ impl MachineState {
|
||||
if let Some(r) = Ratio::from_float(fl.into_inner()) {
|
||||
Ok(Rc::new(r))
|
||||
} else {
|
||||
Err(functor!(self.atom_tbl,
|
||||
"instantiation_error",
|
||||
1,
|
||||
[heap_atom!("(is)/2", self.atom_tbl)]))
|
||||
Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
|
||||
},
|
||||
Number::Integer(bi) =>
|
||||
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
|
||||
@@ -316,9 +307,7 @@ impl MachineState {
|
||||
|
||||
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, Vec<HeapCellValue>>
|
||||
{
|
||||
let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
|
||||
[heap_atom!("(is)/2", self.atom_tbl.clone())]);
|
||||
|
||||
let instantiation_err = functor!("instantiation_error", 1, [heap_atom!("(is)/2")]);
|
||||
let a = self[r].clone();
|
||||
|
||||
if let &Addr::Con(Constant::Number(ref n)) = &a {
|
||||
@@ -378,8 +367,7 @@ impl MachineState {
|
||||
-> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>>
|
||||
{
|
||||
if *r2 == Ratio::zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(Rc::new(&*r1 / &*r2))
|
||||
}
|
||||
@@ -390,13 +378,11 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
if *n2 == BigInt::zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(Rc::new(n1.div_floor(&n2)))
|
||||
},
|
||||
_ => Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
_ => Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,22 +391,19 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
if *n2 == BigInt::zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(Rc::new(&*n1 / &*n2))
|
||||
},
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
fn div(&self, n1: Number, n2: Number) -> Result<Number, Vec<HeapCellValue>>
|
||||
{
|
||||
if n2.is_zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(n1 / n2)
|
||||
}
|
||||
@@ -435,8 +418,7 @@ impl MachineState {
|
||||
_ => Ok(Rc::new(&*n1 >> usize::max_value()))
|
||||
},
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,8 +431,7 @@ impl MachineState {
|
||||
_ => Ok(Rc::new(&*n1 << usize::max_value()))
|
||||
},
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,8 +441,7 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)),
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,8 +451,7 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,14 +460,12 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
if *n2 == BigInt::zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(Rc::new(n1.mod_floor(&n2)))
|
||||
},
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,14 +474,12 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
if *n2 == BigInt::zero() {
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
|
||||
} else {
|
||||
Ok(Rc::new(&*n1 % &*n2))
|
||||
},
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,8 +489,7 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
|
||||
_ =>
|
||||
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
|
||||
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
|
||||
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,15 +635,15 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&FactInstruction::GetStructure(_, ref name, arity, reg, fixity) => {
|
||||
&FactInstruction::GetStructure(ref ct, 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 {
|
||||
if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
|
||||
if narity == arity && ct.name() == *s {
|
||||
self.s = a + 1;
|
||||
self.mode = MachineMode::Read;
|
||||
} else {
|
||||
@@ -681,7 +655,7 @@ impl MachineState {
|
||||
let h = self.heap.h;
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
|
||||
|
||||
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
|
||||
|
||||
@@ -858,10 +832,10 @@ impl MachineState {
|
||||
self[reg] = Addr::Con(constant.clone()),
|
||||
&QueryInstruction::PutList(_, reg) =>
|
||||
self[reg] = Addr::Lis(self.heap.h),
|
||||
&QueryInstruction::PutStructure(_, ref name, arity, reg, fixity) => {
|
||||
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
|
||||
let h = self.heap.h;
|
||||
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
|
||||
self[reg] = Addr::Str(h);
|
||||
},
|
||||
&QueryInstruction::PutUnsafeValue(n, arg) => {
|
||||
@@ -979,11 +953,8 @@ impl MachineState {
|
||||
|
||||
if let HeapCellValue::NamedStr(narity, name, _) = result {
|
||||
if narity + arity > 63 {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"representation_error",
|
||||
1,
|
||||
[heap_atom!("exceeds_max_arity", atom_tbl)]));
|
||||
self.throw_exception(functor!("representation_error", 1,
|
||||
[heap_atom!("exceeds_max_arity")]));
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1003,16 +974,12 @@ impl MachineState {
|
||||
},
|
||||
Addr::Con(Constant::Atom(name)) => (name, 0),
|
||||
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl, "instantiation_error", 0, []));
|
||||
self.throw_exception(functor!("instantiation_error"));
|
||||
return None;
|
||||
},
|
||||
_ => {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"type_error",
|
||||
2,
|
||||
[heap_atom!("callable", atom_tbl),
|
||||
self.throw_exception(functor!("type_error", 2,
|
||||
[heap_atom!("callable"),
|
||||
HeapCellValue::Addr(addr)]));
|
||||
return None;
|
||||
}
|
||||
@@ -1065,10 +1032,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
} else {
|
||||
return Err(functor!(self.atom_tbl,
|
||||
"type_error",
|
||||
1,
|
||||
[heap_atom!("compound_expected", self.atom_tbl)]));
|
||||
return Err(functor!("type_error", 1, [heap_atom!("compound_expected")]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1201,7 +1165,7 @@ impl MachineState {
|
||||
return Ordering::Less;
|
||||
} else if ar1 > ar2 {
|
||||
return Ordering::Greater;
|
||||
} else if *n1 != *n2 {
|
||||
} else if n1 != n2 {
|
||||
return n1.cmp(&n2);
|
||||
} else {
|
||||
continue;
|
||||
@@ -1210,14 +1174,14 @@ impl MachineState {
|
||||
continue,
|
||||
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _))
|
||||
| (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) =>
|
||||
if ar == 2 && *n == "." {
|
||||
if ar == 2 && n.as_str() == "." {
|
||||
continue;
|
||||
} else if ar < 2 {
|
||||
return Ordering::Greater;
|
||||
} else if ar > 2 {
|
||||
return Ordering::Less;
|
||||
} else {
|
||||
return n.cmp(&String::from("."));
|
||||
return n.as_str().cmp(".");
|
||||
},
|
||||
(HeapCellValue::NamedStr(..), _) =>
|
||||
return Ordering::Greater,
|
||||
@@ -1356,8 +1320,7 @@ impl MachineState {
|
||||
let a2 = self.store(self.deref(self[r2].clone()));
|
||||
|
||||
if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
|
||||
CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
|
||||
call_policy);
|
||||
CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
|
||||
}
|
||||
|
||||
self.p += 1;
|
||||
@@ -1373,13 +1336,7 @@ impl MachineState {
|
||||
None => panic!("install_inference_counter: should have installed \\
|
||||
CallWithInferenceLimitCallPolicy.")
|
||||
},
|
||||
_ => {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"type_error",
|
||||
1,
|
||||
[heap_atom!("integer_expected", atom_tbl)]))
|
||||
}
|
||||
_ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
|
||||
};
|
||||
},
|
||||
&BuiltInInstruction::IsAtomic(r) => {
|
||||
@@ -1634,10 +1591,10 @@ impl MachineState {
|
||||
|
||||
self.unify(a1, f_a);
|
||||
} else {
|
||||
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
|
||||
return Err(functor!("instantiation_error"));
|
||||
}
|
||||
} else {
|
||||
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
|
||||
return Err(functor!("instantiation_error"));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
@@ -1681,7 +1638,7 @@ impl MachineState {
|
||||
for (v1, v2) in iter {
|
||||
match (v1, v2) {
|
||||
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
|
||||
if ar1 != ar2 || *n1 != *n2 {
|
||||
if ar1 != ar2 || n1 != n2 {
|
||||
return true;
|
||||
},
|
||||
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
|
||||
@@ -1710,7 +1667,7 @@ impl MachineState {
|
||||
for (v1, v2) in iter {
|
||||
match (v1, v2) {
|
||||
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
|
||||
if ar1 != ar2 || *n1 != *n2 {
|
||||
if ar1 != ar2 || n1 != n2 {
|
||||
return true;
|
||||
},
|
||||
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
|
||||
|
||||
@@ -46,7 +46,7 @@ impl Index<CodePtr> for Machine {
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
|
||||
let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
|
||||
let (code, code_dir, op_dir) = build_code_dir();
|
||||
|
||||
Machine {
|
||||
ms: MachineState::new(atom_tbl),
|
||||
@@ -67,7 +67,7 @@ impl Machine {
|
||||
self.ms.atom_tbl.clone()
|
||||
}
|
||||
|
||||
pub fn add_user_code<'a>(&mut self, name: TabledRc<Atom>, arity: usize, mut code: Code)
|
||||
pub fn add_user_code<'a>(&mut self, name: ClauseName, arity: usize, mut code: Code)
|
||||
-> EvalSession<'a>
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
@@ -165,8 +165,7 @@ impl Machine {
|
||||
|
||||
fn query_stepper<'a>(&mut self)
|
||||
{
|
||||
loop
|
||||
{
|
||||
loop {
|
||||
self.execute_instr();
|
||||
|
||||
if self.failed() {
|
||||
@@ -180,10 +179,8 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
fn record_var_places<'a>(&self,
|
||||
chunk_num: usize,
|
||||
alloc_locs: &AllocVarDict<'a>,
|
||||
heap_locs: &mut HeapVarDict<'a>)
|
||||
fn record_var_places<'a>(&self, chunk_num: usize,
|
||||
alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
|
||||
{
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
macro_rules! clause_name {
|
||||
($name: expr) => (
|
||||
ClauseName::BuiltIn($name)
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! tabled_rc {
|
||||
($e:expr, $tbl:expr) => (
|
||||
TabledRc::new(String::from($e), $tbl.clone())
|
||||
@@ -6,7 +12,10 @@ macro_rules! tabled_rc {
|
||||
|
||||
macro_rules! atom {
|
||||
($e:expr, $tbl:expr) => (
|
||||
Constant::Atom(tabled_rc!($e, $tbl))
|
||||
Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)))
|
||||
);
|
||||
($e:expr) => (
|
||||
Constant::Atom(clause_name!($e))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -47,22 +56,21 @@ macro_rules! query {
|
||||
}
|
||||
|
||||
macro_rules! heap_atom {
|
||||
($name:expr) => (
|
||||
HeapCellValue::Addr(Addr::Con(atom!($name)))
|
||||
);
|
||||
($name:expr, $tbl:expr) => (
|
||||
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! functor {
|
||||
($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
|
||||
if $len > 0 {
|
||||
vec![ HeapCellValue::NamedStr($len,
|
||||
tabled_rc!($name, $tbl),
|
||||
None),
|
||||
$($args),* ]
|
||||
} else {
|
||||
vec![ heap_atom!($name, $tbl) ]
|
||||
}
|
||||
}}
|
||||
($name:expr) => (
|
||||
vec![ heap_atom!($name) ]
|
||||
);
|
||||
($name:expr, $len:expr, [$($args:expr),*]) => (
|
||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! fact {
|
||||
@@ -115,8 +123,11 @@ macro_rules! put_var {
|
||||
}
|
||||
|
||||
macro_rules! put_structure {
|
||||
($tbl:expr, $lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
QueryInstruction::PutStructure($lvl, tabled_rc!($name, $tbl), $arity, $r, $fix)
|
||||
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
|
||||
QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
|
||||
);
|
||||
($atom:expr, $arity:expr, $r:expr, None) => (
|
||||
QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -368,12 +379,11 @@ macro_rules! get_constant {
|
||||
}
|
||||
|
||||
macro_rules! get_structure {
|
||||
($tbl:expr, $atom:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
FactInstruction::GetStructure(Level::Shallow,
|
||||
tabled_rc!($atom, $tbl),
|
||||
$arity,
|
||||
$r,
|
||||
$fix)
|
||||
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
|
||||
FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
|
||||
);
|
||||
($atom:expr, $arity:expr, $r:expr, None) => (
|
||||
FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Submodule src/prolog/parser updated: cd115d7a67...5b74536d6e
@@ -1,4 +1,5 @@
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@@ -6,13 +7,27 @@ use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type TabledData<T> = Rc<RefCell<HashSet<Rc<T>>>>;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TabledRc<T: Hash + Eq> {
|
||||
atom: Rc<T>,
|
||||
table: TabledData<T>
|
||||
}
|
||||
|
||||
impl<T: Ord + Hash + Eq> PartialOrd for TabledRc<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
|
||||
{
|
||||
Some(self.atom.cmp(&other.atom))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord + Hash + Eq> Ord for TabledRc<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering
|
||||
{
|
||||
self.atom.cmp(&other.atom)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> PartialEq for TabledRc<T> {
|
||||
fn eq(&self, other: &TabledRc<T>) -> bool
|
||||
{
|
||||
@@ -23,9 +38,8 @@ impl<T: Hash + Eq> PartialEq for TabledRc<T> {
|
||||
impl<T: Hash + Eq> Eq for TabledRc<T> {}
|
||||
|
||||
impl<T: Hash + Eq> Hash for TabledRc<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H)
|
||||
{
|
||||
self.atom.hash(state)
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.atom.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +54,6 @@ impl<T: Hash + Eq> TabledRc<T> {
|
||||
|
||||
TabledRc { atom, table }
|
||||
}
|
||||
|
||||
pub fn table(&self) -> TabledData<T> {
|
||||
self.table.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> Drop for TabledRc<T> {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::iterators::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
pub trait CompilationTarget<'a> {
|
||||
type Iterator : Iterator<Item=TermRef<'a>>;
|
||||
@@ -9,7 +8,7 @@ pub trait CompilationTarget<'a> {
|
||||
|
||||
fn to_constant(Level, Constant, RegType) -> Self;
|
||||
fn to_list(Level, RegType) -> Self;
|
||||
fn to_structure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>) -> Self;
|
||||
fn to_structure(ClauseType, usize, RegType) -> Self;
|
||||
|
||||
fn to_void(usize) -> Self;
|
||||
fn is_void_instr(&self) -> bool;
|
||||
@@ -40,11 +39,9 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
||||
FactInstruction::GetConstant(lvl, constant, reg)
|
||||
}
|
||||
|
||||
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
|
||||
reg: RegType, fixity: Option<Fixity>)
|
||||
-> Self
|
||||
fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self
|
||||
{
|
||||
FactInstruction::GetStructure(lvl, atom, arity, reg, fixity)
|
||||
FactInstruction::GetStructure(ct, arity, reg)
|
||||
}
|
||||
|
||||
fn to_list(lvl: Level, reg: RegType) -> Self {
|
||||
@@ -105,11 +102,9 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
||||
term.post_order_iter()
|
||||
}
|
||||
|
||||
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
|
||||
reg: RegType, fixity: Option<Fixity>)
|
||||
-> Self
|
||||
fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self
|
||||
{
|
||||
QueryInstruction::PutStructure(lvl, atom, arity, reg, fixity)
|
||||
QueryInstruction::PutStructure(ct, arity, r)
|
||||
}
|
||||
|
||||
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
|
||||
|
||||
@@ -672,8 +672,8 @@ fn test_queries_on_call_n()
|
||||
{
|
||||
let mut wam = Machine::new();
|
||||
|
||||
submit(&mut wam, "maplist(Pred, []).
|
||||
maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
|
||||
submit(&mut wam, "maplist(_, []).
|
||||
maplist(P, [X|Xs]) :- call(P, X), maplist(P, Xs).");
|
||||
submit(&mut wam, "f(a). f(b). f(c).");
|
||||
|
||||
assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).",
|
||||
|
||||
Reference in New Issue
Block a user