[[package]]
name = "rusty-wam"
-version = "0.7.5"
+version = "0.7.6"
dependencies = [
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
[package]
name = "rusty-wam"
-version = "0.7.5"
+version = "0.7.6"
authors = ["Mark Thom"]
[dependencies]
impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
- self.state_stack.push(TermIterState::to_state(lvl, term));
+ self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
}
fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
let state = match term {
&Term::AnonVar =>
return Err(ArithmeticError::InvalidTerm),
- &Term::Clause(_, ref name, ref terms, _) =>
- TermIterState::Clause(0, ClauseType::Root(name), terms),
+ &Term::Clause(ref cell, ref name, ref terms, fixity) =>
+ match ClauseType::from(name.clone(), terms.len(), fixity) {
+ ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) =>
+ Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)),
+ _ => Err(ArithmeticError::InvalidOp)
+ }?,
&Term::Constant(ref cell, ref cons) =>
TermIterState::Constant(Level::Shallow, cell, cons),
&Term::Cons(_, _, _) =>
pub enum ArithTermRef<'a> {
Constant(&'a Constant),
- Op(&'a str, usize), // name, arity.
+ Op(ClauseName, usize), // name, arity.
Var(&'a Cell<VarReg>, &'a Var)
}
match iter_state {
TermIterState::AnonVar(_) =>
return Some(Err(ArithmeticError::UninstantiatedVar)),
- TermIterState::Clause(child_num, ct, child_terms) => {
- let arity = child_terms.len();
+ TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
+ let arity = subterms.len();
if child_num == arity {
return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
} else {
- self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
- self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
+ self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms));
+ self.push_subterm(lvl, subterms[child_num].as_ref());
}
},
TermIterState::Constant(_, _, c) =>
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
}
- fn get_unary_instr(name: &str, a1: ArithmeticTerm, t: usize)
+ fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
- match name {
+ match name.as_str() {
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
_ => Err(ArithmeticError::InvalidOp)
}
}
- fn get_binary_instr(name: &str, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
+ fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
- match name {
+ match name.as_str() {
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
temp
}
- fn instr_from_clause(&mut self, name: &str, arity: usize)
+ fn instr_from_clause(&mut self, name: ClauseName, arity: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
match arity {
self.interm.push(ArithmeticTerm::Reg(r));
},
ArithTermRef::Op(name, arity) => {
- code.push(Line::Arithmetic(self.instr_from_clause(&*name, arity)?));
+ code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
}
}
}
use std::cmp::Ordering;
use std::collections::{HashMap, VecDeque};
use std::fmt;
+use std::hash::{Hash, Hasher};
use std::io::Error as IOError;
use std::num::{ParseFloatError};
use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg};
pub fn first_arg(&self) -> Option<&Term> {
match self {
&PredicateClause::Fact(ref term) => term.first_arg(),
- &PredicateClause::Rule(ref rule) =>
- if let &QueryTerm::Term(ref term) = &rule.head.0 {
- term.first_arg()
- } else {
- None
- }
+ &PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()),
}
}
pub fn arity(&self) -> usize {
match self {
&PredicateClause::Fact(ref term) => term.arity(),
- &PredicateClause::Rule(ref rule) => rule.head.0.arity()
+ &PredicateClause::Rule(ref rule) => rule.head.1.len()
}
}
- pub fn name(&self) -> Option<TabledRc<Atom>> {
+ pub fn name(&self) -> Option<ClauseName> {
match self {
&PredicateClause::Fact(ref term) => term.name(),
- &PredicateClause::Rule(ref rule) =>
- if let &QueryTerm::Term(ref term) = &rule.head.0 {
- term.name()
- } else {
- None
- }
+ &PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
}
}
}
pub enum Declaration {
- Op(usize, Specifier, TabledRc<Atom>)
+ Op(usize, Specifier, ClauseName)
}
pub enum TopLevel {
}
impl TopLevel {
- pub fn name(&self) -> Option<TabledRc<Atom>> {
+ pub fn name(&self) -> Option<ClauseName> {
match self {
&TopLevel::Declaration(_) => None,
&TopLevel::Fact(ref term) => term.name(),
None
},
&TopLevel::Query(_) => None,
- &TopLevel::Rule(Rule { head: (QueryTerm::Term(ref term), _), .. }) =>
- match term {
- &Term::Clause(_, ref name, ..)
- | &Term::Constant(_, Constant::Atom(ref name)) =>
- Some(name.clone()),
- _ =>
- None
- },
- _ => None
+ &TopLevel::Rule(Rule { ref head, .. }) =>
+ Some(head.0.clone())
}
}
&TopLevel::Predicate(ref clauses) =>
clauses.first().map(|t| t.arity()).unwrap_or(0),
&TopLevel::Query(_) => 0,
- &TopLevel::Rule(Rule { head: (ref qt, _), ..}) => qt.arity(),
+ &TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
}
}
}
#[derive(Clone, Copy)]
pub enum Level {
- Deep, Shallow
+ Deep, Root, Shallow
+}
+
+impl Level {
+ pub fn child_level(self) -> Level {
+ match self {
+ Level::Root => Level::Shallow,
+ _ => Level::Deep
+ }
+ }
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub enum Constant {
- Atom(TabledRc<Atom>),
+ Atom(ClauseName),
Number(Number),
String(Rc<String>),
Usize(usize),
#[derive(PartialEq, Eq, Clone)]
pub enum Term {
AnonVar,
- Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
+ Clause(Cell<RegType>, ClauseName, Vec<Box<Term>>, Option<Fixity>),
Cons(Cell<RegType>, Box<Term>, Box<Term>),
Constant(Cell<RegType>, Constant),
Var(Cell<VarReg>, Rc<Var>)
}
-pub enum InlinedQueryTerm {
- CompareNumber(CompareNumberQT, Vec<Box<Term>>),
- IsAtomic(Vec<Box<Term>>),
- IsCompound(Vec<Box<Term>>),
- IsInteger(Vec<Box<Term>>),
- IsRational(Vec<Box<Term>>),
- IsString(Vec<Box<Term>>),
- IsFloat(Vec<Box<Term>>),
- IsNonVar(Vec<Box<Term>>),
- IsVar(Vec<Box<Term>>),
-}
-
-impl InlinedQueryTerm {
- pub fn arity(&self) -> usize {
+#[derive(Clone, Copy)]
+pub enum InlinedClauseType {
+ CompareNumber(CompareNumberQT),
+ IsAtomic,
+ IsCompound,
+ IsInteger,
+ IsRational,
+ IsString,
+ IsFloat,
+ IsNonVar,
+ IsVar,
+}
+
+impl InlinedClauseType {
+ pub fn name(&self) -> &'static str {
match self {
- &InlinedQueryTerm::CompareNumber(_, _) => 2,
- &InlinedQueryTerm::IsAtomic(_) => 1,
- &InlinedQueryTerm::IsCompound(_) => 1,
- &InlinedQueryTerm::IsFloat(_) => 1,
- &InlinedQueryTerm::IsRational(_) => 1,
- &InlinedQueryTerm::IsString(_) => 1,
- &InlinedQueryTerm::IsNonVar(_) => 1,
- &InlinedQueryTerm::IsInteger(_) => 1,
- &InlinedQueryTerm::IsVar(_) => 1,
+ &InlinedClauseType::CompareNumber(qt) => qt.name(),
+ &InlinedClauseType::IsAtomic => "atomic",
+ &InlinedClauseType::IsCompound => "compound",
+ &InlinedClauseType::IsInteger => "integer",
+ &InlinedClauseType::IsRational => "rational",
+ &InlinedClauseType::IsString => "string",
+ &InlinedClauseType::IsFloat => "float",
+ &InlinedClauseType::IsNonVar => "nonvar",
+ &InlinedClauseType::IsVar => "var"
+ }
+ }
+
+ pub fn from(name: &str, arity: usize) -> Option<Self> {
+ match (name, arity) {
+ (">", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan)),
+ ("<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan)),
+ (">=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual)),
+ ("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
+ ("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
+ ("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
+ ("atomic", 1) => Some(InlinedClauseType::IsAtomic),
+ ("compound", 1) => Some(InlinedClauseType::IsCompound),
+ ("integer", 1) => Some(InlinedClauseType::IsInteger),
+ ("rational", 1) => Some(InlinedClauseType::IsRational),
+ ("string", 1) => Some(InlinedClauseType::IsString),
+ ("float", 1) => Some(InlinedClauseType::IsFloat),
+ ("nonvar", 1) => Some(InlinedClauseType::IsNonVar),
+ ("var", 1) => Some(InlinedClauseType::IsVar),
+ _ => None
}
}
}
}
impl CompareNumberQT {
- fn name<'a>(self) -> &'a str {
+ fn name(self) -> &'static str {
match self {
CompareNumberQT::GreaterThan => ">",
CompareNumberQT::LessThan => "<",
}
#[derive(Clone, Copy)]
-pub enum CompareTermQT {
+pub enum CompareTermQT {
LessThan,
LessThanOrEqual,
Equal,
GreaterThanOrEqual,
- GreaterThan,
- NotEqual,
+ GreaterThan,
+ NotEqual,
}
impl CompareTermQT {
pub type JumpStub = Vec<Term>;
pub enum QueryTerm {
- Arg(Vec<Box<Term>>),
- CallN(Vec<Box<Term>>),
- CallWithInferenceLimit(Vec<Box<Term>>),
- Catch(Vec<Box<Term>>),
- Compare(Vec<Box<Term>>),
- CompareTerm(CompareTermQT, Vec<Box<Term>>),
+ Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
Cut,
- Display(Vec<Box<Term>>),
- DuplicateTerm(Vec<Box<Term>>),
- Eq(Vec<Box<Term>>),
- Functor(Vec<Box<Term>>),
- Ground(Vec<Box<Term>>),
- Inlined(InlinedQueryTerm),
- Is(Vec<Box<Term>>),
- Jump(JumpStub),
- NotEq(Vec<Box<Term>>),
- SetupCallCleanup(Vec<Box<Term>>),
- Term(Term),
- Throw(Vec<Box<Term>>)
+ Jump(JumpStub)
}
impl QueryTerm {
pub fn arity(&self) -> usize {
match self {
- &QueryTerm::Arg(_) => 3,
- &QueryTerm::Catch(_) => 3,
- &QueryTerm::Compare(_) => 3,
- &QueryTerm::CompareTerm(..) => 2,
- &QueryTerm::Display(_) => 1,
- &QueryTerm::Throw(_) => 1,
- &QueryTerm::DuplicateTerm(_) => 2,
- &QueryTerm::Eq(_) => 2,
- &QueryTerm::Functor(_) => 3,
- &QueryTerm::Ground(_) => 1,
- &QueryTerm::Inlined(ref term) => term.arity(),
- &QueryTerm::Is(_) => 2,
- &QueryTerm::Jump(ref vars) => vars.len(),
- &QueryTerm::NotEq(_) => 2,
- &QueryTerm::CallN(ref terms) => terms.len(),
- &QueryTerm::CallWithInferenceLimit(_) => 3,
+ &QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
&QueryTerm::Cut => 0,
- &QueryTerm::SetupCallCleanup(_) => 3,
- &QueryTerm::Term(ref term) => term.arity(),
+ &QueryTerm::Jump(ref vars) => vars.len()
}
}
}
pub struct Rule {
- pub head: (QueryTerm, QueryTerm),
+ pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
pub clauses: Vec<QueryTerm>
}
-#[derive(Clone, Copy)]
-pub enum ClauseType<'a> {
+#[derive(Clone)]
+pub enum ClauseType {
Arg,
CallN,
CallWithInferenceLimit,
Catch,
Compare,
- CompareNumber(CompareNumberQT),
CompareTerm(CompareTermQT),
- Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
Display,
DuplicateTerm,
Eq,
Functor,
Ground,
+ Inlined(InlinedClauseType),
Is,
NotEq,
- Root(&'a TabledRc<Atom>),
+ Op(ClauseName, Fixity),
+ Named(ClauseName),
SetupCallCleanup,
Throw,
}
-impl<'a> ClauseType<'a> {
- pub fn name(&self) -> &'a str {
+impl ClauseType {
+ pub fn fixity(&self) -> Option<Fixity> {
+ match self {
+ &ClauseType::Compare | &ClauseType::CompareTerm(_)
+ | &ClauseType::Inlined(InlinedClauseType::CompareNumber(_))
+ | &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In),
+ &ClauseType::Op(_, fixity) => Some(fixity),
+ _ => None
+ }
+ }
+}
+
+#[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 {
- &ClauseType::Arg => "arg",
- &ClauseType::CallN => "call",
- &ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
- &ClauseType::Catch => "catch",
- &ClauseType::Compare => "compare",
- &ClauseType::CompareNumber(qt) => qt.name(),
- &ClauseType::CompareTerm(qt) => qt.name(),
- &ClauseType::Display => "display",
- &ClauseType::Deep(_, _, name, _) => name.as_str(),
- &ClauseType::DuplicateTerm => "duplicate_term",
- &ClauseType::Eq => "==",
- &ClauseType::Functor => "functor",
- &ClauseType::Ground => "ground",
- &ClauseType::Is => "is",
- &ClauseType::NotEq => "\\==",
- &ClauseType::Root(name) => name.as_str(),
- &ClauseType::SetupCallCleanup => "setup_call_cleanup",
- &ClauseType::Throw => "throw"
+ &ClauseName::BuiltIn(s) => s,
+ &ClauseName::User(ref name) => name.as_ref()
}
}
+}
- pub fn level_of_subterms(self) -> Level {
+impl ClauseType {
+ pub fn name(&self) -> ClauseName {
match self {
- ClauseType::Deep(..) => Level::Deep,
- _ => Level::Shallow
+ &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)
+ }
}
}
}
-#[derive(Clone, Copy)]
+impl From<InlinedClauseType> for ClauseType {
+ fn from(inlined_ct: InlinedClauseType) -> Self {
+ ClauseType::Inlined(inlined_ct)
+ }
+}
+
+#[derive(Clone)]
pub enum TermRef<'a> {
AnonVar(Level),
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Constant(Level, &'a Cell<RegType>, &'a Constant),
- Clause(ClauseType<'a>, &'a Vec<Box<Term>>),
+ Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
TermRef::AnonVar(lvl)
| TermRef::Cons(lvl, ..)
| TermRef::Constant(lvl, ..)
- | TermRef::Var(lvl, ..) => lvl,
- TermRef::Clause(ClauseType::Deep(lvl, ..), ..) => lvl,
- _ => Level::Shallow
+ | TermRef::Var(lvl, ..)
+ | TermRef::Clause(lvl, ..) => lvl
}
}
}
Allocate(usize), // num_frames.
ArgCall,
ArgExecute,
- Call(TabledRc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
+ Call(ClauseName, usize, usize), // name, arity, perm_vars after threshold.
CallN(usize), // arity.
CatchCall,
CatchExecute,
DisplayExecute,
Deallocate,
DuplicateTermCall,
- DuplicateTermExecute,
+ DuplicateTermExecute,
DynamicIs,
EqCall,
EqExecute,
- Execute(TabledRc<Atom>, usize),
+ Execute(ClauseName, usize),
ExecuteN(usize),
FunctorCall,
FunctorExecute,
GroundExecute,
JmpByCall(usize, usize), // arity, global_offset.
JmpByExecute(usize, usize),
- IsCall(RegType, ArithmeticTerm),
+ IsCall(RegType, ArithmeticTerm),
IsExecute(RegType, ArithmeticTerm),
NotEqCall,
NotEqExecute,
- Proceed,
+ Proceed,
ThrowCall,
ThrowExecute,
}
&ControlInstruction::ArgExecute => true,
&ControlInstruction::Call(_, _, _) => true,
&ControlInstruction::CatchCall => true,
- &ControlInstruction::CatchExecute => true,
+ &ControlInstruction::CatchExecute => true,
&ControlInstruction::CompareTermCall(..) => true,
&ControlInstruction::CompareTermExecute(..) => true,
&ControlInstruction::DisplayCall => true,
pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, HashMap<Constant, usize>),
- SwitchOnStructure(usize, HashMap<(TabledRc<Atom>, usize), usize>)
+ SwitchOnStructure(usize, HashMap<(ClauseName, usize), usize>)
}
impl From<IndexingInstruction> for Line {
pub enum FactInstruction {
GetConstant(Level, Constant, RegType),
GetList(Level, RegType),
- GetStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
+ GetStructure(ClauseType, usize, RegType),
GetValue(RegType, usize),
GetVariable(RegType, usize),
UnifyConstant(Constant),
GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType),
PutList(Level, RegType),
- PutStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
+ PutStructure(ClauseType, usize, RegType),
PutUnsafeValue(usize, usize),
PutValue(RegType, usize),
PutVariable(RegType, usize),
#[derive(Clone, PartialEq)]
pub enum HeapCellValue {
Addr(Addr),
- NamedStr(usize, TabledRc<Atom>, Option<Fixity>), // arity, name, fixity if it has one.
+ NamedStr(usize, ClauseName, Option<Fixity>), // arity, name, fixity if it has one.
}
impl HeapCellValue {
}
}
- pub fn is_callable(&self) -> bool {
- match self {
- &Term::Clause(..) | &Term::Constant(_, Constant::Atom(_)) =>
- true,
- _ => false
- }
- }
-
- pub fn name(&self) -> Option<TabledRc<Atom>> {
+ pub fn name(&self) -> Option<ClauseName> {
match self {
&Term::Constant(_, Constant::Atom(ref atom))
| &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
pub enum TermIterState<'a> {
AnonVar(Level),
- Clause(usize, ClauseType<'a>, &'a Vec<Box<Term>>),
Constant(Level, &'a Cell<RegType>, &'a Constant),
+ Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
impl<'a> TermIterState<'a> {
- pub fn to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
+ pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
match term {
&Term::AnonVar =>
TermIterState::AnonVar(lvl),
- &Term::Clause(ref cell, ref atom, ref child_terms, fixity) =>
- TermIterState::Clause(0, ClauseType::Deep(lvl, cell, atom, fixity), child_terms),
+ &Term::Clause(ref cell, ref name, ref subterms, fixity) => {
+ let ct = if let Some(fixity) = fixity {
+ ClauseType::Op(name.clone(), fixity)
+ } else {
+ ClauseType::Named(name.clone())
+ };
+
+ TermIterState::Clause(lvl, 0, cell, ct, subterms)
+ },
&Term::Cons(ref cell, ref head, ref tail) =>
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()),
&Term::Constant(ref cell, ref constant) =>
use prolog::ast::*;
use prolog::num::bigint::{BigInt};
-use prolog::tabled_rc::*;
use std::collections::HashMap;
use std::rc::Rc;
-pub type PredicateKey = (TabledRc<Atom>, usize); // name, arity, type.
+pub type PredicateKey = (ClauseName, usize); // name, arity, type.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum PredicateKeyType {
User
}
-pub type OpDirKey = (TabledRc<Atom>, Fixity);
+pub type OpDirKey = (ClauseName, Fixity);
// name and fixity -> operator type and precedence.
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
-fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
+fn get_builtins() -> Code {
vec![internal_call_n!(), // callN/N, 0.
is_atomic!(temp_v!(1)), // atomic/1, 1.
proceed!(),
retry!(7),
trust!(10),
try_me_else!(4),
- fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
- get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
+ fact![get_constant!(atom!("!"), temp_v!(1)),
+ get_structure!(",", 2, temp_v!(2), Some(infix!())),
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
set_cp!(temp_v!(3)),
goto_execute!(83, 3),
retry_me_else!(4),
- fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
- get_constant!(atom!("!", atom_tbl), temp_v!(2))],
+ fact![get_constant!(atom!("!"), temp_v!(1)),
+ get_constant!(atom!("!"), temp_v!(2))],
set_cp!(temp_v!(3)),
proceed!(),
trust_me!(),
- fact![get_constant!(atom!("!", atom_tbl), temp_v!(1))],
+ fact![get_constant!(atom!("!"), temp_v!(1))],
set_cp!(temp_v!(3)),
query![put_value!(temp_v!(2), 1)],
execute_n!(1),
retry_me_else!(8),
allocate!(3),
- fact![get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
+ fact![get_structure!(",", 2, temp_v!(2), Some(infix!())),
unify_variable!(perm_v!(2)),
unify_variable!(perm_v!(1)),
get_var_in_fact!(perm_v!(3), 3)],
retry_me_else!(10),
allocate!(2),
get_level!(perm_v!(2)),
- fact![get_constant!(atom!("!", atom_tbl), temp_v!(2)),
+ fact![get_constant!(atom!("!"), temp_v!(2)),
get_var_in_fact!(perm_v!(1), 3)],
neck_cut!(),
call_n!(1),
indexed_try!(3),
trust!(5),
try_me_else!(3),
- fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
+ fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
goto_execute!(139, 3),
trust_me!(),
- fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
+ fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
unify_void!(2)],
query![put_value!(temp_v!(2), 1)],
neck_cut!(),
goto_execute!(149, 3), // goto get_arg/3.
trust_me!(),
query![get_var_in_query!(temp_v!(4), 1),
- put_structure!(atom_tbl,
- Level::Shallow,
- String::from("type_error"),
- 1,
- temp_v!(1),
- None),
- set_constant!(atom!("integer_expected", atom_tbl))],
+ put_structure!("type_error", 1, temp_v!(1), None),
+ set_constant!(atom!("integer_expected"))],
goto_execute!(59, 1), // goto throw/1.
try_me_else!(5), // arg_/5, 173.
fact![get_value!(temp_v!(1), 2),
trust_me!(),
fact![get_var_in_fact!(temp_v!(3), 1),
get_var_in_fact!(temp_v!(4), 2)],
- query![put_structure!(atom_tbl,
- Level::Shallow,
- String::from("type_error"),
- 2,
- temp_v!(1),
- None),
- set_constant!(atom!("integer_expected", atom_tbl)),
+ query![put_structure!("type_error", 2, temp_v!(1), None),
+ set_constant!(atom!("integer_expected")),
set_value!(temp_v!(4))],
goto_execute!(59, 1), // goto throw/1, 59.
switch_on_term!(1,2,5,0), // length/3, 281.
try_me_else!(5), // 304.
is_var!(temp_v!(1)),
neck_cut!(),
- query![put_constant!(Level::Shallow, atom!("instantiation_error", atom_tbl),
+ query![put_constant!(Level::Shallow,
+ atom!("instantiation_error"),
temp_v!(1))],
goto_execute!(59, 1),
trust_me!(),
get_cleaner_call!(),
query![put_value!(perm_v!(2), 1),
put_var!(temp_v!(4), 2),
- put_constant!(Level::Shallow, atom!("true", atom_tbl), temp_v!(3))],
+ put_constant!(Level::Shallow, atom!("true"), temp_v!(3))],
goto_call!(5, 3), // goto catch/3, 5.
set_cp!(perm_v!(1)),
deallocate!(),
remove_call_policy_check!(),
fail!(),
try_me_else!(4), // handle_ile/3, 444.
- fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
+ fact![get_structure!("inference_limit_exceeded", 1, temp_v!(2), None),
unify_value!(temp_v!(1)),
- get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
+ get_constant!(atom!("inference_limit_exceeded"), temp_v!(3))],
neck_cut!(),
proceed!(),
default_trust_me!(),
]
}
-pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
+pub fn build_code_dir() -> (Code, CodeDir, OpDir)
{
let mut code_dir = HashMap::new();
let mut op_dir = HashMap::new();
- let builtin_code = get_builtins(atom_tbl.clone());
+ let builtin_code = get_builtins();
- op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::In), (XFX, 1200));
- op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::Pre), (FX, 1200));
- op_dir.insert((tabled_rc!("?-", atom_tbl), Fixity::Pre), (FX, 1200));
+ op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200));
+ op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200));
+ op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200));
// control operators.
- op_dir.insert((tabled_rc!("\\+", atom_tbl), Fixity::Pre), (FY, 900));
- op_dir.insert((tabled_rc!("=", atom_tbl), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
+ op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
// arithmetic operators.
- op_dir.insert((tabled_rc!("is", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("+", atom_tbl), Fixity::In), (YFX, 500));
- op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::In), (YFX, 500));
- op_dir.insert((tabled_rc!("/\\", atom_tbl), Fixity::In), (YFX, 500));
- op_dir.insert((tabled_rc!("\\/", atom_tbl), Fixity::In), (YFX, 500));
- op_dir.insert((tabled_rc!("xor", atom_tbl), Fixity::In), (YFX, 500));
- op_dir.insert((tabled_rc!("//", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("/", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("div", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("*", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::Pre), (FY, 200));
- op_dir.insert((tabled_rc!("rdiv", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("<<", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!(">>", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("mod", atom_tbl), Fixity::In), (YFX, 400));
- op_dir.insert((tabled_rc!("rem", atom_tbl), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
+ op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
+ op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
+ op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
+ op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
+ op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
+ op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
+ op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
// arithmetic comparison operators.
- op_dir.insert((tabled_rc!(">", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("<", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("=\\=", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("=:=", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!(">=", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("=<", atom_tbl), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
// control operators.
- op_dir.insert((tabled_rc!(";", atom_tbl), Fixity::In), (XFY, 1100));
- op_dir.insert((tabled_rc!("->", atom_tbl), Fixity::In), (XFY, 1050));
+ op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
+ op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
- op_dir.insert((tabled_rc!("=..", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("==", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("\\==", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("@=<", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("@>=", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("@<", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("@>", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("=@=", atom_tbl), Fixity::In), (XFX, 700));
- op_dir.insert((tabled_rc!("\\=@=", atom_tbl), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
+ op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
// (an extra register is needed for the predicate name)
for arity in 0 .. 63 {
- code_dir.insert((tabled_rc!("call", atom_tbl), arity), (PredicateKeyType::BuiltIn, 0));
+ code_dir.insert((clause_name!("call"), arity), (PredicateKeyType::BuiltIn, 0));
}
- code_dir.insert((tabled_rc!("atomic", atom_tbl), 1), (PredicateKeyType::BuiltIn, 1));
- code_dir.insert((tabled_rc!("var", atom_tbl), 1), (PredicateKeyType::BuiltIn, 3));
- code_dir.insert((tabled_rc!("false", atom_tbl), 0), (PredicateKeyType::BuiltIn, 61));
- code_dir.insert((tabled_rc!("\\+", atom_tbl), 1), (PredicateKeyType::BuiltIn, 62));
- code_dir.insert((tabled_rc!("duplicate_term", atom_tbl), 2), (PredicateKeyType::BuiltIn, 71));
- code_dir.insert((tabled_rc!("catch", atom_tbl), 3), (PredicateKeyType::BuiltIn, 5));
- code_dir.insert((tabled_rc!("throw", atom_tbl), 1), (PredicateKeyType::BuiltIn, 59));
- code_dir.insert((tabled_rc!("=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 73));
- code_dir.insert((tabled_rc!("true", atom_tbl), 0), (PredicateKeyType::BuiltIn, 75));
+ code_dir.insert((clause_name!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
+ code_dir.insert((clause_name!("var"), 1), (PredicateKeyType::BuiltIn, 3));
+ code_dir.insert((clause_name!("false"), 0), (PredicateKeyType::BuiltIn, 61));
+ code_dir.insert((clause_name!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
+ code_dir.insert((clause_name!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
+ code_dir.insert((clause_name!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
+ code_dir.insert((clause_name!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
+ code_dir.insert((clause_name!("="), 2), (PredicateKeyType::BuiltIn, 73));
+ code_dir.insert((clause_name!("true"), 0), (PredicateKeyType::BuiltIn, 75));
- code_dir.insert((tabled_rc!(",", atom_tbl), 2), (PredicateKeyType::BuiltIn, 76));
- code_dir.insert((tabled_rc!(";", atom_tbl), 2), (PredicateKeyType::BuiltIn, 120));
- code_dir.insert((tabled_rc!("->", atom_tbl), 2), (PredicateKeyType::BuiltIn, 138));
+ code_dir.insert((clause_name!(","), 2), (PredicateKeyType::BuiltIn, 76));
+ code_dir.insert((clause_name!(";"), 2), (PredicateKeyType::BuiltIn, 120));
+ code_dir.insert((clause_name!("->"), 2), (PredicateKeyType::BuiltIn, 138));
- code_dir.insert((tabled_rc!("functor", atom_tbl), 3), (PredicateKeyType::BuiltIn, 146));
- code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
- code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
- code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
+ code_dir.insert((clause_name!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
+ code_dir.insert((clause_name!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
+ code_dir.insert((clause_name!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
+ code_dir.insert((clause_name!("display"), 1), (PredicateKeyType::BuiltIn, 192));
- code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
- code_dir.insert((tabled_rc!(">", atom_tbl), 2), (PredicateKeyType::BuiltIn, 196));
- code_dir.insert((tabled_rc!("<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 198));
- code_dir.insert((tabled_rc!(">=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 200));
- code_dir.insert((tabled_rc!("<=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 202));
- code_dir.insert((tabled_rc!("=\\=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 204));
- code_dir.insert((tabled_rc!("=:=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 206));
- code_dir.insert((tabled_rc!("=..", atom_tbl), 2), (PredicateKeyType::BuiltIn, 208));
+ code_dir.insert((clause_name!("is"), 2), (PredicateKeyType::BuiltIn, 194));
+ code_dir.insert((clause_name!(">"), 2), (PredicateKeyType::BuiltIn, 196));
+ code_dir.insert((clause_name!("<"), 2), (PredicateKeyType::BuiltIn, 198));
+ code_dir.insert((clause_name!(">="), 2), (PredicateKeyType::BuiltIn, 200));
+ code_dir.insert((clause_name!("<="), 2), (PredicateKeyType::BuiltIn, 202));
+ code_dir.insert((clause_name!("=\\="), 2), (PredicateKeyType::BuiltIn, 204));
+ code_dir.insert((clause_name!("=:="), 2), (PredicateKeyType::BuiltIn, 206));
+ code_dir.insert((clause_name!("=.."), 2), (PredicateKeyType::BuiltIn, 208));
- code_dir.insert((tabled_rc!("length", atom_tbl), 2), (PredicateKeyType::BuiltIn, 261));
- code_dir.insert((tabled_rc!("setup_call_cleanup", atom_tbl), 3),
+ code_dir.insert((clause_name!("length"), 2), (PredicateKeyType::BuiltIn, 261));
+ code_dir.insert((clause_name!("setup_call_cleanup"), 3),
(PredicateKeyType::BuiltIn, 294));
- code_dir.insert((tabled_rc!("call_with_inference_limit", atom_tbl), 3),
+ code_dir.insert((clause_name!("call_with_inference_limit"), 3),
(PredicateKeyType::BuiltIn, 393));
- code_dir.insert((tabled_rc!("_handle_inference_limit_exceeded", atom_tbl), 2),
+ code_dir.insert((clause_name!("_handle_inference_limit_exceeded"), 2),
(PredicateKeyType::BuiltIn, 421));
- code_dir.insert((tabled_rc!("compound", atom_tbl), 1), (PredicateKeyType::BuiltIn, 372));
- code_dir.insert((tabled_rc!("rational", atom_tbl), 1), (PredicateKeyType::BuiltIn, 374));
- code_dir.insert((tabled_rc!("string", atom_tbl), 1), (PredicateKeyType::BuiltIn, 376));
- code_dir.insert((tabled_rc!("float", atom_tbl), 1), (PredicateKeyType::BuiltIn, 378));
- code_dir.insert((tabled_rc!("nonvar", atom_tbl), 1), (PredicateKeyType::BuiltIn, 380));
+ code_dir.insert((clause_name!("compound"), 1), (PredicateKeyType::BuiltIn, 372));
+ code_dir.insert((clause_name!("rational"), 1), (PredicateKeyType::BuiltIn, 374));
+ code_dir.insert((clause_name!("string"), 1), (PredicateKeyType::BuiltIn, 376));
+ code_dir.insert((clause_name!("float"), 1), (PredicateKeyType::BuiltIn, 378));
+ code_dir.insert((clause_name!("nonvar"), 1), (PredicateKeyType::BuiltIn, 380));
- code_dir.insert((tabled_rc!("ground", atom_tbl), 1), (PredicateKeyType::BuiltIn, 384));
- code_dir.insert((tabled_rc!("==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 385));
- code_dir.insert((tabled_rc!("\\==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 386));
- code_dir.insert((tabled_rc!("@>=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 387));
- code_dir.insert((tabled_rc!("@=<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 388));
- code_dir.insert((tabled_rc!("@>", atom_tbl), 2), (PredicateKeyType::BuiltIn, 389));
- code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
- code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
- code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
- code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
+ code_dir.insert((clause_name!("ground"), 1), (PredicateKeyType::BuiltIn, 384));
+ code_dir.insert((clause_name!("=="), 2), (PredicateKeyType::BuiltIn, 385));
+ code_dir.insert((clause_name!("\\=="), 2), (PredicateKeyType::BuiltIn, 386));
+ code_dir.insert((clause_name!("@>="), 2), (PredicateKeyType::BuiltIn, 387));
+ code_dir.insert((clause_name!("@=<"), 2), (PredicateKeyType::BuiltIn, 388));
+ code_dir.insert((clause_name!("@>"), 2), (PredicateKeyType::BuiltIn, 389));
+ code_dir.insert((clause_name!("@<"), 2), (PredicateKeyType::BuiltIn, 390));
+ code_dir.insert((clause_name!("=@="), 2), (PredicateKeyType::BuiltIn, 391));
+ code_dir.insert((clause_name!("\\=@="), 2), (PredicateKeyType::BuiltIn, 392));
+ code_dir.insert((clause_name!("compare"), 3), (PredicateKeyType::BuiltIn, 464));
(builtin_code, code_dir, op_dir)
}
};
}
- fn compile_clause<Target>(&mut self, ct: ClauseType<'a>, term_loc: GenContext,
- is_exposed: bool, terms: &'a Vec<Box<Term>>,
- target: &mut Vec<Target>)
- where Target: CompilationTarget<'a>
- {
- match ct {
- ClauseType::Deep(lvl, cell, atom, fixity) => {
- self.marker.mark_non_var(lvl, term_loc, cell, target);
- target.push(Target::to_structure(lvl, atom.clone(), terms.len(),
- cell.get(), fixity));
-
- for subterm in terms {
- self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, target);
- }
- },
- _ => {}
- }
- }
-
fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
-> Vec<Target>
where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
for term in iter {
match term {
- TermRef::Clause(ct, terms) =>
- self.compile_clause(ct, term_loc, is_exposed, terms, &mut target),
+ TermRef::Clause(lvl, cell, ct, terms) => {
+ self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ target.push(Target::to_structure(ct, terms.len(), cell.get()));
+
+ for subterm in terms {
+ self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
+ }
+ },
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));
fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a>
{
let mut vs = VariableFixtures::new();
- let at_rule_head = iter.at_rule_head();
- while let Some((chunk_num, lt_arity, terms)) = iter.next() {
- for (i, query_term) in terms.iter().enumerate() {
- let term_loc = if chunk_num == 0 && i == 0 && at_rule_head {
- GenContext::Head
- } else if i < terms.len() - 1 {
- GenContext::Mid(chunk_num)
- } else {
- GenContext::Last(chunk_num)
- };
+ while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
+ for (i, chunked_term) in chunked_terms.iter().enumerate() {
+ let term_loc = match chunked_term {
+ &ChunkedTerm::HeadClause(..) => GenContext::Head,
+ &ChunkedTerm::BodyTerm(_) => if i < chunked_terms.len() - 1 {
+ GenContext::Mid(chunk_num)
+ } else {
+ GenContext::Last(chunk_num)
+ }
+ };
- self.update_var_count(query_term.post_order_iter());
- vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
+ self.update_var_count(chunked_term.post_order_iter());
+ vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
}
}
- let num_of_chunks = iter.chunk_num();
+ let num_of_chunks = iter.chunk_num;
let has_deep_cut = iter.encountered_deep_cut();
vs.populate_restricting_sets();
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
{
match qt {
- &QueryTerm::CallWithInferenceLimit(_) =>
- code.push(goto_call!(393, 3)),
- &QueryTerm::SetupCallCleanup(_) =>
- code.push(goto_call!(294, 3)),
- &QueryTerm::Arg(_) => {
- let call = ControlInstruction::ArgCall;
- code.push(Line::Control(call));
- },
- &QueryTerm::CallN(ref terms) => {
- let call = ControlInstruction::CallN(terms.len());
- code.push(Line::Control(call));
- },
- &QueryTerm::Catch(_) =>
- code.push(Line::Control(ControlInstruction::CatchCall)),
- &QueryTerm::Compare(_) =>
- code.push(Line::Control(ControlInstruction::CompareCall)),
- &QueryTerm::CompareTerm(qt, _) =>
- code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
- &QueryTerm::Display(_) =>
- code.push(Line::Control(ControlInstruction::DisplayCall)),
- &QueryTerm::DuplicateTerm(_) =>
- code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
- &QueryTerm::Eq(_) =>
- code.push(Line::Control(ControlInstruction::EqCall)),
- &QueryTerm::Ground(_) =>
- code.push(Line::Control(ControlInstruction::GroundCall)),
- &QueryTerm::Functor(_) =>
- code.push(Line::Control(ControlInstruction::FunctorCall)),
- &QueryTerm::Inlined(_) =>
- code.push(proceed!()),
&QueryTerm::Jump(ref vars) => {
code.push(jmp_call!(vars.len(), 0));
},
- &QueryTerm::NotEq(_) =>
- code.push(Line::Control(ControlInstruction::NotEqCall)),
- &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
- let call = ControlInstruction::Call(atom.clone(), 0, pvs);
- code.push(Line::Control(call));
- },
- &QueryTerm::Term(Term::Clause(_, ref atom, ref terms, _)) => {
- let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
- code.push(Line::Control(call));
- },
- &QueryTerm::Throw(_) =>
- code.push(Line::Control(ControlInstruction::ThrowCall)),
+ &QueryTerm::Clause(_, ref ct, ref terms) =>
+ match ct {
+ &ClauseType::CallWithInferenceLimit =>
+ code.push(goto_call!(393, 3)),
+ &ClauseType::SetupCallCleanup =>
+ code.push(goto_call!(294, 3)),
+ &ClauseType::Arg => {
+ let call = ControlInstruction::ArgCall;
+ code.push(Line::Control(call));
+ },
+ &ClauseType::CallN => {
+ let call = ControlInstruction::CallN(terms.len());
+ code.push(Line::Control(call));
+ },
+ &ClauseType::Catch =>
+ code.push(Line::Control(ControlInstruction::CatchCall)),
+ &ClauseType::Compare =>
+ code.push(Line::Control(ControlInstruction::CompareCall)),
+ &ClauseType::CompareTerm(qt) =>
+ code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
+ &ClauseType::Display =>
+ code.push(Line::Control(ControlInstruction::DisplayCall)),
+ &ClauseType::DuplicateTerm =>
+ code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
+ &ClauseType::Eq =>
+ code.push(Line::Control(ControlInstruction::EqCall)),
+ &ClauseType::Ground =>
+ code.push(Line::Control(ControlInstruction::GroundCall)),
+ &ClauseType::Functor =>
+ code.push(Line::Control(ControlInstruction::FunctorCall)),
+ &ClauseType::Inlined(_) =>
+ code.push(proceed!()),
+ &ClauseType::NotEq =>
+ code.push(Line::Control(ControlInstruction::NotEqCall)),
+ &ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => {
+ let call = ControlInstruction::Call(name.clone(), terms.len(), pvs);
+ code.push(Line::Control(call));
+ },
+ &ClauseType::Throw =>
+ code.push(Line::Control(ControlInstruction::ThrowCall)),
+ _ => {}
+ },
_ => {}
}
}
dealloc_index
}
- fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
+ fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec<Box<Term>>,
+ term_loc: GenContext, code: &mut Code)
-> Result<(), ParserError>
{
- match term {
- &InlinedQueryTerm::CompareNumber(cmp, ref terms) => {
+ match ct {
+ InlinedClauseType::CompareNumber(cmp) => {
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
at_1.unwrap_or(interm!(1)),
at_2.unwrap_or(interm!(2))));
},
- &InlinedQueryTerm::IsAtomic(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsAtomic =>
+ match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
},
code.push(is_atomic!(r));
}
},
- &InlinedQueryTerm::IsCompound(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsCompound =>
+ match terms[0].as_ref() {
&Term::Clause(..) | &Term::Cons(..) => {
code.push(succeed!());
},
code.push(fail!());
}
},
- &InlinedQueryTerm::IsRational(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsRational =>
+ match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Rational(_))) => {
code.push(succeed!());
},
code.push(fail!());
}
},
- &InlinedQueryTerm::IsFloat(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsFloat =>
+ match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Float(_))) => {
code.push(succeed!());
},
code.push(fail!());
}
},
- &InlinedQueryTerm::IsString(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsString =>
+ match terms[0].as_ref() {
&Term::Constant(_, Constant::String(_)) => {
code.push(succeed!());
},
code.push(fail!());
}
},
- &InlinedQueryTerm::IsNonVar(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsNonVar =>
+ match terms[0].as_ref() {
&Term::AnonVar => {
code.push(fail!());
},
code.push(succeed!());
}
},
- &InlinedQueryTerm::IsInteger(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsInteger =>
+ match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!());
},
code.push(fail!());
},
},
- &InlinedQueryTerm::IsVar(ref inner_term) =>
- match inner_term[0].as_ref() {
+ InlinedClauseType::IsVar =>
+ match terms[0].as_ref() {
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
},
GenContext::Last(chunk_num)
};
+ let term = if let &ChunkedTerm::BodyTerm(ref term) = term {
+ Ok(term)
+ } else {
+ Err(ParserError::InadmissibleQueryTerm)
+ }?;
+
match *term {
&QueryTerm::Cut =>
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
} else {
Line::Cut(CutInstruction::Cut(perm_v!(1)))
- }),
- &QueryTerm::Is(ref terms) => {
+ }),
+ &QueryTerm::Clause(_, ClauseType::Is, ref terms) => {
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode);
if !target.is_empty() {
code.push(Line::Query(target));
}
-
+
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
},
&Term::Constant(_, ref c @ Constant::Number(_)) => {
}
}
},
- &QueryTerm::Inlined(ref term) =>
- try!(self.compile_inlined(term, term_loc, code)),
+ &QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) =>
+ try!(self.compile_inlined(ct, terms, term_loc, code)),
_ => {
let num_perm_vars = if chunk_num == 0 {
conjunct_info.perm_vars()
self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
},
- };
+ };
}
self.marker.reset_contents();
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
{
- // add a proceed to bookend any trailing inlines or cuts.
+ // add a proceed to bookend any trailing cuts.
match toc {
- &QueryTerm::Inlined(_) | &QueryTerm::Cut =>
- code.push(proceed!()),
+ &QueryTerm::Cut => code.push(proceed!()),
_ => {}
};
let iter = ChunkedIterator::from_rule(rule);
let conjunct_info = self.collect_var_data(iter);
- let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+ let &Rule { head: (_, ref args, ref p1), ref clauses } = rule;
let mut code = Vec::new();
- if let &QueryTerm::Term(ref term) = p0 {
- self.marker.reset_arg(term.arity());
- self.compile_seq_prelude(&conjunct_info, &mut code);
+ self.marker.reset_arg(args.len());
+ self.compile_seq_prelude(&conjunct_info, &mut code);
- if let &Term::Clause(..) = term {
- let iter = FactInstruction::iter(term);
- let fact = self.compile_target(iter, GenContext::Head, false);
+ let iter = FactIterator::from_rule_head_clause(args);
+ let fact = self.compile_target(iter, GenContext::Head, false);
- if !fact.is_empty() {
- code.push(Line::Fact(fact));
- }
- }
+ if !fact.is_empty() {
+ code.push(Line::Fact(fact));
+ }
- let iter = ChunkedIterator::from_rule_body(p1, clauses);
- try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
+ 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 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);
- }
+ 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)
- } else {
- Err(ParserError::InvalidRuleHead)
}
+
+ Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
+ Ok(code)
}
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
match lvl {
Level::Deep => target.push(Target::subterm_to_variable(r)),
- Level::Shallow => {
+ Level::Root | Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
}
};
}
-
- fn mark_non_var<Target>(&mut self,
- lvl: Level,
- term_loc: GenContext,
- cell: &Cell<RegType>,
- target: &mut Vec<Target>)
+
+ fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
+ cell: &Cell<RegType>, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = cell.get();
};
match lvl {
- Level::Shallow => {
+ Level::Root | Level::Shallow => {
let k = self.arg_c;
if self.is_curr_arg_distinct_from(var) {
use prolog::ast::*;
+use prolog::iterators::*;
use std::cell::Cell;
use std::collections::{BTreeMap, BTreeSet, HashMap};
}
}
- fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
+ fn mark_head_vars_as_safe(&self, head_iter: FactIterator<'a>, unsafe_vars: &mut HashMap<RegType, bool>)
{
- for term_ref in head.breadth_first_iter() {
+ for term_ref in head_iter {
match term_ref {
TermRef::Var(Level::Shallow, cell, _) => {
unsafe_vars.remove(&cell.get().norm());
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
- pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
+ pub fn mark_unsafe_vars_in_rule(&self, head_iter: FactIterator<'a>, query: &mut CompiledQuery)
{
let mut unsafe_vars = HashMap::new();
self.record_unsafe_vars(&mut unsafe_vars);
- self.mark_head_vars_as_safe(head, &mut unsafe_vars);
+ self.mark_head_vars_as_safe(head_iter, &mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
}
use prolog::ast::*;
use prolog::heap_iter::*;
-use prolog::tabled_rc::*;
use std::cell::Cell;
use std::rc::Rc;
#[derive(Clone)]
pub enum TokenOrRedirect {
- Atom(TabledRc<Atom>),
+ Atom(ClauseName),
Redirect,
Open,
Close,
pub trait HeapCellValueFormatter {
// this function belongs to the display predicate formatter, which it uses
// to format all clauses.
- fn format_struct(&self, arity: usize, name: TabledRc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
+ fn format_struct(&self, arity: usize, name: ClauseName, state_stack: &mut Vec<TokenOrRedirect>)
{
state_stack.push(TokenOrRedirect::Close);
// this can be overloaded to handle special cases, falling back on the default of
// format_struct when convenient.
- fn format_clause(&self, usize, TabledRc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
+ fn format_clause(&self, usize, ClauseType, &mut Vec<TokenOrRedirect>);
}
pub trait HeapCellValueOutputter {
pub struct DisplayFormatter {}
impl HeapCellValueFormatter for DisplayFormatter {
- fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
- state_stack: &mut Vec<TokenOrRedirect>)
+ fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
{
- if fixity.is_some() {
+ if ct.fixity().is_some() {
let mut new_name = String::from("'");
- new_name += name.as_ref();
+ new_name += ct.name().as_str();
new_name += "'";
-
- let name = TabledRc::new(new_name, name.table());
- self.format_struct(arity, name, state_stack);
+
+ self.format_struct(arity, ct.name(), state_stack);
} else {
- self.format_struct(arity, name, state_stack);
+ self.format_struct(arity, ct.name(), state_stack);
}
}
}
pub struct TermFormatter {}
impl HeapCellValueFormatter for TermFormatter {
- fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
- state_stack: &mut Vec<TokenOrRedirect>)
+ fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
{
- if let Some(fixity) = fixity {
+ if let Some(fixity) = ct.fixity() {
match fixity {
Fixity::Post => {
- state_stack.push(TokenOrRedirect::Atom(name));
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Redirect);
},
Fixity::Pre => {
state_stack.push(TokenOrRedirect::Redirect);
state_stack.push(TokenOrRedirect::Space);
- state_stack.push(TokenOrRedirect::Atom(name));
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
},
Fixity::In => {
state_stack.push(TokenOrRedirect::Redirect);
state_stack.push(TokenOrRedirect::Space);
- state_stack.push(TokenOrRedirect::Atom(name));
+ state_stack.push(TokenOrRedirect::Atom(ct.name()));
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Redirect);
}
}
} else {
- self.format_struct(arity, name, state_stack);
+ self.format_struct(arity, ct.name(), state_stack);
}
}
}
fn handle_heap_term(&mut self, heap_val: HeapCellValue) {
match heap_val {
- HeapCellValue::NamedStr(arity, name, fixity) =>
- self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
+ HeapCellValue::NamedStr(arity, name, fixity) => {
+ let ct = ClauseType::from(name, arity, fixity);
+ self.formatter.format_clause(arity, ct, &mut self.state_stack)
+ },
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
if !self.at_cdr("") {
self.outputter.append("[]");
use prolog::ast::*;
-use prolog::tabled_rc::*;
use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
pub struct CodeOffsets {
pub constants: HashMap<Constant, ThirdLevelIndex>,
pub lists: ThirdLevelIndex,
- pub structures: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>
+ pub structures: HashMap<(ClauseName, usize), ThirdLevelIndex>
}
impl CodeOffsets {
}
}
- fn switch_on_structure(str_ind: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>,
+ fn switch_on_structure(str_ind: HashMap<(ClauseName, usize), ThirdLevelIndex>,
prelude: &mut CodeDeque)
-> IntIndex
{
use std::io::{Write, stdin, stdout};
use std::fmt;
+impl fmt::Display for ClauseName {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_str())
+ }
+}
+
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
- write!(f, "get_constant {}, A{}", constant, r.reg_num()),
- &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
- write!(f, "get_constant {}, {}", constant, r),
- &FactInstruction::GetList(Level::Shallow, ref r) =>
- write!(f, "get_list A{}", r.reg_num()),
- &FactInstruction::GetList(Level::Deep, ref r) =>
- write!(f, "get_list {}", r),
- &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r, _) =>
- write!(f, "get_structure {}/{}, {}", name, arity, r),
- &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r, _) =>
- write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
+ &FactInstruction::GetConstant(lvl, ref constant, ref r) =>
+ write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num()),
+ &FactInstruction::GetList(lvl, ref r) =>
+ write!(f, "get_list {}{}", lvl, r.reg_num()),
+ &FactInstruction::GetStructure(ref ct, ref arity, ref r) =>
+ write!(f, "get_structure {}/{}, {}", ct.name(), arity, r),
&FactInstruction::GetValue(ref x, ref a) =>
write!(f, "get_value {}, A{}", x, a),
&FactInstruction::GetVariable(ref x, ref a) =>
match self {
&QueryInstruction::GetVariable(ref x, ref a) =>
write!(f, "query:get_variable {}, A{}", x, a),
- &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
- write!(f, "put_constant {}, A{}", constant, r.reg_num()),
- &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
- write!(f, "put_constant {}, {}", constant, r),
- &QueryInstruction::PutList(Level::Shallow, ref r) =>
- write!(f, "put_list A{}", r.reg_num()),
- &QueryInstruction::PutList(Level::Deep, ref r) =>
- write!(f, "put_list {}", r),
- &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r, _) =>
- write!(f, "put_structure {}/{}, {}", name, arity, r),
- &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r, _) =>
- write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
+ &QueryInstruction::PutConstant(lvl, ref constant, ref r) =>
+ write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num()),
+ &QueryInstruction::PutList(lvl, ref r) =>
+ write!(f, "put_list {}{}", lvl, r.reg_num()),
+ &QueryInstruction::PutStructure(ref ct, ref arity, ref r) =>
+ write!(f, "put_structure {}/{}, {}", ct.name(), arity, r),
&QueryInstruction::PutUnsafeValue(y, a) =>
write!(f, "put_unsafe_value Y{}, A{}", y, a),
&QueryInstruction::PutValue(ref x, ref a) =>
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &Level::Shallow => write!(f, "A"),
+ &Level::Root | &Level::Shallow => write!(f, "A"),
&Level::Deep => write!(f, "X")
}
}
let mut code = try!(cg.compile_query(terms));
compile_appendix(&mut code, queue)?;
-
+
Ok((code, cg.take_vars()))
}
impl<'a> QueryIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
- self.state_stack.push(TermIterState::to_state(lvl, term));
+ self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
+ }
+
+ fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
+ let state_stack = terms.iter().rev()
+ .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
+ .collect();
+
+ QueryIterator { state_stack }
}
fn from_term(term: &'a Term) -> Self {
let state = match term {
&Term::AnonVar =>
return QueryIterator { state_stack: vec![] },
- &Term::Clause(_, ref name, ref terms, _) =>
- TermIterState::Clause(0, ClauseType::Root(name), terms),
+ &Term::Clause(ref r, ref name, ref terms, fixity) =>
+ TermIterState::Clause(Level::Root, 0, r,
+ ClauseType::from(name.clone(), terms.len(), fixity),
+ terms),
&Term::Cons(..) =>
return QueryIterator { state_stack: vec![] },
&Term::Constant(_, _) =>
return QueryIterator { state_stack: vec![] },
&Term::Var(ref cell, ref var) =>
- TermIterState::Var(Level::Shallow, cell, var)
+ TermIterState::Var(Level::Root, cell, var)
};
QueryIterator { state_stack: vec![state] }
fn new(term: &'a QueryTerm) -> Self {
match term {
- &QueryTerm::CallN(ref terms) => {
- let state = TermIterState::Clause(1, ClauseType::CallN, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::CallWithInferenceLimit(ref terms) => {
- let ct = ClauseType::CallWithInferenceLimit;
- let state = TermIterState::Clause(0, ct, terms);
-
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Catch(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Catch, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::DuplicateTerm(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::DuplicateTerm, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Arg(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Arg, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::SetupCallCleanup(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::SetupCallCleanup, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Eq(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Eq, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Functor(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Functor, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Display(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Display, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Ground(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Ground, terms);
+ &QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms) => {
+ let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(qt, ref terms)) => {
- let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Compare(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Compare, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::CompareTerm(qt, ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Is(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::Is, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsNonVar(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsFloat(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsRational(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsCompound(ref terms))
- | &QueryTerm::Inlined(InlinedQueryTerm::IsString(ref terms)) =>
- Self::from_term(terms[0].as_ref()),
- &QueryTerm::NotEq(ref terms) => {
- let state = TermIterState::Clause(0, ClauseType::NotEq, terms);
- QueryIterator { state_stack: vec![state] }
- },
- &QueryTerm::Term(ref term) =>
- Self::from_term(term),
- &QueryTerm::Throw(ref term) => {
- let state = TermIterState::Clause(0, ClauseType::Throw, term);
+ &QueryTerm::Clause(ref cell, ref ct, ref terms) => {
+ let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Cut => QueryIterator { state_stack: vec![] },
&QueryTerm::Jump(ref vars) => {
let state_stack = vars.iter().rev().map(|t| {
- TermIterState::to_state(Level::Shallow, t)
+ TermIterState::subterm_to_state(Level::Shallow, t)
}).collect();
QueryIterator { state_stack }
}
}
-impl QueryTerm {
- pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
- QueryIterator::new(self)
- }
-}
-
impl<'a> Iterator for QueryIterator<'a> {
type Item = TermRef<'a>;
match iter_state {
TermIterState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
- TermIterState::Clause(child_num, ct, child_terms) => {
+ TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
ClauseType::CallN =>
self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
- ClauseType::Deep(..) =>
- return Some(TermRef::Clause(ct, child_terms)),
+ ClauseType::Named(..) | ClauseType::Op(..) =>
+ return match lvl {
+ Level::Root => None,
+ lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms))
+ },
_ =>
return None
};
} else {
- self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
- self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
+ self.state_stack.push(TermIterState::Clause(lvl, child_num + 1,
+ cell, ct, child_terms));
+ self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
}
},
TermIterState::InitialCons(lvl, cell, head, tail) => {
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
- self.push_subterm(Level::Deep, tail);
- self.push_subterm(Level::Deep, head);
+
+ self.push_subterm(lvl.child_level(), tail);
+ self.push_subterm(lvl.child_level(), head);
},
TermIterState::FinalCons(lvl, cell, head, tail) =>
return Some(TermRef::Cons(lvl, cell, head, tail)),
impl<'a> FactIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
- self.state_queue.push_back(TermIterState::to_state(lvl, term));
+ self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
+ }
+
+ 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) -> FactIterator<'a> {
+ fn new(term: &'a Term) -> Self {
let states = match term {
&Term::AnonVar =>
- vec![TermIterState::AnonVar(Level::Shallow)],
- &Term::Clause(.., ref name, ref terms, _) =>
- vec![TermIterState::Clause(0, ClauseType::Root(name), terms)],
+ vec![TermIterState::AnonVar(Level::Root)],
+ &Term::Clause(ref cell, ref name, ref terms, fixity) => {
+ let ct = ClauseType::from(name.clone(), terms.len(), fixity);
+ vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
+ },
&Term::Cons(ref cell, ref head, ref tail) =>
- vec![TermIterState::InitialCons(Level::Shallow,
- cell,
- head.as_ref(),
- tail.as_ref())],
+ vec![TermIterState::InitialCons(Level::Root, cell, head.as_ref(), tail.as_ref())],
&Term::Constant(ref cell, ref constant) =>
- vec![TermIterState::Constant(Level::Shallow, cell, constant)],
+ vec![TermIterState::Constant(Level::Root, cell, constant)],
&Term::Var(ref cell, ref var) =>
- vec![TermIterState::Var(Level::Shallow, cell, var)]
+ vec![TermIterState::Var(Level::Root, cell, var)]
};
FactIterator { state_queue: VecDeque::from(states) }
match state {
TermIterState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
- TermIterState::Clause(_, ct, child_terms) => {
+ TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
for child_term in child_terms {
- self.push_subterm(ct.level_of_subterms(), child_term);
+ self.push_subterm(lvl.child_level(), child_term);
}
- match ct {
- ClauseType::Deep(..) =>
- return Some(TermRef::Clause(ct, child_terms)),
- _ =>
- continue
+ match lvl {
+ Level::Root => continue,
+ _ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
};
},
TermIterState::InitialCons(lvl, cell, head, tail) => {
}
}
+pub enum ChunkedTerm<'a> {
+ HeadClause(ClauseName, &'a Vec<Box<Term>>),
+ BodyTerm(&'a QueryTerm)
+}
+
+impl QueryTerm {
+ pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
+ QueryIterator::new(self)
+ }
+}
+
+impl<'a> ChunkedTerm<'a> {
+ pub fn post_order_iter(&self) -> QueryIterator<'a> {
+ match self {
+ &ChunkedTerm::BodyTerm(ref qt) =>
+ QueryIterator::new(qt),
+ &ChunkedTerm::HeadClause(_, terms) =>
+ QueryIterator::from_rule_head_clause(terms)
+ }
+ }
+}
+
pub struct ChunkedIterator<'a>
{
- term_loc: GenContext,
- iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
+ pub chunk_num: usize,
+ iter: Box<Iterator<Item=ChunkedTerm<'a>> + 'a>,
deep_cut_encountered: bool
}
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
{
ChunkedIterator {
- term_loc: GenContext::Last(0),
- iter: Box::new(terms.iter()),
+ chunk_num: 0,
+ iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
deep_cut_encountered: false
}
}
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
{
- let inner_iter = Box::new(once(p1));
- let iter = inner_iter.chain(clauses.iter());
+ let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
+ let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
ChunkedIterator {
- term_loc: GenContext::Last(0),
+ chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false
}
pub fn from_rule(rule: &'a Rule) -> Self
{
- let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+ let &Rule { head: (ref name, ref args, ref p1), ref clauses } = rule;
- let iter = once(p0);
- let inner_iter = Box::new(once(p1));
- let iter = iter.chain(inner_iter.chain(clauses.iter()));
+ let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
+ let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
+ let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))));
ChunkedIterator {
- term_loc: GenContext::Head,
+ chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false,
}
self.deep_cut_encountered
}
- pub fn at_rule_head(&self) -> bool {
- self.term_loc == GenContext::Head
- }
-
- pub fn chunk_num(&self) -> usize {
- self.term_loc.chunk_num()
- }
-
- fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
+ fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>)
{
let mut arity = 0;
let mut item = Some(term);
while let Some(term) = item {
match term {
- &QueryTerm::Jump(ref vars) => {
+ ChunkedTerm::HeadClause(..) =>
+ result.push(term),
+ ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
result.push(term);
arity = vars.len();
break;
},
- &QueryTerm::CompareTerm(..) => {
- result.push(term);
- arity = 2;
- break;
- },
- &QueryTerm::Term(ref inner_term) =>
- if let GenContext::Head = self.term_loc {
- result.push(term);
- self.term_loc = GenContext::Last(0);
- } else {
- result.push(term);
-
- if inner_term.is_callable() {
- arity = inner_term.arity();
- break;
- }
- },
- &QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
- result.push(term);
- arity = 3;
- break;
- },
- &QueryTerm::CallN(ref child_terms) => {
- result.push(term);
- arity = child_terms.len() + 1;
- break;
- },
- &QueryTerm::Catch(ref child_terms)
- | &QueryTerm::Throw(ref child_terms) => {
+ ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
result.push(term);
- arity = child_terms.len();
- break;
- },
- &QueryTerm::Ground(_) | &QueryTerm::Display(_) => {
- result.push(term);
- arity = 1;
- break;
+
+ if self.chunk_num > 0 {
+ self.deep_cut_encountered = true;
+ }
},
- &QueryTerm::Arg(_)
- | &QueryTerm::Functor(_)
- | &QueryTerm::CallWithInferenceLimit(_) => {
+ ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
+ result.push(term),
+ ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
result.push(term);
- arity = 3;
+ arity = subterms.len() + 1;
break;
},
- &QueryTerm::Eq(_) | &QueryTerm::NotEq(_)
- | &QueryTerm::Is(_) | &QueryTerm::DuplicateTerm(_) => {
+ ChunkedTerm::BodyTerm(qt) => {
result.push(term);
- arity = 2;
+ arity = qt.arity();
break;
- },
- &QueryTerm::Inlined(_) =>
- result.push(term),
- &QueryTerm::Cut => {
- result.push(term);
-
- if self.term_loc.chunk_num() > 0 {
- self.deep_cut_encountered = true;
- }
- },
+ }
};
item = self.iter.next();
}
- let chunk_num = self.term_loc.chunk_num();
-
- if let &mut GenContext::Last(ref mut chunk_num) = &mut self.term_loc {
- *chunk_num += 1;
- }
+ let chunk_num = self.chunk_num;
+ self.chunk_num += 1;
(chunk_num, arity, result)
}
impl<'a> Iterator for ChunkedIterator<'a>
{
// the chunk number, last term arity, and vector of references.
- type Item = (usize, usize, Vec<&'a QueryTerm>);
+ type Item = (usize, usize, Vec<ChunkedTerm<'a>>);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|term| self.take_chunk(term))
pub(crate) trait CallPolicy: Any {
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
- name: TabledRc<Atom>, arity: usize)
+ name: ClauseName, arity: usize)
-> CallResult
{
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
}
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
- name: TabledRc<Atom>, arity: usize)
+ name: ClauseName, arity: usize)
-> CallResult
{
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
impl CallPolicy for DefaultCallPolicy {}
-pub(crate) struct CallWithInferenceLimitCallPolicy {
- atom_tbl: TabledData<Atom>,
+pub(crate) struct CallWithInferenceLimitCallPolicy {
pub(crate) prev_policy: Box<CallPolicy>,
count: BigUint,
limits: Vec<(BigUint, usize)>
}
impl CallWithInferenceLimitCallPolicy {
- pub(crate) fn new_in_place(atom_tbl: TabledData<Atom>, policy: &mut Box<CallPolicy>)
+ pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>)
{
let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
swap(&mut prev_policy, policy);
- let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
+ let new_policy = CallWithInferenceLimitCallPolicy { prev_policy,
count: BigUint::zero(),
limits: vec![] };
*policy = Box::new(new_policy);
fn increment(&mut self) -> CallResult {
if let Some(&(ref limit, bp)) = self.limits.last() {
if self.count == *limit {
- return Err(functor!(self.atom_tbl,
- "inference_limit_exceeded",
- 1,
+ return Err(functor!("inference_limit_exceeded", 1,
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
} else {
self.count += BigUint::one();
}
}
-
+
Ok(())
}
impl CallPolicy for CallWithInferenceLimitCallPolicy {
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
- name: TabledRc<Atom>, arity: usize)
+ name: ClauseName, arity: usize)
-> CallResult
{
self.prev_policy.try_call(machine_st, code_dir, name, arity)?;
}
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
- name: TabledRc<Atom>, arity: usize)
+ name: ClauseName, arity: usize)
-> CallResult
{
self.prev_policy.try_execute(machine_st, code_dir, name, arity)?;
match item {
Addr::Con(Constant::Number(n)) => Ok(n),
- _ => {
- let atom_tbl = self.atom_tbl.clone();
- Err(functor!(self.atom_tbl,
- "instantiation_error",
- 1,
- [heap_atom!("(is)/2", atom_tbl)]))
- }
+ _ => Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
}
},
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
if let Some(r) = Ratio::from_float(fl.into_inner()) {
Ok(Rc::new(r))
} else {
- Err(functor!(self.atom_tbl,
- "instantiation_error",
- 1,
- [heap_atom!("(is)/2", self.atom_tbl)]))
+ Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
},
Number::Integer(bi) =>
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, Vec<HeapCellValue>>
{
- let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
- [heap_atom!("(is)/2", self.atom_tbl.clone())]);
-
+ let instantiation_err = functor!("instantiation_error", 1, [heap_atom!("(is)/2")]);
let a = self[r].clone();
if let &Addr::Con(Constant::Number(ref n)) = &a {
-> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>>
{
if *r2 == Ratio::zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*r1 / &*r2))
}
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(n1.div_floor(&n2)))
},
- _ => Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ _ => Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*n1 / &*n2))
},
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
fn div(&self, n1: Number, n2: Number) -> Result<Number, Vec<HeapCellValue>>
{
if n2.is_zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(n1 / n2)
}
_ => Ok(Rc::new(&*n1 >> usize::max_value()))
},
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
_ => Ok(Rc::new(&*n1 << usize::max_value()))
},
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)),
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(n1.mod_floor(&n2)))
},
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*n1 % &*n2))
},
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
_ =>
- Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
- [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+ Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
_ => self.fail = true
};
},
- &FactInstruction::GetStructure(_, ref name, arity, reg, fixity) => {
+ &FactInstruction::GetStructure(ref ct, arity, reg) => {
let addr = self.deref(self[reg].clone());
match self.store(addr.clone()) {
Addr::Str(a) => {
let result = &self.heap[a];
- if let &HeapCellValue::NamedStr(narity, ref str, _) = result {
- if narity == arity && *name == *str {
+ if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
+ if narity == arity && ct.name() == *s {
self.s = a + 1;
self.mode = MachineMode::Read;
} else {
let h = self.heap.h;
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
- self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
+ self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
self[reg] = Addr::Con(constant.clone()),
&QueryInstruction::PutList(_, reg) =>
self[reg] = Addr::Lis(self.heap.h),
- &QueryInstruction::PutStructure(_, ref name, arity, reg, fixity) => {
+ &QueryInstruction::PutStructure(ref ct, arity, reg) => {
let h = self.heap.h;
- self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
+ self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
self[reg] = Addr::Str(h);
},
&QueryInstruction::PutUnsafeValue(n, arg) => {
if let HeapCellValue::NamedStr(narity, name, _) = result {
if narity + arity > 63 {
- let atom_tbl = self.atom_tbl.clone();
- self.throw_exception(functor!(atom_tbl,
- "representation_error",
- 1,
- [heap_atom!("exceeds_max_arity", atom_tbl)]));
+ self.throw_exception(functor!("representation_error", 1,
+ [heap_atom!("exceeds_max_arity")]));
return None;
}
},
Addr::Con(Constant::Atom(name)) => (name, 0),
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
- let atom_tbl = self.atom_tbl.clone();
- self.throw_exception(functor!(atom_tbl, "instantiation_error", 0, []));
+ self.throw_exception(functor!("instantiation_error"));
return None;
},
_ => {
- let atom_tbl = self.atom_tbl.clone();
- self.throw_exception(functor!(atom_tbl,
- "type_error",
- 2,
- [heap_atom!("callable", atom_tbl),
+ self.throw_exception(functor!("type_error", 2,
+ [heap_atom!("callable"),
HeapCellValue::Addr(addr)]));
return None;
}
_ => self.fail = true
};
} else {
- return Err(functor!(self.atom_tbl,
- "type_error",
- 1,
- [heap_atom!("compound_expected", self.atom_tbl)]));
+ return Err(functor!("type_error", 1, [heap_atom!("compound_expected")]))
}
}
return Ordering::Less;
} else if ar1 > ar2 {
return Ordering::Greater;
- } else if *n1 != *n2 {
+ } else if n1 != n2 {
return n1.cmp(&n2);
} else {
continue;
continue,
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _))
| (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) =>
- if ar == 2 && *n == "." {
+ if ar == 2 && n.as_str() == "." {
continue;
} else if ar < 2 {
return Ordering::Greater;
} else if ar > 2 {
return Ordering::Less;
} else {
- return n.cmp(&String::from("."));
+ return n.as_str().cmp(".");
},
(HeapCellValue::NamedStr(..), _) =>
return Ordering::Greater,
let a2 = self.store(self.deref(self[r2].clone()));
if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
- CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
- call_policy);
+ CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
}
self.p += 1;
None => panic!("install_inference_counter: should have installed \\
CallWithInferenceLimitCallPolicy.")
},
- _ => {
- let atom_tbl = self.atom_tbl.clone();
- self.throw_exception(functor!(atom_tbl,
- "type_error",
- 1,
- [heap_atom!("integer_expected", atom_tbl)]))
- }
+ _ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
};
},
&BuiltInInstruction::IsAtomic(r) => {
self.unify(a1, f_a);
} else {
- return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
+ return Err(functor!("instantiation_error"));
}
} else {
- return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
+ return Err(functor!("instantiation_error"));
}
},
_ => {
for (v1, v2) in iter {
match (v1, v2) {
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
- if ar1 != ar2 || *n1 != *n2 {
+ if ar1 != ar2 || n1 != n2 {
return true;
},
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
for (v1, v2) in iter {
match (v1, v2) {
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
- if ar1 != ar2 || *n1 != *n2 {
+ if ar1 != ar2 || n1 != n2 {
return true;
},
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
impl Machine {
pub fn new() -> Self {
let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
- let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
+ let (code, code_dir, op_dir) = build_code_dir();
Machine {
ms: MachineState::new(atom_tbl),
self.ms.atom_tbl.clone()
}
- pub fn add_user_code<'a>(&mut self, name: TabledRc<Atom>, arity: usize, mut code: Code)
+ pub fn add_user_code<'a>(&mut self, name: ClauseName, arity: usize, mut code: Code)
-> EvalSession<'a>
{
match self.code_dir.get(&(name.clone(), arity)) {
fn query_stepper<'a>(&mut self)
{
- loop
- {
+ loop {
self.execute_instr();
if self.failed() {
}
}
- fn record_var_places<'a>(&self,
- chunk_num: usize,
- alloc_locs: &AllocVarDict<'a>,
- heap_locs: &mut HeapVarDict<'a>)
+ fn record_var_places<'a>(&self, chunk_num: usize,
+ alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
{
for (var, var_data) in alloc_locs {
match var_data {
+macro_rules! clause_name {
+ ($name: expr) => (
+ ClauseName::BuiltIn($name)
+ )
+}
+
macro_rules! tabled_rc {
($e:expr, $tbl:expr) => (
TabledRc::new(String::from($e), $tbl.clone())
macro_rules! atom {
($e:expr, $tbl:expr) => (
- Constant::Atom(tabled_rc!($e, $tbl))
+ Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)))
+ );
+ ($e:expr) => (
+ Constant::Atom(clause_name!($e))
)
}
}
macro_rules! heap_atom {
+ ($name:expr) => (
+ HeapCellValue::Addr(Addr::Con(atom!($name)))
+ );
($name:expr, $tbl:expr) => (
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
)
}
macro_rules! functor {
- ($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
- if $len > 0 {
- vec![ HeapCellValue::NamedStr($len,
- tabled_rc!($name, $tbl),
- None),
- $($args),* ]
- } else {
- vec![ heap_atom!($name, $tbl) ]
- }
- }}
+ ($name:expr) => (
+ vec![ heap_atom!($name) ]
+ );
+ ($name:expr, $len:expr, [$($args:expr),*]) => (
+ vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
+ )
}
macro_rules! fact {
}
macro_rules! put_structure {
- ($tbl:expr, $lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
- QueryInstruction::PutStructure($lvl, tabled_rc!($name, $tbl), $arity, $r, $fix)
+ ($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
+ QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
+ );
+ ($atom:expr, $arity:expr, $r:expr, None) => (
+ QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
)
}
}
macro_rules! get_structure {
- ($tbl:expr, $atom:expr, $arity:expr, $r:expr, $fix:expr) => (
- FactInstruction::GetStructure(Level::Shallow,
- tabled_rc!($atom, $tbl),
- $arity,
- $r,
- $fix)
+ ($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
+ FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
+ );
+ ($atom:expr, $arity:expr, $r:expr, None) => (
+ FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
)
}
-Subproject commit cd115d7a6781a59003f0d52451319ae68988e785
+Subproject commit 5b74536d6edfc55c943f77c72a99ad00dcbd96c4
use std::cell::RefCell;
+use std::cmp::Ordering;
use std::collections::HashSet;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
pub type TabledData<T> = Rc<RefCell<HashSet<Rc<T>>>>;
-
+
#[derive(Clone)]
pub struct TabledRc<T: Hash + Eq> {
atom: Rc<T>,
table: TabledData<T>
}
+impl<T: Ord + Hash + Eq> PartialOrd for TabledRc<T> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering>
+ {
+ Some(self.atom.cmp(&other.atom))
+ }
+}
+
+impl<T: Ord + Hash + Eq> Ord for TabledRc<T> {
+ fn cmp(&self, other: &Self) -> Ordering
+ {
+ self.atom.cmp(&other.atom)
+ }
+}
+
impl<T: Hash + Eq> PartialEq for TabledRc<T> {
fn eq(&self, other: &TabledRc<T>) -> bool
{
impl<T: Hash + Eq> Eq for TabledRc<T> {}
impl<T: Hash + Eq> Hash for TabledRc<T> {
- fn hash<H: Hasher>(&self, state: &mut H)
- {
- self.atom.hash(state)
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.atom.hash(state)
}
}
TabledRc { atom, table }
}
-
- pub fn table(&self) -> TabledData<T> {
- self.table.clone()
- }
}
impl<T: Hash + Eq> Drop for TabledRc<T> {
use prolog::ast::*;
use prolog::iterators::*;
-use prolog::tabled_rc::*;
pub trait CompilationTarget<'a> {
type Iterator : Iterator<Item=TermRef<'a>>;
fn to_constant(Level, Constant, RegType) -> Self;
fn to_list(Level, RegType) -> Self;
- fn to_structure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>) -> Self;
+ fn to_structure(ClauseType, usize, RegType) -> Self;
fn to_void(usize) -> Self;
fn is_void_instr(&self) -> bool;
FactInstruction::GetConstant(lvl, constant, reg)
}
- fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
- reg: RegType, fixity: Option<Fixity>)
- -> Self
+ fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self
{
- FactInstruction::GetStructure(lvl, atom, arity, reg, fixity)
+ FactInstruction::GetStructure(ct, arity, reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
term.post_order_iter()
}
- fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
- reg: RegType, fixity: Option<Fixity>)
- -> Self
+ fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self
{
- QueryInstruction::PutStructure(lvl, atom, arity, reg, fixity)
+ QueryInstruction::PutStructure(ct, arity, r)
}
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
{
let mut wam = Machine::new();
- submit(&mut wam, "maplist(Pred, []).
- maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
+ submit(&mut wam, "maplist(_, []).
+ maplist(P, [X|Xs]) :- call(P, X), maplist(P, Xs).");
submit(&mut wam, "f(a). f(b). f(c).");
assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).",