major refactor.

This commit is contained in:
Mark Thom
2018-02-25 12:13:07 -07:00
parent 05c1275acf
commit cf9db43d5b
20 changed files with 735 additions and 813 deletions

2
Cargo.lock generated
View File

@@ -176,7 +176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rusty-wam"
version = "0.7.5"
version = "0.7.6"
dependencies = [
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package]
name = "rusty-wam"
version = "0.7.5"
version = "0.7.6"
authors = ["Mark Thom"]
[dependencies]

View File

@@ -13,15 +13,19 @@ pub type ArithCont = (Code, Option<ArithmeticTerm>);
impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::to_state(lvl, term));
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
}
fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
let state = match term {
&Term::AnonVar =>
return Err(ArithmeticError::InvalidTerm),
&Term::Clause(_, ref name, ref terms, _) =>
TermIterState::Clause(0, ClauseType::Root(name), terms),
&Term::Clause(ref cell, ref name, ref terms, fixity) =>
match ClauseType::from(name.clone(), terms.len(), fixity) {
ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) =>
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)),
_ => Err(ArithmeticError::InvalidOp)
}?,
&Term::Constant(ref cell, ref cons) =>
TermIterState::Constant(Level::Shallow, cell, cons),
&Term::Cons(_, _, _) =>
@@ -36,7 +40,7 @@ impl<'a> ArithInstructionIterator<'a> {
pub enum ArithTermRef<'a> {
Constant(&'a Constant),
Op(&'a str, usize), // name, arity.
Op(ClauseName, usize), // name, arity.
Var(&'a Cell<VarReg>, &'a Var)
}
@@ -48,14 +52,14 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
match iter_state {
TermIterState::AnonVar(_) =>
return Some(Err(ArithmeticError::UninstantiatedVar)),
TermIterState::Clause(child_num, ct, child_terms) => {
let arity = child_terms.len();
TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
let arity = subterms.len();
if child_num == arity {
return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
} else {
self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms));
self.push_subterm(lvl, subterms[child_num].as_ref());
}
},
TermIterState::Constant(_, _, c) =>
@@ -97,19 +101,19 @@ impl<'a> ArithmeticEvaluator<'a>
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
}
fn get_unary_instr(name: &str, a1: ArithmeticTerm, t: usize)
fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
match name {
match name.as_str() {
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
_ => Err(ArithmeticError::InvalidOp)
}
}
fn get_binary_instr(name: &str, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
match name {
match name.as_str() {
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
@@ -137,7 +141,7 @@ impl<'a> ArithmeticEvaluator<'a>
temp
}
fn instr_from_clause(&mut self, name: &str, arity: usize)
fn instr_from_clause(&mut self, name: ClauseName, arity: usize)
-> Result<ArithmeticInstruction, ArithmeticError>
{
match arity {
@@ -215,7 +219,7 @@ impl<'a> ArithmeticEvaluator<'a>
self.interm.push(ArithmeticTerm::Reg(r));
},
ArithTermRef::Op(name, arity) => {
code.push(Line::Arithmetic(self.instr_from_clause(&*name, arity)?));
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
}
}
}

View File

@@ -8,6 +8,7 @@ use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::{HashMap, VecDeque};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::io::Error as IOError;
use std::num::{ParseFloatError};
use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg};
@@ -46,37 +47,27 @@ impl PredicateClause {
pub fn first_arg(&self) -> Option<&Term> {
match self {
&PredicateClause::Fact(ref term) => term.first_arg(),
&PredicateClause::Rule(ref rule) =>
if let &QueryTerm::Term(ref term) = &rule.head.0 {
term.first_arg()
} else {
None
}
&PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()),
}
}
pub fn arity(&self) -> usize {
match self {
&PredicateClause::Fact(ref term) => term.arity(),
&PredicateClause::Rule(ref rule) => rule.head.0.arity()
&PredicateClause::Rule(ref rule) => rule.head.1.len()
}
}
pub fn name(&self) -> Option<TabledRc<Atom>> {
pub fn name(&self) -> Option<ClauseName> {
match self {
&PredicateClause::Fact(ref term) => term.name(),
&PredicateClause::Rule(ref rule) =>
if let &QueryTerm::Term(ref term) = &rule.head.0 {
term.name()
} else {
None
}
&PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
}
}
}
pub enum Declaration {
Op(usize, Specifier, TabledRc<Atom>)
Op(usize, Specifier, ClauseName)
}
pub enum TopLevel {
@@ -88,7 +79,7 @@ pub enum TopLevel {
}
impl TopLevel {
pub fn name(&self) -> Option<TabledRc<Atom>> {
pub fn name(&self) -> Option<ClauseName> {
match self {
&TopLevel::Declaration(_) => None,
&TopLevel::Fact(ref term) => term.name(),
@@ -99,15 +90,8 @@ impl TopLevel {
None
},
&TopLevel::Query(_) => None,
&TopLevel::Rule(Rule { head: (QueryTerm::Term(ref term), _), .. }) =>
match term {
&Term::Clause(_, ref name, ..)
| &Term::Constant(_, Constant::Atom(ref name)) =>
Some(name.clone()),
_ =>
None
},
_ => None
&TopLevel::Rule(Rule { ref head, .. }) =>
Some(head.0.clone())
}
}
@@ -118,14 +102,23 @@ impl TopLevel {
&TopLevel::Predicate(ref clauses) =>
clauses.first().map(|t| t.arity()).unwrap_or(0),
&TopLevel::Query(_) => 0,
&TopLevel::Rule(Rule { head: (ref qt, _), ..}) => qt.arity(),
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
}
}
}
#[derive(Clone, Copy)]
pub enum Level {
Deep, Shallow
Deep, Root, Shallow
}
impl Level {
pub fn child_level(self) -> Level {
match self {
Level::Root => Level::Shallow,
_ => Level::Deep
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -305,7 +298,7 @@ pub enum Fixity {
#[derive(Clone, Eq, Hash, PartialEq)]
pub enum Constant {
Atom(TabledRc<Atom>),
Atom(ClauseName),
Number(Number),
String(Rc<String>),
Usize(usize),
@@ -332,36 +325,57 @@ impl fmt::Display for Constant {
#[derive(PartialEq, Eq, Clone)]
pub enum Term {
AnonVar,
Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
Clause(Cell<RegType>, ClauseName, Vec<Box<Term>>, Option<Fixity>),
Cons(Cell<RegType>, Box<Term>, Box<Term>),
Constant(Cell<RegType>, Constant),
Var(Cell<VarReg>, Rc<Var>)
}
pub enum InlinedQueryTerm {
CompareNumber(CompareNumberQT, Vec<Box<Term>>),
IsAtomic(Vec<Box<Term>>),
IsCompound(Vec<Box<Term>>),
IsInteger(Vec<Box<Term>>),
IsRational(Vec<Box<Term>>),
IsString(Vec<Box<Term>>),
IsFloat(Vec<Box<Term>>),
IsNonVar(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>),
#[derive(Clone, Copy)]
pub enum InlinedClauseType {
CompareNumber(CompareNumberQT),
IsAtomic,
IsCompound,
IsInteger,
IsRational,
IsString,
IsFloat,
IsNonVar,
IsVar,
}
impl InlinedQueryTerm {
pub fn arity(&self) -> usize {
impl InlinedClauseType {
pub fn name(&self) -> &'static str {
match self {
&InlinedQueryTerm::CompareNumber(_, _) => 2,
&InlinedQueryTerm::IsAtomic(_) => 1,
&InlinedQueryTerm::IsCompound(_) => 1,
&InlinedQueryTerm::IsFloat(_) => 1,
&InlinedQueryTerm::IsRational(_) => 1,
&InlinedQueryTerm::IsString(_) => 1,
&InlinedQueryTerm::IsNonVar(_) => 1,
&InlinedQueryTerm::IsInteger(_) => 1,
&InlinedQueryTerm::IsVar(_) => 1,
&InlinedClauseType::CompareNumber(qt) => qt.name(),
&InlinedClauseType::IsAtomic => "atomic",
&InlinedClauseType::IsCompound => "compound",
&InlinedClauseType::IsInteger => "integer",
&InlinedClauseType::IsRational => "rational",
&InlinedClauseType::IsString => "string",
&InlinedClauseType::IsFloat => "float",
&InlinedClauseType::IsNonVar => "nonvar",
&InlinedClauseType::IsVar => "var"
}
}
pub fn from(name: &str, arity: usize) -> Option<Self> {
match (name, arity) {
(">", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan)),
("<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan)),
(">=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual)),
("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
("atomic", 1) => Some(InlinedClauseType::IsAtomic),
("compound", 1) => Some(InlinedClauseType::IsCompound),
("integer", 1) => Some(InlinedClauseType::IsInteger),
("rational", 1) => Some(InlinedClauseType::IsRational),
("string", 1) => Some(InlinedClauseType::IsString),
("float", 1) => Some(InlinedClauseType::IsFloat),
("nonvar", 1) => Some(InlinedClauseType::IsNonVar),
("var", 1) => Some(InlinedClauseType::IsVar),
_ => None
}
}
}
@@ -377,7 +391,7 @@ pub enum CompareNumberQT {
}
impl CompareNumberQT {
fn name<'a>(self) -> &'a str {
fn name(self) -> &'static str {
match self {
CompareNumberQT::GreaterThan => ">",
CompareNumberQT::LessThan => "<",
@@ -390,13 +404,13 @@ impl CompareNumberQT {
}
#[derive(Clone, Copy)]
pub enum CompareTermQT {
pub enum CompareTermQT {
LessThan,
LessThanOrEqual,
Equal,
GreaterThanOrEqual,
GreaterThan,
NotEqual,
GreaterThan,
NotEqual,
}
impl CompareTermQT {
@@ -417,118 +431,174 @@ impl CompareTermQT {
pub type JumpStub = Vec<Term>;
pub enum QueryTerm {
Arg(Vec<Box<Term>>),
CallN(Vec<Box<Term>>),
CallWithInferenceLimit(Vec<Box<Term>>),
Catch(Vec<Box<Term>>),
Compare(Vec<Box<Term>>),
CompareTerm(CompareTermQT, Vec<Box<Term>>),
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
Cut,
Display(Vec<Box<Term>>),
DuplicateTerm(Vec<Box<Term>>),
Eq(Vec<Box<Term>>),
Functor(Vec<Box<Term>>),
Ground(Vec<Box<Term>>),
Inlined(InlinedQueryTerm),
Is(Vec<Box<Term>>),
Jump(JumpStub),
NotEq(Vec<Box<Term>>),
SetupCallCleanup(Vec<Box<Term>>),
Term(Term),
Throw(Vec<Box<Term>>)
Jump(JumpStub)
}
impl QueryTerm {
pub fn arity(&self) -> usize {
match self {
&QueryTerm::Arg(_) => 3,
&QueryTerm::Catch(_) => 3,
&QueryTerm::Compare(_) => 3,
&QueryTerm::CompareTerm(..) => 2,
&QueryTerm::Display(_) => 1,
&QueryTerm::Throw(_) => 1,
&QueryTerm::DuplicateTerm(_) => 2,
&QueryTerm::Eq(_) => 2,
&QueryTerm::Functor(_) => 3,
&QueryTerm::Ground(_) => 1,
&QueryTerm::Inlined(ref term) => term.arity(),
&QueryTerm::Is(_) => 2,
&QueryTerm::Jump(ref vars) => vars.len(),
&QueryTerm::NotEq(_) => 2,
&QueryTerm::CallN(ref terms) => terms.len(),
&QueryTerm::CallWithInferenceLimit(_) => 3,
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
&QueryTerm::Cut => 0,
&QueryTerm::SetupCallCleanup(_) => 3,
&QueryTerm::Term(ref term) => term.arity(),
&QueryTerm::Jump(ref vars) => vars.len()
}
}
}
pub struct Rule {
pub head: (QueryTerm, QueryTerm),
pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
pub clauses: Vec<QueryTerm>
}
#[derive(Clone, Copy)]
pub enum ClauseType<'a> {
#[derive(Clone)]
pub enum ClauseType {
Arg,
CallN,
CallWithInferenceLimit,
Catch,
Compare,
CompareNumber(CompareNumberQT),
CompareTerm(CompareTermQT),
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
Display,
DuplicateTerm,
Eq,
Functor,
Ground,
Inlined(InlinedClauseType),
Is,
NotEq,
Root(&'a TabledRc<Atom>),
Op(ClauseName, Fixity),
Named(ClauseName),
SetupCallCleanup,
Throw,
}
impl<'a> ClauseType<'a> {
pub fn name(&self) -> &'a str {
impl ClauseType {
pub fn fixity(&self) -> Option<Fixity> {
match self {
&ClauseType::Arg => "arg",
&ClauseType::CallN => "call",
&ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
&ClauseType::Catch => "catch",
&ClauseType::Compare => "compare",
&ClauseType::CompareNumber(qt) => qt.name(),
&ClauseType::CompareTerm(qt) => qt.name(),
&ClauseType::Display => "display",
&ClauseType::Deep(_, _, name, _) => name.as_str(),
&ClauseType::DuplicateTerm => "duplicate_term",
&ClauseType::Eq => "==",
&ClauseType::Functor => "functor",
&ClauseType::Ground => "ground",
&ClauseType::Is => "is",
&ClauseType::NotEq => "\\==",
&ClauseType::Root(name) => name.as_str(),
&ClauseType::SetupCallCleanup => "setup_call_cleanup",
&ClauseType::Throw => "throw"
}
}
pub fn level_of_subterms(self) -> Level {
match self {
ClauseType::Deep(..) => Level::Deep,
_ => Level::Shallow
&ClauseType::Compare | &ClauseType::CompareTerm(_)
| &ClauseType::Inlined(InlinedClauseType::CompareNumber(_))
| &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In),
&ClauseType::Op(_, fixity) => Some(fixity),
_ => None
}
}
}
#[derive(Clone, Copy)]
#[derive(Clone)]
pub enum ClauseName {
BuiltIn(&'static str),
User(TabledRc<Atom>)
}
impl Hash for ClauseName {
fn hash<H: Hasher>(&self, state: &mut H) {
(*self.as_str()).hash(state)
}
}
impl PartialEq for ClauseName {
fn eq(&self, other: &ClauseName) -> bool {
*self.as_str() == *other.as_str()
}
}
impl Eq for ClauseName {}
impl Ord for ClauseName {
fn cmp(&self, other: &ClauseName) -> Ordering {
(*self.as_str()).cmp(other.as_str())
}
}
impl PartialOrd for ClauseName {
fn partial_cmp(&self, other: &ClauseName) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'a> From<&'a TabledRc<Atom>> for ClauseName {
fn from(name: &'a TabledRc<Atom>) -> ClauseName {
ClauseName::User(name.clone())
}
}
impl ClauseName {
pub fn as_str(&self) -> &str {
match self {
&ClauseName::BuiltIn(s) => s,
&ClauseName::User(ref name) => name.as_ref()
}
}
}
impl ClauseType {
pub fn name(&self) -> ClauseName {
match self {
&ClauseType::Arg => ClauseName::BuiltIn("arg"),
&ClauseType::CallN => ClauseName::BuiltIn("call"),
&ClauseType::CallWithInferenceLimit => ClauseName::BuiltIn("call_with_inference_limit"),
&ClauseType::Catch => ClauseName::BuiltIn("catch"),
&ClauseType::Compare => ClauseName::BuiltIn("compare"),
&ClauseType::CompareTerm(qt) => ClauseName::BuiltIn(qt.name()),
&ClauseType::Display => ClauseName::BuiltIn("display"),
&ClauseType::DuplicateTerm => ClauseName::BuiltIn("duplicate_term"),
&ClauseType::Eq => ClauseName::BuiltIn("=="),
&ClauseType::Functor => ClauseName::BuiltIn("functor"),
&ClauseType::Ground => ClauseName::BuiltIn("ground"),
&ClauseType::Inlined(inlined) => ClauseName::BuiltIn(inlined.name()),
&ClauseType::Is => ClauseName::BuiltIn("is"),
&ClauseType::NotEq => ClauseName::BuiltIn("\\=="),
&ClauseType::Op(ref name, _) => name.clone(),
&ClauseType::Named(ref name) => name.clone(),
&ClauseType::SetupCallCleanup => ClauseName::BuiltIn("setup_call_cleanup"),
&ClauseType::Throw => ClauseName::BuiltIn("throw")
}
}
pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
match (name.as_str(), arity) {
("arg", 3) => ClauseType::Arg,
("call", _) => ClauseType::CallN,
("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
("catch", 3) => ClauseType::Catch,
("compare", 3) => ClauseType::Compare,
("@>", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThan),
("@<", 2) => ClauseType::CompareTerm(CompareTermQT::LessThan),
("@>=", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual),
("@<=", 2) => ClauseType::CompareTerm(CompareTermQT::LessThanOrEqual),
("\\=@=", 2) => ClauseType::CompareTerm(CompareTermQT::NotEqual),
("=@=", 2) => ClauseType::CompareTerm(CompareTermQT::Equal),
("display", 1) => ClauseType::Display,
("duplicate_term", 2) => ClauseType::DuplicateTerm,
("==", 2) => ClauseType::Eq,
("functor", 3) => ClauseType::Functor,
("ground", 1) => ClauseType::Ground,
("is", 2) => ClauseType::Is,
("\\==", 2) => ClauseType::NotEq,
("setup_call_cleanup", 3) => ClauseType::SetupCallCleanup,
("throw", 1) => ClauseType::Throw,
_ => if let Some(fixity) = fixity {
ClauseType::Op(name, fixity)
} else {
ClauseType::Named(name)
}
}
}
}
impl From<InlinedClauseType> for ClauseType {
fn from(inlined_ct: InlinedClauseType) -> Self {
ClauseType::Inlined(inlined_ct)
}
}
#[derive(Clone)]
pub enum TermRef<'a> {
AnonVar(Level),
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(ClauseType<'a>, &'a Vec<Box<Term>>),
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
@@ -538,9 +608,8 @@ impl<'a> TermRef<'a> {
TermRef::AnonVar(lvl)
| TermRef::Cons(lvl, ..)
| TermRef::Constant(lvl, ..)
| TermRef::Var(lvl, ..) => lvl,
TermRef::Clause(ClauseType::Deep(lvl, ..), ..) => lvl,
_ => Level::Shallow
| TermRef::Var(lvl, ..)
| TermRef::Clause(lvl, ..) => lvl
}
}
}
@@ -921,7 +990,7 @@ pub enum ControlInstruction {
Allocate(usize), // num_frames.
ArgCall,
ArgExecute,
Call(TabledRc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
Call(ClauseName, usize, usize), // name, arity, perm_vars after threshold.
CallN(usize), // arity.
CatchCall,
CatchExecute,
@@ -934,11 +1003,11 @@ pub enum ControlInstruction {
DisplayExecute,
Deallocate,
DuplicateTermCall,
DuplicateTermExecute,
DuplicateTermExecute,
DynamicIs,
EqCall,
EqExecute,
Execute(TabledRc<Atom>, usize),
Execute(ClauseName, usize),
ExecuteN(usize),
FunctorCall,
FunctorExecute,
@@ -949,11 +1018,11 @@ pub enum ControlInstruction {
GroundExecute,
JmpByCall(usize, usize), // arity, global_offset.
JmpByExecute(usize, usize),
IsCall(RegType, ArithmeticTerm),
IsCall(RegType, ArithmeticTerm),
IsExecute(RegType, ArithmeticTerm),
NotEqCall,
NotEqExecute,
Proceed,
Proceed,
ThrowCall,
ThrowExecute,
}
@@ -965,7 +1034,7 @@ impl ControlInstruction {
&ControlInstruction::ArgExecute => true,
&ControlInstruction::Call(_, _, _) => true,
&ControlInstruction::CatchCall => true,
&ControlInstruction::CatchExecute => true,
&ControlInstruction::CatchExecute => true,
&ControlInstruction::CompareTermCall(..) => true,
&ControlInstruction::CompareTermExecute(..) => true,
&ControlInstruction::DisplayCall => true,
@@ -1003,7 +1072,7 @@ impl ControlInstruction {
pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, HashMap<Constant, usize>),
SwitchOnStructure(usize, HashMap<(TabledRc<Atom>, usize), usize>)
SwitchOnStructure(usize, HashMap<(ClauseName, usize), usize>)
}
impl From<IndexingInstruction> for Line {
@@ -1015,7 +1084,7 @@ impl From<IndexingInstruction> for Line {
pub enum FactInstruction {
GetConstant(Level, Constant, RegType),
GetList(Level, RegType),
GetStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
GetStructure(ClauseType, usize, RegType),
GetValue(RegType, usize),
GetVariable(RegType, usize),
UnifyConstant(Constant),
@@ -1029,7 +1098,7 @@ pub enum QueryInstruction {
GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType),
PutList(Level, RegType),
PutStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
PutStructure(ClauseType, usize, RegType),
PutUnsafeValue(usize, usize),
PutValue(RegType, usize),
PutVariable(RegType, usize),
@@ -1113,7 +1182,7 @@ pub enum Ref {
#[derive(Clone, PartialEq)]
pub enum HeapCellValue {
Addr(Addr),
NamedStr(usize, TabledRc<Atom>, Option<Fixity>), // arity, name, fixity if it has one.
NamedStr(usize, ClauseName, Option<Fixity>), // arity, name, fixity if it has one.
}
impl HeapCellValue {
@@ -1233,15 +1302,7 @@ impl Term {
}
}
pub fn is_callable(&self) -> bool {
match self {
&Term::Clause(..) | &Term::Constant(_, Constant::Atom(_)) =>
true,
_ => false
}
}
pub fn name(&self) -> Option<TabledRc<Atom>> {
pub fn name(&self) -> Option<ClauseName> {
match self {
&Term::Constant(_, Constant::Atom(ref atom))
| &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
@@ -1259,20 +1320,27 @@ impl Term {
pub enum TermIterState<'a> {
AnonVar(Level),
Clause(usize, ClauseType<'a>, &'a Vec<Box<Term>>),
Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Var(Level, &'a Cell<VarReg>, &'a Var)
}
impl<'a> TermIterState<'a> {
pub fn to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
match term {
&Term::AnonVar =>
TermIterState::AnonVar(lvl),
&Term::Clause(ref cell, ref atom, ref child_terms, fixity) =>
TermIterState::Clause(0, ClauseType::Deep(lvl, cell, atom, fixity), child_terms),
&Term::Clause(ref cell, ref name, ref subterms, fixity) => {
let ct = if let Some(fixity) = fixity {
ClauseType::Op(name.clone(), fixity)
} else {
ClauseType::Named(name.clone())
};
TermIterState::Clause(lvl, 0, cell, ct, subterms)
},
&Term::Cons(ref cell, ref head, ref tail) =>
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()),
&Term::Constant(ref cell, ref constant) =>

View File

@@ -1,11 +1,10 @@
use prolog::ast::*;
use prolog::num::bigint::{BigInt};
use prolog::tabled_rc::*;
use std::collections::HashMap;
use std::rc::Rc;
pub type PredicateKey = (TabledRc<Atom>, usize); // name, arity, type.
pub type PredicateKey = (ClauseName, usize); // name, arity, type.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum PredicateKeyType {
@@ -13,13 +12,13 @@ pub enum PredicateKeyType {
User
}
pub type OpDirKey = (TabledRc<Atom>, Fixity);
pub type OpDirKey = (ClauseName, Fixity);
// name and fixity -> operator type and precedence.
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
fn get_builtins() -> Code {
vec![internal_call_n!(), // callN/N, 0.
is_atomic!(temp_v!(1)), // atomic/1, 1.
proceed!(),
@@ -115,25 +114,25 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
retry!(7),
trust!(10),
try_me_else!(4),
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
fact![get_constant!(atom!("!"), temp_v!(1)),
get_structure!(",", 2, temp_v!(2), Some(infix!())),
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
set_cp!(temp_v!(3)),
goto_execute!(83, 3),
retry_me_else!(4),
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
get_constant!(atom!("!", atom_tbl), temp_v!(2))],
fact![get_constant!(atom!("!"), temp_v!(1)),
get_constant!(atom!("!"), temp_v!(2))],
set_cp!(temp_v!(3)),
proceed!(),
trust_me!(),
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1))],
fact![get_constant!(atom!("!"), temp_v!(1))],
set_cp!(temp_v!(3)),
query![put_value!(temp_v!(2), 1)],
execute_n!(1),
retry_me_else!(8),
allocate!(3),
fact![get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
fact![get_structure!(",", 2, temp_v!(2), Some(infix!())),
unify_variable!(perm_v!(2)),
unify_variable!(perm_v!(1)),
get_var_in_fact!(perm_v!(3), 3)],
@@ -147,7 +146,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
retry_me_else!(10),
allocate!(2),
get_level!(perm_v!(2)),
fact![get_constant!(atom!("!", atom_tbl), temp_v!(2)),
fact![get_constant!(atom!("!"), temp_v!(2)),
get_var_in_fact!(perm_v!(1), 3)],
neck_cut!(),
call_n!(1),
@@ -168,12 +167,12 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
indexed_try!(3),
trust!(5),
try_me_else!(3),
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
unify_variable!(temp_v!(1)),
unify_variable!(temp_v!(2))],
goto_execute!(139, 3),
trust_me!(),
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
unify_void!(2)],
query![put_value!(temp_v!(2), 1)],
neck_cut!(),
@@ -232,13 +231,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
goto_execute!(149, 3), // goto get_arg/3.
trust_me!(),
query![get_var_in_query!(temp_v!(4), 1),
put_structure!(atom_tbl,
Level::Shallow,
String::from("type_error"),
1,
temp_v!(1),
None),
set_constant!(atom!("integer_expected", atom_tbl))],
put_structure!("type_error", 1, temp_v!(1), None),
set_constant!(atom!("integer_expected"))],
goto_execute!(59, 1), // goto throw/1.
try_me_else!(5), // arg_/5, 173.
fact![get_value!(temp_v!(1), 2),
@@ -405,13 +399,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
trust_me!(),
fact![get_var_in_fact!(temp_v!(3), 1),
get_var_in_fact!(temp_v!(4), 2)],
query![put_structure!(atom_tbl,
Level::Shallow,
String::from("type_error"),
2,
temp_v!(1),
None),
set_constant!(atom!("integer_expected", atom_tbl)),
query![put_structure!("type_error", 2, temp_v!(1), None),
set_constant!(atom!("integer_expected")),
set_value!(temp_v!(4))],
goto_execute!(59, 1), // goto throw/1, 59.
switch_on_term!(1,2,5,0), // length/3, 281.
@@ -453,7 +442,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
try_me_else!(5), // 304.
is_var!(temp_v!(1)),
neck_cut!(),
query![put_constant!(Level::Shallow, atom!("instantiation_error", atom_tbl),
query![put_constant!(Level::Shallow,
atom!("instantiation_error"),
temp_v!(1))],
goto_execute!(59, 1),
trust_me!(),
@@ -502,7 +492,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
get_cleaner_call!(),
query![put_value!(perm_v!(2), 1),
put_var!(temp_v!(4), 2),
put_constant!(Level::Shallow, atom!("true", atom_tbl), temp_v!(3))],
put_constant!(Level::Shallow, atom!("true"), temp_v!(3))],
goto_call!(5, 3), // goto catch/3, 5.
set_cp!(perm_v!(1)),
deallocate!(),
@@ -621,9 +611,9 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
remove_call_policy_check!(),
fail!(),
try_me_else!(4), // handle_ile/3, 444.
fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
fact![get_structure!("inference_limit_exceeded", 1, temp_v!(2), None),
unify_value!(temp_v!(1)),
get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
get_constant!(atom!("inference_limit_exceeded"), temp_v!(3))],
neck_cut!(),
proceed!(),
default_trust_me!(),
@@ -648,119 +638,119 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
]
}
pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
pub fn build_code_dir() -> (Code, CodeDir, OpDir)
{
let mut code_dir = HashMap::new();
let mut op_dir = HashMap::new();
let builtin_code = get_builtins(atom_tbl.clone());
let builtin_code = get_builtins();
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::In), (XFX, 1200));
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::Pre), (FX, 1200));
op_dir.insert((tabled_rc!("?-", atom_tbl), Fixity::Pre), (FX, 1200));
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200));
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200));
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200));
// control operators.
op_dir.insert((tabled_rc!("\\+", atom_tbl), Fixity::Pre), (FY, 900));
op_dir.insert((tabled_rc!("=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
// arithmetic operators.
op_dir.insert((tabled_rc!("is", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("+", atom_tbl), Fixity::In), (YFX, 500));
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::In), (YFX, 500));
op_dir.insert((tabled_rc!("/\\", atom_tbl), Fixity::In), (YFX, 500));
op_dir.insert((tabled_rc!("\\/", atom_tbl), Fixity::In), (YFX, 500));
op_dir.insert((tabled_rc!("xor", atom_tbl), Fixity::In), (YFX, 500));
op_dir.insert((tabled_rc!("//", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("/", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("div", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("*", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::Pre), (FY, 200));
op_dir.insert((tabled_rc!("rdiv", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("<<", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!(">>", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("mod", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((tabled_rc!("rem", atom_tbl), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
// arithmetic comparison operators.
op_dir.insert((tabled_rc!(">", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("<", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("=\\=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("=:=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!(">=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("=<", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
// control operators.
op_dir.insert((tabled_rc!(";", atom_tbl), Fixity::In), (XFY, 1100));
op_dir.insert((tabled_rc!("->", atom_tbl), Fixity::In), (XFY, 1050));
op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
op_dir.insert((tabled_rc!("=..", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("==", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("\\==", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("@=<", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("@>=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("@<", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("@>", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("=@=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((tabled_rc!("\\=@=", atom_tbl), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
// (an extra register is needed for the predicate name)
for arity in 0 .. 63 {
code_dir.insert((tabled_rc!("call", atom_tbl), arity), (PredicateKeyType::BuiltIn, 0));
code_dir.insert((clause_name!("call"), arity), (PredicateKeyType::BuiltIn, 0));
}
code_dir.insert((tabled_rc!("atomic", atom_tbl), 1), (PredicateKeyType::BuiltIn, 1));
code_dir.insert((tabled_rc!("var", atom_tbl), 1), (PredicateKeyType::BuiltIn, 3));
code_dir.insert((tabled_rc!("false", atom_tbl), 0), (PredicateKeyType::BuiltIn, 61));
code_dir.insert((tabled_rc!("\\+", atom_tbl), 1), (PredicateKeyType::BuiltIn, 62));
code_dir.insert((tabled_rc!("duplicate_term", atom_tbl), 2), (PredicateKeyType::BuiltIn, 71));
code_dir.insert((tabled_rc!("catch", atom_tbl), 3), (PredicateKeyType::BuiltIn, 5));
code_dir.insert((tabled_rc!("throw", atom_tbl), 1), (PredicateKeyType::BuiltIn, 59));
code_dir.insert((tabled_rc!("=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 73));
code_dir.insert((tabled_rc!("true", atom_tbl), 0), (PredicateKeyType::BuiltIn, 75));
code_dir.insert((clause_name!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
code_dir.insert((clause_name!("var"), 1), (PredicateKeyType::BuiltIn, 3));
code_dir.insert((clause_name!("false"), 0), (PredicateKeyType::BuiltIn, 61));
code_dir.insert((clause_name!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
code_dir.insert((clause_name!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
code_dir.insert((clause_name!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
code_dir.insert((clause_name!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
code_dir.insert((clause_name!("="), 2), (PredicateKeyType::BuiltIn, 73));
code_dir.insert((clause_name!("true"), 0), (PredicateKeyType::BuiltIn, 75));
code_dir.insert((tabled_rc!(",", atom_tbl), 2), (PredicateKeyType::BuiltIn, 76));
code_dir.insert((tabled_rc!(";", atom_tbl), 2), (PredicateKeyType::BuiltIn, 120));
code_dir.insert((tabled_rc!("->", atom_tbl), 2), (PredicateKeyType::BuiltIn, 138));
code_dir.insert((clause_name!(","), 2), (PredicateKeyType::BuiltIn, 76));
code_dir.insert((clause_name!(";"), 2), (PredicateKeyType::BuiltIn, 120));
code_dir.insert((clause_name!("->"), 2), (PredicateKeyType::BuiltIn, 138));
code_dir.insert((tabled_rc!("functor", atom_tbl), 3), (PredicateKeyType::BuiltIn, 146));
code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
code_dir.insert((clause_name!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
code_dir.insert((clause_name!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
code_dir.insert((clause_name!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
code_dir.insert((clause_name!("display"), 1), (PredicateKeyType::BuiltIn, 192));
code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
code_dir.insert((tabled_rc!(">", atom_tbl), 2), (PredicateKeyType::BuiltIn, 196));
code_dir.insert((tabled_rc!("<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 198));
code_dir.insert((tabled_rc!(">=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 200));
code_dir.insert((tabled_rc!("<=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 202));
code_dir.insert((tabled_rc!("=\\=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 204));
code_dir.insert((tabled_rc!("=:=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 206));
code_dir.insert((tabled_rc!("=..", atom_tbl), 2), (PredicateKeyType::BuiltIn, 208));
code_dir.insert((clause_name!("is"), 2), (PredicateKeyType::BuiltIn, 194));
code_dir.insert((clause_name!(">"), 2), (PredicateKeyType::BuiltIn, 196));
code_dir.insert((clause_name!("<"), 2), (PredicateKeyType::BuiltIn, 198));
code_dir.insert((clause_name!(">="), 2), (PredicateKeyType::BuiltIn, 200));
code_dir.insert((clause_name!("<="), 2), (PredicateKeyType::BuiltIn, 202));
code_dir.insert((clause_name!("=\\="), 2), (PredicateKeyType::BuiltIn, 204));
code_dir.insert((clause_name!("=:="), 2), (PredicateKeyType::BuiltIn, 206));
code_dir.insert((clause_name!("=.."), 2), (PredicateKeyType::BuiltIn, 208));
code_dir.insert((tabled_rc!("length", atom_tbl), 2), (PredicateKeyType::BuiltIn, 261));
code_dir.insert((tabled_rc!("setup_call_cleanup", atom_tbl), 3),
code_dir.insert((clause_name!("length"), 2), (PredicateKeyType::BuiltIn, 261));
code_dir.insert((clause_name!("setup_call_cleanup"), 3),
(PredicateKeyType::BuiltIn, 294));
code_dir.insert((tabled_rc!("call_with_inference_limit", atom_tbl), 3),
code_dir.insert((clause_name!("call_with_inference_limit"), 3),
(PredicateKeyType::BuiltIn, 393));
code_dir.insert((tabled_rc!("_handle_inference_limit_exceeded", atom_tbl), 2),
code_dir.insert((clause_name!("_handle_inference_limit_exceeded"), 2),
(PredicateKeyType::BuiltIn, 421));
code_dir.insert((tabled_rc!("compound", atom_tbl), 1), (PredicateKeyType::BuiltIn, 372));
code_dir.insert((tabled_rc!("rational", atom_tbl), 1), (PredicateKeyType::BuiltIn, 374));
code_dir.insert((tabled_rc!("string", atom_tbl), 1), (PredicateKeyType::BuiltIn, 376));
code_dir.insert((tabled_rc!("float", atom_tbl), 1), (PredicateKeyType::BuiltIn, 378));
code_dir.insert((tabled_rc!("nonvar", atom_tbl), 1), (PredicateKeyType::BuiltIn, 380));
code_dir.insert((clause_name!("compound"), 1), (PredicateKeyType::BuiltIn, 372));
code_dir.insert((clause_name!("rational"), 1), (PredicateKeyType::BuiltIn, 374));
code_dir.insert((clause_name!("string"), 1), (PredicateKeyType::BuiltIn, 376));
code_dir.insert((clause_name!("float"), 1), (PredicateKeyType::BuiltIn, 378));
code_dir.insert((clause_name!("nonvar"), 1), (PredicateKeyType::BuiltIn, 380));
code_dir.insert((tabled_rc!("ground", atom_tbl), 1), (PredicateKeyType::BuiltIn, 384));
code_dir.insert((tabled_rc!("==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 385));
code_dir.insert((tabled_rc!("\\==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 386));
code_dir.insert((tabled_rc!("@>=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 387));
code_dir.insert((tabled_rc!("@=<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 388));
code_dir.insert((tabled_rc!("@>", atom_tbl), 2), (PredicateKeyType::BuiltIn, 389));
code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
code_dir.insert((clause_name!("ground"), 1), (PredicateKeyType::BuiltIn, 384));
code_dir.insert((clause_name!("=="), 2), (PredicateKeyType::BuiltIn, 385));
code_dir.insert((clause_name!("\\=="), 2), (PredicateKeyType::BuiltIn, 386));
code_dir.insert((clause_name!("@>="), 2), (PredicateKeyType::BuiltIn, 387));
code_dir.insert((clause_name!("@=<"), 2), (PredicateKeyType::BuiltIn, 388));
code_dir.insert((clause_name!("@>"), 2), (PredicateKeyType::BuiltIn, 389));
code_dir.insert((clause_name!("@<"), 2), (PredicateKeyType::BuiltIn, 390));
code_dir.insert((clause_name!("=@="), 2), (PredicateKeyType::BuiltIn, 391));
code_dir.insert((clause_name!("\\=@="), 2), (PredicateKeyType::BuiltIn, 392));
code_dir.insert((clause_name!("compare"), 3), (PredicateKeyType::BuiltIn, 464));
(builtin_code, code_dir, op_dir)
}

View File

@@ -156,25 +156,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
};
}
fn compile_clause<Target>(&mut self, ct: ClauseType<'a>, term_loc: GenContext,
is_exposed: bool, terms: &'a Vec<Box<Term>>,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
match ct {
ClauseType::Deep(lvl, cell, atom, fixity) => {
self.marker.mark_non_var(lvl, term_loc, cell, target);
target.push(Target::to_structure(lvl, atom.clone(), terms.len(),
cell.get(), fixity));
for subterm in terms {
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, target);
}
},
_ => {}
}
}
fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
-> Vec<Target>
where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
@@ -183,8 +164,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
for term in iter {
match term {
TermRef::Clause(ct, terms) =>
self.compile_clause(ct, term_loc, is_exposed, terms, &mut target),
TermRef::Clause(lvl, cell, ct, terms) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(ct, terms.len(), cell.get()));
for subterm in terms {
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
}
},
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));
@@ -214,24 +201,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a>
{
let mut vs = VariableFixtures::new();
let at_rule_head = iter.at_rule_head();
while let Some((chunk_num, lt_arity, terms)) = iter.next() {
for (i, query_term) in terms.iter().enumerate() {
let term_loc = if chunk_num == 0 && i == 0 && at_rule_head {
GenContext::Head
} else if i < terms.len() - 1 {
GenContext::Mid(chunk_num)
} else {
GenContext::Last(chunk_num)
};
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
for (i, chunked_term) in chunked_terms.iter().enumerate() {
let term_loc = match chunked_term {
&ChunkedTerm::HeadClause(..) => GenContext::Head,
&ChunkedTerm::BodyTerm(_) => if i < chunked_terms.len() - 1 {
GenContext::Mid(chunk_num)
} else {
GenContext::Last(chunk_num)
}
};
self.update_var_count(query_term.post_order_iter());
vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
self.update_var_count(chunked_term.post_order_iter());
vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
}
}
let num_of_chunks = iter.chunk_num();
let num_of_chunks = iter.chunk_num;
let has_deep_cut = iter.encountered_deep_cut();
vs.populate_restricting_sets();
@@ -245,51 +232,51 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
{
match qt {
&QueryTerm::CallWithInferenceLimit(_) =>
code.push(goto_call!(393, 3)),
&QueryTerm::SetupCallCleanup(_) =>
code.push(goto_call!(294, 3)),
&QueryTerm::Arg(_) => {
let call = ControlInstruction::ArgCall;
code.push(Line::Control(call));
},
&QueryTerm::CallN(ref terms) => {
let call = ControlInstruction::CallN(terms.len());
code.push(Line::Control(call));
},
&QueryTerm::Catch(_) =>
code.push(Line::Control(ControlInstruction::CatchCall)),
&QueryTerm::Compare(_) =>
code.push(Line::Control(ControlInstruction::CompareCall)),
&QueryTerm::CompareTerm(qt, _) =>
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
&QueryTerm::Display(_) =>
code.push(Line::Control(ControlInstruction::DisplayCall)),
&QueryTerm::DuplicateTerm(_) =>
code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
&QueryTerm::Eq(_) =>
code.push(Line::Control(ControlInstruction::EqCall)),
&QueryTerm::Ground(_) =>
code.push(Line::Control(ControlInstruction::GroundCall)),
&QueryTerm::Functor(_) =>
code.push(Line::Control(ControlInstruction::FunctorCall)),
&QueryTerm::Inlined(_) =>
code.push(proceed!()),
&QueryTerm::Jump(ref vars) => {
code.push(jmp_call!(vars.len(), 0));
},
&QueryTerm::NotEq(_) =>
code.push(Line::Control(ControlInstruction::NotEqCall)),
&QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
code.push(Line::Control(call));
},
&QueryTerm::Term(Term::Clause(_, ref atom, ref terms, _)) => {
let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
code.push(Line::Control(call));
},
&QueryTerm::Throw(_) =>
code.push(Line::Control(ControlInstruction::ThrowCall)),
&QueryTerm::Clause(_, ref ct, ref terms) =>
match ct {
&ClauseType::CallWithInferenceLimit =>
code.push(goto_call!(393, 3)),
&ClauseType::SetupCallCleanup =>
code.push(goto_call!(294, 3)),
&ClauseType::Arg => {
let call = ControlInstruction::ArgCall;
code.push(Line::Control(call));
},
&ClauseType::CallN => {
let call = ControlInstruction::CallN(terms.len());
code.push(Line::Control(call));
},
&ClauseType::Catch =>
code.push(Line::Control(ControlInstruction::CatchCall)),
&ClauseType::Compare =>
code.push(Line::Control(ControlInstruction::CompareCall)),
&ClauseType::CompareTerm(qt) =>
code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
&ClauseType::Display =>
code.push(Line::Control(ControlInstruction::DisplayCall)),
&ClauseType::DuplicateTerm =>
code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
&ClauseType::Eq =>
code.push(Line::Control(ControlInstruction::EqCall)),
&ClauseType::Ground =>
code.push(Line::Control(ControlInstruction::GroundCall)),
&ClauseType::Functor =>
code.push(Line::Control(ControlInstruction::FunctorCall)),
&ClauseType::Inlined(_) =>
code.push(proceed!()),
&ClauseType::NotEq =>
code.push(Line::Control(ControlInstruction::NotEqCall)),
&ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => {
let call = ControlInstruction::Call(name.clone(), terms.len(), pvs);
code.push(Line::Control(call));
},
&ClauseType::Throw =>
code.push(Line::Control(ControlInstruction::ThrowCall)),
_ => {}
},
_ => {}
}
}
@@ -344,11 +331,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
dealloc_index
}
fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec<Box<Term>>,
term_loc: GenContext, code: &mut Code)
-> Result<(), ParserError>
{
match term {
&InlinedQueryTerm::CompareNumber(cmp, ref terms) => {
match ct {
InlinedClauseType::CompareNumber(cmp) => {
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
@@ -359,8 +347,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
at_1.unwrap_or(interm!(1)),
at_2.unwrap_or(interm!(2))));
},
&InlinedQueryTerm::IsAtomic(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsAtomic =>
match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
},
@@ -372,8 +360,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(is_atomic!(r));
}
},
&InlinedQueryTerm::IsCompound(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsCompound =>
match terms[0].as_ref() {
&Term::Clause(..) | &Term::Cons(..) => {
code.push(succeed!());
},
@@ -385,8 +373,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(fail!());
}
},
&InlinedQueryTerm::IsRational(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsRational =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Rational(_))) => {
code.push(succeed!());
},
@@ -398,8 +386,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(fail!());
}
},
&InlinedQueryTerm::IsFloat(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsFloat =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Float(_))) => {
code.push(succeed!());
},
@@ -411,8 +399,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(fail!());
}
},
&InlinedQueryTerm::IsString(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsString =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::String(_)) => {
code.push(succeed!());
},
@@ -424,8 +412,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(fail!());
}
},
&InlinedQueryTerm::IsNonVar(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsNonVar =>
match terms[0].as_ref() {
&Term::AnonVar => {
code.push(fail!());
},
@@ -437,8 +425,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(succeed!());
}
},
&InlinedQueryTerm::IsInteger(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsInteger =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!());
},
@@ -450,8 +438,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(fail!());
},
},
&InlinedQueryTerm::IsVar(ref inner_term) =>
match inner_term[0].as_ref() {
InlinedClauseType::IsVar =>
match terms[0].as_ref() {
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
},
@@ -488,14 +476,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
GenContext::Last(chunk_num)
};
let term = if let &ChunkedTerm::BodyTerm(ref term) = term {
Ok(term)
} else {
Err(ParserError::InadmissibleQueryTerm)
}?;
match *term {
&QueryTerm::Cut =>
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
} else {
Line::Cut(CutInstruction::Cut(perm_v!(1)))
}),
&QueryTerm::Is(ref terms) => {
}),
&QueryTerm::Clause(_, ClauseType::Is, ref terms) => {
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode);
@@ -510,7 +504,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
if !target.is_empty() {
code.push(Line::Query(target));
}
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
},
&Term::Constant(_, ref c @ Constant::Number(_)) => {
@@ -524,8 +518,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}
}
},
&QueryTerm::Inlined(ref term) =>
try!(self.compile_inlined(term, term_loc, code)),
&QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) =>
try!(self.compile_inlined(ct, terms, term_loc, code)),
_ => {
let num_perm_vars = if chunk_num == 0 {
conjunct_info.perm_vars()
@@ -535,7 +529,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
},
};
};
}
self.marker.reset_contents();
@@ -559,10 +553,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
{
// add a proceed to bookend any trailing inlines or cuts.
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::Inlined(_) | &QueryTerm::Cut =>
code.push(proceed!()),
&QueryTerm::Cut => code.push(proceed!()),
_ => {}
};
@@ -579,42 +572,37 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
let iter = ChunkedIterator::from_rule(rule);
let conjunct_info = self.collect_var_data(iter);
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let &Rule { head: (_, ref args, ref p1), ref clauses } = rule;
let mut code = Vec::new();
if let &QueryTerm::Term(ref term) = p0 {
self.marker.reset_arg(term.arity());
self.compile_seq_prelude(&conjunct_info, &mut code);
self.marker.reset_arg(args.len());
self.compile_seq_prelude(&conjunct_info, &mut code);
if let &Term::Clause(..) = term {
let iter = FactInstruction::iter(term);
let fact = self.compile_target(iter, GenContext::Head, false);
let iter = FactIterator::from_rule_head_clause(args);
let fact = self.compile_target(iter, GenContext::Head, false);
if !fact.is_empty() {
code.push(Line::Fact(fact));
}
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
if conjunct_info.allocates() {
let index = if let &Line::Control(_) = code.last().unwrap() {
code.len() - 2
} else {
code.len() - 1
};
if let &mut Line::Query(ref mut query) = &mut code[index] {
conjunct_info.perm_vs.mark_unsafe_vars_in_rule(term, query);
}
}
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
Ok(code)
} else {
Err(ParserError::InvalidRuleHead)
if !fact.is_empty() {
code.push(Line::Fact(fact));
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
if conjunct_info.allocates() {
let index = if let &Line::Control(_) = code.last().unwrap() {
code.len() - 2
} else {
code.len() - 1
};
if let &mut Line::Query(ref mut query) = &mut code[index] {
let head_iter = FactIterator::from_rule_head_clause(args);
conjunct_info.perm_vs.mark_unsafe_vars_in_rule(head_iter, query);
}
}
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
Ok(code)
}
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)

View File

@@ -210,7 +210,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
match lvl {
Level::Deep => target.push(Target::subterm_to_variable(r)),
Level::Shallow => {
Level::Root | Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
@@ -218,12 +218,9 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
}
};
}
fn mark_non_var<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>)
fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
cell: &Cell<RegType>, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = cell.get();
@@ -270,7 +267,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
};
match lvl {
Level::Shallow => {
Level::Root | Level::Shallow => {
let k = self.arg_c;
if self.is_curr_arg_distinct_from(var) {

View File

@@ -1,4 +1,5 @@
use prolog::ast::*;
use prolog::iterators::*;
use std::cell::Cell;
use std::collections::{BTreeMap, BTreeSet, HashMap};
@@ -275,9 +276,9 @@ impl<'a> VariableFixtures<'a>
}
}
fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
fn mark_head_vars_as_safe(&self, head_iter: FactIterator<'a>, unsafe_vars: &mut HashMap<RegType, bool>)
{
for term_ref in head.breadth_first_iter() {
for term_ref in head_iter {
match term_ref {
TermRef::Var(Level::Shallow, cell, _) => {
unsafe_vars.remove(&cell.get().norm());
@@ -294,12 +295,12 @@ impl<'a> VariableFixtures<'a>
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
pub fn mark_unsafe_vars_in_rule(&self, head_iter: FactIterator<'a>, query: &mut CompiledQuery)
{
let mut unsafe_vars = HashMap::new();
self.record_unsafe_vars(&mut unsafe_vars);
self.mark_head_vars_as_safe(head, &mut unsafe_vars);
self.mark_head_vars_as_safe(head_iter, &mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
}

View File

@@ -1,13 +1,12 @@
use prolog::ast::*;
use prolog::heap_iter::*;
use prolog::tabled_rc::*;
use std::cell::Cell;
use std::rc::Rc;
#[derive(Clone)]
pub enum TokenOrRedirect {
Atom(TabledRc<Atom>),
Atom(ClauseName),
Redirect,
Open,
Close,
@@ -21,7 +20,7 @@ pub enum TokenOrRedirect {
pub trait HeapCellValueFormatter {
// this function belongs to the display predicate formatter, which it uses
// to format all clauses.
fn format_struct(&self, arity: usize, name: TabledRc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
fn format_struct(&self, arity: usize, name: ClauseName, state_stack: &mut Vec<TokenOrRedirect>)
{
state_stack.push(TokenOrRedirect::Close);
@@ -38,7 +37,7 @@ pub trait HeapCellValueFormatter {
// this can be overloaded to handle special cases, falling back on the default of
// format_struct when convenient.
fn format_clause(&self, usize, TabledRc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
fn format_clause(&self, usize, ClauseType, &mut Vec<TokenOrRedirect>);
}
pub trait HeapCellValueOutputter {
@@ -95,18 +94,16 @@ impl HeapCellValueOutputter for PrinterOutputter {
pub struct DisplayFormatter {}
impl HeapCellValueFormatter for DisplayFormatter {
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
state_stack: &mut Vec<TokenOrRedirect>)
fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
{
if fixity.is_some() {
if ct.fixity().is_some() {
let mut new_name = String::from("'");
new_name += name.as_ref();
new_name += ct.name().as_str();
new_name += "'";
let name = TabledRc::new(new_name, name.table());
self.format_struct(arity, name, state_stack);
self.format_struct(arity, ct.name(), state_stack);
} else {
self.format_struct(arity, name, state_stack);
self.format_struct(arity, ct.name(), state_stack);
}
}
}
@@ -114,31 +111,30 @@ impl HeapCellValueFormatter for DisplayFormatter {
pub struct TermFormatter {}
impl HeapCellValueFormatter for TermFormatter {
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
state_stack: &mut Vec<TokenOrRedirect>)
fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
{
if let Some(fixity) = fixity {
if let Some(fixity) = ct.fixity() {
match fixity {
Fixity::Post => {
state_stack.push(TokenOrRedirect::Atom(name));
state_stack.push(TokenOrRedirect::Atom(ct.name()));
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Redirect);
},
Fixity::Pre => {
state_stack.push(TokenOrRedirect::Redirect);
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Atom(name));
state_stack.push(TokenOrRedirect::Atom(ct.name()));
},
Fixity::In => {
state_stack.push(TokenOrRedirect::Redirect);
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Atom(name));
state_stack.push(TokenOrRedirect::Atom(ct.name()));
state_stack.push(TokenOrRedirect::Space);
state_stack.push(TokenOrRedirect::Redirect);
}
}
} else {
self.format_struct(arity, name, state_stack);
self.format_struct(arity, ct.name(), state_stack);
}
}
}
@@ -161,8 +157,10 @@ impl<'a, Formatter: HeapCellValueFormatter, Outputter: HeapCellValueOutputter>
fn handle_heap_term(&mut self, heap_val: HeapCellValue) {
match heap_val {
HeapCellValue::NamedStr(arity, name, fixity) =>
self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
HeapCellValue::NamedStr(arity, name, fixity) => {
let ct = ClauseType::from(name, arity, fixity);
self.formatter.format_clause(arity, ct, &mut self.state_stack)
},
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
if !self.at_cdr("") {
self.outputter.append("[]");

View File

@@ -1,5 +1,4 @@
use prolog::ast::*;
use prolog::tabled_rc::*;
use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
@@ -12,7 +11,7 @@ enum IntIndex {
pub struct CodeOffsets {
pub constants: HashMap<Constant, ThirdLevelIndex>,
pub lists: ThirdLevelIndex,
pub structures: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>
pub structures: HashMap<(ClauseName, usize), ThirdLevelIndex>
}
impl CodeOffsets {
@@ -145,7 +144,7 @@ impl CodeOffsets {
}
}
fn switch_on_structure(str_ind: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>,
fn switch_on_structure(str_ind: HashMap<(ClauseName, usize), ThirdLevelIndex>,
prelude: &mut CodeDeque)
-> IntIndex
{

View File

@@ -13,21 +13,21 @@ use termion::event::Key;
use std::io::{Write, stdin, stdout};
use std::fmt;
impl fmt::Display for ClauseName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
write!(f, "get_constant {}, A{}", constant, r.reg_num()),
&FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
write!(f, "get_constant {}, {}", constant, r),
&FactInstruction::GetList(Level::Shallow, ref r) =>
write!(f, "get_list A{}", r.reg_num()),
&FactInstruction::GetList(Level::Deep, ref r) =>
write!(f, "get_list {}", r),
&FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r, _) =>
write!(f, "get_structure {}/{}, {}", name, arity, r),
&FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r, _) =>
write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
&FactInstruction::GetConstant(lvl, ref constant, ref r) =>
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num()),
&FactInstruction::GetList(lvl, ref r) =>
write!(f, "get_list {}{}", lvl, r.reg_num()),
&FactInstruction::GetStructure(ref ct, ref arity, ref r) =>
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r),
&FactInstruction::GetValue(ref x, ref a) =>
write!(f, "get_value {}, A{}", x, a),
&FactInstruction::GetVariable(ref x, ref a) =>
@@ -51,18 +51,12 @@ impl fmt::Display for QueryInstruction {
match self {
&QueryInstruction::GetVariable(ref x, ref a) =>
write!(f, "query:get_variable {}, A{}", x, a),
&QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
write!(f, "put_constant {}, A{}", constant, r.reg_num()),
&QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
write!(f, "put_constant {}, {}", constant, r),
&QueryInstruction::PutList(Level::Shallow, ref r) =>
write!(f, "put_list A{}", r.reg_num()),
&QueryInstruction::PutList(Level::Deep, ref r) =>
write!(f, "put_list {}", r),
&QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r, _) =>
write!(f, "put_structure {}/{}, {}", name, arity, r),
&QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r, _) =>
write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
&QueryInstruction::PutConstant(lvl, ref constant, ref r) =>
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num()),
&QueryInstruction::PutList(lvl, ref r) =>
write!(f, "put_list {}{}", lvl, r.reg_num()),
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) =>
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r),
&QueryInstruction::PutUnsafeValue(y, a) =>
write!(f, "put_unsafe_value Y{}, A{}", y, a),
&QueryInstruction::PutValue(ref x, ref a) =>
@@ -382,7 +376,7 @@ impl fmt::Display for CutInstruction {
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Level::Shallow => write!(f, "A"),
&Level::Root | &Level::Shallow => write!(f, "A"),
&Level::Deep => write!(f, "X")
}
}
@@ -531,7 +525,7 @@ fn compile_query<'a>(terms: &'a Vec<QueryTerm>, queue: &'a Vec<TopLevel>)
let mut code = try!(cg.compile_query(terms));
compile_appendix(&mut code, queue)?;
Ok((code, cg.take_vars()))
}

View File

@@ -10,21 +10,31 @@ pub struct QueryIterator<'a> {
impl<'a> QueryIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::to_state(lvl, term));
self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
}
fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
let state_stack = terms.iter().rev()
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
.collect();
QueryIterator { state_stack }
}
fn from_term(term: &'a Term) -> Self {
let state = match term {
&Term::AnonVar =>
return QueryIterator { state_stack: vec![] },
&Term::Clause(_, ref name, ref terms, _) =>
TermIterState::Clause(0, ClauseType::Root(name), terms),
&Term::Clause(ref r, ref name, ref terms, fixity) =>
TermIterState::Clause(Level::Root, 0, r,
ClauseType::from(name.clone(), terms.len(), fixity),
terms),
&Term::Cons(..) =>
return QueryIterator { state_stack: vec![] },
&Term::Constant(_, _) =>
return QueryIterator { state_stack: vec![] },
&Term::Var(ref cell, ref var) =>
TermIterState::Var(Level::Shallow, cell, var)
TermIterState::Var(Level::Root, cell, var)
};
QueryIterator { state_stack: vec![state] }
@@ -32,87 +42,18 @@ impl<'a> QueryIterator<'a> {
fn new(term: &'a QueryTerm) -> Self {
match term {
&QueryTerm::CallN(ref terms) => {
let state = TermIterState::Clause(1, ClauseType::CallN, terms);
&QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms) => {
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::CallWithInferenceLimit(ref terms) => {
let ct = ClauseType::CallWithInferenceLimit;
let state = TermIterState::Clause(0, ct, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Catch(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Catch, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::DuplicateTerm(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::DuplicateTerm, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Arg(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Arg, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::SetupCallCleanup(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::SetupCallCleanup, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Eq(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Eq, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Functor(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Functor, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Display(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Display, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Ground(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Ground, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(qt, ref terms)) => {
let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Compare(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Compare, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::CompareTerm(qt, ref terms) => {
let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Is(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::Is, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsNonVar(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsFloat(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsRational(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsCompound(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsString(ref terms)) =>
Self::from_term(terms[0].as_ref()),
&QueryTerm::NotEq(ref terms) => {
let state = TermIterState::Clause(0, ClauseType::NotEq, terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Term(ref term) =>
Self::from_term(term),
&QueryTerm::Throw(ref term) => {
let state = TermIterState::Clause(0, ClauseType::Throw, term);
&QueryTerm::Clause(ref cell, ref ct, ref terms) => {
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator { state_stack: vec![state] }
},
&QueryTerm::Cut => QueryIterator { state_stack: vec![] },
&QueryTerm::Jump(ref vars) => {
let state_stack = vars.iter().rev().map(|t| {
TermIterState::to_state(Level::Shallow, t)
TermIterState::subterm_to_state(Level::Shallow, t)
}).collect();
QueryIterator { state_stack }
@@ -121,12 +62,6 @@ impl<'a> QueryIterator<'a> {
}
}
impl QueryTerm {
pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
QueryIterator::new(self)
}
}
impl<'a> Iterator for QueryIterator<'a> {
type Item = TermRef<'a>;
@@ -135,25 +70,30 @@ impl<'a> Iterator for QueryIterator<'a> {
match iter_state {
TermIterState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
TermIterState::Clause(child_num, ct, child_terms) => {
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
ClauseType::CallN =>
self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
ClauseType::Deep(..) =>
return Some(TermRef::Clause(ct, child_terms)),
ClauseType::Named(..) | ClauseType::Op(..) =>
return match lvl {
Level::Root => None,
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms))
},
_ =>
return None
};
} else {
self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1,
cell, ct, child_terms));
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
}
},
TermIterState::InitialCons(lvl, cell, head, tail) => {
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
self.push_subterm(Level::Deep, tail);
self.push_subterm(Level::Deep, head);
self.push_subterm(lvl.child_level(), tail);
self.push_subterm(lvl.child_level(), head);
},
TermIterState::FinalCons(lvl, cell, head, tail) =>
return Some(TermRef::Cons(lvl, cell, head, tail)),
@@ -174,24 +114,31 @@ pub struct FactIterator<'a> {
impl<'a> FactIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_queue.push_back(TermIterState::to_state(lvl, term));
self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
}
fn new(term: &'a Term) -> FactIterator<'a> {
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
let state_queue = terms.iter()
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
.collect();
FactIterator { state_queue }
}
fn new(term: &'a Term) -> Self {
let states = match term {
&Term::AnonVar =>
vec![TermIterState::AnonVar(Level::Shallow)],
&Term::Clause(.., ref name, ref terms, _) =>
vec![TermIterState::Clause(0, ClauseType::Root(name), terms)],
vec![TermIterState::AnonVar(Level::Root)],
&Term::Clause(ref cell, ref name, ref terms, fixity) => {
let ct = ClauseType::from(name.clone(), terms.len(), fixity);
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
},
&Term::Cons(ref cell, ref head, ref tail) =>
vec![TermIterState::InitialCons(Level::Shallow,
cell,
head.as_ref(),
tail.as_ref())],
vec![TermIterState::InitialCons(Level::Root, cell, head.as_ref(), tail.as_ref())],
&Term::Constant(ref cell, ref constant) =>
vec![TermIterState::Constant(Level::Shallow, cell, constant)],
vec![TermIterState::Constant(Level::Root, cell, constant)],
&Term::Var(ref cell, ref var) =>
vec![TermIterState::Var(Level::Shallow, cell, var)]
vec![TermIterState::Var(Level::Root, cell, var)]
};
FactIterator { state_queue: VecDeque::from(states) }
@@ -206,16 +153,14 @@ impl<'a> Iterator for FactIterator<'a> {
match state {
TermIterState::AnonVar(lvl) =>
return Some(TermRef::AnonVar(lvl)),
TermIterState::Clause(_, ct, child_terms) => {
TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
for child_term in child_terms {
self.push_subterm(ct.level_of_subterms(), child_term);
self.push_subterm(lvl.child_level(), child_term);
}
match ct {
ClauseType::Deep(..) =>
return Some(TermRef::Clause(ct, child_terms)),
_ =>
continue
match lvl {
Level::Root => continue,
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
};
},
TermIterState::InitialCons(lvl, cell, head, tail) => {
@@ -246,10 +191,32 @@ impl Term {
}
}
pub enum ChunkedTerm<'a> {
HeadClause(ClauseName, &'a Vec<Box<Term>>),
BodyTerm(&'a QueryTerm)
}
impl QueryTerm {
pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
QueryIterator::new(self)
}
}
impl<'a> ChunkedTerm<'a> {
pub fn post_order_iter(&self) -> QueryIterator<'a> {
match self {
&ChunkedTerm::BodyTerm(ref qt) =>
QueryIterator::new(qt),
&ChunkedTerm::HeadClause(_, terms) =>
QueryIterator::from_rule_head_clause(terms)
}
}
}
pub struct ChunkedIterator<'a>
{
term_loc: GenContext,
iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
pub chunk_num: usize,
iter: Box<Iterator<Item=ChunkedTerm<'a>> + 'a>,
deep_cut_encountered: bool
}
@@ -258,19 +225,19 @@ impl<'a> ChunkedIterator<'a>
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
{
ChunkedIterator {
term_loc: GenContext::Last(0),
iter: Box::new(terms.iter()),
chunk_num: 0,
iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
deep_cut_encountered: false
}
}
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
{
let inner_iter = Box::new(once(p1));
let iter = inner_iter.chain(clauses.iter());
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
ChunkedIterator {
term_loc: GenContext::Last(0),
chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false
}
@@ -278,14 +245,14 @@ impl<'a> ChunkedIterator<'a>
pub fn from_rule(rule: &'a Rule) -> Self
{
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let &Rule { head: (ref name, ref args, ref p1), ref clauses } = rule;
let iter = once(p0);
let inner_iter = Box::new(once(p1));
let iter = iter.chain(inner_iter.chain(clauses.iter()));
let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))));
ChunkedIterator {
term_loc: GenContext::Head,
chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false,
}
@@ -295,15 +262,7 @@ impl<'a> ChunkedIterator<'a>
self.deep_cut_encountered
}
pub fn at_rule_head(&self) -> bool {
self.term_loc == GenContext::Head
}
pub fn chunk_num(&self) -> usize {
self.term_loc.chunk_num()
}
fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>)
{
let mut arity = 0;
let mut item = Some(term);
@@ -311,81 +270,39 @@ impl<'a> ChunkedIterator<'a>
while let Some(term) = item {
match term {
&QueryTerm::Jump(ref vars) => {
ChunkedTerm::HeadClause(..) =>
result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
result.push(term);
arity = vars.len();
break;
},
&QueryTerm::CompareTerm(..) => {
result.push(term);
arity = 2;
break;
},
&QueryTerm::Term(ref inner_term) =>
if let GenContext::Head = self.term_loc {
result.push(term);
self.term_loc = GenContext::Last(0);
} else {
result.push(term);
if inner_term.is_callable() {
arity = inner_term.arity();
break;
}
},
&QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
result.push(term);
arity = 3;
break;
},
&QueryTerm::CallN(ref child_terms) => {
result.push(term);
arity = child_terms.len() + 1;
break;
},
&QueryTerm::Catch(ref child_terms)
| &QueryTerm::Throw(ref child_terms) => {
result.push(term);
arity = child_terms.len();
break;
},
&QueryTerm::Ground(_) | &QueryTerm::Display(_) => {
result.push(term);
arity = 1;
break;
},
&QueryTerm::Arg(_)
| &QueryTerm::Functor(_)
| &QueryTerm::CallWithInferenceLimit(_) => {
result.push(term);
arity = 3;
break;
},
&QueryTerm::Eq(_) | &QueryTerm::NotEq(_)
| &QueryTerm::Is(_) | &QueryTerm::DuplicateTerm(_) => {
result.push(term);
arity = 2;
break;
},
&QueryTerm::Inlined(_) =>
result.push(term),
&QueryTerm::Cut => {
ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
result.push(term);
if self.term_loc.chunk_num() > 0 {
if self.chunk_num > 0 {
self.deep_cut_encountered = true;
}
},
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
result.push(term);
arity = subterms.len() + 1;
break;
},
ChunkedTerm::BodyTerm(qt) => {
result.push(term);
arity = qt.arity();
break;
}
};
item = self.iter.next();
}
let chunk_num = self.term_loc.chunk_num();
if let &mut GenContext::Last(ref mut chunk_num) = &mut self.term_loc {
*chunk_num += 1;
}
let chunk_num = self.chunk_num;
self.chunk_num += 1;
(chunk_num, arity, result)
}
@@ -394,7 +311,7 @@ impl<'a> ChunkedIterator<'a>
impl<'a> Iterator for ChunkedIterator<'a>
{
// the chunk number, last term arity, and vector of references.
type Item = (usize, usize, Vec<&'a QueryTerm>);
type Item = (usize, usize, Vec<ChunkedTerm<'a>>);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|term| self.take_chunk(term))

View File

@@ -185,7 +185,7 @@ pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
pub(crate) trait CallPolicy: Any {
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
name: TabledRc<Atom>, arity: usize)
name: ClauseName, arity: usize)
-> CallResult
{
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
@@ -204,7 +204,7 @@ pub(crate) trait CallPolicy: Any {
}
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
name: TabledRc<Atom>, arity: usize)
name: ClauseName, arity: usize)
-> CallResult
{
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
@@ -351,20 +351,19 @@ pub(crate) struct DefaultCallPolicy {}
impl CallPolicy for DefaultCallPolicy {}
pub(crate) struct CallWithInferenceLimitCallPolicy {
atom_tbl: TabledData<Atom>,
pub(crate) struct CallWithInferenceLimitCallPolicy {
pub(crate) prev_policy: Box<CallPolicy>,
count: BigUint,
limits: Vec<(BigUint, usize)>
}
impl CallWithInferenceLimitCallPolicy {
pub(crate) fn new_in_place(atom_tbl: TabledData<Atom>, policy: &mut Box<CallPolicy>)
pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>)
{
let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
swap(&mut prev_policy, policy);
let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
let new_policy = CallWithInferenceLimitCallPolicy { prev_policy,
count: BigUint::zero(),
limits: vec![] };
*policy = Box::new(new_policy);
@@ -373,15 +372,13 @@ impl CallWithInferenceLimitCallPolicy {
fn increment(&mut self) -> CallResult {
if let Some(&(ref limit, bp)) = self.limits.last() {
if self.count == *limit {
return Err(functor!(self.atom_tbl,
"inference_limit_exceeded",
1,
return Err(functor!("inference_limit_exceeded", 1,
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
} else {
self.count += BigUint::one();
}
}
Ok(())
}
@@ -422,7 +419,7 @@ impl CallWithInferenceLimitCallPolicy {
impl CallPolicy for CallWithInferenceLimitCallPolicy {
fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
name: TabledRc<Atom>, arity: usize)
name: ClauseName, arity: usize)
-> CallResult
{
self.prev_policy.try_call(machine_st, code_dir, name, arity)?;
@@ -430,7 +427,7 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
}
fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
name: TabledRc<Atom>, arity: usize)
name: ClauseName, arity: usize)
-> CallResult
{
self.prev_policy.try_execute(machine_st, code_dir, name, arity)?;

View File

@@ -269,13 +269,7 @@ impl MachineState {
match item {
Addr::Con(Constant::Number(n)) => Ok(n),
_ => {
let atom_tbl = self.atom_tbl.clone();
Err(functor!(self.atom_tbl,
"instantiation_error",
1,
[heap_atom!("(is)/2", atom_tbl)]))
}
_ => Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
}
},
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
@@ -292,10 +286,7 @@ impl MachineState {
if let Some(r) = Ratio::from_float(fl.into_inner()) {
Ok(Rc::new(r))
} else {
Err(functor!(self.atom_tbl,
"instantiation_error",
1,
[heap_atom!("(is)/2", self.atom_tbl)]))
Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
},
Number::Integer(bi) =>
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
@@ -316,9 +307,7 @@ impl MachineState {
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, Vec<HeapCellValue>>
{
let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
[heap_atom!("(is)/2", self.atom_tbl.clone())]);
let instantiation_err = functor!("instantiation_error", 1, [heap_atom!("(is)/2")]);
let a = self[r].clone();
if let &Addr::Con(Constant::Number(ref n)) = &a {
@@ -378,8 +367,7 @@ impl MachineState {
-> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>>
{
if *r2 == Ratio::zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*r1 / &*r2))
}
@@ -390,13 +378,11 @@ impl MachineState {
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(n1.div_floor(&n2)))
},
_ => Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
_ => Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -405,22 +391,19 @@ impl MachineState {
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*n1 / &*n2))
},
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
fn div(&self, n1: Number, n2: Number) -> Result<Number, Vec<HeapCellValue>>
{
if n2.is_zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(n1 / n2)
}
@@ -435,8 +418,7 @@ impl MachineState {
_ => Ok(Rc::new(&*n1 >> usize::max_value()))
},
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -449,8 +431,7 @@ impl MachineState {
_ => Ok(Rc::new(&*n1 << usize::max_value()))
},
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -460,8 +441,7 @@ impl MachineState {
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)),
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -471,8 +451,7 @@ impl MachineState {
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -481,14 +460,12 @@ impl MachineState {
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(n1.mod_floor(&n2)))
},
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -497,14 +474,12 @@ impl MachineState {
match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) =>
if *n2 == BigInt::zero() {
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("zero_divisor", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
} else {
Ok(Rc::new(&*n1 % &*n2))
},
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -514,8 +489,7 @@ impl MachineState {
(Number::Integer(n1), Number::Integer(n2)) =>
Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
_ =>
Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
[heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
}
}
@@ -661,15 +635,15 @@ impl MachineState {
_ => self.fail = true
};
},
&FactInstruction::GetStructure(_, ref name, arity, reg, fixity) => {
&FactInstruction::GetStructure(ref ct, arity, reg) => {
let addr = self.deref(self[reg].clone());
match self.store(addr.clone()) {
Addr::Str(a) => {
let result = &self.heap[a];
if let &HeapCellValue::NamedStr(narity, ref str, _) = result {
if narity == arity && *name == *str {
if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
if narity == arity && ct.name() == *s {
self.s = a + 1;
self.mode = MachineMode::Read;
} else {
@@ -681,7 +655,7 @@ impl MachineState {
let h = self.heap.h;
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
@@ -858,10 +832,10 @@ impl MachineState {
self[reg] = Addr::Con(constant.clone()),
&QueryInstruction::PutList(_, reg) =>
self[reg] = Addr::Lis(self.heap.h),
&QueryInstruction::PutStructure(_, ref name, arity, reg, fixity) => {
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
let h = self.heap.h;
self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
self[reg] = Addr::Str(h);
},
&QueryInstruction::PutUnsafeValue(n, arg) => {
@@ -979,11 +953,8 @@ impl MachineState {
if let HeapCellValue::NamedStr(narity, name, _) = result {
if narity + arity > 63 {
let atom_tbl = self.atom_tbl.clone();
self.throw_exception(functor!(atom_tbl,
"representation_error",
1,
[heap_atom!("exceeds_max_arity", atom_tbl)]));
self.throw_exception(functor!("representation_error", 1,
[heap_atom!("exceeds_max_arity")]));
return None;
}
@@ -1003,16 +974,12 @@ impl MachineState {
},
Addr::Con(Constant::Atom(name)) => (name, 0),
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
let atom_tbl = self.atom_tbl.clone();
self.throw_exception(functor!(atom_tbl, "instantiation_error", 0, []));
self.throw_exception(functor!("instantiation_error"));
return None;
},
_ => {
let atom_tbl = self.atom_tbl.clone();
self.throw_exception(functor!(atom_tbl,
"type_error",
2,
[heap_atom!("callable", atom_tbl),
self.throw_exception(functor!("type_error", 2,
[heap_atom!("callable"),
HeapCellValue::Addr(addr)]));
return None;
}
@@ -1065,10 +1032,7 @@ impl MachineState {
_ => self.fail = true
};
} else {
return Err(functor!(self.atom_tbl,
"type_error",
1,
[heap_atom!("compound_expected", self.atom_tbl)]));
return Err(functor!("type_error", 1, [heap_atom!("compound_expected")]))
}
}
@@ -1201,7 +1165,7 @@ impl MachineState {
return Ordering::Less;
} else if ar1 > ar2 {
return Ordering::Greater;
} else if *n1 != *n2 {
} else if n1 != n2 {
return n1.cmp(&n2);
} else {
continue;
@@ -1210,14 +1174,14 @@ impl MachineState {
continue,
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _))
| (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) =>
if ar == 2 && *n == "." {
if ar == 2 && n.as_str() == "." {
continue;
} else if ar < 2 {
return Ordering::Greater;
} else if ar > 2 {
return Ordering::Less;
} else {
return n.cmp(&String::from("."));
return n.as_str().cmp(".");
},
(HeapCellValue::NamedStr(..), _) =>
return Ordering::Greater,
@@ -1356,8 +1320,7 @@ impl MachineState {
let a2 = self.store(self.deref(self[r2].clone()));
if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
call_policy);
CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
}
self.p += 1;
@@ -1373,13 +1336,7 @@ impl MachineState {
None => panic!("install_inference_counter: should have installed \\
CallWithInferenceLimitCallPolicy.")
},
_ => {
let atom_tbl = self.atom_tbl.clone();
self.throw_exception(functor!(atom_tbl,
"type_error",
1,
[heap_atom!("integer_expected", atom_tbl)]))
}
_ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
};
},
&BuiltInInstruction::IsAtomic(r) => {
@@ -1634,10 +1591,10 @@ impl MachineState {
self.unify(a1, f_a);
} else {
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
return Err(functor!("instantiation_error"));
}
} else {
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
return Err(functor!("instantiation_error"));
}
},
_ => {
@@ -1681,7 +1638,7 @@ impl MachineState {
for (v1, v2) in iter {
match (v1, v2) {
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
if ar1 != ar2 || *n1 != *n2 {
if ar1 != ar2 || n1 != n2 {
return true;
},
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
@@ -1710,7 +1667,7 @@ impl MachineState {
for (v1, v2) in iter {
match (v1, v2) {
(HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
if ar1 != ar2 || *n1 != *n2 {
if ar1 != ar2 || n1 != n2 {
return true;
},
(HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>

View File

@@ -46,7 +46,7 @@ impl Index<CodePtr> for Machine {
impl Machine {
pub fn new() -> Self {
let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
let (code, code_dir, op_dir) = build_code_dir();
Machine {
ms: MachineState::new(atom_tbl),
@@ -67,7 +67,7 @@ impl Machine {
self.ms.atom_tbl.clone()
}
pub fn add_user_code<'a>(&mut self, name: TabledRc<Atom>, arity: usize, mut code: Code)
pub fn add_user_code<'a>(&mut self, name: ClauseName, arity: usize, mut code: Code)
-> EvalSession<'a>
{
match self.code_dir.get(&(name.clone(), arity)) {
@@ -165,8 +165,7 @@ impl Machine {
fn query_stepper<'a>(&mut self)
{
loop
{
loop {
self.execute_instr();
if self.failed() {
@@ -180,10 +179,8 @@ impl Machine {
}
}
fn record_var_places<'a>(&self,
chunk_num: usize,
alloc_locs: &AllocVarDict<'a>,
heap_locs: &mut HeapVarDict<'a>)
fn record_var_places<'a>(&self, chunk_num: usize,
alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
{
for (var, var_data) in alloc_locs {
match var_data {

View File

@@ -1,3 +1,9 @@
macro_rules! clause_name {
($name: expr) => (
ClauseName::BuiltIn($name)
)
}
macro_rules! tabled_rc {
($e:expr, $tbl:expr) => (
TabledRc::new(String::from($e), $tbl.clone())
@@ -6,7 +12,10 @@ macro_rules! tabled_rc {
macro_rules! atom {
($e:expr, $tbl:expr) => (
Constant::Atom(tabled_rc!($e, $tbl))
Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)))
);
($e:expr) => (
Constant::Atom(clause_name!($e))
)
}
@@ -47,22 +56,21 @@ macro_rules! query {
}
macro_rules! heap_atom {
($name:expr) => (
HeapCellValue::Addr(Addr::Con(atom!($name)))
);
($name:expr, $tbl:expr) => (
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
)
}
macro_rules! functor {
($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
if $len > 0 {
vec![ HeapCellValue::NamedStr($len,
tabled_rc!($name, $tbl),
None),
$($args),* ]
} else {
vec![ heap_atom!($name, $tbl) ]
}
}}
($name:expr) => (
vec![ heap_atom!($name) ]
);
($name:expr, $len:expr, [$($args:expr),*]) => (
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
)
}
macro_rules! fact {
@@ -115,8 +123,11 @@ macro_rules! put_var {
}
macro_rules! put_structure {
($tbl:expr, $lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
QueryInstruction::PutStructure($lvl, tabled_rc!($name, $tbl), $arity, $r, $fix)
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
);
($atom:expr, $arity:expr, $r:expr, None) => (
QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
)
}
@@ -368,12 +379,11 @@ macro_rules! get_constant {
}
macro_rules! get_structure {
($tbl:expr, $atom:expr, $arity:expr, $r:expr, $fix:expr) => (
FactInstruction::GetStructure(Level::Shallow,
tabled_rc!($atom, $tbl),
$arity,
$r,
$fix)
($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
);
($atom:expr, $arity:expr, $r:expr, None) => (
FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
)
}

View File

@@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::HashSet;
use std::fmt;
use std::hash::{Hash, Hasher};
@@ -6,13 +7,27 @@ use std::ops::Deref;
use std::rc::Rc;
pub type TabledData<T> = Rc<RefCell<HashSet<Rc<T>>>>;
#[derive(Clone)]
pub struct TabledRc<T: Hash + Eq> {
atom: Rc<T>,
table: TabledData<T>
}
impl<T: Ord + Hash + Eq> PartialOrd for TabledRc<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
{
Some(self.atom.cmp(&other.atom))
}
}
impl<T: Ord + Hash + Eq> Ord for TabledRc<T> {
fn cmp(&self, other: &Self) -> Ordering
{
self.atom.cmp(&other.atom)
}
}
impl<T: Hash + Eq> PartialEq for TabledRc<T> {
fn eq(&self, other: &TabledRc<T>) -> bool
{
@@ -23,9 +38,8 @@ impl<T: Hash + Eq> PartialEq for TabledRc<T> {
impl<T: Hash + Eq> Eq for TabledRc<T> {}
impl<T: Hash + Eq> Hash for TabledRc<T> {
fn hash<H: Hasher>(&self, state: &mut H)
{
self.atom.hash(state)
fn hash<H: Hasher>(&self, state: &mut H) {
self.atom.hash(state)
}
}
@@ -40,10 +54,6 @@ impl<T: Hash + Eq> TabledRc<T> {
TabledRc { atom, table }
}
pub fn table(&self) -> TabledData<T> {
self.table.clone()
}
}
impl<T: Hash + Eq> Drop for TabledRc<T> {

View File

@@ -1,6 +1,5 @@
use prolog::ast::*;
use prolog::iterators::*;
use prolog::tabled_rc::*;
pub trait CompilationTarget<'a> {
type Iterator : Iterator<Item=TermRef<'a>>;
@@ -9,7 +8,7 @@ pub trait CompilationTarget<'a> {
fn to_constant(Level, Constant, RegType) -> Self;
fn to_list(Level, RegType) -> Self;
fn to_structure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>) -> Self;
fn to_structure(ClauseType, usize, RegType) -> Self;
fn to_void(usize) -> Self;
fn is_void_instr(&self) -> bool;
@@ -40,11 +39,9 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
FactInstruction::GetConstant(lvl, constant, reg)
}
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
reg: RegType, fixity: Option<Fixity>)
-> Self
fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self
{
FactInstruction::GetStructure(lvl, atom, arity, reg, fixity)
FactInstruction::GetStructure(ct, arity, reg)
}
fn to_list(lvl: Level, reg: RegType) -> Self {
@@ -105,11 +102,9 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
term.post_order_iter()
}
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
reg: RegType, fixity: Option<Fixity>)
-> Self
fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self
{
QueryInstruction::PutStructure(lvl, atom, arity, reg, fixity)
QueryInstruction::PutStructure(ct, arity, r)
}
fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {

View File

@@ -672,8 +672,8 @@ fn test_queries_on_call_n()
{
let mut wam = Machine::new();
submit(&mut wam, "maplist(Pred, []).
maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
submit(&mut wam, "maplist(_, []).
maplist(P, [X|Xs]) :- call(P, X), maplist(P, Xs).");
submit(&mut wam, "f(a). f(b). f(c).");
assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).",