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