Format code using 'cargo fmt'

This commit is contained in:
Atul Bhosale
2019-09-23 19:35:37 +07:00
parent 8207fdea40
commit 1273e2d52d
36 changed files with 8738 additions and 6375 deletions

View File

@@ -1,8 +1,12 @@
#[macro_use] extern crate cfg_if; #[macro_use]
#[macro_use] extern crate downcast; extern crate cfg_if;
#[macro_use]
extern crate downcast;
extern crate indexmap; extern crate indexmap;
#[macro_use] extern crate prolog_parser; #[macro_use]
#[macro_use] extern crate ref_thread_local; extern crate prolog_parser;
#[macro_use]
extern crate ref_thread_local;
cfg_if! { cfg_if! {
if #[cfg(feature = "readline_rs_compat")] { if #[cfg(feature = "readline_rs_compat")] {

View File

@@ -8,19 +8,29 @@ use prolog::targets::*;
use std::cell::Cell; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
pub trait Allocator<'a> pub trait Allocator<'a> {
{
fn new() -> Self; fn new() -> Self;
fn mark_anon_var<Target>(&mut self, Level, GenContext, &mut Vec<Target>) fn mark_anon_var<Target>(&mut self, Level, GenContext, &mut Vec<Target>)
where Target: CompilationTarget<'a>; where
Target: CompilationTarget<'a>;
fn mark_non_var<Target>(&mut self, Level, GenContext, &'a Cell<RegType>, &mut Vec<Target>) fn mark_non_var<Target>(&mut self, Level, GenContext, &'a Cell<RegType>, &mut Vec<Target>)
where Target: CompilationTarget<'a>; where
fn mark_reserved_var<Target>(&mut self, Rc<Var>, Level, &'a Cell<VarReg>, GenContext, Target: CompilationTarget<'a>;
&mut Vec<Target>, RegType, bool) fn mark_reserved_var<Target>(
where Target: CompilationTarget<'a>; &mut self,
Rc<Var>,
Level,
&'a Cell<VarReg>,
GenContext,
&mut Vec<Target>,
RegType,
bool,
) where
Target: CompilationTarget<'a>;
fn mark_var<Target>(&mut self, Rc<Var>, Level, &'a Cell<VarReg>, GenContext, &mut Vec<Target>) fn mark_var<Target>(&mut self, Rc<Var>, Level, &'a Cell<VarReg>, GenContext, &mut Vec<Target>)
where Target: CompilationTarget<'a>; where
Target: CompilationTarget<'a>;
fn reset(&mut self); fn reset(&mut self);
fn reset_contents(&mut self) {} fn reset_contents(&mut self) {}
@@ -34,15 +44,15 @@ pub trait Allocator<'a>
fn take_bindings(self) -> AllocVarDict; fn take_bindings(self) -> AllocVarDict;
fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a> fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a> {
{
let mut perm_vs = VariableFixtures::new(); let mut perm_vs = VariableFixtures::new();
for (var, (var_status, cells)) in vs.into_iter() { for (var, (var_status, cells)) in vs.into_iter() {
match var_status { match var_status {
VarStatus::Temp(chunk_num, tvd) => { VarStatus::Temp(chunk_num, tvd) => {
self.bindings_mut().insert(var.clone(), VarData::Temp(chunk_num, 0, tvd)); self.bindings_mut()
}, .insert(var.clone(), VarData::Temp(chunk_num, 0, tvd));
}
VarStatus::Perm(_) => { VarStatus::Perm(_) => {
self.bindings_mut().insert(var.clone(), VarData::Perm(0)); self.bindings_mut().insert(var.clone(), VarData::Perm(0));
perm_vs.insert(var, (var_status, cells)); perm_vs.insert(var, (var_status, cells));
@@ -54,7 +64,9 @@ pub trait Allocator<'a>
} }
fn get(&self, var: Rc<Var>) -> RegType { fn get(&self, var: Rc<Var>) -> RegType {
self.bindings().get(&var).map_or(temp_v!(0), |v| v.as_reg_type()) self.bindings()
.get(&var)
.map_or(temp_v!(0), |v| v.as_reg_type())
} }
fn is_unbound(&self, var: Rc<Var>) -> bool { fn is_unbound(&self, var: Rc<Var>) -> bool {
@@ -64,7 +76,7 @@ pub trait Allocator<'a>
fn record_register(&mut self, var: Rc<Var>, r: RegType) { fn record_register(&mut self, var: Rc<Var>, r: RegType) {
match self.bindings_mut().get_mut(&var).unwrap() { match self.bindings_mut().get_mut(&var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(), &mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
&mut VarData::Perm(ref mut s) => *s = r.reg_num() &mut VarData::Perm(ref mut s) => *s = r.reg_num(),
} }
} }
} }

View File

@@ -10,60 +10,66 @@ use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use prolog::ordered_float::*; use prolog::ordered_float::*;
use prolog::rug::{Assign, Integer, Rational};
use prolog::rug::ops::PowAssign; use prolog::rug::ops::PowAssign;
use prolog::rug::{Assign, Integer, Rational};
use std::cell::Cell; use std::cell::Cell;
use std::cmp::{Ordering, min, max}; use std::cmp::{max, min, Ordering};
use std::f64; use std::f64;
use std::num::FpCategory; use std::num::FpCategory;
use std::ops::{Add, Sub, Div, Mul, Neg}; use std::ops::{Add, Div, Mul, Neg, Sub};
use std::rc::Rc; use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
pub struct ArithInstructionIterator<'a> { pub struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>> state_stack: Vec<TermIterState<'a>>,
} }
pub type ArithCont = (Code, Option<ArithmeticTerm>); pub type ArithCont = (Code, Option<ArithmeticTerm>);
impl<'a> ArithInstructionIterator<'a> { impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) { fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::subterm_to_state(lvl, term)); self.state_stack
.push(TermIterState::subterm_to_state(lvl, term));
} }
fn new(term: &'a Term) -> Result<Self, ArithmeticError> { fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
let state = match term { let state = match term {
&Term::AnonVar => &Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
return Err(ArithmeticError::UninstantiatedVar), &Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
&Term::Clause(ref cell, ref name, ref terms, ref fixity) =>
match ClauseType::from(name.clone(), terms.len(), fixity.clone()) { match ClauseType::from(name.clone(), terms.len(), fixity.clone()) {
ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) => ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) => {
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)), Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}
ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => { ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
let ct = ClauseType::Named(clause_name!("float"), 1, CodeIndex::default()); let ct = ClauseType::Named(clause_name!("float"), 1, CodeIndex::default());
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)) Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}, }
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name.clone(), _ => Err(ArithmeticError::NonEvaluableFunctor(
fixity.clone()), Constant::Atom(name.clone(), fixity.clone()),
terms.len())) terms.len(),
}?, )),
&Term::Constant(ref cell, ref cons) => }?
TermIterState::Constant(Level::Shallow, cell, cons), }
&Term::Cons(_, _, _) => &Term::Constant(ref cell, ref cons) => {
return Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2)), TermIterState::Constant(Level::Shallow, cell, cons)
&Term::Var(ref cell, ref var) => }
TermIterState::Var(Level::Shallow, cell, var.clone()) &Term::Cons(_, _, _) => {
return Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))
}
&Term::Var(ref cell, ref var) => TermIterState::Var(Level::Shallow, cell, var.clone()),
}; };
Ok(ArithInstructionIterator { state_stack: vec![state] }) Ok(ArithInstructionIterator {
state_stack: vec![state],
})
} }
} }
pub enum ArithTermRef<'a> { pub enum ArithTermRef<'a> {
Constant(&'a Constant), Constant(&'a Constant),
Op(ClauseName, usize), // name, arity. Op(ClauseName, usize), // name, arity.
Var(&'a Cell<VarReg>, Rc<Var>) Var(&'a Cell<VarReg>, Rc<Var>),
} }
impl<'a> Iterator for ArithInstructionIterator<'a> { impl<'a> Iterator for ArithInstructionIterator<'a> {
@@ -72,24 +78,28 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() { while let Some(iter_state) = self.state_stack.pop() {
match iter_state { match iter_state {
TermIterState::AnonVar(_) => TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
return Some(Err(ArithmeticError::UninstantiatedVar)),
TermIterState::Clause(lvl, child_num, cell, ct, subterms) => { TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
let arity = subterms.len(); let arity = subterms.len();
if child_num == arity { if child_num == arity {
return Some(Ok(ArithTermRef::Op(ct.name(), arity))); return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
} else { } else {
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms)); self.state_stack.push(TermIterState::Clause(
lvl,
child_num + 1,
cell,
ct,
subterms,
));
self.push_subterm(lvl, subterms[child_num].as_ref()); self.push_subterm(lvl, subterms[child_num].as_ref());
} }
}, }
TermIterState::Constant(_, _, c) => TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))),
return Some(Ok(ArithTermRef::Constant(c))), TermIterState::Var(_, cell, var) => {
TermIterState::Var(_, cell, var) => return Some(Ok(ArithTermRef::Var(cell, var.clone())))
return Some(Ok(ArithTermRef::Var(cell, var.clone()))), }
_ => _ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))),
return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2)))
}; };
} }
@@ -100,7 +110,7 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
pub struct ArithmeticEvaluator<'a> { pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict, bindings: &'a AllocVarDict,
interm: Vec<ArithmeticTerm>, interm: Vec<ArithmeticTerm>,
interm_c: usize interm_c: usize,
} }
pub trait ArithmeticTermIter<'a> { pub trait ArithmeticTermIter<'a> {
@@ -117,15 +127,20 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
} }
} }
impl<'a> ArithmeticEvaluator<'a> impl<'a> ArithmeticEvaluator<'a> {
{
pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self { pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int } ArithmeticEvaluator {
bindings,
interm: Vec::new(),
interm_c: target_int,
}
} }
fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize) fn get_unary_instr(
-> Result<ArithmeticInstruction, ArithmeticError> name: ClauseName,
{ a1: ArithmeticTerm,
t: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
match name.as_str() { match name.as_str() {
"abs" => Ok(ArithmeticInstruction::Abs(a1, t)), "abs" => Ok(ArithmeticInstruction::Abs(a1, t)),
"-" => Ok(ArithmeticInstruction::Neg(a1, t)), "-" => Ok(ArithmeticInstruction::Neg(a1, t)),
@@ -145,13 +160,19 @@ impl<'a> ArithmeticEvaluator<'a>
"ceiling" => Ok(ArithmeticInstruction::Ceiling(a1, t)), "ceiling" => Ok(ArithmeticInstruction::Ceiling(a1, t)),
"floor" => Ok(ArithmeticInstruction::Floor(a1, t)), "floor" => Ok(ArithmeticInstruction::Floor(a1, t)),
"\\" => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)), "\\" => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), 1)) _ => Err(ArithmeticError::NonEvaluableFunctor(
Constant::Atom(name, None),
1,
)),
} }
} }
fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize) fn get_binary_instr(
-> Result<ArithmeticInstruction, ArithmeticError> name: ClauseName,
{ a1: ArithmeticTerm,
a2: ArithmeticTerm,
t: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
match name.as_str() { match name.as_str() {
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)), "+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
"-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)), "-" => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
@@ -172,7 +193,10 @@ impl<'a> ArithmeticEvaluator<'a>
"mod" => Ok(ArithmeticInstruction::Mod(a1, a2, t)), "mod" => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
"rem" => Ok(ArithmeticInstruction::Rem(a1, a2, t)), "rem" => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
"atan2" => Ok(ArithmeticInstruction::ATan2(a1, a2, t)), "atan2" => Ok(ArithmeticInstruction::ATan2(a1, a2, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), 2)) _ => Err(ArithmeticError::NonEvaluableFunctor(
Constant::Atom(name, None),
2,
)),
} }
} }
@@ -185,9 +209,11 @@ impl<'a> ArithmeticEvaluator<'a>
temp temp
} }
fn instr_from_clause(&mut self, name: ClauseName, arity: usize) fn instr_from_clause(
-> Result<ArithmeticInstruction, ArithmeticError> &mut self,
{ name: ClauseName,
arity: usize,
) -> Result<ArithmeticInstruction, ArithmeticError> {
match arity { match arity {
1 => { 1 => {
let a1 = self.interm.pop().unwrap(); let a1 = self.interm.pop().unwrap();
@@ -200,7 +226,7 @@ impl<'a> ArithmeticEvaluator<'a>
}; };
Self::get_unary_instr(name, a1, ninterm) Self::get_unary_instr(name, a1, ninterm)
}, }
2 => { 2 => {
let a2 = self.interm.pop().unwrap(); let a2 = self.interm.pop().unwrap();
let a1 = self.interm.pop().unwrap(); let a1 = self.interm.pop().unwrap();
@@ -224,35 +250,44 @@ impl<'a> ArithmeticEvaluator<'a>
}; };
Self::get_binary_instr(name, a1, a2, ninterm) Self::get_binary_instr(name, a1, a2, ninterm)
}, }
_ => Err(ArithmeticError::NonEvaluableFunctor(Constant::Atom(name, None), arity)) _ => Err(ArithmeticError::NonEvaluableFunctor(
Constant::Atom(name, None),
arity,
)),
} }
} }
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> { fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
match c { match c {
&Constant::Integer(ref n) => &Constant::Integer(ref n) => self
self.interm.push(ArithmeticTerm::Number(Number::Integer(n.clone()))), .interm
&Constant::Float(ref n) => .push(ArithmeticTerm::Number(Number::Integer(n.clone()))),
self.interm.push(ArithmeticTerm::Number(Number::Float(n.clone()))), &Constant::Float(ref n) => self
&Constant::Rational(ref n) => .interm
self.interm.push(ArithmeticTerm::Number(Number::Rational(n.clone()))), .push(ArithmeticTerm::Number(Number::Float(n.clone()))),
&Constant::Atom(ref name, _) if name.as_str() == "pi" => &Constant::Rational(ref n) => self
self.interm.push(ArithmeticTerm::Number(Number::Float(OrderedFloat(f64::consts::PI)))), .interm
_ => .push(ArithmeticTerm::Number(Number::Rational(n.clone()))),
return Err(ArithmeticError::NonEvaluableFunctor(c.clone(), 0)) &Constant::Atom(ref name, _) if name.as_str() == "pi" => {
self.interm
.push(ArithmeticTerm::Number(Number::Float(OrderedFloat(
f64::consts::PI,
))))
}
_ => return Err(ArithmeticError::NonEvaluableFunctor(c.clone(), 0)),
} }
Ok(()) Ok(())
} }
pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError> pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError>
where Iter: ArithmeticTermIter<'a> where
Iter: ArithmeticTermIter<'a>,
{ {
let mut code = vec![]; let mut code = vec![];
for term_ref in src.iter()? for term_ref in src.iter()? {
{
match term_ref? { match term_ref? {
ArithTermRef::Constant(c) => self.push_constant(c)?, ArithTermRef::Constant(c) => self.push_constant(c)?,
ArithTermRef::Var(cell, name) => { ArithTermRef::Var(cell, name) => {
@@ -260,14 +295,14 @@ impl<'a> ArithmeticEvaluator<'a>
match self.bindings.get(&name) { match self.bindings.get(&name) {
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t), Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p), Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
_ => return Err(ArithmeticError::UninstantiatedVar) _ => return Err(ArithmeticError::UninstantiatedVar),
} }
} else { } else {
cell.get().norm() cell.get().norm()
}; };
self.interm.push(ArithmeticTerm::Reg(r)); self.interm.push(ArithmeticTerm::Reg(r));
}, }
ArithTermRef::Op(name, arity) => { ArithTermRef::Op(name, arity) => {
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?)); code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
} }
@@ -281,10 +316,10 @@ impl<'a> ArithmeticEvaluator<'a>
// integer division rounding function -- 9.1.3.1. // integer division rounding function -- 9.1.3.1.
pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> { pub fn rnd_i<'a>(n: &'a Number) -> RefOrOwned<'a, Integer> {
match n { match n {
&Number::Integer(ref n) => &Number::Integer(ref n) => RefOrOwned::Borrowed(n),
RefOrOwned::Borrowed(n), &Number::Float(OrderedFloat(f)) => {
&Number::Float(OrderedFloat(f)) => RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0)))
RefOrOwned::Owned(Integer::from_f64(f.floor()).unwrap_or_else(|| Integer::from(0))), }
&Number::Rational(ref r) => { &Number::Rational(ref r) => {
let r_ref = r.fract_floor_ref(); let r_ref = r.fract_floor_ref();
let (mut fract, mut floor) = (Rational::new(), Integer::new()); let (mut fract, mut floor) = (Rational::new(), Integer::new());
@@ -300,24 +335,25 @@ pub fn rnd_f(n: &Number) -> f64 {
match n { match n {
&Number::Integer(ref n) => n.to_f64(), &Number::Integer(ref n) => n.to_f64(),
&Number::Float(OrderedFloat(f)) => f, &Number::Float(OrderedFloat(f)) => f,
&Number::Rational(ref r) => r.to_f64() &Number::Rational(ref r) => r.to_f64(),
} }
} }
// floating point result function -- 9.1.4.2. // floating point result function -- 9.1.4.2.
pub fn result_f<Round>(n: &Number, round: Round) -> Result<f64, EvalError> pub fn result_f<Round>(n: &Number, round: Round) -> Result<f64, EvalError>
where Round: Fn(&Number) -> f64 where
Round: Fn(&Number) -> f64,
{ {
let f = rnd_f(n); let f = rnd_f(n);
classify_float(f, round) classify_float(f, round)
} }
fn classify_float<Round>(f: f64, round: Round) -> Result<f64, EvalError> fn classify_float<Round>(f: f64, round: Round) -> Result<f64, EvalError>
where Round: Fn(&Number) -> f64 where
Round: Fn(&Number) -> f64,
{ {
match f.classify() { match f.classify() {
FpCategory::Normal | FpCategory::Zero => FpCategory::Normal | FpCategory::Zero => Ok(round(&Number::Float(OrderedFloat(f)))),
Ok(round(&Number::Float(OrderedFloat(f)))),
FpCategory::Infinite => { FpCategory::Infinite => {
let f = round(&Number::Float(OrderedFloat(f))); let f = round(&Number::Float(OrderedFloat(f)));
@@ -326,9 +362,9 @@ fn classify_float<Round>(f: f64, round: Round) -> Result<f64, EvalError>
} else { } else {
Err(EvalError::FloatOverflow) Err(EvalError::FloatOverflow)
} }
}, }
FpCategory::Nan => Err(EvalError::Undefined), FpCategory::Nan => Err(EvalError::Undefined),
_ => Ok(round(&Number::Float(OrderedFloat(f)))) _ => Ok(round(&Number::Float(OrderedFloat(f)))),
} }
} }
@@ -361,21 +397,23 @@ impl Add<Number> for Number {
fn add(self, rhs: Number) -> Self::Output { fn add(self, rhs: Number) -> Self::Output {
match (self, rhs) { match (self, rhs) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
Ok(Number::Integer(n1 + n2)), // add_i
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) (Number::Integer(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?)), Ok(Number::Float(add_f(float_i_to_f(&n1)?, n2)?))
}
(Number::Integer(n1), Number::Rational(n2)) (Number::Integer(n1), Number::Rational(n2))
| (Number::Rational(n2), Number::Integer(n1)) => | (Number::Rational(n2), Number::Integer(n1)) => {
Ok(Number::Rational(Rational::from(n1) + n2)), Ok(Number::Rational(Rational::from(n1) + n2))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) (Number::Rational(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?)), Ok(Number::Float(add_f(float_r_to_f(&n1)?, n2)?))
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => }
Ok(Number::Float(add_f(f1, f2)?)), (Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Float(add_f(f1, f2)?))
Ok(Number::Rational(r1 + r2)) }
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
} }
} }
} }
@@ -387,7 +425,7 @@ impl Neg for Number {
match self { match self {
Number::Integer(n) => Number::Integer(-n), Number::Integer(n) => Number::Integer(-n),
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)), Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
Number::Rational(r) => Number::Rational(-r) Number::Rational(r) => Number::Rational(-r),
} }
} }
} }
@@ -405,21 +443,23 @@ impl Mul<Number> for Number {
fn mul(self, rhs: Number) -> Self::Output { fn mul(self, rhs: Number) -> Self::Output {
match (self, rhs) { match (self, rhs) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
Ok(Number::Integer(n1 * n2)), // mul_i
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) (Number::Integer(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => | (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?)), Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
}
(Number::Integer(n1), Number::Rational(n2)) (Number::Integer(n1), Number::Rational(n2))
| (Number::Rational(n2), Number::Integer(n1)) => | (Number::Rational(n2), Number::Integer(n1)) => {
Ok(Number::Rational(Rational::from(n1) * n2)), Ok(Number::Rational(Rational::from(n1) * n2))
}
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) (Number::Rational(n1), Number::Float(OrderedFloat(n2)))
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => | (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(mul_f(float_r_to_f(&n1)?, n2)?)), Ok(Number::Float(mul_f(float_r_to_f(&n1)?, n2)?))
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => }
Ok(Number::Float(mul_f(f1, f2)?)), (Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Float(mul_f(f1, f2)?))
Ok(Number::Rational(r1 * r2)) }
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
} }
} }
} }
@@ -429,24 +469,37 @@ impl Div<Number> for Number {
fn div(self, rhs: Number) -> Self::Output { fn div(self, rhs: Number) -> Self::Output {
match (self, rhs) { match (self, rhs) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Float(div_f(
Ok(Number::Float(div_f(float_i_to_f(&n1)?, float_i_to_f(&n2)?)?)), float_i_to_f(&n1)?,
(Number::Integer(n1), Number::Float(OrderedFloat(n2))) => float_i_to_f(&n2)?,
Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?)), )?)),
(Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => (Number::Integer(n1), Number::Float(OrderedFloat(n2))) => {
Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?)), Ok(Number::Float(div_f(float_i_to_f(&n1)?, n2)?))
(Number::Integer(n1), Number::Rational(n2)) => }
Ok(Number::Float(div_f(float_i_to_f(&n1)?, float_r_to_f(&n2)?)?)), (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
(Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f(n2, float_i_to_f(&n1)?)?))
Ok(Number::Float(div_f(float_r_to_f(&n2)?, float_i_to_f(&n1)?)?)), }
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => (Number::Integer(n1), Number::Rational(n2)) => Ok(Number::Float(div_f(
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?)), float_i_to_f(&n1)?,
(Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => float_r_to_f(&n2)?,
Ok(Number::Float(div_f(n2, float_r_to_f(&n1)?)?)), )?)),
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => (Number::Rational(n2), Number::Integer(n1)) => Ok(Number::Float(div_f(
Ok(Number::Float(div_f(f1, f2)?)), float_r_to_f(&n2)?,
(Number::Rational(r1), Number::Rational(r2)) => float_i_to_f(&n1)?,
Ok(Number::Float(div_f(float_r_to_f(&r1)?, float_r_to_f(&r2)?)?)) )?)),
(Number::Rational(n1), Number::Float(OrderedFloat(n2))) => {
Ok(Number::Float(div_f(float_r_to_f(&n1)?, n2)?))
}
(Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
Ok(Number::Float(div_f(n2, float_r_to_f(&n1)?)?))
}
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
Ok(Number::Float(div_f(f1, f2)?))
}
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Float(div_f(
float_r_to_f(&r1)?,
float_r_to_f(&r2)?,
)?)),
} }
} }
} }
@@ -454,24 +507,15 @@ impl Div<Number> for Number {
impl PartialOrd for Number { impl PartialOrd for Number {
fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> { fn partial_cmp(&self, rhs: &Number) -> Option<Ordering> {
match (self, rhs) { match (self, rhs) {
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => (&Number::Integer(ref n1), &Number::Integer(ref n2)) => Some(n1.cmp(n2)),
Some(n1.cmp(n2)), (&Number::Integer(_), Number::Float(_)) => Some(Ordering::Greater),
(&Number::Integer(_), Number::Float(_)) => (&Number::Float(_), &Number::Integer(_)) => Some(Ordering::Less),
Some(Ordering::Greater), (&Number::Integer(_), &Number::Rational(_)) => Some(Ordering::Greater),
(&Number::Float(_), &Number::Integer(_)) => (&Number::Rational(_), &Number::Integer(_)) => Some(Ordering::Less),
Some(Ordering::Less), (&Number::Rational(_), Number::Float(_)) => Some(Ordering::Greater),
(&Number::Integer(_), &Number::Rational(_)) => (&Number::Float(_), &Number::Rational(_)) => Some(Ordering::Less),
Some(Ordering::Greater), (&Number::Float(f1), &Number::Float(f2)) => Some(f1.cmp(&f2)),
(&Number::Rational(_), &Number::Integer(_)) => (&Number::Rational(ref r1), &Number::Rational(ref r2)) => Some(r1.cmp(&r2)),
Some(Ordering::Less),
(&Number::Rational(_), Number::Float(_)) =>
Some(Ordering::Greater),
(&Number::Float(_), &Number::Rational(_)) =>
Some(Ordering::Less),
(&Number::Float(f1), &Number::Float(f2)) =>
Some(f1.cmp(&f2)),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) =>
Some(r1.cmp(&r2))
} }
} }
} }
@@ -479,31 +523,21 @@ impl PartialOrd for Number {
impl Ord for Number { impl Ord for Number {
fn cmp(&self, rhs: &Number) -> Ordering { fn cmp(&self, rhs: &Number) -> Ordering {
match (self, rhs) { match (self, rhs) {
(&Number::Integer(ref n1), &Number::Integer(ref n2)) => (&Number::Integer(ref n1), &Number::Integer(ref n2)) => n1.cmp(n2),
n1.cmp(n2), (&Number::Integer(_), Number::Float(_)) => Ordering::Greater,
(&Number::Integer(_), Number::Float(_)) => (&Number::Float(_), &Number::Integer(_)) => Ordering::Less,
Ordering::Greater, (&Number::Integer(_), &Number::Rational(_)) => Ordering::Greater,
(&Number::Float(_), &Number::Integer(_)) => (&Number::Rational(_), &Number::Integer(_)) => Ordering::Less,
Ordering::Less, (&Number::Rational(_), Number::Float(_)) => Ordering::Greater,
(&Number::Integer(_), &Number::Rational(_)) => (&Number::Float(_), &Number::Rational(_)) => Ordering::Less,
Ordering::Greater, (&Number::Float(f1), &Number::Float(f2)) => f1.cmp(&f2),
(&Number::Rational(_), &Number::Integer(_)) => (&Number::Rational(ref r1), &Number::Rational(ref r2)) => r1.cmp(&r2),
Ordering::Less,
(&Number::Rational(_), Number::Float(_)) =>
Ordering::Greater,
(&Number::Float(_), &Number::Rational(_)) =>
Ordering::Less,
(&Number::Float(f1), &Number::Float(f2)) =>
f1.cmp(&f2),
(&Number::Rational(ref r1), &Number::Rational(ref r2)) =>
r1.cmp(&r2)
} }
} }
} }
// Computes n ^ power. Ignores the sign of power. // Computes n ^ power. Ignores the sign of power.
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
{
let mut power = power.abs(); let mut power = power.abs();
if power == 0 { if power == 0 {

View File

@@ -14,7 +14,7 @@ pub enum CompareNumberQT {
GreaterThanOrEqual, GreaterThanOrEqual,
LessThanOrEqual, LessThanOrEqual,
NotEqual, NotEqual,
Equal Equal,
} }
impl CompareNumberQT { impl CompareNumberQT {
@@ -25,7 +25,7 @@ impl CompareNumberQT {
CompareNumberQT::GreaterThanOrEqual => ">=", CompareNumberQT::GreaterThanOrEqual => ">=",
CompareNumberQT::LessThanOrEqual => "=<", CompareNumberQT::LessThanOrEqual => "=<",
CompareNumberQT::NotEqual => "=\\=", CompareNumberQT::NotEqual => "=\\=",
CompareNumberQT::Equal => "=:=" CompareNumberQT::Equal => "=:=",
} }
} }
} }
@@ -53,7 +53,7 @@ impl CompareTermQT {
pub enum ArithmeticTerm { pub enum ArithmeticTerm {
Reg(RegType), Reg(RegType),
Interm(usize), Interm(usize),
Number(Number) Number(Number),
} }
impl ArithmeticTerm { impl ArithmeticTerm {
@@ -78,7 +78,7 @@ pub enum InlinedClauseType {
IsFloat(RegType), IsFloat(RegType),
IsNonVar(RegType), IsNonVar(RegType),
IsPartialString(RegType), IsPartialString(RegType),
IsVar(RegType) IsVar(RegType),
} }
ref_thread_local! { ref_thread_local! {
@@ -233,7 +233,7 @@ pub enum SystemClauseType {
UnwindStack, UnwindStack,
Variant, Variant,
WAMInstructions, WAMInstructions,
WriteTerm WriteTerm,
} }
impl SystemClauseType { impl SystemClauseType {
@@ -246,15 +246,20 @@ impl SystemClauseType {
&SystemClauseType::AtomChars => clause_name!("$atom_chars"), &SystemClauseType::AtomChars => clause_name!("$atom_chars"),
&SystemClauseType::AtomCodes => clause_name!("$atom_codes"), &SystemClauseType::AtomCodes => clause_name!("$atom_codes"),
&SystemClauseType::AtomLength => clause_name!("$atom_length"), &SystemClauseType::AtomLength => clause_name!("$atom_length"),
&SystemClauseType::ModuleAssertDynamicPredicateToFront => clause_name!("$module_asserta"), &SystemClauseType::ModuleAssertDynamicPredicateToFront => {
&SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"), clause_name!("$module_asserta")
}
&SystemClauseType::ModuleAssertDynamicPredicateToBack => {
clause_name!("$module_assertz")
}
&SystemClauseType::CharCode => clause_name!("$char_code"), &SystemClauseType::CharCode => clause_name!("$char_code"),
&SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"), &SystemClauseType::CharsToNumber => clause_name!("$chars_to_number"),
&SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"), &SystemClauseType::CodesToNumber => clause_name!("$codes_to_number"),
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
&SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"), &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
&SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults) => &SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults) => {
clause_name!("$submit_query_and_print_results"), clause_name!("$submit_query_and_print_results")
}
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"), &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
@@ -265,13 +270,21 @@ impl SystemClauseType {
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"), &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"), &SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
&SystemClauseType::GetChar => clause_name!("$get_char"), &SystemClauseType::GetChar => clause_name!("$get_char"),
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"), &SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => clause_name!("$truncate_if_no_lh_growth_diff"), clause_name!("$truncate_if_no_lh_growth")
}
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => {
clause_name!("$truncate_if_no_lh_growth_diff")
}
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"), &SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
&SystemClauseType::GetAttrVarQueueDelimiter => clause_name!("$get_attr_var_queue_delim"), &SystemClauseType::GetAttrVarQueueDelimiter => {
clause_name!("$get_attr_var_queue_delim")
}
&SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"), &SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"),
&SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"), &SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"),
&SystemClauseType::GetLiftedHeapFromOffsetDiff => clause_name!("$get_lh_from_offset_diff"), &SystemClauseType::GetLiftedHeapFromOffsetDiff => {
clause_name!("$get_lh_from_offset_diff")
}
&SystemClauseType::GetBValue => clause_name!("$get_b_value"), &SystemClauseType::GetBValue => clause_name!("$get_b_value"),
&SystemClauseType::GetClause => clause_name!("$get_clause"), &SystemClauseType::GetClause => clause_name!("$get_clause"),
&SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"), &SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"),
@@ -285,7 +298,9 @@ impl SystemClauseType {
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"), &SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
&SystemClauseType::OpDeclaration => clause_name!("$op$"), &SystemClauseType::OpDeclaration => clause_name!("$op$"),
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"), &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"), &SystemClauseType::InstallInferenceCounter => {
clause_name!("$install_inference_counter")
}
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"), &SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"), &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleOf => clause_name!("$module_of"), &SystemClauseType::ModuleOf => clause_name!("$module_of"),
@@ -311,7 +326,9 @@ impl SystemClauseType {
&SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"), &SystemClauseType::ResetGlobalVarAtKey => clause_name!("$reset_global_var_at_key"),
&SystemClauseType::RetractClause => clause_name!("$retract_clause"), &SystemClauseType::RetractClause => clause_name!("$retract_clause"),
&SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetBlock => clause_name!("$reset_block"),
&SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"), &SystemClauseType::ReturnFromAttributeGoals => {
clause_name!("$return_from_attribute_goals")
}
&SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"), &SystemClauseType::ReturnFromVerifyAttr => clause_name!("$return_from_verify_attr"),
&SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SetBall => clause_name!("$set_ball"),
&SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"), &SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"),
@@ -358,8 +375,12 @@ impl SystemClauseType {
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal), ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar), ("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
("$get_char", 1) => Some(SystemClauseType::GetChar), ("$get_char", 1) => Some(SystemClauseType::GetChar),
("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth), ("$truncate_if_no_lh_growth", 1) => {
("$truncate_if_no_lh_growth_diff", 2) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff), Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
}
("$truncate_if_no_lh_growth_diff", 2) => {
Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff)
}
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList), ("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
("$get_b_value", 1) => Some(SystemClauseType::GetBValue), ("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
("$get_clause", 2) => Some(SystemClauseType::GetClause), ("$get_clause", 2) => Some(SystemClauseType::GetClause),
@@ -406,8 +427,9 @@ impl SystemClauseType {
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
("$submit_query_and_print_results", 2) => ("$submit_query_and_print_results", 2) => Some(SystemClauseType::REPL(
Some(SystemClauseType::REPL(REPLCodePtr::SubmitQueryAndPrintResults)), REPLCodePtr::SubmitQueryAndPrintResults,
)),
("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo), ("$truncate_lh_to", 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
@@ -415,7 +437,7 @@ impl SystemClauseType {
("$variant", 2) => Some(SystemClauseType::Variant), ("$variant", 2) => Some(SystemClauseType::Variant),
("$write_term", 5) => Some(SystemClauseType::WriteTerm), ("$write_term", 5) => Some(SystemClauseType::WriteTerm),
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions), ("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
_ => None _ => None,
} }
} }
} }
@@ -448,7 +470,7 @@ pub enum ClauseType {
Inlined(InlinedClauseType), Inlined(InlinedClauseType),
Named(ClauseName, usize, CodeIndex), // name, arity, index. Named(ClauseName, usize, CodeIndex), // name, arity, index.
Op(ClauseName, SharedOpDesc, CodeIndex), Op(ClauseName, SharedOpDesc, CodeIndex),
System(SystemClauseType) System(SystemClauseType),
} }
impl BuiltInClauseType { impl BuiltInClauseType {
@@ -498,15 +520,13 @@ impl BuiltInClauseType {
impl ClauseType { impl ClauseType {
pub fn spec(&self) -> Option<SharedOpDesc> { pub fn spec(&self) -> Option<SharedOpDesc> {
match self { match self {
&ClauseType::Op(_, ref spec, _) => &ClauseType::Op(_, ref spec, _) => Some(spec.clone()),
Some(spec.clone()),
&ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) &ClauseType::Inlined(InlinedClauseType::CompareNumber(..))
| &ClauseType::BuiltIn(BuiltInClauseType::Is(..)) | &ClauseType::BuiltIn(BuiltInClauseType::Is(..))
| &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_)) | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_))
| &ClauseType::BuiltIn(BuiltInClauseType::NotEq) | &ClauseType::BuiltIn(BuiltInClauseType::NotEq)
| &ClauseType::BuiltIn(BuiltInClauseType::Eq) => | &ClauseType::BuiltIn(BuiltInClauseType::Eq) => Some(SharedOpDesc::new(700, XFX)),
Some(SharedOpDesc::new(700, XFX)), _ => None,
_ => None
} }
} }
@@ -523,18 +543,23 @@ impl ClauseType {
} }
pub fn from(name: ClauseName, arity: usize, spec: Option<SharedOpDesc>) -> Self { pub fn from(name: ClauseName, arity: usize, spec: Option<SharedOpDesc>) -> Self {
CLAUSE_TYPE_FORMS.borrow().get(&(name.as_str(), arity)).cloned() CLAUSE_TYPE_FORMS
.unwrap_or_else(|| .borrow()
.get(&(name.as_str(), arity))
.cloned()
.unwrap_or_else(|| {
SystemClauseType::from(name.as_str(), arity) SystemClauseType::from(name.as_str(), arity)
.map(ClauseType::System) .map(ClauseType::System)
.unwrap_or_else(|| .unwrap_or_else(|| {
if let Some(spec) = spec { if let Some(spec) = spec {
ClauseType::Op(name, spec, CodeIndex::default()) ClauseType::Op(name, spec, CodeIndex::default())
} else if name.as_str() == "call" { } else if name.as_str() == "call" {
ClauseType::CallN ClauseType::CallN
} else { } else {
ClauseType::Named(name, arity, CodeIndex::default()) ClauseType::Named(name, arity, CodeIndex::default())
})) }
})
})
} }
} }

View File

@@ -21,7 +21,7 @@ pub struct CodeGenerator<TermMarker> {
flags: MachineFlags, flags: MachineFlags,
marker: TermMarker, marker: TermMarker,
var_count: IndexMap<Rc<Var>, usize>, var_count: IndexMap<Rc<Var>, usize>,
non_counted_bt: bool non_counted_bt: bool,
} }
pub struct ConjunctInfo<'a> { pub struct ConjunctInfo<'a> {
@@ -30,10 +30,13 @@ pub struct ConjunctInfo<'a> {
pub has_deep_cut: bool, pub has_deep_cut: bool,
} }
impl<'a> ConjunctInfo<'a> impl<'a> ConjunctInfo<'a> {
{
fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self { fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self {
ConjunctInfo { perm_vs, num_of_chunks, has_deep_cut } ConjunctInfo {
perm_vs,
num_of_chunks,
has_deep_cut,
}
} }
fn allocates(&self) -> bool { fn allocates(&self) -> bool {
@@ -60,7 +63,8 @@ impl<'a> ConjunctInfo<'a>
let mut index = right_index; let mut index = right_index;
if let Line::Query(_) = &code[right_index] { if let Line::Query(_) = &code[right_index] {
while let Line::Query(_) = &code[index] { // index >= 0. while let Line::Query(_) = &code[index] {
// index >= 0.
if index == 0 { if index == 0 {
break; break;
} else { } else {
@@ -68,7 +72,8 @@ impl<'a> ConjunctInfo<'a>
} }
} }
if let Line::Query(_) = &code[index] {} else { if let Line::Query(_) = &code[index] {
} else {
index += 1; index += 1;
} }
@@ -89,21 +94,21 @@ impl<'a> ConjunctInfo<'a>
} }
} }
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
{
pub fn new(non_counted_bt: bool, flags: MachineFlags) -> Self { pub fn new(non_counted_bt: bool, flags: MachineFlags) -> Self {
CodeGenerator { marker: Allocator::new(), CodeGenerator {
marker: Allocator::new(),
var_count: IndexMap::new(), var_count: IndexMap::new(),
non_counted_bt, non_counted_bt,
flags } flags,
}
} }
pub fn take_vars(self) -> AllocVarDict { pub fn take_vars(self) -> AllocVarDict {
self.marker.take_bindings() self.marker.take_bindings()
} }
fn update_var_count<Iter: Iterator<Item=TermRef<'a>>>(&mut self, iter: Iter) fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
{
for term in iter { for term in iter {
if let TermRef::Var(_, _, var) = term { if let TermRef::Var(_, _, var) = term {
let entry = self.var_count.entry(var).or_insert(0); let entry = self.var_count.entry(var).or_insert(0);
@@ -116,10 +121,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
*self.var_count.get(var).unwrap() *self.var_count.get(var).unwrap()
} }
fn mark_non_callable(&mut self, name: Rc<Var>, arity: usize, term_loc: GenContext, fn mark_non_callable(
vr: &'a Cell<VarReg>, code: &mut Code) &mut self,
-> RegType name: Rc<Var>,
{ arity: usize,
term_loc: GenContext,
vr: &'a Cell<VarReg>,
code: &mut Code,
) -> RegType {
match self.marker.bindings().get(&name) { match self.marker.bindings().get(&name) {
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t), Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p), Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
@@ -127,7 +136,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
let mut target = Vec::new(); let mut target = Vec::new();
self.marker.reset_arg(arity); self.marker.reset_arg(arity);
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target); self.marker
.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
if !target.is_empty() { if !target.is_empty() {
for query_instr in target { for query_instr in target {
@@ -141,7 +151,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} }
fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>) fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
where Target: CompilationTarget<'a> where
Target: CompilationTarget<'a>,
{ {
if let Some(ref mut instr) = target.last_mut() { if let Some(ref mut instr) = target.last_mut() {
if Target::is_void_instr(&*instr) { if Target::is_void_instr(&*instr) {
@@ -153,36 +164,48 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
target.push(Target::to_void(1)); target.push(Target::to_void(1));
} }
fn subterm_to_instr<Target>(&mut self, fn subterm_to_instr<Target>(
&mut self,
subterm: &'a Term, subterm: &'a Term,
term_loc: GenContext, term_loc: GenContext,
is_exposed: bool, is_exposed: bool,
target: &mut Vec<Target>) target: &mut Vec<Target>,
where Target: CompilationTarget<'a> ) where
Target: CompilationTarget<'a>,
{ {
match subterm { match subterm {
&Term::AnonVar if is_exposed => &Term::AnonVar if is_exposed => {
self.marker.mark_anon_var(Level::Deep, term_loc, target), self.marker.mark_anon_var(Level::Deep, term_loc, target)
&Term::AnonVar => }
Self::add_or_increment_void_instr(target), &Term::AnonVar => Self::add_or_increment_void_instr(target),
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => { &Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _, _) => {
self.marker.mark_non_var(Level::Deep, term_loc, cell, target); self.marker
.mark_non_var(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get())); target.push(Target::clause_arg_to_instr(cell.get()));
}, }
&Term::Constant(_, ref constant) => &Term::Constant(_, ref constant) => {
target.push(Target::constant_subterm(constant.clone())), target.push(Target::constant_subterm(constant.clone()))
&Term::Var(ref cell, ref var) => }
&Term::Var(ref cell, ref var) => {
if is_exposed || self.get_var_count(var) > 1 { if is_exposed || self.get_var_count(var) > 1 {
self.marker.mark_var(var.clone(), Level::Deep, cell, term_loc, target); self.marker
.mark_var(var.clone(), Level::Deep, cell, term_loc, target);
} else { } else {
Self::add_or_increment_void_instr(target); Self::add_or_increment_void_instr(target);
} }
}
}; };
} }
fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool) fn compile_target<Target, Iter>(
-> Vec<Target> &mut self,
where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>> iter: Iter,
term_loc: GenContext,
is_exposed: bool,
) -> Vec<Target>
where
Target: CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
{ {
let mut target = Vec::new(); let mut target = Vec::new();
@@ -195,37 +218,48 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
for subterm in terms { for subterm in terms {
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target); self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
} }
}, }
TermRef::Cons(lvl, cell, head, tail) => { TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target); self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get())); target.push(Target::to_list(lvl, cell.get()));
self.subterm_to_instr(head, term_loc, is_exposed, &mut target); self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target); self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
}, }
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => { TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
self.marker.mark_non_var(lvl, term_loc, cell, &mut target); self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
target.push(Target::to_constant(lvl, constant.clone(), cell.get())); target.push(Target::to_constant(lvl, constant.clone(), cell.get()));
}, }
TermRef::AnonVar(lvl @ Level::Shallow) => TermRef::AnonVar(lvl @ Level::Shallow) => {
if let GenContext::Head = term_loc { if let GenContext::Head = term_loc {
self.marker.advance_arg(); self.marker.advance_arg();
} else { } else {
self.marker.mark_anon_var(lvl, term_loc, &mut target); self.marker.mark_anon_var(lvl, term_loc, &mut target);
}, }
}
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => { TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
if self.marker.is_unbound(var.clone()) { if self.marker.is_unbound(var.clone()) {
if term_loc != GenContext::Head { if term_loc != GenContext::Head {
self.marker.mark_reserved_var(var.clone(), lvl, cell, term_loc, self.marker.mark_reserved_var(
&mut target, perm_v!(1), false); var.clone(),
lvl,
cell,
term_loc,
&mut target,
perm_v!(1),
false,
);
continue; continue;
} }
} }
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target); self.marker
}, .mark_var(var.clone(), lvl, cell, term_loc, &mut target);
TermRef::Var(lvl @ Level::Shallow, cell, var) => }
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target), TermRef::Var(lvl @ Level::Shallow, cell, var) => {
self.marker
.mark_var(var.clone(), lvl, cell, term_loc, &mut target)
}
_ => {} _ => {}
}; };
} }
@@ -233,19 +267,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
target target
} }
fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
{
let mut vs = VariableFixtures::new(); let mut vs = VariableFixtures::new();
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() { while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
for (i, chunked_term) in chunked_terms.iter().enumerate() { for (i, chunked_term) in chunked_terms.iter().enumerate() {
let term_loc = match chunked_term { let term_loc = match chunked_term {
&ChunkedTerm::HeadClause(..) => GenContext::Head, &ChunkedTerm::HeadClause(..) => GenContext::Head,
&ChunkedTerm::BodyTerm(_) => if i < chunked_terms.len() - 1 { &ChunkedTerm::BodyTerm(_) => {
if i < chunked_terms.len() - 1 {
GenContext::Mid(chunk_num) GenContext::Mid(chunk_num)
} else { } else {
GenContext::Last(chunk_num) GenContext::Last(chunk_num)
} }
}
}; };
self.update_var_count(chunked_term.post_order_iter()); self.update_var_count(chunked_term.post_order_iter());
@@ -264,45 +299,45 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut) ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
} }
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) {
{
match qt { match qt {
&QueryTerm::Jump(ref vars) => &QueryTerm::Jump(ref vars) => code.push(jmp_call!(vars.len(), 0, pvs)),
code.push(jmp_call!(vars.len(), 0, pvs)), &QueryTerm::Clause(_, ref ct, ref terms, true) => {
&QueryTerm::Clause(_, ref ct, ref terms, true) => code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs))
code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs)), }
&QueryTerm::Clause(_, ref ct, ref terms, false) => &QueryTerm::Clause(_, ref ct, ref terms, false) => {
code.push(call_clause!(ct.clone(), terms.len(), pvs)), code.push(call_clause!(ct.clone(), terms.len(), pvs))
}
_ => {} _ => {}
} }
} }
fn lco(code: &mut Code) -> usize fn lco(code: &mut Code) -> usize {
{
let mut dealloc_index = code.len() - 1; let mut dealloc_index = code.len() - 1;
match code.last_mut() { match code.last_mut() {
Some(&mut Line::Control(ref mut ctrl)) => Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
match ctrl { &mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
&mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => *last_call = true
*last_call = true, }
&mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => &mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => *last_call = true,
*last_call = true, &mut ControlInstruction::Proceed => {}
&mut ControlInstruction::Proceed => {}, _ => dealloc_index += 1,
_ => dealloc_index += 1
}, },
Some(&mut Line::Cut(CutInstruction::Cut(_))) => Some(&mut Line::Cut(CutInstruction::Cut(_))) => dealloc_index += 1,
dealloc_index += 1,
_ => {} _ => {}
}; };
dealloc_index dealloc_index
} }
fn compile_inlined(&mut self, ct: &InlinedClauseType, terms: &'a Vec<Box<Term>>, fn compile_inlined(
term_loc: GenContext, code: &mut Code) &mut self,
-> Result<(), ParserError> ct: &InlinedClauseType,
{ terms: &'a Vec<Box<Term>>,
term_loc: GenContext,
code: &mut Code,
) -> Result<(), ParserError> {
match ct { match ct {
&InlinedClauseType::CompareNumber(cmp, ..) => { &InlinedClauseType::CompareNumber(cmp, ..) => {
if let &Term::Var(ref vr, ref name) = terms[0].as_ref() { if let &Term::Var(ref vr, ref name) = terms[0].as_ref() {
@@ -319,17 +354,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.append(&mut lcode); code.append(&mut lcode);
code.append(&mut rcode); code.append(&mut rcode);
code.push(compare_number_instr!(cmp, code.push(compare_number_instr!(
cmp,
at_1.unwrap_or(interm!(1)), at_1.unwrap_or(interm!(1)),
at_2.unwrap_or(interm!(2)))); at_2.unwrap_or(interm!(2))
}, ));
&InlinedClauseType::IsAtom(..) => }
match terms[0].as_ref() { &InlinedClauseType::IsAtom(..) => match terms[0].as_ref() {
&Term::Constant(_, Constant::Char(_)) &Term::Constant(_, Constant::Char(_))
| &Term::Constant(_, Constant::EmptyList) | &Term::Constant(_, Constant::EmptyList)
| &Term::Constant(_, Constant::Atom(..)) => { | &Term::Constant(_, Constant::Atom(..)) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atom!(r)); code.push(is_atom!(r));
@@ -338,134 +374,131 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
&InlinedClauseType::IsAtomic(..) => &InlinedClauseType::IsAtomic(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => { &Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!()); code.push(fail!());
}, }
&Term::Constant(..) => { &Term::Constant(..) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_atomic!(r)); code.push(is_atomic!(r));
} }
}, },
&InlinedClauseType::IsCompound(..) => &InlinedClauseType::IsCompound(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Clause(..) | &Term::Cons(..) => { &Term::Clause(..) | &Term::Cons(..) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_compound!(r)); code.push(is_compound!(r));
}, }
_ => { _ => {
code.push(fail!()); code.push(fail!());
} }
}, },
&InlinedClauseType::IsRational(..) => &InlinedClauseType::IsRational(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Constant(_, Constant::Rational(_)) => { &Term::Constant(_, Constant::Rational(_)) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_rational!(r)); code.push(is_rational!(r));
}, }
_ => { _ => {
code.push(fail!()); code.push(fail!());
} }
}, },
&InlinedClauseType::IsFloat(..) => &InlinedClauseType::IsFloat(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Constant(_, Constant::Float(_)) => { &Term::Constant(_, Constant::Float(_)) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_float!(r)); code.push(is_float!(r));
}, }
_ => { _ => {
code.push(fail!()); code.push(fail!());
} }
}, },
&InlinedClauseType::IsString(..) => &InlinedClauseType::IsString(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Constant(_, Constant::String(_)) => { &Term::Constant(_, Constant::String(_)) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_string!(r)); code.push(is_string!(r));
}, }
_ => { _ => {
code.push(fail!()); code.push(fail!());
} }
}, },
&InlinedClauseType::IsNonVar(..) => &InlinedClauseType::IsNonVar(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::AnonVar => { &Term::AnonVar => {
code.push(fail!()); code.push(fail!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_nonvar!(r)); code.push(is_nonvar!(r));
}, }
_ => { _ => {
code.push(succeed!()); code.push(succeed!());
} }
}, },
&InlinedClauseType::IsInteger(..) => &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Constant(_, Constant::CharCode(_)) &Term::Constant(_, Constant::CharCode(_))
| &Term::Constant(_, Constant::Integer(_)) => { | &Term::Constant(_, Constant::Integer(_)) => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_integer!(r)); code.push(is_integer!(r));
}, }
_ => { _ => {
code.push(fail!()); code.push(fail!());
}
}, },
}, &InlinedClauseType::IsVar(..) => match terms[0].as_ref() {
&InlinedClauseType::IsVar(..) =>
match terms[0].as_ref() {
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => { &Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!()); code.push(fail!());
}, }
&Term::AnonVar => { &Term::AnonVar => {
code.push(succeed!()); code.push(succeed!());
}, }
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_var!(r)); code.push(is_var!(r));
} }
}, },
&InlinedClauseType::IsPartialString(..) => &InlinedClauseType::IsPartialString(..) => match terms[0].as_ref() {
match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
code.push(is_partial_string!(r)); code.push(is_partial_string!(r));
},
_ => code.push(fail!())
} }
_ => code.push(fail!()),
},
} }
Ok(()) Ok(())
} }
fn call_arith_eval(&self, term: &'a Term, target_int: usize) -> Result<ArithCont, ArithmeticError> fn call_arith_eval(
{ &self,
term: &'a Term,
target_int: usize,
) -> Result<ArithCont, ArithmeticError> {
let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings(), target_int); let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings(), target_int);
evaluator.eval(term) evaluator.eval(term)
} }
fn compile_is_call(&mut self, terms: &'a Vec<Box<Term>>, code: &mut Code, fn compile_is_call(
term_loc: GenContext, use_default_call_policy: bool) &mut self,
-> Result<(), ParserError> terms: &'a Vec<Box<Term>>,
{ code: &mut Code,
term_loc: GenContext,
use_default_call_policy: bool,
) -> Result<(), ParserError> {
let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?; let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode); code.append(&mut acode);
@@ -474,8 +507,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
let mut target = vec![]; let mut target = vec![];
self.marker.reset_arg(2); self.marker.reset_arg(2);
self.marker.mark_var(name.clone(), Level::Shallow, vr, self.marker
term_loc, &mut target); .mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
if !target.is_empty() { if !target.is_empty() {
code.extend(target.into_iter().map(Line::Query)); code.extend(target.into_iter().map(Line::Query));
@@ -486,65 +519,88 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} else { } else {
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
} }
}, }
&Term::Constant(_, ref c @ Constant::Integer(_)) => { &Term::Constant(_, ref c @ Constant::Integer(_)) => {
code.push(Line::Query(put_constant!(Level::Shallow, c.clone(), temp_v!(1)))); code.push(Line::Query(put_constant!(
Level::Shallow,
c.clone(),
temp_v!(1)
)));
if use_default_call_policy { if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
} else { } else {
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
} }
}, }
&Term::Constant(_, ref c @ Constant::Float(_)) => { &Term::Constant(_, ref c @ Constant::Float(_)) => {
code.push(Line::Query(put_constant!(Level::Shallow, c.clone(), temp_v!(1)))); code.push(Line::Query(put_constant!(
Level::Shallow,
c.clone(),
temp_v!(1)
)));
if use_default_call_policy { if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
} else { } else {
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
} }
}, }
&Term::Constant(_, ref c @ Constant::Rational(_)) => { &Term::Constant(_, ref c @ Constant::Rational(_)) => {
code.push(Line::Query(put_constant!(Level::Shallow, c.clone(), temp_v!(1)))); code.push(Line::Query(put_constant!(
Level::Shallow,
c.clone(),
temp_v!(1)
)));
if use_default_call_policy { if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
} else { } else {
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))))
} }
}, }
_ => code.push(fail!()) _ => code.push(fail!()),
}) })
} }
#[inline] #[inline]
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
{
let r = self.marker.get(Rc::new(String::from("!"))); let r = self.marker.get(Rc::new(String::from("!")));
cell.set(VarReg::Norm(r)); cell.set(VarReg::Norm(r));
code.push(set_cp!(cell.get().norm())); code.push(set_cp!(cell.get().norm()));
} }
fn compile_get_level_and_unify(&mut self, code: &mut Code, cell: &'a Cell<VarReg>, fn compile_get_level_and_unify(
var: Rc<Var>, term_loc: GenContext) &mut self,
{ code: &mut Code,
cell: &'a Cell<VarReg>,
var: Rc<Var>,
term_loc: GenContext,
) {
let mut target = Vec::new(); let mut target = Vec::new();
self.marker.reset_arg(1); self.marker.reset_arg(1);
self.marker.mark_var(var, Level::Shallow, cell, term_loc, &mut target); self.marker
.mark_var(var, Level::Shallow, cell, term_loc, &mut target);
if !target.is_empty() { if !target.is_empty() {
code.extend(target.into_iter().map(|query_instr| Line::Query(query_instr))); code.extend(
target
.into_iter()
.map(|query_instr| Line::Query(query_instr)),
);
} }
code.push(get_level_and_unify!(cell.get().norm())); code.push(get_level_and_unify!(cell.get().norm()));
} }
fn compile_seq(&mut self, iter: ChunkedIterator<'a>, conjunct_info: &ConjunctInfo<'a>, fn compile_seq(
code: &mut Code, is_exposed: bool) &mut self,
-> Result<(), ParserError> iter: ChunkedIterator<'a>,
{ conjunct_info: &ConjunctInfo<'a>,
code: &mut Code,
is_exposed: bool,
) -> Result<(), ParserError> {
for (chunk_num, _, terms) in iter.rule_body_iter() { for (chunk_num, _, terms) in iter.rule_body_iter() {
for (i, term) in terms.iter().enumerate() { for (i, term) in terms.iter().enumerate() {
let term_loc = if i + 1 < terms.len() { let term_loc = if i + 1 < terms.len() {
@@ -554,21 +610,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
}; };
match *term { match *term {
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => &QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
self.compile_get_level_and_unify(code, cell, var.clone(), term_loc), self.compile_get_level_and_unify(code, cell, var.clone(), term_loc)
&QueryTerm::UnblockedCut(ref cell) => }
self.compile_unblocked_cut(code, cell), &QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
&QueryTerm::BlockedCut => &QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut) Line::Cut(CutInstruction::NeckCut)
} else { } else {
Line::Cut(CutInstruction::Cut(perm_v!(1))) Line::Cut(CutInstruction::Cut(perm_v!(1)))
}), }),
&QueryTerm::Clause(_, ClauseType::BuiltIn(BuiltInClauseType::Is(..)), &QueryTerm::Clause(
ref terms, use_default_call_policy) _,
=> self.compile_is_call(terms, code, term_loc, use_default_call_policy)?, ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) ref terms,
=> self.compile_inlined(ct, terms, term_loc, code)?, use_default_call_policy,
) => self.compile_is_call(terms, code, term_loc, use_default_call_policy)?,
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
self.compile_inlined(ct, terms, term_loc, code)?
}
_ => { _ => {
let num_perm_vars = if chunk_num == 0 { let num_perm_vars = if chunk_num == 0 {
conjunct_info.perm_vars() conjunct_info.perm_vars()
@@ -577,7 +636,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
}; };
self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed); self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
}, }
} }
} }
@@ -587,8 +646,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
Ok(()) Ok(())
} }
fn compile_seq_prelude(&mut self, conjunct_info: &ConjunctInfo, body: &mut Code) fn compile_seq_prelude(&mut self, conjunct_info: &ConjunctInfo, body: &mut Code) {
{
if conjunct_info.allocates() { if conjunct_info.allocates() {
let perm_vars = conjunct_info.perm_vars(); let perm_vars = conjunct_info.perm_vars();
@@ -600,8 +658,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} }
} }
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) {
{
// add a proceed to bookend any trailing cuts. // add a proceed to bookend any trailing cuts.
match toc { match toc {
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()), &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
@@ -617,12 +674,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} }
} }
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, ParserError> pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Result<Code, ParserError> {
{
let iter = ChunkedIterator::from_rule(rule); let iter = ChunkedIterator::from_rule(rule);
let conjunct_info = self.collect_var_data(iter); let conjunct_info = self.collect_var_data(iter);
let &Rule { head: (_, ref args, ref p1), ref clauses } = rule; let &Rule {
head: (_, ref args, ref p1),
ref clauses,
} = rule;
let mut code = Vec::new(); let mut code = Vec::new();
self.marker.reset_at_head(args); self.marker.reset_at_head(args);
@@ -652,8 +711,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
Ok(code) Ok(code)
} }
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
{
let mut unsafe_vars = IndexMap::new(); let mut unsafe_vars = IndexMap::new();
for var_status in self.marker.bindings().values() { for var_status in self.marker.bindings().values() {
@@ -662,17 +720,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
for fact_instr in fact.iter_mut() { for fact_instr in fact.iter_mut() {
match fact_instr { match fact_instr {
&mut FactInstruction::UnifyValue(reg) => &mut FactInstruction::UnifyValue(reg) => {
if let Some(found) = unsafe_vars.get_mut(&reg) { if let Some(found) = unsafe_vars.get_mut(&reg) {
if !*found { if !*found {
*found = true; *found = true;
*fact_instr = FactInstruction::UnifyLocalValue(reg); *fact_instr = FactInstruction::UnifyLocalValue(reg);
} }
}, }
&mut FactInstruction::UnifyVariable(reg) => }
&mut FactInstruction::UnifyVariable(reg) => {
if let Some(found) = unsafe_vars.get_mut(&reg) { if let Some(found) = unsafe_vars.get_mut(&reg) {
*found = true; *found = true;
}, }
}
_ => {} _ => {}
}; };
} }
@@ -680,8 +740,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
UnsafeVarMarker { unsafe_vars } UnsafeVarMarker { unsafe_vars }
} }
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code {
{
self.update_var_count(post_order_iter(term)); self.update_var_count(post_order_iter(term));
let mut vs = VariableFixtures::new(); let mut vs = VariableFixtures::new();
@@ -711,9 +770,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code code
} }
fn compile_query_line(&mut self, term: &'a QueryTerm, term_loc: GenContext, fn compile_query_line(
code: &mut Code, num_perm_vars_left: usize, is_exposed: bool) &mut self,
{ term: &'a QueryTerm,
term_loc: GenContext,
code: &mut Code,
num_perm_vars_left: usize,
is_exposed: bool,
) {
self.marker.reset_arg(term.arity()); self.marker.reset_arg(term.arity());
let iter = query_term_post_order_iter(term); let iter = query_term_post_order_iter(term);
@@ -728,8 +792,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
Self::add_conditional_call(code, term, num_perm_vars_left); Self::add_conditional_call(code, term, num_perm_vars_left);
} }
pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, ParserError> pub fn compile_query(&mut self, query: &'a Vec<QueryTerm>) -> Result<Code, ParserError> {
{
let iter = ChunkedIterator::from_term_sequence(query); let iter = ChunkedIterator::from_term_sequence(query);
let conjunct_info = self.collect_var_data(iter); let conjunct_info = self.collect_var_data(iter);
@@ -750,8 +813,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
Ok(code) Ok(code)
} }
fn split_predicate(clauses: &Vec<PredicateClause>) -> Vec<(usize, usize)> fn split_predicate(clauses: &Vec<PredicateClause>) -> Vec<(usize, usize)> {
{
let mut subseqs = Vec::new(); let mut subseqs = Vec::new();
let mut left_index = 0; let mut left_index = 0;
@@ -764,7 +826,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
subseqs.push((right_index, right_index + 1)); subseqs.push((right_index, right_index + 1));
left_index = right_index + 1; left_index = right_index + 1;
}, }
_ => {} _ => {}
} }
} }
@@ -792,9 +854,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} }
} }
fn compile_pred_subseq<'b: 'a>(&mut self, clauses: &'b [PredicateClause]) fn compile_pred_subseq<'b: 'a>(
-> Result<Code, ParserError> &mut self,
{ clauses: &'b [PredicateClause],
) -> Result<Code, ParserError> {
let mut code_body = Vec::new(); let mut code_body = Vec::new();
let mut code_offsets = CodeOffsets::new(self.flags); let mut code_offsets = CodeOffsets::new(self.flags);
@@ -804,17 +867,15 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
self.marker.reset(); self.marker.reset();
let mut clause_code = match clause { let mut clause_code = match clause {
&PredicateClause::Fact(ref fact) => &PredicateClause::Fact(ref fact) => self.compile_fact(fact),
self.compile_fact(fact), &PredicateClause::Rule(ref rule) => try!(self.compile_rule(rule)),
&PredicateClause::Rule(ref rule) =>
try!(self.compile_rule(rule))
}; };
if num_clauses > 1 { if num_clauses > 1 {
let choice = match i { let choice = match i {
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1), 0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
_ if i == num_clauses - 1 => self.trust_me(), _ if i == num_clauses - 1 => self.trust_me(),
_ => self.retry_me_else(clause_code.len() + 1) _ => self.retry_me_else(clause_code.len() + 1),
}; };
code_body.push(Line::Choice(choice)); code_body.push(Line::Choice(choice));
@@ -834,9 +895,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
Ok(code) Ok(code)
} }
pub fn compile_predicate<'b: 'a>(&mut self, clauses: &'b Vec<PredicateClause>) pub fn compile_predicate<'b: 'a>(
-> Result<Code, ParserError> &mut self,
{ clauses: &'b Vec<PredicateClause>,
) -> Result<Code, ParserError> {
let mut code = Vec::new(); let mut code = Vec::new();
let split_pred = Self::split_predicate(&clauses); let split_pred = Self::split_predicate(&clauses);
let multi_seq = split_pred.len() > 1; let multi_seq = split_pred.len() > 1;
@@ -848,7 +910,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
let choice = match l { let choice = match l {
0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1), 0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
_ if r == clauses.len() => self.trust_me(), _ if r == clauses.len() => self.trust_me(),
_ => self.retry_me_else(code_segment.len() + 1) _ => self.retry_me_else(code_segment.len() + 1),
}; };
code.push(Line::Choice(choice)); code.push(Line::Choice(choice));

View File

@@ -3,8 +3,8 @@ use indexmap::IndexMap;
use prolog_parser::ast::*; use prolog_parser::ast::*;
use prolog::allocator::*; use prolog::allocator::*;
use prolog::forms::*;
use prolog::fixtures::*; use prolog::fixtures::*;
use prolog::forms::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use prolog::targets::*; use prolog::targets::*;
@@ -25,16 +25,14 @@ impl DebrayAllocator {
fn is_curr_arg_distinct_from(&self, var: &Var) -> bool { fn is_curr_arg_distinct_from(&self, var: &Var) -> bool {
match self.contents.get(&self.arg_c) { match self.contents.get(&self.arg_c) {
Some(t_var) if **t_var != *var => true, Some(t_var) if **t_var != *var => true,
_ => false _ => false,
} }
} }
fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool {
{
match self.bindings.get(var).unwrap() { match self.bindings.get(var).unwrap() {
&VarData::Temp(_, _, ref tvd) => &VarData::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)),
tvd.use_set.contains(&(GenContext::Head, r)), _ => false,
_ => false
} }
} }
@@ -44,8 +42,7 @@ impl DebrayAllocator {
in_use_range || self.in_use.contains(&r) in_use_range || self.in_use.contains(&r)
} }
fn alloc_with_cr(&self, var: &Var) -> usize fn alloc_with_cr(&self, var: &Var) -> usize {
{
match self.bindings.get(var) { match self.bindings.get(var) {
Some(&VarData::Temp(_, _, ref tvd)) => { Some(&VarData::Temp(_, _, ref tvd)) => {
for &(_, reg) in tvd.use_set.iter() { for &(_, reg) in tvd.use_set.iter() {
@@ -66,13 +63,12 @@ impl DebrayAllocator {
} }
result result
}, }
_ => 0 _ => 0,
} }
} }
fn alloc_with_ca(&self, var: &Var) -> usize fn alloc_with_ca(&self, var: &Var) -> usize {
{
match self.bindings.get(var) { match self.bindings.get(var) {
Some(&VarData::Temp(_, _, ref tvd)) => { Some(&VarData::Temp(_, _, ref tvd)) => {
for &(_, reg) in tvd.use_set.iter() { for &(_, reg) in tvd.use_set.iter() {
@@ -95,13 +91,12 @@ impl DebrayAllocator {
} }
result result
}, }
_ => 0 _ => 0,
} }
} }
fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Rc<Var>, usize)> fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Rc<Var>, usize)> {
{
// we want to allocate a register to the k^{th} parameter, par_k. // we want to allocate a register to the k^{th} parameter, par_k.
// par_k may not be a temporary variable. // par_k may not be a temporary variable.
let k = self.arg_c; let k = self.arg_c;
@@ -121,13 +116,14 @@ impl DebrayAllocator {
} }
None None
}, }
_ => None _ => None,
} }
} }
fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Target>) fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Target>)
where Target: CompilationTarget<'a> where
Target: CompilationTarget<'a>,
{ {
match self.alloc_in_last_goal_hint(chunk_num) { match self.alloc_in_last_goal_hint(chunk_num) {
Some((var, r)) => { Some((var, r)) => {
@@ -144,27 +140,32 @@ impl DebrayAllocator {
self.record_register(var, r); self.record_register(var, r);
self.in_use.insert(r.reg_num()); self.in_use.insert(r.reg_num());
} }
}, }
_ => {} _ => {}
}; };
} }
fn alloc_reg_to_var<'a, Target>(&mut self, var: &Var, lvl: Level, term_loc: GenContext, fn alloc_reg_to_var<'a, Target>(
target: &mut Vec<Target>) &mut self,
-> usize var: &Var,
where Target: CompilationTarget<'a> lvl: Level,
term_loc: GenContext,
target: &mut Vec<Target>,
) -> usize
where
Target: CompilationTarget<'a>,
{ {
match term_loc { match term_loc {
GenContext::Head => GenContext::Head => {
if let Level::Shallow = lvl { if let Level::Shallow = lvl {
self.evacuate_arg(0, target); self.evacuate_arg(0, target);
self.alloc_with_cr(var) self.alloc_with_cr(var)
} else { } else {
self.alloc_with_ca(var) self.alloc_with_ca(var)
}, }
GenContext::Mid(_) => }
self.alloc_with_ca(var), GenContext::Mid(_) => self.alloc_with_ca(var),
GenContext::Last(chunk_num) => GenContext::Last(chunk_num) => {
if let Level::Shallow = lvl { if let Level::Shallow = lvl {
self.evacuate_arg(chunk_num, target); self.evacuate_arg(chunk_num, target);
self.alloc_with_cr(var) self.alloc_with_cr(var)
@@ -173,9 +174,9 @@ impl DebrayAllocator {
} }
} }
} }
}
fn alloc_reg_to_non_var(&mut self) -> usize fn alloc_reg_to_non_var(&mut self) -> usize {
{
let mut final_index = 0; let mut final_index = 0;
for index in self.temp_lb.. { for index in self.temp_lb.. {
@@ -190,20 +191,18 @@ impl DebrayAllocator {
final_index final_index
} }
fn in_place(&self, var: &Var, term_loc: GenContext, r: RegType, k: usize) -> bool fn in_place(&self, var: &Var, term_loc: GenContext, r: RegType, k: usize) -> bool {
{
match term_loc { match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k, GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => match self.bindings().get(var).unwrap() { _ => match self.bindings().get(var).unwrap() {
&VarData::Temp(_, o, _) if r.reg_num() == k => o == k, &VarData::Temp(_, o, _) if r.reg_num() == k => o == k,
_ => false _ => false,
} },
} }
} }
} }
impl<'a> Allocator<'a> for DebrayAllocator impl<'a> Allocator<'a> for DebrayAllocator {
{
fn new() -> DebrayAllocator { fn new() -> DebrayAllocator {
DebrayAllocator { DebrayAllocator {
arity: 0, arity: 0,
@@ -211,12 +210,13 @@ impl<'a> Allocator<'a> for DebrayAllocator
temp_lb: 1, temp_lb: 1,
bindings: IndexMap::new(), bindings: IndexMap::new(),
contents: IndexMap::new(), contents: IndexMap::new(),
in_use: BTreeSet::new() in_use: BTreeSet::new(),
} }
} }
fn mark_anon_var<Target>(&mut self, lvl: Level, term_loc: GenContext, target: &mut Vec<Target>) fn mark_anon_var<Target>(&mut self, lvl: Level, term_loc: GenContext, target: &mut Vec<Target>)
where Target: CompilationTarget<'a> where
Target: CompilationTarget<'a>,
{ {
let r = RegType::Temp(self.alloc_reg_to_non_var()); let r = RegType::Temp(self.alloc_reg_to_non_var());
@@ -236,9 +236,14 @@ impl<'a> Allocator<'a> for DebrayAllocator
}; };
} }
fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext, fn mark_non_var<Target>(
cell: &Cell<RegType>, target: &mut Vec<Target>) &mut self,
where Target: CompilationTarget<'a> lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>,
) where
Target: CompilationTarget<'a>,
{ {
let r = cell.get(); let r = cell.get();
@@ -252,7 +257,7 @@ impl<'a> Allocator<'a> for DebrayAllocator
self.arg_c += 1; self.arg_c += 1;
RegType::Temp(k) RegType::Temp(k)
}, }
_ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()), _ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()),
_ => { _ => {
self.in_use.insert(r.reg_num()); self.in_use.insert(r.reg_num());
@@ -263,9 +268,15 @@ impl<'a> Allocator<'a> for DebrayAllocator
cell.set(r); cell.set(r);
} }
fn mark_var<Target>(&mut self, var: Rc<Var>, lvl: Level, cell: &'a Cell<VarReg>, fn mark_var<Target>(
term_loc: GenContext, target: &mut Vec<Target>) &mut self,
where Target: CompilationTarget<'a> var: Rc<Var>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>,
) where
Target: CompilationTarget<'a>,
{ {
let (r, is_new_var) = match self.get(var.clone()) { let (r, is_new_var) = match self.get(var.clone()) {
RegType::Temp(0) => { RegType::Temp(0) => {
@@ -274,23 +285,30 @@ impl<'a> Allocator<'a> for DebrayAllocator
cell.set(VarReg::Norm(RegType::Temp(o))); cell.set(VarReg::Norm(RegType::Temp(o)));
(RegType::Temp(o), true) (RegType::Temp(o), true)
}, }
RegType::Perm(0) => { RegType::Perm(0) => {
let pr = cell.get().norm(); let pr = cell.get().norm();
self.record_register(var.clone(), pr); self.record_register(var.clone(), pr);
(pr, true) (pr, true)
}, }
r => (r, false) r => (r, false),
}; };
self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var); self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var);
} }
fn mark_reserved_var<Target>(&mut self, var: Rc<Var>, lvl: Level, cell: &'a Cell<VarReg>, fn mark_reserved_var<Target>(
term_loc: GenContext, target: &mut Vec<Target>, r: RegType, &mut self,
is_new_var: bool) var: Rc<Var>,
where Target: CompilationTarget<'a> lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>,
r: RegType,
is_new_var: bool,
) where
Target: CompilationTarget<'a>,
{ {
match lvl { match lvl {
Level::Root | Level::Shallow => { Level::Root | Level::Shallow => {
@@ -311,8 +329,8 @@ impl<'a> Allocator<'a> for DebrayAllocator
target.push(Target::argument_to_value(r, k)); target.push(Target::argument_to_value(r, k));
} }
} }
}, }
Level::Deep if is_new_var => Level::Deep if is_new_var => {
if let GenContext::Head = term_loc { if let GenContext::Head = term_loc {
if self.occurs_shallowly_in_head(&var, r.reg_num()) { if self.occurs_shallowly_in_head(&var, r.reg_num()) {
target.push(Target::subterm_to_value(r)); target.push(Target::subterm_to_value(r));
@@ -321,9 +339,9 @@ impl<'a> Allocator<'a> for DebrayAllocator
} }
} else { } else {
target.push(Target::subterm_to_variable(r)); target.push(Target::subterm_to_variable(r));
}, }
Level::Deep => }
target.push(Target::subterm_to_value(r)) Level::Deep => target.push(Target::subterm_to_value(r)),
}; };
if !r.is_perm() { if !r.is_perm() {

View File

@@ -7,15 +7,16 @@ use prolog::iterators::*;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::cell::Cell; use std::cell::Cell;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::{IntoIter, IterMut, Values}; use std::collections::btree_map::{IntoIter, IterMut, Values};
use std::collections::{BTreeMap, BTreeSet};
use std::mem::swap; use std::mem::swap;
use std::rc::Rc; use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
// labeled with chunk numbers. // labeled with chunk numbers.
pub enum VarStatus { pub enum VarStatus {
Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) Perm(usize),
Temp(usize, TempVarData), // Perm(chunk_num) | Temp(chunk_num, _)
} }
pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; pub type OccurrenceSet = BTreeSet<(GenContext, usize)>;
@@ -23,14 +24,15 @@ pub type OccurrenceSet = BTreeSet<(GenContext, usize)>;
// Perm: 0 initially, a stack register once processed. // Perm: 0 initially, a stack register once processed.
// Temp: labeled with chunk_num and temp offset (unassigned if 0). // Temp: labeled with chunk_num and temp offset (unassigned if 0).
pub enum VarData { pub enum VarData {
Perm(usize), Temp(usize, usize, TempVarData) Perm(usize),
Temp(usize, usize, TempVarData),
} }
impl VarData { impl VarData {
pub fn as_reg_type(&self) -> RegType { pub fn as_reg_type(&self) -> RegType {
match self { match self {
&VarData::Temp(_, r, _) => RegType::Temp(r), &VarData::Temp(_, r, _) => RegType::Temp(r),
&VarData::Perm(r) => RegType::Perm(r) &VarData::Perm(r) => RegType::Perm(r),
} }
} }
} }
@@ -39,7 +41,7 @@ pub struct TempVarData {
pub last_term_arity: usize, pub last_term_arity: usize,
pub use_set: OccurrenceSet, pub use_set: OccurrenceSet,
pub no_use_set: BTreeSet<usize>, pub no_use_set: BTreeSet<usize>,
pub conflict_set: BTreeSet<usize> pub conflict_set: BTreeSet<usize>,
} }
impl TempVarData { impl TempVarData {
@@ -48,7 +50,7 @@ impl TempVarData {
last_term_arity: last_term_arity, last_term_arity: last_term_arity,
use_set: BTreeSet::new(), use_set: BTreeSet::new(),
no_use_set: BTreeSet::new(), no_use_set: BTreeSet::new(),
conflict_set: BTreeSet::new() conflict_set: BTreeSet::new(),
} }
} }
@@ -79,8 +81,7 @@ impl TempVarData {
type VariableFixture<'a> = (VarStatus, Vec<&'a Cell<VarReg>>); type VariableFixture<'a> = (VarStatus, Vec<&'a Cell<VarReg>>);
pub struct VariableFixtures<'a>(BTreeMap<Rc<Var>, VariableFixture<'a>>); pub struct VariableFixtures<'a>(BTreeMap<Rc<Var>, VariableFixture<'a>>);
impl<'a> VariableFixtures<'a> impl<'a> VariableFixtures<'a> {
{
pub fn new() -> Self { pub fn new() -> Self {
VariableFixtures(BTreeMap::new()) VariableFixtures(BTreeMap::new())
} }
@@ -90,8 +91,7 @@ impl<'a> VariableFixtures<'a>
} }
// computes no_use and conflict sets for all temp vars. // computes no_use and conflict sets for all temp vars.
pub fn populate_restricting_sets(&mut self) pub fn populate_restricting_sets(&mut self) {
{
// three stages: // three stages:
// 1. move the use sets of each variable to a local IndexMap, use_set // 1. move the use sets of each variable to a local IndexMap, use_set
// (iterate mutably, swap mutable refs). // (iterate mutably, swap mutable refs).
@@ -133,7 +133,7 @@ impl<'a> VariableFixtures<'a>
&mut (VarStatus::Temp(_, ref mut u_data), _) => { &mut (VarStatus::Temp(_, ref mut u_data), _) => {
u_data.use_set = use_set; u_data.use_set = use_set;
u_data.populate_conflict_set(); u_data.populate_conflict_set();
}, }
_ => {} _ => {}
}; };
} }
@@ -147,21 +147,16 @@ impl<'a> VariableFixtures<'a>
self.0.iter_mut() self.0.iter_mut()
} }
fn record_temp_info(&mut self, fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) {
tvd: &mut TempVarData,
arg_c: usize,
term_loc: GenContext)
{
match term_loc { match term_loc {
GenContext::Head | GenContext::Last(_) => { GenContext::Head | GenContext::Last(_) => {
tvd.use_set.insert((term_loc, arg_c)); tvd.use_set.insert((term_loc, arg_c));
}, }
_ => {} _ => {}
}; };
} }
pub fn vars_above_threshold(&self, index: usize) -> usize pub fn vars_above_threshold(&self, index: usize) -> usize {
{
let mut var_count = 0; let mut var_count = 0;
for &(ref var_status, _) in self.values() { for &(ref var_status, _) in self.values() {
@@ -176,25 +171,28 @@ impl<'a> VariableFixtures<'a>
} }
pub fn mark_vars_in_chunk<I>(&mut self, iter: I, lt_arity: usize, term_loc: GenContext) pub fn mark_vars_in_chunk<I>(&mut self, iter: I, lt_arity: usize, term_loc: GenContext)
where I: Iterator<Item=TermRef<'a>> where
I: Iterator<Item = TermRef<'a>>,
{ {
let chunk_num = term_loc.chunk_num(); let chunk_num = term_loc.chunk_num();
let mut arg_c = 1; let mut arg_c = 1;
for term_ref in iter { for term_ref in iter {
if let &TermRef::Var(lvl, cell, ref var) = &term_ref { if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
let mut status = self.0.remove(var) let mut status = self.0.remove(var).unwrap_or((
.unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)),
Vec::new())); Vec::new(),
));
status.1.push(cell); status.1.push(cell);
match status.0 { match status.0 {
VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => {
if let Level::Shallow = lvl { if let Level::Shallow = lvl {
self.record_temp_info(tvd, arg_c, term_loc); self.record_temp_info(tvd, arg_c, term_loc);
}, }
_ => status.0 = VarStatus::Perm(chunk_num) }
_ => status.0 = VarStatus::Perm(chunk_num),
}; };
self.0.insert(var.clone(), status); self.0.insert(var.clone(), status);
@@ -218,14 +216,12 @@ impl<'a> VariableFixtures<'a>
self.0.len() self.0.len()
} }
pub fn set_perm_vals(&self, has_deep_cuts: bool) pub fn set_perm_vals(&self, has_deep_cuts: bool) {
{ let mut values_vec: Vec<_> = self
let mut values_vec : Vec<_> = self.values() .values()
.filter_map(|ref v| { .filter_map(|ref v| match &v.0 {
match &v.0 {
&VarStatus::Perm(i) => Some((i, &v.1)), &VarStatus::Perm(i) => Some((i, &v.1)),
_ => None _ => None,
}
}) })
.collect(); .collect();
@@ -242,13 +238,13 @@ impl<'a> VariableFixtures<'a>
} }
pub struct UnsafeVarMarker { pub struct UnsafeVarMarker {
pub unsafe_vars: IndexMap<RegType, bool> pub unsafe_vars: IndexMap<RegType, bool>,
} }
impl UnsafeVarMarker { impl UnsafeVarMarker {
pub fn new() -> Self { pub fn new() -> Self {
UnsafeVarMarker { UnsafeVarMarker {
unsafe_vars: IndexMap::new() unsafe_vars: IndexMap::new(),
} }
} }
@@ -264,35 +260,38 @@ impl UnsafeVarMarker {
pub fn mark_safe_vars(&mut self, query_instr: &mut QueryInstruction) { pub fn mark_safe_vars(&mut self, query_instr: &mut QueryInstruction) {
match query_instr { match query_instr {
&mut QueryInstruction::PutVariable(RegType::Temp(r), _) => &mut QueryInstruction::PutVariable(RegType::Temp(r), _) => {
if let Some(found) = self.unsafe_vars.get_mut(&RegType::Temp(r)) { if let Some(found) = self.unsafe_vars.get_mut(&RegType::Temp(r)) {
*found = true; *found = true;
}, }
&mut QueryInstruction::SetVariable(reg) => }
&mut QueryInstruction::SetVariable(reg) => {
if let Some(found) = self.unsafe_vars.get_mut(&reg) { if let Some(found) = self.unsafe_vars.get_mut(&reg) {
*found = true; *found = true;
}, }
}
_ => {} _ => {}
} }
} }
pub fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction) pub fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction) {
{
match query_instr { match query_instr {
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) => &mut QueryInstruction::PutValue(RegType::Perm(i), arg) => {
if let Some(found) = self.unsafe_vars.get_mut(&RegType::Perm(i)) { if let Some(found) = self.unsafe_vars.get_mut(&RegType::Perm(i)) {
if !*found { if !*found {
*found = true; *found = true;
*query_instr = QueryInstruction::PutUnsafeValue(i, arg); *query_instr = QueryInstruction::PutUnsafeValue(i, arg);
} }
}, }
&mut QueryInstruction::SetValue(reg) => }
&mut QueryInstruction::SetValue(reg) => {
if let Some(found) = self.unsafe_vars.get_mut(&reg) { if let Some(found) = self.unsafe_vars.get_mut(&reg) {
if !*found { if !*found {
*found = true; *found = true;
*query_instr = QueryInstruction::SetLocalValue(reg); *query_instr = QueryInstruction::SetLocalValue(reg);
} }
}, }
}
_ => {} _ => {}
} }
} }

View File

@@ -34,11 +34,9 @@ impl TopLevel {
match self { match self {
&TopLevel::Declaration(_) => None, &TopLevel::Declaration(_) => None,
&TopLevel::Fact(ref term) => term.name(), &TopLevel::Fact(ref term) => term.name(),
&TopLevel::Predicate(ref clauses) => &TopLevel::Predicate(ref clauses) => clauses.0.first().and_then(|ref term| term.name()),
clauses.0.first().and_then(|ref term| term.name()),
&TopLevel::Query(_) => None, &TopLevel::Query(_) => None,
&TopLevel::Rule(Rule { ref head, .. }) => &TopLevel::Rule(Rule { ref head, .. }) => Some(head.0.clone()),
Some(head.0.clone())
} }
} }
@@ -46,33 +44,34 @@ impl TopLevel {
match self { match self {
&TopLevel::Declaration(_) => 0, &TopLevel::Declaration(_) => 0,
&TopLevel::Fact(ref term) => term.arity(), &TopLevel::Fact(ref term) => term.arity(),
&TopLevel::Predicate(ref clauses) => &TopLevel::Predicate(ref clauses) => clauses.0.first().map(|t| t.arity()).unwrap_or(0),
clauses.0.first().map(|t| t.arity()).unwrap_or(0),
&TopLevel::Query(_) => 0, &TopLevel::Query(_) => 0,
&TopLevel::Rule(Rule { ref head, .. }) => head.1.len() &TopLevel::Rule(Rule { ref head, .. }) => head.1.len(),
} }
} }
pub fn is_end_of_file_atom(&self) -> bool { pub fn is_end_of_file_atom(&self) -> bool {
match self { match self {
&TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _))) => &TopLevel::Fact(Term::Constant(_, Constant::Atom(ref name, _))) => {
return name.as_str() == "end_of_file", return name.as_str() == "end_of_file"
_ => }
false _ => false,
} }
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum Level { pub enum Level {
Deep, Root, Shallow Deep,
Root,
Shallow,
} }
impl Level { impl Level {
pub fn child_level(self) -> Level { pub fn child_level(self) -> Level {
match self { match self {
Level::Root => Level::Shallow, Level::Root => Level::Shallow,
_ => Level::Deep _ => Level::Deep,
} }
} }
} }
@@ -84,7 +83,7 @@ pub enum QueryTerm {
BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
UnblockedCut(Cell<VarReg>), UnblockedCut(Cell<VarReg>),
GetLevelAndUnify(Cell<VarReg>, Rc<Var>), GetLevelAndUnify(Cell<VarReg>, Rc<Var>),
Jump(JumpStub) Jump(JumpStub),
} }
impl QueryTerm { impl QueryTerm {
@@ -108,7 +107,7 @@ impl QueryTerm {
#[derive(Clone)] #[derive(Clone)]
pub struct Rule { pub struct Rule {
pub head: (ClauseName, Vec<Box<Term>>, QueryTerm), pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
pub clauses: Vec<QueryTerm> pub clauses: Vec<QueryTerm>,
} }
#[derive(Clone)] #[derive(Clone)]
@@ -127,7 +126,8 @@ impl Predicate {
#[inline] #[inline]
pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> { pub fn predicate_indicator(&self) -> Option<(ClauseName, usize)> {
self.0.first() self.0
.first()
.and_then(|clause| clause.name().map(|name| (name, clause.arity()))) .and_then(|clause| clause.name().map(|name| (name, clause.arity())))
} }
} }
@@ -137,7 +137,7 @@ pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
#[derive(Clone)] #[derive(Clone)]
pub enum PredicateClause { pub enum PredicateClause {
Fact(Term), Fact(Term),
Rule(Rule) Rule(Rule),
} }
impl PredicateClause { impl PredicateClause {
@@ -151,7 +151,7 @@ impl PredicateClause {
pub fn arity(&self) -> usize { pub fn arity(&self) -> usize {
match self { match self {
&PredicateClause::Fact(ref term) => term.arity(), &PredicateClause::Fact(ref term) => term.arity(),
&PredicateClause::Rule(ref rule) => rule.head.1.len() &PredicateClause::Rule(ref rule) => rule.head.1.len(),
} }
} }
@@ -166,7 +166,7 @@ impl PredicateClause {
#[derive(Clone)] #[derive(Clone)]
pub enum ModuleSource { pub enum ModuleSource {
Library(ClauseName), Library(ClauseName),
File(ClauseName) File(ClauseName),
} }
#[derive(Clone)] #[derive(Clone)]
@@ -178,18 +178,26 @@ pub enum Declaration {
NonCountedBacktracking(ClauseName, usize), // name, arity NonCountedBacktracking(ClauseName, usize), // name, arity
Op(OpDecl), Op(OpDecl),
UseModule(ModuleSource), UseModule(ModuleSource),
UseQualifiedModule(ModuleSource, Vec<PredicateKey>) UseQualifiedModule(ModuleSource, Vec<PredicateKey>),
} }
impl Declaration { impl Declaration {
#[inline] #[inline]
pub fn is_module_decl(&self) -> bool { pub fn is_module_decl(&self) -> bool {
if let &Declaration::Module(_) = self { true } else { false } if let &Declaration::Module(_) = self {
true
} else {
false
}
} }
#[inline] #[inline]
pub fn is_end_of_file(&self) -> bool { pub fn is_end_of_file(&self) -> bool {
if let &Declaration::EndOfFile = self { true } else { false } if let &Declaration::EndOfFile = self {
true
} else {
false
}
} }
} }
@@ -207,15 +215,14 @@ impl OpDecl {
self.insert_into_op_dir(clause_name!(""), op_dir, 0); self.insert_into_op_dir(clause_name!(""), op_dir, 0);
} }
fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) fn insert_into_op_dir(&self, module: ClauseName, op_dir: &mut OpDir, prec: usize) {
{
let (spec, name) = (self.1, self.2.clone()); let (spec, name) = (self.1, self.2.clone());
let fixity = match spec { let fixity = match spec {
XFY | XFX | YFX => Fixity::In, XFY | XFX | YFX => Fixity::In,
XF | YF => Fixity::Post, XF | YF => Fixity::Post,
FX | FY => Fixity::Pre, FX | FY => Fixity::Pre,
_ => return _ => return,
}; };
match op_dir.get(&(name.clone(), fixity)) { match op_dir.get(&(name.clone(), fixity)) {
@@ -229,9 +236,12 @@ impl OpDecl {
op_dir.insert((name, fixity), OpDirValue::new(spec, prec, module)); op_dir.insert((name, fixity), OpDirValue::new(spec, prec, module));
} }
pub fn submit(&self, module: ClauseName, existing_desc: Option<OpDesc>, op_dir: &mut OpDir) pub fn submit(
-> Result<(), SessionError> &self,
{ module: ClauseName,
existing_desc: Option<OpDesc>,
op_dir: &mut OpDir,
) -> Result<(), SessionError> {
let (prec, spec, name) = (self.0, self.1, self.2.clone()); let (prec, spec, name) = (self.0, self.1, self.2.clone());
if is_infix!(spec) { if is_infix!(spec) {
@@ -254,25 +264,30 @@ impl OpDecl {
} }
} }
pub pub fn fetch_atom_op_spec(
fn fetch_atom_op_spec(name: ClauseName, spec: Option<SharedOpDesc>, op_dir: &OpDir) name: ClauseName,
-> Option<SharedOpDesc> spec: Option<SharedOpDesc>,
{ op_dir: &OpDir,
) -> Option<SharedOpDesc> {
fetch_op_spec(name.clone(), 1, spec.clone(), op_dir) fetch_op_spec(name.clone(), 1, spec.clone(), op_dir)
.or_else(|| fetch_op_spec(name, 2, spec, op_dir)) .or_else(|| fetch_op_spec(name, 2, spec, op_dir))
} }
pub pub fn fetch_op_spec(
fn fetch_op_spec(name: ClauseName, arity: usize, spec: Option<SharedOpDesc>, op_dir: &OpDir) name: ClauseName,
-> Option<SharedOpDesc> arity: usize,
{ spec: Option<SharedOpDesc>,
spec.or_else(|| { op_dir: &OpDir,
match arity { ) -> Option<SharedOpDesc> {
2 => op_dir.get(&(name, Fixity::In)).and_then(|OpDirValue(spec, _)| spec.or_else(|| match arity {
2 => op_dir
.get(&(name, Fixity::In))
.and_then(|OpDirValue(spec, _)| {
if spec.prec() > 0 { if spec.prec() > 0 {
Some(spec.clone()) Some(spec.clone())
} else { } else {
None None
}
}), }),
1 => { 1 => {
if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) { if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
@@ -281,25 +296,26 @@ fn fetch_op_spec(name: ClauseName, arity: usize, spec: Option<SharedOpDesc>, op_
} }
} }
op_dir.get(&(name.clone(), Fixity::Post)) op_dir
.and_then(|OpDirValue(spec, _)| .get(&(name.clone(), Fixity::Post))
.and_then(|OpDirValue(spec, _)| {
if spec.prec() > 0 { if spec.prec() > 0 {
Some(spec.clone()) Some(spec.clone())
} else { } else {
None None
})
},
_ => None
} }
}) })
} }
_ => None,
})
}
pub type ModuleDir = IndexMap<ClauseName, Module>; pub type ModuleDir = IndexMap<ClauseName, Module>;
#[derive(Clone)] #[derive(Clone)]
pub struct ModuleDecl { pub struct ModuleDecl {
pub name: ClauseName, pub name: ClauseName,
pub exports: Vec<PredicateKey> pub exports: Vec<PredicateKey>,
} }
pub struct Module { pub struct Module {
@@ -311,14 +327,14 @@ pub struct Module {
pub goal_expansions: (Predicate, VecDeque<TopLevel>), pub goal_expansions: (Predicate, VecDeque<TopLevel>),
pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope. pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions. pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions.
pub inserted_expansions: bool // has the module been successfully inserted into toplevel?? pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
} }
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub enum Number { pub enum Number {
Float(OrderedFloat<f64>), Float(OrderedFloat<f64>),
Integer(Integer), Integer(Integer),
Rational(Rational) Rational(Rational),
} }
impl Default for Number { impl Default for Number {
@@ -332,7 +348,7 @@ impl Number {
match self { match self {
Number::Integer(n) => Constant::Integer(n), Number::Integer(n) => Constant::Integer(n),
Number::Float(f) => Constant::Float(f), Number::Float(f) => Constant::Float(f),
Number::Rational(r) => Constant::Rational(r) Number::Rational(r) => Constant::Rational(r),
} }
} }
@@ -341,7 +357,7 @@ impl Number {
match self { match self {
&Number::Integer(ref n) => n > &0, &Number::Integer(ref n) => n > &0,
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(), &Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
&Number::Rational(ref r) => r > &0 &Number::Rational(ref r) => r > &0,
} }
} }
@@ -350,7 +366,7 @@ impl Number {
match self { match self {
&Number::Integer(ref n) => n < &0, &Number::Integer(ref n) => n < &0,
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(), &Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
&Number::Rational(ref r) => r < &0 &Number::Rational(ref r) => r < &0,
} }
} }
@@ -359,7 +375,7 @@ impl Number {
match self { match self {
&Number::Integer(ref n) => n == &0, &Number::Integer(ref n) => n == &0,
&Number::Float(f) => f == OrderedFloat(0f64), &Number::Float(f) => f == OrderedFloat(0f64),
&Number::Rational(ref r) => r == &0 &Number::Rational(ref r) => r == &0,
} }
} }
@@ -368,7 +384,7 @@ impl Number {
match self { match self {
Number::Integer(n) => Number::Integer(n.abs()), Number::Integer(n) => Number::Integer(n.abs()),
Number::Float(f) => Number::Float(OrderedFloat(f.abs())), Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
Number::Rational(r) => Number::Rational(r.abs()) Number::Rational(r) => Number::Rational(r.abs()),
} }
} }
} }

View File

@@ -11,14 +11,14 @@ use std::vec::Vec;
pub struct HCPreOrderIterator<'a> { pub struct HCPreOrderIterator<'a> {
pub machine_st: &'a MachineState, pub machine_st: &'a MachineState,
pub state_stack: Vec<Addr> pub state_stack: Vec<Addr>,
} }
impl<'a> HCPreOrderIterator<'a> { impl<'a> HCPreOrderIterator<'a> {
pub fn new(machine_st: &'a MachineState, a: Addr) -> Self pub fn new(machine_st: &'a MachineState, a: Addr) -> Self {
{
HCPreOrderIterator { HCPreOrderIterator {
machine_st, state_stack: vec![a] machine_st,
state_stack: vec![a],
} }
} }
@@ -26,8 +26,7 @@ impl<'a> HCPreOrderIterator<'a> {
&self.machine_st &self.machine_st
} }
fn follow_heap(&mut self, h: usize) -> Addr fn follow_heap(&mut self, h: usize) -> Addr {
{
match &self.machine_st.heap[h] { match &self.machine_st.heap[h] {
&HeapCellValue::NamedStr(arity, _, _) => { &HeapCellValue::NamedStr(arity, _, _) => {
for idx in (1..arity + 1).rev() { for idx in (1..arity + 1).rev() {
@@ -35,50 +34,51 @@ impl<'a> HCPreOrderIterator<'a> {
} }
Addr::HeapCell(h) Addr::HeapCell(h)
}, }
&HeapCellValue::Addr(ref a) => &HeapCellValue::Addr(ref a) => self.follow(a.clone()),
self.follow(a.clone())
} }
} }
// called under the assumption that the location at r is about to // called under the assumption that the location at r is about to
// be visited, and so any follow up states need to be added to // be visited, and so any follow up states need to be added to
// state_stack. returns the dereferenced Addr from Ref. // state_stack. returns the dereferenced Addr from Ref.
fn follow(&mut self, addr: Addr) -> Addr fn follow(&mut self, addr: Addr) -> Addr {
{
let da = self.machine_st.store(self.machine_st.deref(addr)); let da = self.machine_st.store(self.machine_st.deref(addr));
match da { match da {
Addr::Con(Constant::String(ref s)) => { Addr::Con(Constant::String(ref s)) => {
match self.machine_st.machine_flags().double_quotes { match self.machine_st.machine_flags().double_quotes {
DoubleQuotes::Chars => DoubleQuotes::Chars => {
if let Some(c) = s.head() { if let Some(c) = s.head() {
let tail = s.tail(); let tail = s.tail();
self.state_stack.push(Addr::Con(Constant::String(tail))); self.state_stack.push(Addr::Con(Constant::String(tail)));
self.state_stack.push(Addr::Con(Constant::Char(c))); self.state_stack.push(Addr::Con(Constant::Char(c)));
}, }
DoubleQuotes::Codes => }
DoubleQuotes::Codes => {
if let Some(c) = s.head() { if let Some(c) = s.head() {
let tail = s.tail(); let tail = s.tail();
self.state_stack.push(Addr::Con(Constant::String(tail))); self.state_stack.push(Addr::Con(Constant::String(tail)));
self.state_stack.push(Addr::Con(Constant::CharCode(c as u8))); self.state_stack
}, .push(Addr::Con(Constant::CharCode(c as u8)));
}
}
_ => {} _ => {}
} }
Addr::Con(Constant::String(s.clone())) Addr::Con(Constant::String(s.clone()))
}, }
Addr::Con(_) | Addr::DBRef(_) => da, Addr::Con(_) | Addr::DBRef(_) => da,
Addr::Lis(a) => { Addr::Lis(a) => {
self.state_stack.push(Addr::HeapCell(a + 1)); self.state_stack.push(Addr::HeapCell(a + 1));
self.state_stack.push(Addr::HeapCell(a)); self.state_stack.push(Addr::HeapCell(a));
da da
}, }
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => da, Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => da,
Addr::Str(s) => self.follow_heap(s) // record terms of structure. Addr::Str(s) => self.follow_heap(s), // record terms of structure.
} }
} }
} }
@@ -87,26 +87,26 @@ impl<'a> Iterator for HCPreOrderIterator<'a> {
type Item = HeapCellValue; type Item = HeapCellValue;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.state_stack.pop().map(|a| { self.state_stack.pop().map(|a| match self.follow(a) {
match self.follow(a) { Addr::HeapCell(h) => self.machine_st.heap[h].clone(),
Addr::HeapCell(h) => Addr::StackCell(fr, sc) => {
self.machine_st.heap[h].clone(), HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone())
Addr::StackCell(fr, sc) =>
HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone()),
da =>
HeapCellValue::Addr(da)
} }
da => HeapCellValue::Addr(da),
}) })
} }
} }
pub trait MutStackHCIterator where Self: Iterator<Item=HeapCellValue> { pub trait MutStackHCIterator
where
Self: Iterator<Item = HeapCellValue>,
{
fn stack(&mut self) -> &mut Vec<Addr>; fn stack(&mut self) -> &mut Vec<Addr>;
} }
pub struct HCPostOrderIterator<HCIter> { pub struct HCPostOrderIterator<HCIter> {
base_iter: HCIter, base_iter: HCIter,
parent_stack: Vec<(usize, HeapCellValue)> // number of children, parent node. parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
} }
impl<HCIter> Deref for HCPostOrderIterator<HCIter> { impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
@@ -121,7 +121,7 @@ impl<HCIter: Iterator<Item=HeapCellValue>> HCPostOrderIterator<HCIter> {
pub fn new(base_iter: HCIter) -> Self { pub fn new(base_iter: HCIter) -> Self {
HCPostOrderIterator { HCPostOrderIterator {
base_iter, base_iter,
parent_stack: vec![] parent_stack: vec![],
} }
} }
} }
@@ -141,10 +141,12 @@ impl<HCIter: Iterator<Item=HeapCellValue>> Iterator for HCPostOrderIterator<HCIt
if let Some(item) = self.base_iter.next() { if let Some(item) = self.base_iter.next() {
match item { match item {
HeapCellValue::NamedStr(arity, name, fix) => HeapCellValue::NamedStr(arity, name, fix) => self
self.parent_stack.push((arity, HeapCellValue::NamedStr(arity, name, fix))), .parent_stack
HeapCellValue::Addr(Addr::Lis(a)) => .push((arity, HeapCellValue::NamedStr(arity, name, fix))),
self.parent_stack.push((2, HeapCellValue::Addr(Addr::Lis(a)))), HeapCellValue::Addr(Addr::Lis(a)) => self
.parent_stack
.push((2, HeapCellValue::Addr(Addr::Lis(a)))),
child_node => { child_node => {
return Some(child_node); return Some(child_node);
} }
@@ -167,16 +169,22 @@ impl MachineState {
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a)) HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
} }
pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicIterator<HCPreOrderIterator<'a>> pub fn acyclic_pre_order_iter<'a>(
{ &'a self,
a: Addr,
) -> HCAcyclicIterator<HCPreOrderIterator<'a>> {
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a)) HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
} }
pub fn zipped_acyclic_pre_order_iter<'a>(&'a self, a1: Addr, a2: Addr) pub fn zipped_acyclic_pre_order_iter<'a>(
-> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> &'a self,
{ a1: Addr,
HCZippedAcyclicIterator::new(HCPreOrderIterator::new(self, a1), a2: Addr,
HCPreOrderIterator::new(self, a2)) ) -> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> {
HCZippedAcyclicIterator::new(
HCPreOrderIterator::new(self, a1),
HCPreOrderIterator::new(self, a2),
)
} }
} }
@@ -188,13 +196,15 @@ impl<'a> MutStackHCIterator for HCPreOrderIterator<'a> {
pub struct HCAcyclicIterator<HCIter> { pub struct HCAcyclicIterator<HCIter> {
iter: HCIter, iter: HCIter,
seen: IndexSet<Addr> seen: IndexSet<Addr>,
} }
impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
{
pub fn new(iter: HCIter) -> Self { pub fn new(iter: HCIter) -> Self {
HCAcyclicIterator { iter, seen: IndexSet::new() } HCAcyclicIterator {
iter,
seen: IndexSet::new(),
}
} }
} }
@@ -207,7 +217,8 @@ impl<HCIter> Deref for HCAcyclicIterator<HCIter> {
} }
impl<HCIter> Iterator for HCAcyclicIterator<HCIter> impl<HCIter> Iterator for HCAcyclicIterator<HCIter>
where HCIter: Iterator<Item=HeapCellValue> + MutStackHCIterator where
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
{ {
type Item = HeapCellValue; type Item = HeapCellValue;
@@ -229,19 +240,23 @@ pub struct HCZippedAcyclicIterator<HCIter> {
i1: HCIter, i1: HCIter,
i2: HCIter, i2: HCIter,
seen: IndexSet<(Addr, Addr)>, seen: IndexSet<(Addr, Addr)>,
pub first_to_expire: Ordering pub first_to_expire: Ordering,
} }
impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
{
pub fn new(i1: HCIter, i2: HCIter) -> Self { pub fn new(i1: HCIter, i2: HCIter) -> Self {
HCZippedAcyclicIterator { i1, i2, seen: IndexSet::new(), HCZippedAcyclicIterator {
first_to_expire: Ordering::Equal } i1,
i2,
seen: IndexSet::new(),
first_to_expire: Ordering::Equal,
}
} }
} }
impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter> impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
where HCIter: Iterator<Item=HeapCellValue> + MutStackHCIterator where
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
{ {
type Item = (HeapCellValue, HeapCellValue); type Item = (HeapCellValue, HeapCellValue);
@@ -257,17 +272,16 @@ impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
} }
match (self.i1.next(), self.i2.next()) { match (self.i1.next(), self.i2.next()) {
(Some(v1), Some(v2)) => (Some(v1), Some(v2)) => Some((v1, v2)),
Some((v1, v2)),
(Some(_), None) => { (Some(_), None) => {
self.first_to_expire = Ordering::Greater; self.first_to_expire = Ordering::Greater;
None None
}, }
(None, Some(_)) => { (None, Some(_)) => {
self.first_to_expire = Ordering::Less; self.first_to_expire = Ordering::Less;
None None
}, }
_ => None _ => None,
} }
} }
} }

View File

@@ -7,7 +7,7 @@ use prolog::heap_iter::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::*; use prolog::machine::machine_state::*;
use prolog::ordered_float::OrderedFloat; use prolog::ordered_float::OrderedFloat;
use prolog::rug::{Integer}; use prolog::rug::Integer;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
@@ -20,25 +20,25 @@ use std::rc::Rc;
#[derive(Clone)] #[derive(Clone)]
pub enum DirectedOp { pub enum DirectedOp {
Left(ClauseName, SharedOpDesc), Left(ClauseName, SharedOpDesc),
Right(ClauseName, SharedOpDesc) Right(ClauseName, SharedOpDesc),
} }
impl DirectedOp { impl DirectedOp {
#[inline] #[inline]
fn as_str(&self) -> &str { fn as_str(&self) -> &str {
match self { match self {
&DirectedOp::Left(ref name, _) | &DirectedOp::Right(ref name, _) => &DirectedOp::Left(ref name, _) | &DirectedOp::Right(ref name, _) => name.as_str(),
name.as_str()
} }
} }
#[inline] #[inline]
fn is_negative_sign(&self) -> bool { fn is_negative_sign(&self) -> bool {
match self { match self {
&DirectedOp::Left(ref name, ref cell) | &DirectedOp::Right(ref name, ref cell) => &DirectedOp::Left(ref name, ref cell) | &DirectedOp::Right(ref name, ref cell) => {
name.as_str() == "-" && is_prefix!(cell.assoc()) name.as_str() == "-" && is_prefix!(cell.assoc())
} }
} }
}
#[inline] #[inline]
fn is_left(&self) -> bool { fn is_left(&self) -> bool {
@@ -50,8 +50,7 @@ impl DirectedOp {
} }
} }
fn needs_bracketing(child_spec: &SharedOpDesc, op: &DirectedOp) -> bool fn needs_bracketing(child_spec: &SharedOpDesc, op: &DirectedOp) -> bool {
{
match op { match op {
&DirectedOp::Left(ref name, ref cell) => { &DirectedOp::Left(ref name, ref cell) => {
let (priority, spec) = cell.get(); let (priority, spec) = cell.get();
@@ -65,7 +64,7 @@ fn needs_bracketing(child_spec: &SharedOpDesc, op: &DirectedOp) -> bool
let is_strict_right = is_yfx!(spec) || is_xfx!(spec) || is_fx!(spec); let is_strict_right = is_yfx!(spec) || is_xfx!(spec) || is_fx!(spec);
child_spec.prec() > priority || (child_spec.prec() == priority && is_strict_right) child_spec.prec() > priority || (child_spec.prec() == priority && is_strict_right)
}, }
&DirectedOp::Right(_, ref cell) => { &DirectedOp::Right(_, ref cell) => {
let (priority, spec) = cell.get(); let (priority, spec) = cell.get();
let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec); let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec);
@@ -89,53 +88,51 @@ impl<'a> HCPreOrderIterator<'a> {
* by brackets. * by brackets.
*/ */
fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool
where P: Fn(Constant) -> bool where
P: Fn(Constant) -> bool,
{ {
let mut addr = match self.state_stack.last().cloned() { let mut addr = match self.state_stack.last().cloned() {
Some(addr) => addr, Some(addr) => addr,
None => return false None => return false,
}; };
let mut parent_spec = DirectedOp::Left(clause_name!("-"), SharedOpDesc::new(200, FY)); let mut parent_spec = DirectedOp::Left(clause_name!("-"), SharedOpDesc::new(200, FY));
loop { loop {
match self.machine_st.store(self.machine_st.deref(addr)) { match self.machine_st.store(self.machine_st.deref(addr)) {
Addr::Str(s) => Addr::Str(s) => match &self.machine_st.heap[s] {
match &self.machine_st.heap[s] {
&HeapCellValue::NamedStr(_, ref name, Some(ref spec)) &HeapCellValue::NamedStr(_, ref name, Some(ref spec))
if is_postfix!(spec.assoc()) || is_infix!(spec.assoc()) => if is_postfix!(spec.assoc()) || is_infix!(spec.assoc()) =>
{
if needs_bracketing(spec, &parent_spec) { if needs_bracketing(spec, &parent_spec) {
return false; return false;
} else { } else {
addr = Addr::HeapCell(s + 1); addr = Addr::HeapCell(s + 1);
parent_spec = DirectedOp::Right(name.clone(), spec.clone()); parent_spec = DirectedOp::Right(name.clone(), spec.clone());
}
}
_ => return false,
}, },
_ => Addr::Con(Constant::Integer(n)) => return property_check(Constant::Integer(n)),
return false Addr::Con(Constant::Float(n)) => return property_check(Constant::Float(n)),
}, Addr::Con(Constant::Rational(n)) => return property_check(Constant::Rational(n)),
Addr::Con(Constant::Integer(n)) => _ => return false,
return property_check(Constant::Integer(n)),
Addr::Con(Constant::Float(n)) =>
return property_check(Constant::Float(n)),
Addr::Con(Constant::Rational(n)) =>
return property_check(Constant::Rational(n)),
_ =>
return false
} }
} }
} }
fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool
where P: Fn(Constant) -> bool where
P: Fn(Constant) -> bool,
{ {
let addr = match self.state_stack.last().cloned() { let addr = match self.state_stack.last().cloned() {
Some(addr) => addr, Some(addr) => addr,
None => return false None => return false,
}; };
match self.machine_st.store(self.machine_st.deref(addr)) { match self.machine_st.store(self.machine_st.deref(addr)) {
Addr::Con(c) => property_check(c), Addr::Con(c) => property_check(c),
_ => false _ => false,
} }
} }
} }
@@ -151,7 +148,7 @@ fn char_to_string(c: char) -> String {
'\u{08}' => "\\b".to_string(), // UTF-8 backspace '\u{08}' => "\\b".to_string(), // UTF-8 backspace
'\u{07}' => "\\a".to_string(), // UTF-8 alert '\u{07}' => "\\a".to_string(), // UTF-8 alert
'\x20'...'\x7e' => c.to_string(), '\x20'...'\x7e' => c.to_string(),
_ => format!("\\x{:x}\\", c as u32) _ => format!("\\x{:x}\\", c as u32),
} }
} }
@@ -190,14 +187,16 @@ pub trait HCValueOutputter {
} }
pub struct PrinterOutputter { pub struct PrinterOutputter {
contents: String contents: String,
} }
impl HCValueOutputter for PrinterOutputter { impl HCValueOutputter for PrinterOutputter {
type Output = String; type Output = String;
fn new() -> Self { fn new() -> Self {
PrinterOutputter { contents: String::new() } PrinterOutputter {
contents: String::new(),
}
} }
fn append(&mut self, contents: &str) { fn append(&mut self, contents: &str) {
@@ -253,16 +252,14 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
} }
#[inline] #[inline]
fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool {
{
if let &Some(ref op) = op { if let &Some(ref op) = op {
op.is_negative_sign() && iter.leftmost_leaf_has_property(|c| { op.is_negative_sign()
match c { && iter.leftmost_leaf_has_property(|c| match c {
Constant::Integer(n) => n > 0, Constant::Integer(n) => n > 0,
Constant::Float(f) => f > OrderedFloat(0f64), Constant::Float(f) => f > OrderedFloat(0f64),
Constant::Rational(r) => r > 0, Constant::Rational(r) => r > 0,
_ => false _ => false,
}
}) })
} else { } else {
false false
@@ -271,13 +268,13 @@ fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp
impl MachineState { impl MachineState {
pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> { pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> {
static CHAR_CODES: [char; 26] = ['A','B','C','D','E','F','G','H','I','J', static CHAR_CODES: [char; 26] = [
'K','L','M','N','O','P','Q','R','S','T', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'U','V','W','X','Y','Z']; 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];
match self.store(self.deref(addr)) { match self.store(self.deref(addr)) {
Addr::Con(Constant::Integer(ref n)) Addr::Con(Constant::Integer(ref n)) if n >= &0 => {
if n >= &0 => {
let n = Integer::from(offset + n); let n = Integer::from(offset + n);
let i = n.mod_u(26) as usize; let i = n.mod_u(26) as usize;
@@ -289,8 +286,8 @@ impl MachineState {
} else { } else {
format!("{}{}", CHAR_CODES[i], j) format!("{}{}", CHAR_CODES[i], j)
}) })
}, }
_ => None _ => None,
} }
} }
} }
@@ -311,23 +308,26 @@ pub struct HCPrinter<'a, Outputter> {
pub(crate) numbervars_offset: Integer, pub(crate) numbervars_offset: Integer,
pub(crate) numbervars: bool, pub(crate) numbervars: bool,
pub(crate) quoted: bool, pub(crate) quoted: bool,
pub(crate) ignore_ops: bool pub(crate) ignore_ops: bool,
} }
macro_rules! push_space_if_amb { macro_rules! push_space_if_amb {
($self:expr, $atom:expr, $action:block) => ( ($self:expr, $atom:expr, $action:block) => {
if $self.ambiguity_check($atom) { if $self.ambiguity_check($atom) {
$self.outputter.push_char(' '); $self.outputter.push_char(' ');
$action; $action;
} else { } else {
$action; $action;
} }
) };
} }
pub fn requires_space(atom: &str, op: &str) -> bool { pub fn requires_space(atom: &str, op: &str) -> bool {
match atom.chars().last() { match atom.chars().last() {
Some(ac) => op.chars().next().map(|oc| { Some(ac) => op
.chars()
.next()
.map(|oc| {
if ac == '0' { if ac == '0' {
oc == 'b' || oc == 'x' || oc == 'o' || oc == '\'' oc == 'b' || oc == 'x' || oc == 'o' || oc == '\''
} else if alpha_numeric_char!(ac) { } else if alpha_numeric_char!(ac) {
@@ -345,16 +345,23 @@ pub fn requires_space(atom: &str, op: &str) -> bool {
} else { } else {
false false
} }
}).unwrap_or(false), })
_ => false .unwrap_or(false),
_ => false,
} }
} }
fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict {
{ machine_st
machine_st.heap_locs.iter().map(|(var, var_addr)| { .heap_locs
(machine_st.store(machine_st.deref(var_addr.clone())), var.clone()) .iter()
}).collect() .map(|(var, var_addr)| {
(
machine_st.store(machine_st.deref(var_addr.clone())),
var.clone(),
)
})
.collect()
} }
fn non_quoted_graphic_token<Iter: Iterator<Item = char>>(mut iter: Iter, c: char) -> bool { fn non_quoted_graphic_token<Iter: Iterator<Item = char>>(mut iter: Iter, c: char) -> bool {
@@ -362,21 +369,25 @@ fn non_quoted_graphic_token<Iter: Iterator<Item=char>>(mut iter: Iter, c: char)
return match iter.next() { return match iter.next() {
None => true, None => true,
Some('*') => false, // if we start with comment token, we must quote. Some('*') => false, // if we start with comment token, we must quote.
Some(c) => if graphic_token_char!(c) { Some(c) => {
if graphic_token_char!(c) {
iter.all(|c| graphic_token_char!(c)) iter.all(|c| graphic_token_char!(c))
} else { } else {
false false
} }
} }
};
} else if c == '.' { } else if c == '.' {
return match iter.next() { return match iter.next() {
None => false, None => false,
Some(c) => if graphic_token_char!(c) { Some(c) => {
if graphic_token_char!(c) {
iter.all(|c| graphic_token_char!(c)) iter.all(|c| graphic_token_char!(c))
} else { } else {
false false
} }
} }
};
} else { } else {
iter.all(|c| graphic_token_char!(c)) iter.all(|c| graphic_token_char!(c))
} }
@@ -406,11 +417,10 @@ fn non_quoted_token<Iter: Iterator<Item=char>>(mut iter: Iter) -> bool {
} }
} }
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
{ pub fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self {
pub fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self HCPrinter {
{ outputter: output,
HCPrinter { outputter: output,
machine_st, machine_st,
op_dir, op_dir,
state_stack: vec![], state_stack: vec![],
@@ -423,15 +433,21 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
quoted: false, quoted: false,
ignore_ops: false, ignore_ops: false,
cyclic_terms: IndexMap::new(), cyclic_terms: IndexMap::new(),
var_names: IndexMap::new() } var_names: IndexMap::new(),
}
} }
pub fn from_heap_locs(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) pub fn from_heap_locs(
-> Self machine_st: &'a MachineState,
{ op_dir: &'a OpDir,
output: Outputter,
) -> Self {
let mut printer = Self::new(machine_st, op_dir, output); let mut printer = Self::new(machine_st, op_dir, output);
printer.toplevel_spec = Some(DirectedOp::Right(clause_name!("="), SharedOpDesc::new(700, XFX))); printer.toplevel_spec = Some(DirectedOp::Right(
clause_name!("="),
SharedOpDesc::new(700, XFX),
));
printer.heap_locs = reverse_heap_locs(machine_st); printer.heap_locs = reverse_heap_locs(machine_st);
printer printer
@@ -449,8 +465,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
#[inline] #[inline]
fn ambiguity_check(&self, atom: &str) -> bool fn ambiguity_check(&self, atom: &str) -> bool {
{
let tail = self.outputter.range_from(self.last_item_idx..); let tail = self.outputter.range_from(self.last_item_idx..);
requires_space(tail, atom) requires_space(tail, atom)
} }
@@ -460,7 +475,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone()); let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
} else if is_prefix!(spec.assoc()) { } else if is_prefix!(spec.assoc()) {
match ct.name().as_str() { match ct.name().as_str() {
"-" | "\\" => { "-" | "\\" => {
@@ -472,28 +488,31 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone()); let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
} else { // if is_infix!(spec.assoc()) } else {
// if is_infix!(spec.assoc())
match ct.name().as_str() { match ct.name().as_str() {
"|" => { "|" => {
self.format_bar_separator_op(ct.name(), spec); self.format_bar_separator_op(ct.name(), spec);
return; return;
}, }
_ => {} _ => {}
}; };
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone()); let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone()); let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec)); self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
} }
} }
fn format_struct(&mut self, arity: usize, name: ClauseName) fn format_struct(&mut self, arity: usize, name: ClauseName) {
{
self.state_stack.push(TokenOrRedirect::Close); self.state_stack.push(TokenOrRedirect::Close);
for _ in 0..arity { for _ in 0..arity {
@@ -507,34 +526,33 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
self.state_stack.push(TokenOrRedirect::Atom(name)); self.state_stack.push(TokenOrRedirect::Atom(name));
} }
fn format_prefix_op_with_space(&mut self, name: ClauseName, spec: SharedOpDesc) fn format_prefix_op_with_space(&mut self, name: ClauseName, spec: SharedOpDesc) {
{
let op = DirectedOp::Left(name.clone(), spec); let op = DirectedOp::Left(name.clone(), spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(op));
self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Space);
self.state_stack.push(TokenOrRedirect::Atom(name)); self.state_stack.push(TokenOrRedirect::Atom(name));
} }
fn format_bar_separator_op(&mut self, name: ClauseName, spec: SharedOpDesc) fn format_bar_separator_op(&mut self, name: ClauseName, spec: SharedOpDesc) {
{
let left_directed_op = DirectedOp::Left(name.clone(), spec.clone()); let left_directed_op = DirectedOp::Left(name.clone(), spec.clone());
let right_directed_op = DirectedOp::Right(name.clone(), spec.clone()); let right_directed_op = DirectedOp::Right(name.clone(), spec.clone());
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op)); self.state_stack
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
} }
fn format_curly_braces(&mut self) fn format_curly_braces(&mut self) {
{
self.state_stack.push(TokenOrRedirect::RightCurly); self.state_stack.push(TokenOrRedirect::RightCurly);
self.state_stack.push(TokenOrRedirect::FunctorRedirect); self.state_stack.push(TokenOrRedirect::FunctorRedirect);
self.state_stack.push(TokenOrRedirect::LeftCurly); self.state_stack.push(TokenOrRedirect::LeftCurly);
} }
fn format_numbered_vars(&mut self, iter: &mut HCPreOrderIterator) -> bool fn format_numbered_vars(&mut self, iter: &mut HCPreOrderIterator) -> bool {
{
let addr = iter.stack().last().cloned().unwrap(); let addr = iter.stack().last().cloned().unwrap();
// 7.10.4 // 7.10.4
@@ -547,8 +565,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
false false
} }
fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType) fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType) {
{
if self.numbervars && is_numbered_var(&ct, arity) { if self.numbervars && is_numbered_var(&ct, arity) {
if self.format_numbered_vars(iter) { if self.format_numbered_vars(iter) {
return; return;
@@ -570,7 +587,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
match (ct.name().as_str(), arity) { match (ct.name().as_str(), arity) {
("{}", 1) if !self.ignore_ops => self.format_curly_braces(), ("{}", 1) if !self.ignore_ops => self.format_curly_braces(),
_ => self.format_struct(arity, ct.name()) _ => self.format_struct(arity, ct.name()),
}; };
} }
@@ -586,8 +603,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
self.outputter.append(s); self.outputter.append(s);
} }
fn offset_as_string(&self, iter: &mut HCPreOrderIterator, addr: Addr) -> Option<String> fn offset_as_string(&self, iter: &mut HCPreOrderIterator, addr: Addr) -> Option<String> {
{
if let Some(var) = self.var_names.get(&addr) { if let Some(var) = self.var_names.get(&addr) {
if addr.as_var().is_some() { if addr.as_var().is_some() {
return Some(format!("{}", var)); return Some(format!("{}", var));
@@ -598,23 +614,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
match addr { match addr {
Addr::AttrVar(h) => Addr::AttrVar(h) => Some(format!("_{}", h + 1)),
Some(format!("_{}", h + 1)), Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) => Some(format!("_{}", h)),
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) => Addr::StackCell(fr, sc) => Some(format!("_s_{}_{}", fr, sc)),
Some(format!("_{}", h)), _ => None,
Addr::StackCell(fr, sc) =>
Some(format!("_s_{}_{}", fr, sc)),
_ => None
} }
} }
fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option<HeapCellValue> fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option<HeapCellValue> {
{
iter.stack().last().cloned().and_then(|addr| { iter.stack().last().cloned().and_then(|addr| {
let addr = self.machine_st.store(self.machine_st.deref(addr)); let addr = self.machine_st.store(self.machine_st.deref(addr));
match self.heap_locs.get(&addr).cloned() { match self.heap_locs.get(&addr).cloned() {
Some(var) => if !self.printed_vars.contains(&addr) { Some(var) => {
if !self.printed_vars.contains(&addr) {
self.printed_vars.insert(addr); self.printed_vars.insert(addr);
return iter.next(); return iter.next();
} else { } else {
@@ -624,10 +637,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
}); });
return None; return None;
}, }
None => if self.machine_st.is_cyclic_term(addr.clone()) { }
None => {
if self.machine_st.is_cyclic_term(addr.clone()) {
match self.cyclic_terms.get(&addr).cloned() { match self.cyclic_terms.get(&addr).cloned() {
Some(reps) => Some(reps) => {
if reps > 0 { if reps > 0 {
self.cyclic_terms.insert(addr, reps - 1); self.cyclic_terms.insert(addr, reps - 1);
iter.next() iter.next()
@@ -639,7 +654,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
iter.stack().pop(); iter.stack().pop();
self.cyclic_terms.remove(&addr); self.cyclic_terms.remove(&addr);
None None
}, }
}
None => { None => {
self.cyclic_terms.insert(addr, 2); self.cyclic_terms.insert(addr, 2);
iter.next() iter.next()
@@ -649,6 +665,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
iter.next() iter.next()
} }
} }
}
}) })
} }
@@ -708,7 +725,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
match n { match n {
Number::Float(fl) => Number::Float(fl) => {
if &fl == &OrderedFloat(0f64) { if &fl == &OrderedFloat(0f64) {
push_space_if_amb!(self, "0", { push_space_if_amb!(self, "0", {
self.append_str("0"); self.append_str("0");
@@ -720,7 +737,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
push_space_if_amb!(self, &output_str, { push_space_if_amb!(self, &output_str, {
self.append_str(&output_str.trim()); self.append_str(&output_str.trim());
}); });
}, }
}
n => { n => {
let output_str = format!("{}", n); let output_str = format!("{}", n);
@@ -737,7 +755,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) { fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
match c { match c {
Constant::Atom(atom, spec) => Constant::Atom(atom, spec) => {
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) { if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
let mut result = String::new(); let mut result = String::new();
@@ -762,14 +780,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
push_space_if_amb!(self, atom.as_str(), { push_space_if_amb!(self, atom.as_str(), {
self.print_atom(&atom); self.print_atom(&atom);
}); });
}, }
}
Constant::Char(c) if non_quoted_token(once(c)) => { Constant::Char(c) if non_quoted_token(once(c)) => {
let c = char_to_string(c); let c = char_to_string(c);
push_space_if_amb!(self, &c, { push_space_if_amb!(self, &c, {
self.append_str(c.as_str()); self.append_str(c.as_str());
}); });
}, }
Constant::Char(c) => { Constant::Char(c) => {
let mut result = String::new(); let mut result = String::new();
@@ -784,27 +803,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
push_space_if_amb!(self, &result, { push_space_if_amb!(self, &result, {
self.append_str(result.as_str()); self.append_str(result.as_str());
}); });
}, }
Constant::CharCode(c) => Constant::CharCode(c) => self.append_str(&format!("{}", c)),
self.append_str(&format!("{}", c)), Constant::EmptyList => self.append_str("[]"),
Constant::EmptyList => Constant::Integer(n) => self.print_number(Number::Integer(n), op),
self.append_str("[]"), Constant::Float(n) => self.print_number(Number::Float(n), op),
Constant::Integer(n) => Constant::Rational(n) => self.print_number(Number::Rational(n), op),
self.print_number(Number::Integer(n), op), Constant::String(s) => self.print_string(s),
Constant::Float(n) => Constant::Usize(i) => self.append_str(&format!("u{}", i)),
self.print_number(Number::Float(n), op),
Constant::Rational(n) =>
self.print_number(Number::Rational(n), op),
Constant::String(s) =>
self.print_string(s),
Constant::Usize(i) =>
self.append_str(&format!("u{}", i))
} }
} }
fn print_string(&mut self, s: StringList) { fn print_string(&mut self, s: StringList) {
match self.machine_st.machine_flags().double_quotes { match self.machine_st.machine_flags().double_quotes {
DoubleQuotes::Chars | DoubleQuotes::Codes => DoubleQuotes::Chars | DoubleQuotes::Codes => {
if !s.is_empty() { if !s.is_empty() {
if self.ignore_ops { if self.ignore_ops {
self.format_struct(2, clause_name!(".")); self.format_struct(2, clause_name!("."));
@@ -817,7 +829,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
} else if !self.at_cdr("") { } else if !self.at_cdr("") {
self.append_str("[]"); self.append_str("[]");
}, }
}
DoubleQuotes::Atom => { DoubleQuotes::Atom => {
let borrowed_str = s.borrow(); let borrowed_str = s.borrow();
let mut atom = String::new(); let mut atom = String::new();
@@ -836,7 +849,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
fn push_list(&mut self) { fn push_list(&mut self) {
let cell = Rc::new(Cell::new(true)); let cell = Rc::new(Cell::new(true));
self.state_stack.push(TokenOrRedirect::CloseList(cell.clone())); self.state_stack
.push(TokenOrRedirect::CloseList(cell.clone()));
self.state_stack.push(TokenOrRedirect::FunctorRedirect); self.state_stack.push(TokenOrRedirect::FunctorRedirect);
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
@@ -845,20 +859,25 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
self.state_stack.push(TokenOrRedirect::OpenList(cell)); self.state_stack.push(TokenOrRedirect::OpenList(cell));
} }
fn handle_op_as_struct(&mut self, name: ClauseName, arity: usize, iter: &mut HCPreOrderIterator, fn handle_op_as_struct(
op: &Option<DirectedOp>, is_functor_redirect: bool, spec: SharedOpDesc, &mut self,
negated_operand: bool) name: ClauseName,
{ arity: usize,
iter: &mut HCPreOrderIterator,
op: &Option<DirectedOp>,
is_functor_redirect: bool,
spec: SharedOpDesc,
negated_operand: bool,
) {
let add_brackets = if !self.ignore_ops { let add_brackets = if !self.ignore_ops {
negated_operand || if let Some(ref op) = op { negated_operand
|| if let Some(ref op) = op {
if self.numbervars && arity == 1 && name.as_str() == "$VAR" { if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
!iter.immediate_leaf_has_property(|c| { !iter.immediate_leaf_has_property(|c| match c {
match c {
Constant::Integer(n) => n >= 0, Constant::Integer(n) => n >= 0,
Constant::Float(f) => f >= OrderedFloat(0f64), Constant::Float(f) => f >= OrderedFloat(0f64),
Constant::Rational(r) => r >= 0, Constant::Rational(r) => r >= 0,
_ => false _ => false,
}
}) && needs_bracketing(&spec, op) }) && needs_bracketing(&spec, op)
} else { } else {
needs_bracketing(&spec, op) needs_bracketing(&spec, op)
@@ -888,41 +907,52 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
} }
fn handle_heap_term(
fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option<DirectedOp>, &mut self,
is_functor_redirect: bool) iter: &mut HCPreOrderIterator,
{ op: Option<DirectedOp>,
is_functor_redirect: bool,
) {
let negated_operand = negated_op_needs_bracketing(iter, &op); let negated_operand = negated_op_needs_bracketing(iter, &op);
let heap_val = match self.check_for_seen(iter) { let heap_val = match self.check_for_seen(iter) {
Some(heap_val) => heap_val, Some(heap_val) => heap_val,
None => return None => return,
}; };
match heap_val { match heap_val {
HeapCellValue::NamedStr(arity, name, spec) => HeapCellValue::NamedStr(arity, name, spec) => {
if let Some(spec) = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir) { if let Some(spec) = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir) {
self.handle_op_as_struct(name, arity, iter, &op, is_functor_redirect, spec, self.handle_op_as_struct(
negated_operand); name,
arity,
iter,
&op,
is_functor_redirect,
spec,
negated_operand,
);
} else { } else {
push_space_if_amb!(self, name.as_str(), { push_space_if_amb!(self, name.as_str(), {
let ct = ClauseType::from(name, arity, spec); let ct = ClauseType::from(name, arity, spec);
self.format_clause(iter, arity, ct); self.format_clause(iter, arity, ct);
}); });
}, }
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => }
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => {
if !self.at_cdr("") { if !self.at_cdr("") {
self.append_str("[]"); self.append_str("[]");
}, }
HeapCellValue::Addr(Addr::Con(c)) => }
self.print_constant(c, &op), HeapCellValue::Addr(Addr::Con(c)) => self.print_constant(c, &op),
HeapCellValue::Addr(Addr::Lis(_)) => HeapCellValue::Addr(Addr::Lis(_)) => {
if self.ignore_ops { if self.ignore_ops {
self.format_struct(2, clause_name!(".")); self.format_struct(2, clause_name!("."));
} else { } else {
self.push_list(); self.push_list();
}, }
HeapCellValue::Addr(addr) => }
HeapCellValue::Addr(addr) => {
if let Some(offset_str) = self.offset_as_string(iter, addr) { if let Some(offset_str) = self.offset_as_string(iter, addr) {
push_space_if_amb!(self, &offset_str, { push_space_if_amb!(self, &offset_str, {
self.append_str(offset_str.as_str()); self.append_str(offset_str.as_str());
@@ -930,6 +960,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
} }
} }
} }
}
fn at_cdr(&mut self, tr: &str) -> bool { fn at_cdr(&mut self, tr: &str) -> bool {
let len = self.outputter.len(); let len = self.outputter.len();
@@ -950,40 +981,34 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
loop { loop {
if let Some(loc_data) = self.state_stack.pop() { if let Some(loc_data) = self.state_stack.pop() {
match loc_data { match loc_data {
TokenOrRedirect::Atom(atom) => TokenOrRedirect::Atom(atom) => self.print_atom(&atom),
self.print_atom(&atom), TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
TokenOrRedirect::Op(atom, _) => TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()),
self.print_op(atom.as_str()), TokenOrRedirect::CompositeRedirect(op) => {
TokenOrRedirect::NumberedVar(num_var) => self.handle_heap_term(&mut iter, Some(op), false)
self.append_str(num_var.as_str()), }
TokenOrRedirect::CompositeRedirect(op) => TokenOrRedirect::FunctorRedirect => {
self.handle_heap_term(&mut iter, Some(op), false), self.handle_heap_term(&mut iter, None, true)
TokenOrRedirect::FunctorRedirect => }
self.handle_heap_term(&mut iter, None, true), TokenOrRedirect::Close => self.push_char(')'),
TokenOrRedirect::Close => TokenOrRedirect::Open => self.push_char('('),
self.push_char(')'), TokenOrRedirect::OpenList(delimit) => {
TokenOrRedirect::Open =>
self.push_char('('),
TokenOrRedirect::OpenList(delimit) =>
if !self.at_cdr(",") { if !self.at_cdr(",") {
self.push_char('['); self.push_char('[');
} else { } else {
delimit.set(false); delimit.set(false);
}, }
TokenOrRedirect::CloseList(delimit) => }
TokenOrRedirect::CloseList(delimit) => {
if delimit.get() { if delimit.get() {
self.push_char(']'); self.push_char(']');
}, }
TokenOrRedirect::HeadTailSeparator => }
self.append_str("|"), TokenOrRedirect::HeadTailSeparator => self.append_str("|"),
TokenOrRedirect::Comma => TokenOrRedirect::Comma => self.append_str(","),
self.append_str(","), TokenOrRedirect::Space => self.push_char(' '),
TokenOrRedirect::Space => TokenOrRedirect::LeftCurly => self.push_char('{'),
self.push_char(' '), TokenOrRedirect::RightCurly => self.push_char('}'),
TokenOrRedirect::LeftCurly =>
self.push_char('{'),
TokenOrRedirect::RightCurly =>
self.push_char('}'),
} }
} else if !iter.stack().is_empty() { } else if !iter.stack().is_empty() {
let spec = self.toplevel_spec.take(); let spec = self.toplevel_spec.take();

View File

@@ -9,14 +9,16 @@ use std::hash::Hash;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum IntIndex { enum IntIndex {
External(usize), Fail, Internal(usize) External(usize),
Fail,
Internal(usize),
} }
pub struct CodeOffsets { pub struct CodeOffsets {
flags: MachineFlags, flags: MachineFlags,
pub constants: IndexMap<Constant, ThirdLevelIndex>, pub constants: IndexMap<Constant, ThirdLevelIndex>,
pub lists: ThirdLevelIndex, pub lists: ThirdLevelIndex,
pub structures: IndexMap<(ClauseName, usize), ThirdLevelIndex> pub structures: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
} }
impl CodeOffsets { impl CodeOffsets {
@@ -25,15 +27,16 @@ impl CodeOffsets {
flags, flags,
constants: IndexMap::new(), constants: IndexMap::new(),
lists: Vec::new(), lists: Vec::new(),
structures: IndexMap::new() structures: IndexMap::new(),
} }
} }
fn cap_choice_seq_with_trust(prelude: &mut ThirdLevelIndex) { fn cap_choice_seq_with_trust(prelude: &mut ThirdLevelIndex) {
prelude.last_mut().map(|instr| { prelude.last_mut().map(|instr| {
match instr { match instr {
&mut IndexedChoiceInstruction::Retry(i) => &mut IndexedChoiceInstruction::Retry(i) => {
*instr = IndexedChoiceInstruction::Trust(i), *instr = IndexedChoiceInstruction::Trust(i)
}
_ => {} _ => {}
}; };
}); });
@@ -47,44 +50,50 @@ impl CodeOffsets {
} }
} }
pub fn index_term(&mut self, first_arg: &Term, index: usize) pub fn index_term(&mut self, first_arg: &Term, index: usize) {
{
match first_arg { match first_arg {
&Term::Clause(_, ref name, ref terms, _) => { &Term::Clause(_, ref name, ref terms, _) => {
let code = self.structures.entry((name.clone(), terms.len())) let code = self
.structures
.entry((name.clone(), terms.len()))
.or_insert(Vec::new()); .or_insert(Vec::new());
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
code.push(Self::add_index(is_initial_index, index)); code.push(Self::add_index(is_initial_index, index));
}, }
&Term::Cons(..) => { &Term::Cons(..) => {
let is_initial_index = self.lists.is_empty(); let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index)); self.lists.push(Self::add_index(is_initial_index, index));
}, }
&Term::Constant(_, Constant::String(ref s)) &Term::Constant(_, Constant::String(ref s))
if !self.flags.double_quotes.is_atom() && !s.is_empty() => { // strings are lists in this case. if !self.flags.double_quotes.is_atom() && !s.is_empty() =>
{
// strings are lists in this case.
let is_initial_index = self.lists.is_empty(); let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index)); self.lists.push(Self::add_index(is_initial_index, index));
}, }
&Term::Constant(_, Constant::String(ref s)) &Term::Constant(_, Constant::String(ref s))
if !self.flags.double_quotes.is_atom() && s.is_expandable() => { if !self.flags.double_quotes.is_atom() && s.is_expandable() =>
{
let is_initial_index = self.lists.is_empty(); let is_initial_index = self.lists.is_empty();
self.lists.push(Self::add_index(is_initial_index, index)); self.lists.push(Self::add_index(is_initial_index, index));
}, }
&Term::Constant(_, ref constant) => { &Term::Constant(_, ref constant) => {
let code = self.constants.entry(constant.clone()) let code = self.constants.entry(constant.clone()).or_insert(Vec::new());
.or_insert(Vec::new());
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
code.push(Self::add_index(is_initial_index, index)); code.push(Self::add_index(is_initial_index, index));
}, }
_ => {} _ => {}
}; };
} }
fn second_level_index<Index>(indices: IndexMap<Index, ThirdLevelIndex>, prelude: &mut CodeDeque) fn second_level_index<Index>(
-> IndexMap<Index, IntIndex> indices: IndexMap<Index, ThirdLevelIndex>,
where Index: Eq + Hash prelude: &mut CodeDeque,
) -> IndexMap<Index, IntIndex>
where
Index: Eq + Hash,
{ {
let mut index_locs = IndexMap::new(); let mut index_locs = IndexMap::new();
@@ -111,9 +120,9 @@ impl CodeOffsets {
no_constants && no_structures && no_lists no_constants && no_structures && no_lists
} }
fn flatten_index<Index>(index: IndexMap<Index, IntIndex>, len: usize) fn flatten_index<Index>(index: IndexMap<Index, IntIndex>, len: usize) -> IndexMap<Index, usize>
-> IndexMap<Index, usize> where
where Index: Eq + Hash Index: Eq + Hash,
{ {
let mut flattened_index = IndexMap::new(); let mut flattened_index = IndexMap::new();
@@ -121,10 +130,10 @@ impl CodeOffsets {
match int_index { match int_index {
IntIndex::External(offset) => { IntIndex::External(offset) => {
flattened_index.insert(key, offset + len + 1); flattened_index.insert(key, offset + len + 1);
}, }
IntIndex::Internal(offset) => { IntIndex::Internal(offset) => {
flattened_index.insert(key, offset + 1); flattened_index.insert(key, offset + 1);
}, }
_ => {} _ => {}
}; };
} }
@@ -132,18 +141,18 @@ impl CodeOffsets {
flattened_index flattened_index
} }
fn adjust_internal_index(index: IntIndex) -> IntIndex fn adjust_internal_index(index: IntIndex) -> IntIndex {
{
match index { match index {
IntIndex::Internal(o) => IntIndex::Internal(o + 1), IntIndex::Internal(o) => IntIndex::Internal(o + 1),
IntIndex::External(o) => IntIndex::External(o), IntIndex::External(o) => IntIndex::External(o),
_ => IntIndex::Fail _ => IntIndex::Fail,
} }
} }
fn switch_on_constant(con_ind: IndexMap<Constant, ThirdLevelIndex>, prelude: &mut CodeDeque) fn switch_on_constant(
-> IntIndex con_ind: IndexMap<Constant, ThirdLevelIndex>,
{ prelude: &mut CodeDeque,
) -> IntIndex {
let con_ind = Self::second_level_index(con_ind, prelude); let con_ind = Self::second_level_index(con_ind, prelude);
if con_ind.len() > 1 { if con_ind.len() > 1 {
@@ -154,16 +163,18 @@ impl CodeOffsets {
IntIndex::Internal(1) IntIndex::Internal(1)
} else { } else {
con_ind.values().next() con_ind
.values()
.next()
.map(|index| Self::adjust_internal_index(*index)) .map(|index| Self::adjust_internal_index(*index))
.unwrap_or(IntIndex::Fail) .unwrap_or(IntIndex::Fail)
} }
} }
fn switch_on_structure(str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>, fn switch_on_structure(
prelude: &mut CodeDeque) str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
-> IntIndex prelude: &mut CodeDeque,
{ ) -> IntIndex {
let str_ind = Self::second_level_index(str_ind, prelude); let str_ind = Self::second_level_index(str_ind, prelude);
if str_ind.len() > 1 { if str_ind.len() > 1 {
@@ -174,40 +185,43 @@ impl CodeOffsets {
IntIndex::Internal(1) IntIndex::Internal(1)
} else { } else {
str_ind.values().next() str_ind
.values()
.next()
.map(|index| Self::adjust_internal_index(*index)) .map(|index| Self::adjust_internal_index(*index))
.unwrap_or(IntIndex::Fail) .unwrap_or(IntIndex::Fail)
} }
} }
fn switch_on_list(mut lists: ThirdLevelIndex, prelude: &mut CodeDeque) -> IntIndex fn switch_on_list(mut lists: ThirdLevelIndex, prelude: &mut CodeDeque) -> IntIndex {
{
if lists.len() > 1 { if lists.len() > 1 {
Self::cap_choice_seq_with_trust(&mut lists); Self::cap_choice_seq_with_trust(&mut lists);
prelude.extend(lists.into_iter().map(|i| Line::from(i))); prelude.extend(lists.into_iter().map(|i| Line::from(i)));
IntIndex::Internal(0) IntIndex::Internal(0)
} else { } else {
lists.first() lists
.first()
.map(|i| IntIndex::External(i.offset())) .map(|i| IntIndex::External(i.offset()))
.unwrap_or(IntIndex::Fail) .unwrap_or(IntIndex::Fail)
} }
} }
fn switch_on_str_offset_from(str_loc: IntIndex, prelude_len: usize, con_loc: IntIndex) fn switch_on_str_offset_from(
-> usize str_loc: IntIndex,
{ prelude_len: usize,
con_loc: IntIndex,
) -> usize {
match str_loc { match str_loc {
IntIndex::External(o) => o + prelude_len + 1, IntIndex::External(o) => o + prelude_len + 1,
IntIndex::Fail => 0, IntIndex::Fail => 0,
IntIndex::Internal(_) => match con_loc { IntIndex::Internal(_) => match con_loc {
IntIndex::Internal(_) => 2, IntIndex::Internal(_) => 2,
_ => 1 _ => 1,
} },
} }
} }
fn switch_on_con_offset_from(con_loc: IntIndex, prelude_len: usize) -> usize fn switch_on_con_offset_from(con_loc: IntIndex, prelude_len: usize) -> usize {
{
match con_loc { match con_loc {
IntIndex::External(offset) => offset + prelude_len + 1, IntIndex::External(offset) => offset + prelude_len + 1,
IntIndex::Fail => 0, IntIndex::Fail => 0,
@@ -215,18 +229,19 @@ impl CodeOffsets {
} }
} }
fn switch_on_lst_offset_from(lst_loc: IntIndex, prelude_len: usize, lst_offset: usize) fn switch_on_lst_offset_from(
-> usize lst_loc: IntIndex,
{ prelude_len: usize,
lst_offset: usize,
) -> usize {
match lst_loc { match lst_loc {
IntIndex::External(o) => o + prelude_len + 1, IntIndex::External(o) => o + prelude_len + 1,
IntIndex::Fail => 0, IntIndex::Fail => 0,
IntIndex::Internal(_) => prelude_len - lst_offset + 1 IntIndex::Internal(_) => prelude_len - lst_offset + 1,
} }
} }
pub fn add_indices(self, code: &mut Code, mut code_body: Code) pub fn add_indices(self, code: &mut Code, mut code_body: Code) {
{
if self.no_indices() { if self.no_indices() {
*code = code_body; *code = code_body;
return; return;
@@ -246,8 +261,9 @@ impl CodeOffsets {
match line { match line {
&mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i)) &mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i))
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i)) | &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i))
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => | &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => {
*i += prelude_length - index, *i += prelude_length - index
}
_ => {} _ => {}
} }
} }
@@ -256,10 +272,8 @@ impl CodeOffsets {
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len()); let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len(), lst_offset); let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len(), lst_offset);
let switch_instr = IndexingInstruction::SwitchOnTerm(prelude.len() + 1, let switch_instr =
con_loc, IndexingInstruction::SwitchOnTerm(prelude.len() + 1, con_loc, lst_loc, str_loc);
lst_loc,
str_loc);
prelude.push_front(Line::from(switch_instr)); prelude.push_front(Line::from(switch_instr));

View File

@@ -13,22 +13,17 @@ use std::collections::VecDeque;
fn reg_type_into_functor(r: RegType) -> MachineStub { fn reg_type_into_functor(r: RegType) -> MachineStub {
match r { match r {
RegType::Temp(r) => RegType::Temp(r) => functor!("x", 1, [heap_integer!(Integer::from(r))]),
functor!("x", 1, [heap_integer!(Integer::from(r))]), RegType::Perm(r) => functor!("y", 1, [heap_integer!(Integer::from(r))]),
RegType::Perm(r) =>
functor!("y", 1, [heap_integer!(Integer::from(r))])
} }
} }
impl Level { impl Level {
fn into_functor(self) -> MachineStub { fn into_functor(self) -> MachineStub {
match self { match self {
Level::Root => Level::Root => functor!("level", 1, [heap_atom!("root")]),
functor!("level", 1, [heap_atom!("root")]), Level::Shallow => functor!("level", 1, [heap_atom!("shallow")]),
Level::Shallow => Level::Deep => functor!("level", 1, [heap_atom!("deep")]),
functor!("level", 1, [heap_atom!("shallow")]),
Level::Deep =>
functor!("level", 1, [heap_atom!("deep")]),
} }
} }
} }
@@ -36,12 +31,11 @@ impl Level {
impl ArithmeticTerm { impl ArithmeticTerm {
fn into_functor(&self) -> MachineStub { fn into_functor(&self) -> MachineStub {
match self { match self {
&ArithmeticTerm::Reg(r) => &ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
reg_type_into_functor(r), &ArithmeticTerm::Interm(i) => {
&ArithmeticTerm::Interm(i) => functor!("intermediate", 1, [heap_integer!(Integer::from(i))])
functor!("intermediate", 1, [heap_integer!(Integer::from(i))]), }
&ArithmeticTerm::Number(ref n) => &ArithmeticTerm::Number(ref n) => vec![heap_con!(n.clone().to_constant())],
vec![heap_con!(n.clone().to_constant())]
} }
} }
} }
@@ -51,22 +45,25 @@ pub enum ChoiceInstruction {
DefaultTrustMe, DefaultTrustMe,
RetryMeElse(usize), RetryMeElse(usize),
TrustMe, TrustMe,
TryMeElse(usize) TryMeElse(usize),
} }
impl ChoiceInstruction { impl ChoiceInstruction {
pub fn to_functor(&self) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&ChoiceInstruction::TryMeElse(offset) => &ChoiceInstruction::TryMeElse(offset) => {
functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))]), functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))])
&ChoiceInstruction::RetryMeElse(offset) => }
functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))]), &ChoiceInstruction::RetryMeElse(offset) => {
&ChoiceInstruction::TrustMe => functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))])
vec![heap_atom!("trust_me")], }
&ChoiceInstruction::DefaultRetryMeElse(offset) => &ChoiceInstruction::TrustMe => vec![heap_atom!("trust_me")],
functor!("default_retry_me_else", 1, [heap_integer!(Integer::from(offset))]), &ChoiceInstruction::DefaultRetryMeElse(offset) => functor!(
&ChoiceInstruction::DefaultTrustMe => "default_retry_me_else",
vec![heap_atom!("default_trust_me")], 1,
[heap_integer!(Integer::from(offset))]
),
&ChoiceInstruction::DefaultTrustMe => vec![heap_atom!("default_trust_me")],
} }
} }
} }
@@ -75,7 +72,7 @@ pub enum CutInstruction {
Cut(RegType), Cut(RegType),
GetLevel(RegType), GetLevel(RegType),
GetLevelAndUnify(RegType), GetLevelAndUnify(RegType),
NeckCut NeckCut,
} }
impl CutInstruction { impl CutInstruction {
@@ -85,19 +82,18 @@ impl CutInstruction {
let mut stub = functor!("cut", 1, [heap_str!(h + 2)]); let mut stub = functor!("cut", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&CutInstruction::GetLevel(r) => { &CutInstruction::GetLevel(r) => {
let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]); let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&CutInstruction::GetLevelAndUnify(r) => { &CutInstruction::GetLevelAndUnify(r) => {
let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]); let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&CutInstruction::NeckCut => &CutInstruction::NeckCut => vec![heap_atom!("neck_cut")],
vec![heap_atom!("neck_cut")]
} }
} }
} }
@@ -105,7 +101,7 @@ impl CutInstruction {
pub enum IndexedChoiceInstruction { pub enum IndexedChoiceInstruction {
Retry(usize), Retry(usize),
Trust(usize), Trust(usize),
Try(usize) Try(usize),
} }
impl From<IndexedChoiceInstruction> for Line { impl From<IndexedChoiceInstruction> for Line {
@@ -119,21 +115,24 @@ impl IndexedChoiceInstruction {
match self { match self {
&IndexedChoiceInstruction::Retry(offset) => offset, &IndexedChoiceInstruction::Retry(offset) => offset,
&IndexedChoiceInstruction::Trust(offset) => offset, &IndexedChoiceInstruction::Trust(offset) => offset,
&IndexedChoiceInstruction::Try(offset) => offset &IndexedChoiceInstruction::Try(offset) => offset,
} }
} }
pub fn to_functor(&self) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&IndexedChoiceInstruction::Try(offset) => &IndexedChoiceInstruction::Try(offset) => {
functor!("try", 1, [heap_integer!(Integer::from(offset))]), functor!("try", 1, [heap_integer!(Integer::from(offset))])
&IndexedChoiceInstruction::Trust(offset) => }
functor!("trust", 1, [heap_integer!(Integer::from(offset))]), &IndexedChoiceInstruction::Trust(offset) => {
&IndexedChoiceInstruction::Retry(offset) => functor!("trust", 1, [heap_integer!(Integer::from(offset))])
}
&IndexedChoiceInstruction::Retry(offset) => {
functor!("retry", 1, [heap_integer!(Integer::from(offset))]) functor!("retry", 1, [heap_integer!(Integer::from(offset))])
} }
} }
} }
}
pub enum Line { pub enum Line {
Arithmetic(ArithmeticInstruction), Arithmetic(ArithmeticInstruction),
@@ -143,7 +142,7 @@ pub enum Line {
Fact(FactInstruction), Fact(FactInstruction),
Indexing(IndexingInstruction), Indexing(IndexingInstruction),
IndexedChoice(IndexedChoiceInstruction), IndexedChoice(IndexedChoiceInstruction),
Query(QueryInstruction) Query(QueryInstruction),
} }
impl Line { impl Line {
@@ -152,7 +151,7 @@ impl Line {
&Line::Cut(_) => true, &Line::Cut(_) => true,
&Line::Fact(_) => true, &Line::Fact(_) => true,
&Line::Query(_) => true, &Line::Query(_) => true,
_ => false _ => false,
} }
} }
@@ -165,7 +164,7 @@ impl Line {
&Line::Fact(ref fact_instr) => fact_instr.to_functor(h), &Line::Fact(ref fact_instr) => fact_instr.to_functor(h),
&Line::Indexing(ref indexing_instr) => indexing_instr.to_functor(), &Line::Indexing(ref indexing_instr) => indexing_instr.to_functor(),
&Line::IndexedChoice(ref indexed_choice_instr) => indexed_choice_instr.to_functor(), &Line::IndexedChoice(ref indexed_choice_instr) => indexed_choice_instr.to_functor(),
&Line::Query(ref query_instr) => query_instr.to_functor(h) &Line::Query(ref query_instr) => query_instr.to_functor(h),
} }
} }
} }
@@ -208,33 +207,46 @@ pub enum ArithmeticInstruction {
Floor(ArithmeticTerm, usize), Floor(ArithmeticTerm, usize),
Neg(ArithmeticTerm, usize), Neg(ArithmeticTerm, usize),
Plus(ArithmeticTerm, usize), Plus(ArithmeticTerm, usize),
BitwiseComplement(ArithmeticTerm, usize) BitwiseComplement(ArithmeticTerm, usize),
} }
fn arith_instr_unary_functor(h: usize, name: &'static str, at: &ArithmeticTerm, t: usize) fn arith_instr_unary_functor(
-> MachineStub h: usize,
{ name: &'static str,
at: &ArithmeticTerm,
t: usize,
) -> MachineStub {
let at_stub = at.into_functor(); let at_stub = at.into_functor();
let mut stub = functor!(name, 2, let mut stub = functor!(
[heap_cell!(h + 4), name,
heap_integer!(Integer::from(t))]); 2,
[heap_cell!(h + 4), heap_integer!(Integer::from(t))]
);
stub.extend(at_stub.into_iter()); stub.extend(at_stub.into_iter());
stub stub
} }
fn arith_instr_bin_functor(h: usize, name: &'static str, at_1: &ArithmeticTerm, fn arith_instr_bin_functor(
at_2: &ArithmeticTerm, t: usize) h: usize,
-> MachineStub name: &'static str,
{ at_1: &ArithmeticTerm,
at_2: &ArithmeticTerm,
t: usize,
) -> MachineStub {
let at_1_stub = at_1.into_functor(); let at_1_stub = at_1.into_functor();
let at_2_stub = at_2.into_functor(); let at_2_stub = at_2.into_functor();
let mut stub = functor!(name, 3, let mut stub = functor!(
[heap_cell!(h + 4), name,
3,
[
heap_cell!(h + 4),
heap_cell!(h + 4 + at_1_stub.len()), heap_cell!(h + 4 + at_1_stub.len()),
heap_integer!(Integer::from(t))]); heap_integer!(Integer::from(t))
]
);
stub.extend(at_1_stub.into_iter()); stub.extend(at_1_stub.into_iter());
stub.extend(at_2_stub.into_iter()); stub.extend(at_2_stub.into_iter());
@@ -245,80 +257,93 @@ fn arith_instr_bin_functor(h: usize, name: &'static str, at_1: &ArithmeticTerm,
impl ArithmeticInstruction { impl ArithmeticInstruction {
pub fn to_functor(&self, h: usize) -> MachineStub { pub fn to_functor(&self, h: usize) -> MachineStub {
match self { match self {
&ArithmeticInstruction::Add(ref at_1, ref at_2, t) => &ArithmeticInstruction::Add(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "add", at_1, at_2, t), arith_instr_bin_functor(h, "add", at_1, at_2, t)
&ArithmeticInstruction::Sub(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "sub", at_1, at_2, t), &ArithmeticInstruction::Sub(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::Mul(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "sub", at_1, at_2, t)
arith_instr_bin_functor(h, "mul", at_1, at_2, t), }
&ArithmeticInstruction::IntPow(ref at_1, ref at_2, t) => &ArithmeticInstruction::Mul(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "int_pow", at_1, at_2, t), arith_instr_bin_functor(h, "mul", at_1, at_2, t)
&ArithmeticInstruction::Pow(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "pow", at_1, at_2, t), &ArithmeticInstruction::IntPow(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::IDiv(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "int_pow", at_1, at_2, t)
arith_instr_bin_functor(h, "idiv", at_1, at_2, t), }
&ArithmeticInstruction::Max(ref at_1, ref at_2, t) => &ArithmeticInstruction::Pow(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "max", at_1, at_2, t), arith_instr_bin_functor(h, "pow", at_1, at_2, t)
&ArithmeticInstruction::Min(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "min", at_1, at_2, t), &ArithmeticInstruction::IDiv(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::IntFloorDiv(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "idiv", at_1, at_2, t)
arith_instr_bin_functor(h, "int_floor_div", at_1, at_2, t), }
&ArithmeticInstruction::RDiv(ref at_1, ref at_2, t) => &ArithmeticInstruction::Max(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "rdiv", at_1, at_2, t), arith_instr_bin_functor(h, "max", at_1, at_2, t)
&ArithmeticInstruction::Div(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "div", at_1, at_2, t), &ArithmeticInstruction::Min(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::Shl(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "min", at_1, at_2, t)
arith_instr_bin_functor(h, "shl", at_1, at_2, t), }
&ArithmeticInstruction::Shr(ref at_1, ref at_2, t) => &ArithmeticInstruction::IntFloorDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "shr", at_1, at_2, t), arith_instr_bin_functor(h, "int_floor_div", at_1, at_2, t)
&ArithmeticInstruction::Xor(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "xor", at_1, at_2, t), &ArithmeticInstruction::RDiv(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::And(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "rdiv", at_1, at_2, t)
arith_instr_bin_functor(h, "and", at_1, at_2, t), }
&ArithmeticInstruction::Or(ref at_1, ref at_2, t) => &ArithmeticInstruction::Div(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "or", at_1, at_2, t), arith_instr_bin_functor(h, "div", at_1, at_2, t)
&ArithmeticInstruction::Mod(ref at_1, ref at_2, t) => }
arith_instr_bin_functor(h, "mod", at_1, at_2, t), &ArithmeticInstruction::Shl(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::Rem(ref at_1, ref at_2, t) => arith_instr_bin_functor(h, "shl", at_1, at_2, t)
arith_instr_bin_functor(h, "rem", at_1, at_2, t), }
&ArithmeticInstruction::ATan2(ref at_1, ref at_2, t) => &ArithmeticInstruction::Shr(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, "rem", at_1, at_2, t), arith_instr_bin_functor(h, "shr", at_1, at_2, t)
&ArithmeticInstruction::Cos(ref at, t) => }
arith_instr_unary_functor(h, "cos", at, t), &ArithmeticInstruction::Xor(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::Sin(ref at, t) => arith_instr_bin_functor(h, "xor", at_1, at_2, t)
arith_instr_unary_functor(h, "sin", at, t), }
&ArithmeticInstruction::Tan(ref at, t) => &ArithmeticInstruction::And(ref at_1, ref at_2, t) => {
arith_instr_unary_functor(h, "tan", at, t), arith_instr_bin_functor(h, "and", at_1, at_2, t)
&ArithmeticInstruction::Log(ref at, t) => }
arith_instr_unary_functor(h, "log", at, t), &ArithmeticInstruction::Or(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::Exp(ref at, t) => arith_instr_bin_functor(h, "or", at_1, at_2, t)
arith_instr_unary_functor(h, "exp", at, t), }
&ArithmeticInstruction::ACos(ref at, t) => &ArithmeticInstruction::Mod(ref at_1, ref at_2, t) => {
arith_instr_unary_functor(h, "acos", at, t), arith_instr_bin_functor(h, "mod", at_1, at_2, t)
&ArithmeticInstruction::ASin(ref at, t) => }
arith_instr_unary_functor(h, "asin", at, t), &ArithmeticInstruction::Rem(ref at_1, ref at_2, t) => {
&ArithmeticInstruction::ATan(ref at, t) => arith_instr_bin_functor(h, "rem", at_1, at_2, t)
arith_instr_unary_functor(h, "atan", at, t), }
&ArithmeticInstruction::Sqrt(ref at, t) => &ArithmeticInstruction::ATan2(ref at_1, ref at_2, t) => {
arith_instr_unary_functor(h, "sqrt", at, t), arith_instr_bin_functor(h, "rem", at_1, at_2, t)
&ArithmeticInstruction::Abs(ref at, t) => }
arith_instr_unary_functor(h, "abs", at, t), &ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
&ArithmeticInstruction::Float(ref at, t) => &ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
arith_instr_unary_functor(h, "float", at, t), &ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
&ArithmeticInstruction::Truncate(ref at, t) => &ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t),
arith_instr_unary_functor(h, "truncate", at, t), &ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t),
&ArithmeticInstruction::Round(ref at, t) => &ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t),
arith_instr_unary_functor(h, "round", at, t), &ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t),
&ArithmeticInstruction::Ceiling(ref at, t) => &ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t),
arith_instr_unary_functor(h, "ceiling", at, t), &ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t),
&ArithmeticInstruction::Floor(ref at, t) => &ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t),
arith_instr_unary_functor(h, "floor", at, t), &ArithmeticInstruction::Float(ref at, t) => {
&ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "float", at, t)
arith_instr_unary_functor(h, "-", at, t), }
&ArithmeticInstruction::Plus(ref at, t) => &ArithmeticInstruction::Truncate(ref at, t) => {
arith_instr_unary_functor(h, "+", at, t), arith_instr_unary_functor(h, "truncate", at, t)
&ArithmeticInstruction::BitwiseComplement(ref at, t) => }
arith_instr_unary_functor(h, "\\", at, t), &ArithmeticInstruction::Round(ref at, t) => {
arith_instr_unary_functor(h, "round", at, t)
}
&ArithmeticInstruction::Ceiling(ref at, t) => {
arith_instr_unary_functor(h, "ceiling", at, t)
}
&ArithmeticInstruction::Floor(ref at, t) => {
arith_instr_unary_functor(h, "floor", at, t)
}
&ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(h, "-", at, t),
&ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(h, "+", at, t),
&ArithmeticInstruction::BitwiseComplement(ref at, t) => {
arith_instr_unary_functor(h, "\\", at, t)
}
} }
} }
} }
@@ -329,7 +354,7 @@ pub enum ControlInstruction {
CallClause(ClauseType, usize, usize, bool, bool), CallClause(ClauseType, usize, usize, bool, bool),
Deallocate, Deallocate,
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call. JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
Proceed Proceed,
} }
impl ControlInstruction { impl ControlInstruction {
@@ -337,26 +362,36 @@ impl ControlInstruction {
match self { match self {
&ControlInstruction::CallClause(..) => true, &ControlInstruction::CallClause(..) => true,
&ControlInstruction::JmpBy(..) => true, &ControlInstruction::JmpBy(..) => true,
_ => false _ => false,
} }
} }
pub fn to_functor(&self) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&ControlInstruction::Allocate(num_frames) => &ControlInstruction::Allocate(num_frames) => {
functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))]), functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))])
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => }
functor!("call", 2, [heap_con!(Constant::Atom(ct.name(), None)), &ControlInstruction::CallClause(ref ct, arity, _, false, _) => functor!(
heap_integer!(Integer::from(arity))]), "call",
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => 2,
functor!("execute", 2, [heap_con!(Constant::Atom(ct.name(), None)), [
heap_integer!(Integer::from(arity))]), heap_con!(Constant::Atom(ct.name(), None)),
&ControlInstruction::Deallocate => heap_integer!(Integer::from(arity))
vec![heap_atom!("deallocate")], ]
&ControlInstruction::JmpBy(_, offset, ..) => ),
functor!("jmp_by", 1, [heap_integer!(Integer::from(offset))]), &ControlInstruction::CallClause(ref ct, arity, _, true, _) => functor!(
&ControlInstruction::Proceed => "execute",
vec![heap_atom!("proceed")] 2,
[
heap_con!(Constant::Atom(ct.name(), None)),
heap_integer!(Integer::from(arity))
]
),
&ControlInstruction::Deallocate => vec![heap_atom!("deallocate")],
&ControlInstruction::JmpBy(_, offset, ..) => {
functor!("jmp_by", 1, [heap_integer!(Integer::from(offset))])
}
&ControlInstruction::Proceed => vec![heap_atom!("proceed")],
} }
} }
} }
@@ -364,7 +399,7 @@ impl ControlInstruction {
pub enum IndexingInstruction { pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize), SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, IndexMap<Constant, usize>), SwitchOnConstant(usize, IndexMap<Constant, usize>),
SwitchOnStructure(usize, IndexMap<(ClauseName, usize), usize>) SwitchOnStructure(usize, IndexMap<(ClauseName, usize), usize>),
} }
impl From<IndexingInstruction> for Line { impl From<IndexingInstruction> for Line {
@@ -376,18 +411,26 @@ impl From<IndexingInstruction> for Line {
impl IndexingInstruction { impl IndexingInstruction {
pub fn to_functor(&self) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => &IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => functor!(
functor!("switch_on_term", 4, "switch_on_term",
[heap_integer!(Integer::from(vars)), 4,
[
heap_integer!(Integer::from(vars)),
heap_integer!(Integer::from(constants)), heap_integer!(Integer::from(constants)),
heap_integer!(Integer::from(lists)), heap_integer!(Integer::from(lists)),
heap_integer!(Integer::from(structures))]), heap_integer!(Integer::from(structures))
&IndexingInstruction::SwitchOnConstant(constants, _) => ]
functor!("switch_on_constant", 1, ),
[heap_integer!(Integer::from(constants))]), &IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
&IndexingInstruction::SwitchOnStructure(structures, _) => "switch_on_constant",
functor!("switch_on_structure", 1, 1,
[heap_integer!(Integer::from(structures))]) [heap_integer!(Integer::from(constants))]
),
&IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
"switch_on_structure",
1,
[heap_integer!(Integer::from(structures))]
),
} }
} }
} }
@@ -403,82 +446,96 @@ pub enum FactInstruction {
UnifyLocalValue(RegType), UnifyLocalValue(RegType),
UnifyVariable(RegType), UnifyVariable(RegType),
UnifyValue(RegType), UnifyValue(RegType),
UnifyVoid(usize) UnifyVoid(usize),
} }
impl FactInstruction { impl FactInstruction {
pub fn to_functor(&self, h: usize) -> MachineStub { pub fn to_functor(&self, h: usize) -> MachineStub {
match self { match self {
&FactInstruction::GetConstant(lvl, ref constant, r) => { &FactInstruction::GetConstant(lvl, ref constant, r) => {
let mut stub = functor!("get_constant", 3, let mut stub = functor!(
[heap_str!(h + 4), "get_constant",
3,
[
heap_str!(h + 4),
heap_con!(constant.clone()), heap_con!(constant.clone()),
heap_str!(h + 6)]); heap_str!(h + 6)
]
);
stub.append(&mut lvl.into_functor()); stub.append(&mut lvl.into_functor());
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::GetList(lvl, r) => { &FactInstruction::GetList(lvl, r) => {
let mut stub = functor!("get_list", 2, let mut stub = functor!("get_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
[heap_str!(h + 3),
heap_str!(h + 5)]);
stub.append(&mut lvl.into_functor()); stub.append(&mut lvl.into_functor());
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::GetStructure(ref ct, arity, r) => { &FactInstruction::GetStructure(ref ct, arity, r) => {
let mut stub = functor!("get_structure", 3, let mut stub = functor!(
[heap_con!(Constant::Atom(ct.name(), None)), "get_structure",
3,
[
heap_con!(Constant::Atom(ct.name(), None)),
heap_integer!(Integer::from(arity)), heap_integer!(Integer::from(arity)),
heap_str!(h + 4)]); heap_str!(h + 4)
]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::GetValue(r, arg) => { &FactInstruction::GetValue(r, arg) => {
let mut stub = functor!("get_value", 2, let mut stub = functor!(
[heap_str!(h + 3), "get_value",
heap_integer!(Integer::from(arg))]); 2,
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::GetVariable(r, arg) => { &FactInstruction::GetVariable(r, arg) => {
let mut stub = functor!("get_variable", 2, let mut stub = functor!(
[heap_str!(h + 3), "get_variable",
heap_integer!(Integer::from(arg))]); 2,
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::UnifyConstant(ref constant) => &FactInstruction::UnifyConstant(ref constant) => {
functor!("unify_constant", 1, [heap_con!(constant.clone())]), functor!("unify_constant", 1, [heap_con!(constant.clone())])
}
&FactInstruction::UnifyLocalValue(r) => { &FactInstruction::UnifyLocalValue(r) => {
let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]); let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::UnifyVariable(r) => { &FactInstruction::UnifyVariable(r) => {
let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]); let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::UnifyValue(r) => { &FactInstruction::UnifyValue(r) => {
let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]); let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&FactInstruction::UnifyVoid(vars) => &FactInstruction::UnifyVoid(vars) => {
functor!("unify_void", 1, [heap_integer!(Integer::from(vars))]) functor!("unify_void", 1, [heap_integer!(Integer::from(vars))])
} }
} }
} }
}
#[derive(Clone)] #[derive(Clone)]
pub enum QueryInstruction { pub enum QueryInstruction {
@@ -493,95 +550,115 @@ pub enum QueryInstruction {
SetLocalValue(RegType), SetLocalValue(RegType),
SetVariable(RegType), SetVariable(RegType),
SetValue(RegType), SetValue(RegType),
SetVoid(usize) SetVoid(usize),
} }
impl QueryInstruction { impl QueryInstruction {
pub fn to_functor(&self, h: usize) -> MachineStub { pub fn to_functor(&self, h: usize) -> MachineStub {
match self { match self {
&QueryInstruction::PutUnsafeValue(norm, arg) => &QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
functor!("put_unsafe_value", 2, "put_unsafe_value",
[heap_integer!(Integer::from(norm)), 2,
heap_integer!(Integer::from(arg))]), [
heap_integer!(Integer::from(norm)),
heap_integer!(Integer::from(arg))
]
),
&QueryInstruction::PutConstant(lvl, ref constant, r) => { &QueryInstruction::PutConstant(lvl, ref constant, r) => {
let mut stub = functor!("put_constant", 3, let mut stub = functor!(
[heap_str!(h + 4), "put_constant",
3,
[
heap_str!(h + 4),
heap_con!(constant.clone()), heap_con!(constant.clone()),
heap_str!(h + 6)]); heap_str!(h + 6)
]
);
stub.append(&mut lvl.into_functor()); stub.append(&mut lvl.into_functor());
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::PutList(lvl, r) => { &QueryInstruction::PutList(lvl, r) => {
let mut stub = functor!("put_list", 2, let mut stub = functor!("put_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
[heap_str!(h + 3),
heap_str!(h + 5)]);
stub.append(&mut lvl.into_functor()); stub.append(&mut lvl.into_functor());
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::PutStructure(ref ct, arity, r) => { &QueryInstruction::PutStructure(ref ct, arity, r) => {
let mut stub = functor!("put_structure", 3, let mut stub = functor!(
[heap_con!(Constant::Atom(ct.name(), None)), "put_structure",
3,
[
heap_con!(Constant::Atom(ct.name(), None)),
heap_integer!(Integer::from(arity)), heap_integer!(Integer::from(arity)),
heap_str!(h + 4)]); heap_str!(h + 4)
]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::PutValue(r, arg) => { &QueryInstruction::PutValue(r, arg) => {
let mut stub = functor!("put_value", 2, let mut stub = functor!(
[heap_str!(h + 3), "put_value",
heap_integer!(Integer::from(arg))]); 2,
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::GetVariable(r, arg) => { &QueryInstruction::GetVariable(r, arg) => {
let mut stub = functor!("get_variable", 2, let mut stub = functor!(
[heap_str!(h + 3), "get_variable",
heap_integer!(Integer::from(arg))]); 2,
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::PutVariable(r, arg) => { &QueryInstruction::PutVariable(r, arg) => {
let mut stub = functor!("put_variable", 2, let mut stub = functor!(
[heap_str!(h + 3), "put_variable",
heap_integer!(Integer::from(arg))]); 2,
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::SetConstant(ref constant) => &QueryInstruction::SetConstant(ref constant) => {
functor!("set_constant", 1, [heap_con!(constant.clone())]), functor!("set_constant", 1, [heap_con!(constant.clone())])
}
&QueryInstruction::SetLocalValue(r) => { &QueryInstruction::SetLocalValue(r) => {
let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]); let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::SetVariable(r) => { &QueryInstruction::SetVariable(r) => {
let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]); let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::SetValue(r) => { &QueryInstruction::SetValue(r) => {
let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]); let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]);
stub.append(&mut reg_type_into_functor(r)); stub.append(&mut reg_type_into_functor(r));
stub stub
}, }
&QueryInstruction::SetVoid(vars) => &QueryInstruction::SetVoid(vars) => {
functor!("set_void", 1, [heap_integer!(Integer::from(vars))]) functor!("set_void", 1, [heap_integer!(Integer::from(vars))])
} }
} }
} }
}
pub type CompiledFact = Vec<FactInstruction>; pub type CompiledFact = Vec<FactInstruction>;

View File

@@ -16,7 +16,7 @@ pub enum TermRef<'a> {
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term), Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Constant(Level, &'a Cell<RegType>, &'a Constant), Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>), Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
Var(Level, &'a Cell<VarReg>, Rc<Var>) Var(Level, &'a Cell<VarReg>, Rc<Var>),
} }
impl<'a> TermRef<'a> { impl<'a> TermRef<'a> {
@@ -26,7 +26,7 @@ impl<'a> TermRef<'a> {
| TermRef::Cons(lvl, ..) | TermRef::Cons(lvl, ..)
| TermRef::Constant(lvl, ..) | TermRef::Constant(lvl, ..)
| TermRef::Var(lvl, ..) | TermRef::Var(lvl, ..)
| TermRef::Clause(lvl, ..) => lvl | TermRef::Clause(lvl, ..) => lvl,
} }
} }
} }
@@ -34,17 +34,22 @@ impl<'a> TermRef<'a> {
pub enum TermIterState<'a> { pub enum TermIterState<'a> {
AnonVar(Level), AnonVar(Level),
Constant(Level, &'a Cell<RegType>, &'a Constant), Constant(Level, &'a Cell<RegType>, &'a Constant),
Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>), Clause(
Level,
usize,
&'a Cell<RegType>,
ClauseType,
&'a Vec<Box<Term>>,
),
InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term), InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term), FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
Var(Level, &'a Cell<VarReg>, Rc<Var>) Var(Level, &'a Cell<VarReg>, Rc<Var>),
} }
impl<'a> TermIterState<'a> { impl<'a> TermIterState<'a> {
pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
match term { match term {
&Term::AnonVar => &Term::AnonVar => TermIterState::AnonVar(lvl),
TermIterState::AnonVar(lvl),
&Term::Clause(ref cell, ref name, ref subterms, ref spec) => { &Term::Clause(ref cell, ref name, ref subterms, ref spec) => {
let ct = if let Some(spec) = spec { let ct = if let Some(spec) = spec {
ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default()) ClauseType::Op(name.clone(), spec.clone(), CodeIndex::default())
@@ -53,13 +58,12 @@ impl<'a> TermIterState<'a> {
}; };
TermIterState::Clause(lvl, 0, cell, ct, subterms) TermIterState::Clause(lvl, 0, cell, ct, subterms)
}, }
&Term::Cons(ref cell, ref head, ref tail) => &Term::Cons(ref cell, ref head, ref tail) => {
TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()), TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref())
&Term::Constant(ref cell, ref constant) => }
TermIterState::Constant(lvl, cell, constant), &Term::Constant(ref cell, ref constant) => TermIterState::Constant(lvl, cell, constant),
&Term::Var(ref cell, ref var) => &Term::Var(ref cell, ref var) => TermIterState::Var(lvl, cell, var.clone()),
TermIterState::Var(lvl, cell, var.clone())
} }
} }
} }
@@ -70,11 +74,14 @@ pub struct QueryIterator<'a> {
impl<'a> QueryIterator<'a> { impl<'a> QueryIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) { fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::subterm_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 { fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
let state_stack = terms.iter().rev() let state_stack = terms
.iter()
.rev()
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref())) .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
.collect(); .collect();
@@ -83,50 +90,74 @@ impl<'a> QueryIterator<'a> {
fn from_term(term: &'a Term) -> Self { fn from_term(term: &'a Term) -> Self {
let state = match term { let state = match term {
&Term::AnonVar => &Term::AnonVar => {
return QueryIterator { state_stack: vec![] }, return QueryIterator {
&Term::Clause(ref r, ref name, ref terms, ref fixity) => state_stack: vec![],
TermIterState::Clause(Level::Root, 0, r, }
}
&Term::Clause(ref r, ref name, ref terms, ref fixity) => TermIterState::Clause(
Level::Root,
0,
r,
ClauseType::from(name.clone(), terms.len(), fixity.clone()), ClauseType::from(name.clone(), terms.len(), fixity.clone()),
terms), terms,
&Term::Cons(..) => ),
return QueryIterator { state_stack: vec![] }, &Term::Cons(..) => {
&Term::Constant(_, _) => return QueryIterator {
return QueryIterator { state_stack: vec![] }, state_stack: vec![],
&Term::Var(ref cell, ref var) => }
TermIterState::Var(Level::Root, cell, (*var).clone()) }
&Term::Constant(_, _) => {
return QueryIterator {
state_stack: vec![],
}
}
&Term::Var(ref cell, ref var) => TermIterState::Var(Level::Root, cell, (*var).clone()),
}; };
QueryIterator { state_stack: vec![state] } QueryIterator {
state_stack: vec![state],
}
} }
fn new(term: &'a QueryTerm) -> Self { fn new(term: &'a QueryTerm) -> Self {
match term { match term {
&QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms, _) => { &QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms, _) => {
let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms); let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
QueryIterator { state_stack: vec![state] } QueryIterator {
}, state_stack: vec![state],
}
}
&QueryTerm::Clause(ref cell, ref ct, ref terms, _) => { &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms); let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator { state_stack: vec![state] } QueryIterator {
}, state_stack: vec![state],
}
}
&QueryTerm::UnblockedCut(ref cell) => { &QueryTerm::UnblockedCut(ref cell) => {
let state = TermIterState::Var(Level::Root, cell, rc_atom!("!")); let state = TermIterState::Var(Level::Root, cell, rc_atom!("!"));
QueryIterator { state_stack: vec![state] } QueryIterator {
}, state_stack: vec![state],
}
}
&QueryTerm::GetLevelAndUnify(ref cell, ref var) => { &QueryTerm::GetLevelAndUnify(ref cell, ref var) => {
let state = TermIterState::Var(Level::Root, cell, var.clone()); let state = TermIterState::Var(Level::Root, cell, var.clone());
QueryIterator { state_stack: vec![state] } QueryIterator {
}, state_stack: vec![state],
}
}
&QueryTerm::Jump(ref vars) => { &QueryTerm::Jump(ref vars) => {
let state_stack = vars.iter().rev().map(|t| { let state_stack = vars
TermIterState::subterm_to_state(Level::Shallow, t) .iter()
}).collect(); .rev()
.map(|t| TermIterState::subterm_to_state(Level::Shallow, t))
.collect();
QueryIterator { state_stack } QueryIterator { state_stack }
}
&QueryTerm::BlockedCut => QueryIterator {
state_stack: vec![],
}, },
&QueryTerm::BlockedCut =>
QueryIterator { state_stack: vec![] },
} }
} }
} }
@@ -137,39 +168,46 @@ impl<'a> Iterator for QueryIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() { while let Some(iter_state) = self.state_stack.pop() {
match iter_state { match iter_state {
TermIterState::AnonVar(lvl) => TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
return Some(TermRef::AnonVar(lvl)),
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => { TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() { if child_num == child_terms.len() {
match ct { match ct {
ClauseType::CallN => ClauseType::CallN => {
self.push_subterm(Level::Shallow, child_terms[0].as_ref()), self.push_subterm(Level::Shallow, child_terms[0].as_ref())
ClauseType::Named(..) | ClauseType::Op(..) => }
ClauseType::Named(..) | ClauseType::Op(..) => {
return match lvl { return match lvl {
Level::Root => None, Level::Root => None,
lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)) lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms)),
}, }
_ => }
return None _ => return None,
}; };
} else { } else {
self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, self.state_stack.push(TermIterState::Clause(
cell, ct, child_terms)); lvl,
child_num + 1,
cell,
ct,
child_terms,
));
self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref()); self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
} }
}, }
TermIterState::InitialCons(lvl, cell, head, tail) => { TermIterState::InitialCons(lvl, cell, head, tail) => {
self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail)); self.state_stack
.push(TermIterState::FinalCons(lvl, cell, head, tail));
self.push_subterm(lvl.child_level(), tail); self.push_subterm(lvl.child_level(), tail);
self.push_subterm(lvl.child_level(), head); self.push_subterm(lvl.child_level(), head);
}, }
TermIterState::FinalCons(lvl, cell, head, tail) => TermIterState::FinalCons(lvl, cell, head, tail) => {
return Some(TermRef::Cons(lvl, cell, head, tail)), return Some(TermRef::Cons(lvl, cell, head, tail))
TermIterState::Constant(lvl, cell, constant) => }
return Some(TermRef::Constant(lvl, cell, constant)), TermIterState::Constant(lvl, cell, constant) => {
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Constant(lvl, cell, constant))
return Some(TermRef::Var(lvl, cell, var)) }
TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
}; };
} }
@@ -179,39 +217,52 @@ impl<'a> Iterator for QueryIterator<'a> {
pub struct FactIterator<'a> { pub struct FactIterator<'a> {
state_queue: VecDeque<TermIterState<'a>>, state_queue: VecDeque<TermIterState<'a>>,
iterable_root: bool iterable_root: bool,
} }
impl<'a> FactIterator<'a> { impl<'a> FactIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) { fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term)); self.state_queue
.push_back(TermIterState::subterm_to_state(lvl, term));
} }
pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self { pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
let state_queue = terms.iter() let state_queue = terms
.iter()
.map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref())) .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
.collect(); .collect();
FactIterator { state_queue, iterable_root: false } FactIterator {
state_queue,
iterable_root: false,
}
} }
fn new(term: &'a Term, iterable_root: bool) -> Self { fn new(term: &'a Term, iterable_root: bool) -> Self {
let states = match term { let states = match term {
&Term::AnonVar => &Term::AnonVar => vec![TermIterState::AnonVar(Level::Root)],
vec![TermIterState::AnonVar(Level::Root)],
&Term::Clause(ref cell, ref name, ref terms, ref fixity) => { &Term::Clause(ref cell, ref name, ref terms, ref fixity) => {
let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone()); let ct = ClauseType::from(name.clone(), terms.len(), fixity.clone());
vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)] vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
}, }
&Term::Cons(ref cell, ref head, ref tail) => &Term::Cons(ref cell, ref head, ref tail) => vec![TermIterState::InitialCons(
vec![TermIterState::InitialCons(Level::Root, cell, head.as_ref(), tail.as_ref())], Level::Root,
&Term::Constant(ref cell, ref constant) => cell,
vec![TermIterState::Constant(Level::Root, cell, constant)], head.as_ref(),
&Term::Var(ref cell, ref var) => tail.as_ref(),
)],
&Term::Constant(ref cell, ref constant) => {
vec![TermIterState::Constant(Level::Root, cell, constant)]
}
&Term::Var(ref cell, ref var) => {
vec![TermIterState::Var(Level::Root, cell, var.clone())] vec![TermIterState::Var(Level::Root, cell, var.clone())]
}
}; };
FactIterator { state_queue: VecDeque::from(states), iterable_root } FactIterator {
state_queue: VecDeque::from(states),
iterable_root,
}
} }
} }
@@ -221,8 +272,7 @@ impl<'a> Iterator for FactIterator<'a> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
while let Some(state) = self.state_queue.pop_front() { while let Some(state) = self.state_queue.pop_front() {
match state { match state {
TermIterState::AnonVar(lvl) => TermIterState::AnonVar(lvl) => return Some(TermRef::AnonVar(lvl)),
return Some(TermRef::AnonVar(lvl)),
TermIterState::Clause(lvl, _, cell, ct, child_terms) => { TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
for child_term in child_terms { for child_term in child_terms {
self.push_subterm(lvl.child_level(), child_term); self.push_subterm(lvl.child_level(), child_term);
@@ -230,19 +280,19 @@ impl<'a> Iterator for FactIterator<'a> {
match lvl { match lvl {
Level::Root if !self.iterable_root => continue, Level::Root if !self.iterable_root => continue,
_ => return Some(TermRef::Clause(lvl, cell, ct, child_terms)) _ => return Some(TermRef::Clause(lvl, cell, ct, child_terms)),
}; };
}, }
TermIterState::InitialCons(lvl, cell, head, tail) => { TermIterState::InitialCons(lvl, cell, head, tail) => {
self.push_subterm(Level::Deep, head); self.push_subterm(Level::Deep, head);
self.push_subterm(Level::Deep, tail); self.push_subterm(Level::Deep, tail);
return Some(TermRef::Cons(lvl, cell, head, tail)); return Some(TermRef::Cons(lvl, cell, head, tail));
}, }
TermIterState::Constant(lvl, cell, constant) => TermIterState::Constant(lvl, cell, constant) => {
return Some(TermRef::Constant(lvl, cell, constant)), return Some(TermRef::Constant(lvl, cell, constant))
TermIterState::Var(lvl, cell, var) => }
return Some(TermRef::Var(lvl, cell, var)), TermIterState::Var(lvl, cell, var) => return Some(TermRef::Var(lvl, cell, var)),
_ => {} _ => {}
} }
} }
@@ -261,7 +311,7 @@ pub fn breadth_first_iter(term: &Term, iterable_root: bool) -> FactIterator {
pub enum ChunkedTerm<'a> { pub enum ChunkedTerm<'a> {
HeadClause(ClauseName, &'a Vec<Box<Term>>), HeadClause(ClauseName, &'a Vec<Box<Term>>),
BodyTerm(&'a QueryTerm) BodyTerm(&'a QueryTerm),
} }
pub fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> { pub fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> {
@@ -271,10 +321,8 @@ pub fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterato
impl<'a> ChunkedTerm<'a> { impl<'a> ChunkedTerm<'a> {
pub fn post_order_iter(&self) -> QueryIterator<'a> { pub fn post_order_iter(&self) -> QueryIterator<'a> {
match self { match self {
&ChunkedTerm::BodyTerm(ref qt) => &ChunkedTerm::BodyTerm(ref qt) => QueryIterator::new(qt),
QueryIterator::new(qt), &ChunkedTerm::HeadClause(_, terms) => QueryIterator::from_rule_head_clause(terms),
&ChunkedTerm::HeadClause(_, terms) =>
QueryIterator::from_rule_head_clause(terms)
} }
} }
} }
@@ -291,28 +339,26 @@ fn contains_cut_var<'a, Iter: Iterator<Item=&'a Term>>(terms: Iter) -> bool {
false false
} }
pub struct ChunkedIterator<'a> pub struct ChunkedIterator<'a> {
{
pub chunk_num: usize, pub chunk_num: usize,
iter: Box<Iterator<Item = ChunkedTerm<'a>> + 'a>, iter: Box<Iterator<Item = ChunkedTerm<'a>> + 'a>,
deep_cut_encountered: bool, deep_cut_encountered: bool,
cut_var_in_head: bool cut_var_in_head: bool,
} }
type ChunkedIteratorItem<'a> = (usize, usize, Vec<ChunkedTerm<'a>>); type ChunkedIteratorItem<'a> = (usize, usize, Vec<ChunkedTerm<'a>>);
type RuleBodyIteratorItem<'a> = (usize, usize, Vec<&'a QueryTerm>); type RuleBodyIteratorItem<'a> = (usize, usize, Vec<&'a QueryTerm>);
impl<'a> ChunkedIterator<'a> impl<'a> ChunkedIterator<'a> {
{ pub fn rule_body_iter(self) -> Box<Iterator<Item = RuleBodyIteratorItem<'a>> + 'a> {
pub fn rule_body_iter(self) -> Box<Iterator<Item=RuleBodyIteratorItem<'a>> + 'a>
{
Box::new(self.filter_map(|(cn, lt_arity, terms)| { Box::new(self.filter_map(|(cn, lt_arity, terms)| {
let filtered_terms: Vec<_> = terms.into_iter().filter_map(|ct| { let filtered_terms: Vec<_> = terms
match ct { .into_iter()
.filter_map(|ct| match ct {
ChunkedTerm::BodyTerm(qt) => Some(qt), ChunkedTerm::BodyTerm(qt) => Some(qt),
_ => None _ => None,
} })
}).collect(); .collect();
if filtered_terms.is_empty() { if filtered_terms.is_empty() {
None None
@@ -322,18 +368,16 @@ impl<'a> ChunkedIterator<'a>
})) }))
} }
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self {
{
ChunkedIterator { ChunkedIterator {
chunk_num: 0, chunk_num: 0,
iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))), iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
deep_cut_encountered: false, deep_cut_encountered: false,
cut_var_in_head: false cut_var_in_head: false,
} }
} }
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
{
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))); let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
@@ -341,13 +385,15 @@ impl<'a> ChunkedIterator<'a>
chunk_num: 0, chunk_num: 0,
iter: Box::new(iter), iter: Box::new(iter),
deep_cut_encountered: false, deep_cut_encountered: false,
cut_var_in_head: false cut_var_in_head: false,
} }
} }
pub fn from_rule(rule: &'a Rule) -> Self pub fn from_rule(rule: &'a Rule) -> Self {
{ let &Rule {
let &Rule { head: (ref name, ref args, ref p1), ref clauses } = rule; head: (ref name, ref args, ref p1),
ref clauses,
} = rule;
let iter = once(ChunkedTerm::HeadClause(name.clone(), args)); let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1))); let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
@@ -357,7 +403,7 @@ impl<'a> ChunkedIterator<'a>
chunk_num: 0, chunk_num: 0,
iter: Box::new(iter), iter: Box::new(iter),
deep_cut_encountered: false, deep_cut_encountered: false,
cut_var_in_head: false cut_var_in_head: false,
} }
} }
@@ -365,8 +411,7 @@ impl<'a> ChunkedIterator<'a>
self.deep_cut_encountered self.deep_cut_encountered
} }
fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>) fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>) {
{
let mut arity = 0; let mut arity = 0;
let mut item = Some(term); let mut item = Some(term);
let mut result = Vec::new(); let mut result = Vec::new();
@@ -379,7 +424,7 @@ impl<'a> ChunkedIterator<'a>
} }
result.push(term); result.push(term);
}, }
ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => { ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
result.push(term); result.push(term);
arity = vars.len(); arity = vars.len();
@@ -389,30 +434,35 @@ impl<'a> ChunkedIterator<'a>
} }
break; break;
}, }
ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => { ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => {
result.push(term); result.push(term);
if self.chunk_num > 0 { if self.chunk_num > 0 {
self.deep_cut_encountered = true; self.deep_cut_encountered = true;
} }
}, }
ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => { ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => {
self.deep_cut_encountered = true; self.deep_cut_encountered = true;
result.push(term); result.push(term);
arity = 1; arity = 1;
break; break;
}, }
ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) => ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut(..)) => result.push(term),
result.push(term), ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => {
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => result.push(term)
result.push(term), }
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms, _)) => { ChunkedTerm::BodyTerm(&QueryTerm::Clause(
_,
ClauseType::CallN,
ref subterms,
_,
)) => {
result.push(term); result.push(term);
arity = subterms.len() + 1; arity = subterms.len() + 1;
break; break;
}, }
ChunkedTerm::BodyTerm(qt) => { ChunkedTerm::BodyTerm(qt) => {
result.push(term); result.push(term);
arity = qt.arity(); arity = qt.arity();
@@ -430,8 +480,7 @@ impl<'a> ChunkedIterator<'a>
} }
} }
impl<'a> Iterator for ChunkedIterator<'a> impl<'a> Iterator for ChunkedIterator<'a> {
{
// the chunk number, last term arity, and vector of references. // the chunk number, last term arity, and vector of references.
type Item = ChunkedIteratorItem<'a>; type Item = ChunkedIteratorItem<'a>;

View File

@@ -10,7 +10,7 @@ pub struct Frame {
pub e: usize, pub e: usize,
pub cp: LocalCodePtr, pub cp: LocalCodePtr,
pub interrupt_cp: LocalCodePtr, pub interrupt_cp: LocalCodePtr,
perms: Vec<Addr> perms: Vec<Addr>,
} }
impl Frame { impl Frame {
@@ -20,7 +20,7 @@ impl Frame {
e: e, e: e,
cp: cp, cp: cp,
interrupt_cp: LocalCodePtr::default(), interrupt_cp: LocalCodePtr::default(),
perms: (1 .. n+1).map(|i| Addr::StackCell(fr, i)).collect() perms: (1..n + 1).map(|i| Addr::StackCell(fr, i)).collect(),
} }
} }

View File

@@ -26,7 +26,7 @@ impl AttrVarInitializer {
bindings: vec![], bindings: vec![],
cp: LocalCodePtr::default(), cp: LocalCodePtr::default(),
verify_attrs_loc, verify_attrs_loc,
project_attrs_loc project_attrs_loc,
} }
} }
@@ -38,8 +38,7 @@ impl AttrVarInitializer {
} }
impl MachineState { impl MachineState {
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
{
if self.attr_var_init.bindings.is_empty() { if self.attr_var_init.bindings.is_empty() {
self.attr_var_init.cp = self.p.local(); self.attr_var_init.cp = self.p.local();
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc); self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
@@ -49,17 +48,24 @@ impl MachineState {
} }
fn populate_var_and_value_lists(&mut self) -> (Addr, Addr) { fn populate_var_and_value_lists(&mut self) -> (Addr, Addr) {
let iter = self.attr_var_init.bindings.iter().map(|(ref h, _)| Addr::AttrVar(*h)); let iter = self
.attr_var_init
.bindings
.iter()
.map(|(ref h, _)| Addr::AttrVar(*h));
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter)); let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
let iter = self.attr_var_init.bindings.iter().map(|(_, ref addr)| addr.clone()); let iter = self
.attr_var_init
.bindings
.iter()
.map(|(_, ref addr)| addr.clone());
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter)); let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
(var_list_addr, value_list_addr) (var_list_addr, value_list_addr)
} }
fn verify_attributes(&mut self) fn verify_attributes(&mut self) {
{
for (h, _) in &self.attr_var_init.bindings { for (h, _) in &self.attr_var_init.bindings {
self.heap[*h] = HeapCellValue::Addr(Addr::AttrVar(*h)); self.heap[*h] = HeapCellValue::Addr(Addr::AttrVar(*h));
} }
@@ -70,15 +76,14 @@ impl MachineState {
self[temp_v!(2)] = value_list_addr; self[temp_v!(2)] = value_list_addr;
} }
pub(super) pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr>
{
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..] let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
.iter().filter_map(|h| .iter()
match self.store(self.deref(Addr::HeapCell(*h))) { .filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
Addr::AttrVar(h) => Some(Addr::AttrVar(h)), Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
_ => None _ => None,
}).collect(); })
.collect();
attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2)); attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
@@ -86,8 +91,7 @@ impl MachineState {
attr_vars.into_iter() attr_vars.into_iter()
} }
fn populate_project_attr_lists(&mut self) -> (Addr, Addr) fn populate_project_attr_lists(&mut self) -> (Addr, Addr) {
{
let mut query_vars = IndexSet::new(); let mut query_vars = IndexSet::new();
let attr_vars = self.gather_attr_vars_created_since(0); let attr_vars = self.gather_attr_vars_created_since(0);
@@ -98,10 +102,10 @@ impl MachineState {
match value { match value {
HeapCellValue::Addr(Addr::HeapCell(h)) => { HeapCellValue::Addr(Addr::HeapCell(h)) => {
query_vars.insert(Addr::HeapCell(h)); query_vars.insert(Addr::HeapCell(h));
}, }
HeapCellValue::Addr(Addr::StackCell(fr, sc)) => { HeapCellValue::Addr(Addr::StackCell(fr, sc)) => {
query_vars.insert(Addr::StackCell(fr, sc)); query_vars.insert(Addr::StackCell(fr, sc));
}, }
_ => {} _ => {}
}; };
} }
@@ -113,8 +117,7 @@ impl MachineState {
(query_var_list, attr_var_list) (query_var_list, attr_var_list)
} }
pub(super) pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
fn verify_attr_interrupt(&mut self, p: usize) {
let rs = MAX_ARITY; let rs = MAX_ARITY;
// store temp vars in perm vars slots along with self.b0 and // store temp vars in perm vars slots along with self.b0 and
@@ -141,8 +144,7 @@ impl MachineState {
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
} }
fn print_attribute_goals_string(&mut self, op_dir: &OpDir) -> String fn print_attribute_goals_string(&mut self, op_dir: &OpDir) -> String {
{
let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]); let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
if attr_goals.is_empty() { if attr_goals.is_empty() {
@@ -174,9 +176,7 @@ impl MachineState {
} }
impl Machine { impl Machine {
pub pub fn attribute_goals(&mut self) -> String {
fn attribute_goals(&mut self) -> String
{
let p = self.machine_st.attr_var_init.project_attrs_loc; let p = self.machine_st.attr_var_init.project_attrs_loc;
let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists(); let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists();
@@ -186,9 +186,14 @@ impl Machine {
self.machine_st[temp_v!(2)] = attr_vars; self.machine_st[temp_v!(2)] = attr_vars;
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo, self.machine_st.query_stepper(
&mut readline::input_stream()); &mut self.indices,
&mut self.policies,
&mut self.code_repo,
&mut readline::input_stream(),
);
self.machine_st.print_attribute_goals_string(&self.indices.op_dir) self.machine_st
.print_attribute_goals_string(&self.indices.op_dir)
} }
} }

View File

@@ -17,7 +17,7 @@ pub struct CodeRepo {
pub(super) term_expanders: Code, pub(super) term_expanders: Code,
pub(super) code: Code, pub(super) code: Code,
pub(super) in_situ_code: Code, pub(super) in_situ_code: Code,
pub(super) term_dir: TermDir pub(super) term_dir: TermDir,
} }
impl CodeRepo { impl CodeRepo {
@@ -29,36 +29,51 @@ impl CodeRepo {
term_expanders: Code::new(), term_expanders: Code::new(),
code: Code::new(), code: Code::new(),
in_situ_code: Code::new(), in_situ_code: Code::new(),
term_dir: TermDir::new() term_dir: TermDir::new(),
} }
} }
#[inline] #[inline]
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) { pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
self.term_dir.get(&key) self.term_dir
.get(&key)
.map(|entry| ((entry.0).0.len(), entry.1.len())) .map(|entry| ((entry.0).0.len(), entry.1.len()))
.unwrap_or((0, 0)) .unwrap_or((0, 0))
} }
#[inline] #[inline]
pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize) pub fn truncate_terms(
-> (Predicate, VecDeque<TopLevel>) &mut self,
{ key: PredicateKey,
self.term_dir.get_mut(&key) len: usize,
.map(|entry| (Predicate((entry.0).0.drain(len ..).collect()), queue_len: usize,
entry.1.drain(queue_len ..).collect())) ) -> (Predicate, VecDeque<TopLevel>) {
self.term_dir
.get_mut(&key)
.map(|entry| {
(
Predicate((entry.0).0.drain(len..).collect()),
entry.1.drain(queue_len..).collect(),
)
})
.unwrap_or((Predicate::new(), VecDeque::from(vec![]))) .unwrap_or((Predicate::new(), VecDeque::from(vec![])))
} }
pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir, pub fn add_in_situ_result(
flags: MachineFlags) &mut self,
-> Result<(), SessionError> result: &CompiledResult,
{ in_situ_code_dir: &mut InSituCodeDir,
flags: MachineFlags,
) -> Result<(), SessionError> {
let (ref decl, ref queue) = result; let (ref decl, ref queue) = result;
let (name, arity) = decl.0.first().and_then(|cl| { let (name, arity) = decl
.0
.first()
.and_then(|cl| {
let arity = cl.arity(); let arity = cl.arity();
cl.name().map(|name| (name, arity)) cl.name().map(|name| (name, arity))
}).ok_or(SessionError::NamelessEntry)?; })
.ok_or(SessionError::NamelessEntry)?;
let p = self.in_situ_code.len(); let p = self.in_situ_code.len();
in_situ_code_dir.insert((name, arity), p); in_situ_code_dir.insert((name, arity), p);
@@ -74,53 +89,57 @@ impl CodeRepo {
} }
#[inline] #[inline]
pub(super) pub(super) fn size_of_cached_query(&self) -> usize {
fn size_of_cached_query(&self) -> usize {
self.cached_query.len() self.cached_query.len()
} }
pub(super) pub(super) fn lookup_instr<'a>(
fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option<RefOrOwned<'a, Line>> &'a self,
{ last_call: bool,
p: &CodePtr,
) -> Option<RefOrOwned<'a, Line>> {
match p { match p {
&CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => &CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => {
if p < self.goal_expanders.len() { if p < self.goal_expanders.len() {
Some(RefOrOwned::Borrowed(&self.goal_expanders[p])) Some(RefOrOwned::Borrowed(&self.goal_expanders[p]))
} else { } else {
None None
}, }
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => }
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => {
if p < self.term_expanders.len() { if p < self.term_expanders.len() {
Some(RefOrOwned::Borrowed(&self.term_expanders[p])) Some(RefOrOwned::Borrowed(&self.term_expanders[p]))
} else { } else {
None None
}, }
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => }
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => {
if p < self.cached_query.len() { if p < self.cached_query.len() {
Some(RefOrOwned::Borrowed(&self.cached_query[p])) Some(RefOrOwned::Borrowed(&self.cached_query[p]))
} else { } else {
None None
}, }
&CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) => }
Some(RefOrOwned::Borrowed(&self.in_situ_code[p])), &CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) => {
&CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.in_situ_code[p]))
Some(RefOrOwned::Borrowed(&self.code[p])), }
&CodePtr::REPL(..) => &CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.code[p])),
None, &CodePtr::REPL(..) => None,
&CodePtr::BuiltInClause(ref built_in, _) => { &CodePtr::BuiltInClause(ref built_in, _) => {
let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()), let call_clause = call_clause!(
ClauseType::BuiltIn(built_in.clone()),
built_in.arity(), built_in.arity(),
0, last_call); 0,
last_call
);
Some(RefOrOwned::Owned(call_clause)) Some(RefOrOwned::Owned(call_clause))
}, }
&CodePtr::CallN(arity, _) => { &CodePtr::CallN(arity, _) => {
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call); let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
Some(RefOrOwned::Owned(call_clause)) Some(RefOrOwned::Owned(call_clause))
}, }
&CodePtr::VerifyAttrInterrupt(p) => &CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
Some(RefOrOwned::Borrowed(&self.code[p])), &CodePtr::DynamicTransaction(..) => None,
&CodePtr::DynamicTransaction(..) =>
None
} }
} }
} }

View File

@@ -2,15 +2,15 @@ use prolog_parser::ast::*;
use prolog_parser::parser::get_desc; use prolog_parser::parser::get_desc;
use prolog_parser::tabled_rc::TabledData; use prolog_parser::tabled_rc::TabledData;
use prolog::instructions::*;
use prolog::codegen::*; use prolog::codegen::*;
use prolog::debray_allocator::*; use prolog::debray_allocator::*;
use prolog::forms::*; use prolog::forms::*;
use prolog::machine::*; use prolog::instructions::*;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use prolog::machine::term_expansion::{ExpansionAdditionResult}; use prolog::machine::term_expansion::ExpansionAdditionResult;
use prolog::machine::toplevel::*; use prolog::machine::toplevel::*;
use prolog::machine::*;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
@@ -25,28 +25,19 @@ use std::path::PathBuf;
fn print_code(code: &Code) { fn print_code(code: &Code) {
for clause in code { for clause in code {
match clause { match clause {
&Line::Arithmetic(ref arith) => &Line::Arithmetic(ref arith) => println!("{}", arith),
println!("{}", arith), &Line::Fact(ref fact_instr) => println!("{}", fact_instr),
&Line::Fact(ref fact_instr) => &Line::Cut(ref cut) => println!("{}", cut),
println!("{}", fact_instr), &Line::Choice(ref choice) => println!("{}", choice),
&Line::Cut(ref cut) => &Line::Control(ref control) => println!("{}", control),
println!("{}", cut), &Line::IndexedChoice(ref choice) => println!("{}", choice),
&Line::Choice(ref choice) => &Line::Indexing(ref indexing) => println!("{}", indexing),
println!("{}", choice), &Line::Query(ref query_instr) => println!("{}", query_instr),
&Line::Control(ref control) =>
println!("{}", control),
&Line::IndexedChoice(ref choice) =>
println!("{}", choice),
&Line::Indexing(ref indexing) =>
println!("{}", indexing),
&Line::Query(ref query_instr) =>
println!("{}", query_instr)
} }
} }
} }
fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, SessionError> fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, SessionError> {
{
let mut path = PathBuf::from(filename); let mut path = PathBuf::from(filename);
if !path.is_file() { if !path.is_file() {
@@ -63,8 +54,7 @@ fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, S
Ok(path) Ok(path)
} }
fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName, SessionError> fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName, SessionError> {
{
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?; let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
let file_handle = File::open(&path).or_else(|_| { let file_handle = File::open(&path).or_else(|_| {
@@ -94,52 +84,53 @@ fn load_module_from_file(wam: &mut Machine, filename: &str) -> Result<ClauseName
match compile_work_impl(&mut compiler, wam, indices, results) { match compile_work_impl(&mut compiler, wam, indices, results) {
EvalSession::Error(e) => Err(e), EvalSession::Error(e) => Err(e),
_ => Ok(module_name) _ => Ok(module_name),
} }
} }
pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>); pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
// throw errors if declaration or query found. // throw errors if declaration or query found.
fn compile_relation(tl: &TopLevel, non_counted_bt: bool, flags: MachineFlags) fn compile_relation(
-> Result<Code, ParserError> tl: &TopLevel,
{ non_counted_bt: bool,
flags: MachineFlags,
) -> Result<Code, ParserError> {
let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt, flags); let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt, flags);
match tl { match tl {
&TopLevel::Declaration(_) | &TopLevel::Query(_) => &TopLevel::Declaration(_) | &TopLevel::Query(_) => Err(ParserError::ExpectedRel),
Err(ParserError::ExpectedRel), &TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses.0),
&TopLevel::Predicate(ref clauses) => &TopLevel::Fact(ref fact) => Ok(cg.compile_fact(fact)),
cg.compile_predicate(&clauses.0), &TopLevel::Rule(ref rule) => cg.compile_rule(rule),
&TopLevel::Fact(ref fact) =>
Ok(cg.compile_fact(fact)),
&TopLevel::Rule(ref rule) =>
cg.compile_rule(rule)
} }
} }
// set first jmp_by_call or jmp_by_index instruction to code.len() - // set first jmp_by_call or jmp_by_index instruction to code.len() -
// idx, where idx is the place it occurs. It only does this to the // idx, where idx is the place it occurs. It only does this to the
// *first* uninitialized jmp index it encounters, then returns. // *first* uninitialized jmp index it encounters, then returns.
fn set_first_index(code: &mut Code) fn set_first_index(code: &mut Code) {
{
let code_len = code.len(); let code_len = code.len();
for (idx, line) in code.iter_mut().enumerate() { for (idx, line) in code.iter_mut().enumerate() {
match line { match line {
&mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) if *offset == 0 => { &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..))
if *offset == 0 =>
{
*offset = code_len - idx; *offset = code_len - idx;
break; break;
}, }
_ => {} _ => {}
}; };
} }
} }
pub fn compile_appendix(code: &mut Code, queue: &VecDeque<TopLevel>, non_counted_bt: bool, pub fn compile_appendix(
flags: MachineFlags) code: &mut Code,
-> Result<(), ParserError> queue: &VecDeque<TopLevel>,
{ non_counted_bt: bool,
flags: MachineFlags,
) -> Result<(), ParserError> {
for tl in queue.iter() { for tl in queue.iter() {
set_first_index(code); set_first_index(code);
code.append(&mut compile_relation(tl, non_counted_bt, flags)?); code.append(&mut compile_relation(tl, non_counted_bt, flags)?);
@@ -149,9 +140,11 @@ pub fn compile_appendix(code: &mut Code, queue: &VecDeque<TopLevel>, non_counted
} }
impl CodeRepo { impl CodeRepo {
pub fn compile_hook(&mut self, hook: CompileTimeHook, flags: MachineFlags) pub fn compile_hook(
-> Result<(), ParserError> &mut self,
{ hook: CompileTimeHook,
flags: MachineFlags,
) -> Result<(), ParserError> {
let key = (hook.name(), hook.arity()); let key = (hook.name(), hook.arity());
match self.term_dir.get(&key) { match self.term_dir.get(&key) {
@@ -162,20 +155,24 @@ impl CodeRepo {
compile_appendix(&mut code, &preds.1, false, flags)?; compile_appendix(&mut code, &preds.1, false, flags)?;
Ok(match hook { Ok(match hook {
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
self.term_expanders = code, self.term_expanders = code
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => }
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
self.goal_expanders = code self.goal_expanders = code
}
}) })
}, }
None => Ok(()) None => Ok(()),
} }
} }
} }
fn compile_query(terms: Vec<QueryTerm>, queue: VecDeque<TopLevel>, flags: MachineFlags) fn compile_query(
-> Result<(Code, AllocVarDict), ParserError> terms: Vec<QueryTerm>,
{ queue: VecDeque<TopLevel>,
flags: MachineFlags,
) -> Result<(Code, AllocVarDict), ParserError> {
// count backtracking inferences. // count backtracking inferences.
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags); let mut cg = CodeGenerator::<DebrayAllocator>::new(false, flags);
let mut code = try!(cg.compile_query(&terms)); let mut code = try!(cg.compile_query(&terms));
@@ -184,9 +181,11 @@ fn compile_query(terms: Vec<QueryTerm>, queue: VecDeque<TopLevel>, flags: Machin
Ok((code, cg.take_vars())) Ok((code, cg.take_vars()))
} }
fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declaration) fn compile_decl(
-> Result<IndexStore, SessionError> wam: &mut Machine,
{ compiler: &mut ListingCompiler,
decl: Declaration,
) -> Result<IndexStore, SessionError> {
let flags = wam.machine_flags(); let flags = wam.machine_flags();
let mut indices = default_index_store!(wam.indices.atom_tbl.clone()); let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
@@ -195,14 +194,14 @@ fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declara
Ok(indices) Ok(indices)
} }
pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession {
{
match packet { match packet {
TopLevelPacket::Query(terms, queue) => TopLevelPacket::Query(terms, queue) => {
match compile_query(terms, queue, wam.machine_flags()) { match compile_query(terms, queue, wam.machine_flags()) {
Ok((code, vars)) => wam.submit_query(code, vars), Ok((code, vars)) => wam.submit_query(code, vars),
Err(e) => EvalSession::from(e) Err(e) => EvalSession::from(e),
}, }
}
TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => { TopLevelPacket::Decl(TopLevel::Declaration(decl), _) => {
let mut compiler = ListingCompiler::new(&wam.code_repo); let mut compiler = ListingCompiler::new(&wam.code_repo);
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl)); let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
@@ -211,13 +210,12 @@ pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession
add_toplevel_code(wam, vec![], indices); add_toplevel_code(wam, vec![], indices);
EvalSession::EntrySuccess EvalSession::EntrySuccess
}, }
_ => EvalSession::from(SessionError::UserPrompt) _ => EvalSession::from(SessionError::UserPrompt),
} }
} }
fn update_module_indices(wam: &Machine, module_name: ClauseName, mut indices: IndexStore) fn update_module_indices(wam: &Machine, module_name: ClauseName, mut indices: IndexStore) {
{
match wam.indices.modules.get(&module_name) { match wam.indices.modules.get(&module_name) {
Some(module) => { Some(module) => {
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new()); let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
@@ -232,49 +230,61 @@ fn update_module_indices(wam: &Machine, module_name: ClauseName, mut indices: In
} }
match wam.indices.code_dir.get(&key) { match wam.indices.code_dir.get(&key) {
Some(idx) => if idx.0.borrow().1 == module_name { Some(idx) => {
if idx.0.borrow().1 == module_name {
set_code_index!(idx, p, module_name.clone()); set_code_index!(idx, p, module_name.clone());
}, }
}
_ => {} _ => {}
} }
} }
}, }
_ => unreachable!() _ => unreachable!(),
}; };
} }
fn add_hooks_to_mockup(code_repo: &mut CodeRepo, hook: CompileTimeHook, fn add_hooks_to_mockup(
expansions: (Predicate, VecDeque<TopLevel>)) code_repo: &mut CodeRepo,
{ hook: CompileTimeHook,
expansions: (Predicate, VecDeque<TopLevel>),
) {
let key = (hook.name(), hook.arity()); let key = (hook.name(), hook.arity());
let preds = code_repo.term_dir.entry(key.clone()) let preds = code_repo
.term_dir
.entry(key.clone())
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
(preds.0).0.extend((expansions.0).0.into_iter()); (preds.0).0.extend((expansions.0).0.into_iter());
preds.1.extend(expansions.1.into_iter()); preds.1.extend(expansions.1.into_iter());
} }
fn setup_module_expansions(wam: &mut Machine, module_name: ClauseName) fn setup_module_expansions(wam: &mut Machine, module_name: ClauseName) {
{
match wam.indices.modules.get(&module_name) { match wam.indices.modules.get(&module_name) {
Some(module) => { Some(module) => {
let term_expansions = module.term_expansions.clone(); let term_expansions = module.term_expansions.clone();
let goal_expansions = module.goal_expansions.clone(); let goal_expansions = module.goal_expansions.clone();
add_hooks_to_mockup(&mut wam.code_repo, CompileTimeHook::TermExpansion, add_hooks_to_mockup(
term_expansions); &mut wam.code_repo,
add_hooks_to_mockup(&mut wam.code_repo, CompileTimeHook::GoalExpansion, CompileTimeHook::TermExpansion,
goal_expansions); term_expansions,
}, );
_ => unreachable!() add_hooks_to_mockup(
&mut wam.code_repo,
CompileTimeHook::GoalExpansion,
goal_expansions,
);
}
_ => unreachable!(),
} }
} }
pub(super) pub(super) fn compile_into_module<R: Read>(
fn compile_into_module<R: Read>(wam: &mut Machine, module_name: ClauseName, wam: &mut Machine,
src: ParsingStream<R>, name: ClauseName) module_name: ClauseName,
-> EvalSession src: ParsingStream<R>,
{ name: ClauseName,
) -> EvalSession {
let mut indices = default_index_store!(wam.atom_tbl_of(&name)); let mut indices = default_index_store!(wam.atom_tbl_of(&name));
try_eval_session!(setup_indices(wam, module_name.clone(), &mut indices)); try_eval_session!(setup_indices(wam, module_name.clone(), &mut indices));
@@ -289,21 +299,25 @@ fn compile_into_module<R: Read>(wam: &mut Machine, module_name: ClauseName,
} }
} }
fn compile_into_module_impl<R: Read>(wam: &mut Machine, compiler: &mut ListingCompiler, fn compile_into_module_impl<R: Read>(
module_name: ClauseName, src: ParsingStream<R>, wam: &mut Machine,
mut indices: IndexStore) compiler: &mut ListingCompiler,
-> Result<(), SessionError> module_name: ClauseName,
{ src: ParsingStream<R>,
mut indices: IndexStore,
) -> Result<(), SessionError> {
setup_module_expansions(wam, module_name.clone()); setup_module_expansions(wam, module_name.clone());
let flags = wam.machine_flags(); let flags = wam.machine_flags();
wam.code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?; wam.code_repo
wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?; .compile_hook(CompileTimeHook::TermExpansion, flags)?;
wam.code_repo
.compile_hook(CompileTimeHook::GoalExpansion, flags)?;
let results = compiler.gather_items(wam, src, &mut indices)?; let results = compiler.gather_items(wam, src, &mut indices)?;
let module_code = compiler.generate_code(results.worker_results, wam, let module_code =
&mut indices.code_dir, 0)?; compiler.generate_code(results.worker_results, wam, &mut indices.code_dir, 0)?;
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len()); let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)?; clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)?;
@@ -321,39 +335,53 @@ pub struct GatherResult {
pub(crate) worker_results: Vec<PredicateCompileQueue>, pub(crate) worker_results: Vec<PredicateCompileQueue>,
toplevel_results: Vec<PredicateCompileQueue>, toplevel_results: Vec<PredicateCompileQueue>,
toplevel_indices: IndexStore, toplevel_indices: IndexStore,
addition_results: ExpansionAdditionResult addition_results: ExpansionAdditionResult,
} }
pub struct ClauseCodeGenerator { pub struct ClauseCodeGenerator {
len_offset: usize, len_offset: usize,
code: Code, code: Code,
pi_to_loc: IndexMap<PredicateKey, usize> pi_to_loc: IndexMap<PredicateKey, usize>,
} }
impl ClauseCodeGenerator { impl ClauseCodeGenerator {
#[inline] #[inline]
fn new(len_offset: usize) -> Self { fn new(len_offset: usize) -> Self {
ClauseCodeGenerator { len_offset, code: vec![], pi_to_loc: IndexMap::new() } ClauseCodeGenerator {
len_offset,
code: vec![],
pi_to_loc: IndexMap::new(),
}
} }
fn generate_clause_code(&mut self, dynamic_clause_map: DynamicClauseMap, wam: &Machine) fn generate_clause_code(
-> Result<(), SessionError> &mut self,
{ dynamic_clause_map: DynamicClauseMap,
wam: &Machine,
) -> Result<(), SessionError> {
for ((name, arity), heads_and_tails) in dynamic_clause_map { for ((name, arity), heads_and_tails) in dynamic_clause_map {
if heads_and_tails.is_empty() { if heads_and_tails.is_empty() {
continue; continue;
} }
let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| { let predicate = Predicate(
let clause = Term::Clause(Cell::default(), clause_name!("clause"), heads_and_tails
.into_iter()
.map(|(head, tail)| {
let clause = Term::Clause(
Cell::default(),
clause_name!("clause"),
vec![Box::new(head), Box::new(tail)], vec![Box::new(head), Box::new(tail)],
None); None,
);
PredicateClause::Fact(clause) PredicateClause::Fact(clause)
}).collect()); })
.collect(),
);
let p = self.code.len() + wam.code_repo.code.len() + self.len_offset; let p = self.code.len() + wam.code_repo.code.len() + self.len_offset;
let mut decl_code = compile_relation(&TopLevel::Predicate(predicate), false, let mut decl_code =
wam.machine_flags())?; compile_relation(&TopLevel::Predicate(predicate), false, wam.machine_flags())?;
compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?; compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?;
@@ -368,7 +396,10 @@ impl ClauseCodeGenerator {
wam.code_repo.code.extend(self.code.into_iter()); wam.code_repo.code.extend(self.code.into_iter());
for ((name, arity), p) in self.pi_to_loc { for ((name, arity), p) in self.pi_to_loc {
let entry = wam.indices.dynamic_code_dir.entry((name.owning_module(), name, arity)) let entry = wam
.indices
.dynamic_code_dir
.entry((name.owning_module(), name, arity))
.or_insert(DynamicPredicateInfo::default()); .or_insert(DynamicPredicateInfo::default());
entry.clauses_subsection_p = p; entry.clauses_subsection_p = p;
@@ -381,11 +412,10 @@ pub struct ListingCompiler {
module: Option<Module>, module: Option<Module>,
user_term_dir: TermDir, user_term_dir: TermDir,
orig_term_expansion_lens: (usize, usize), orig_term_expansion_lens: (usize, usize),
orig_goal_expansion_lens: (usize, usize) orig_goal_expansion_lens: (usize, usize),
} }
fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) {
{
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new()); let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
let op_dir = mem::replace(&mut indices.op_dir, OpDir::new()); let op_dir = mem::replace(&mut indices.op_dir, OpDir::new());
@@ -394,8 +424,7 @@ fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore)
} }
#[inline] #[inline]
fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indices: IndexStore) fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indices: IndexStore) {
{
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new()); let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
let op_dir = mem::replace(&mut indices.op_dir, OpDir::new()); let op_dir = mem::replace(&mut indices.op_dir, OpDir::new());
@@ -404,17 +433,21 @@ fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indice
for (name, arity) in indices.code_dir.keys().cloned() { for (name, arity) in indices.code_dir.keys().cloned() {
if name.owning_module() == module.module_decl.name { if name.owning_module() == module.module_decl.name {
wam.indices.dynamic_code_dir.remove(&(name.owning_module(), name, arity)); wam.indices
.dynamic_code_dir
.remove(&(name.owning_module(), name, arity));
} }
} }
wam.add_module(module, code); wam.add_module(module, code);
} }
fn add_non_module_code(wam: &mut Machine, dynamic_clause_map: DynamicClauseMap, code: Code, fn add_non_module_code(
indices: IndexStore) wam: &mut Machine,
-> Result<(), SessionError> dynamic_clause_map: DynamicClauseMap,
{ code: Code,
indices: IndexStore,
) -> Result<(), SessionError> {
wam.check_toplevel_code(&indices)?; wam.check_toplevel_code(&indices)?;
let mut clause_code_generator = ClauseCodeGenerator::new(code.len()); let mut clause_code_generator = ClauseCodeGenerator::new(code.len());
@@ -433,8 +466,10 @@ impl ListingCompiler {
non_counted_bt_preds: IndexSet::new(), non_counted_bt_preds: IndexSet::new(),
module: None, module: None,
user_term_dir: TermDir::new(), user_term_dir: TermDir::new(),
orig_term_expansion_lens: code_repo.term_dir_entry_len((clause_name!("term_expansion"), 2)), orig_term_expansion_lens: code_repo
orig_goal_expansion_lens: code_repo.term_dir_entry_len((clause_name!("goal_expansion"), 2)), .term_dir_entry_len((clause_name!("term_expansion"), 2)),
orig_goal_expansion_lens: code_repo
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
} }
} }
@@ -442,8 +477,7 @@ impl ListingCompiler {
Replace calls to self with a localized index cell, not available to the global CodeIndex. Replace calls to self with a localized index cell, not available to the global CodeIndex.
This is done to implement logical update semantics for dynamic database updates. This is done to implement logical update semantics for dynamic database updates.
*/ */
fn localize_self_calls(&mut self, name: ClauseName, arity: usize, code: &mut Code, p: usize) fn localize_self_calls(&mut self, name: ClauseName, arity: usize, code: &mut Code, p: usize) {
{
let self_idx = CodeIndex::default(); let self_idx = CodeIndex::default();
set_code_index!(self_idx, IndexPtr::Index(p), self.get_module_name()); set_code_index!(self_idx, IndexPtr::Index(p), self.get_module_name());
@@ -451,33 +485,43 @@ impl ListingCompiler {
if let &mut Line::Control(ControlInstruction::CallClause(ref mut ct, ..)) = instr { if let &mut Line::Control(ControlInstruction::CallClause(ref mut ct, ..)) = instr {
match ct { match ct {
&mut ClauseType::Named(ref ct_name, ct_arity, ref mut idx) &mut ClauseType::Named(ref ct_name, ct_arity, ref mut idx)
if ct_name == &name && arity == ct_arity => { if ct_name == &name && arity == ct_arity =>
{
*idx = self_idx.clone(); *idx = self_idx.clone();
}, }
&mut ClauseType::Op(ref op_name, ref shared_op_desc, ref mut idx) &mut ClauseType::Op(ref op_name, ref shared_op_desc, ref mut idx)
if op_name == &name && shared_op_desc.arity() == arity => { if op_name == &name && shared_op_desc.arity() == arity =>
{
*idx = self_idx.clone(); *idx = self_idx.clone();
}, }
_ => {} _ => {}
} }
} }
} }
} }
fn use_module(&mut self, submodule: ClauseName, code_repo: &mut CodeRepo, flags: MachineFlags, fn use_module(
wam_indices: &mut IndexStore, indices: &mut IndexStore) &mut self,
-> Result<(), SessionError> submodule: ClauseName,
{ code_repo: &mut CodeRepo,
flags: MachineFlags,
wam_indices: &mut IndexStore,
indices: &mut IndexStore,
) -> Result<(), SessionError> {
let module_name = self.get_module_name(); let module_name = self.get_module_name();
if let Some(mut submodule) = wam_indices.take_module(submodule) { if let Some(mut submodule) = wam_indices.take_module(submodule) {
unwind_protect!(indices.use_module(code_repo, flags, &submodule), unwind_protect!(
wam_indices.insert_module(submodule)); indices.use_module(code_repo, flags, &submodule),
wam_indices.insert_module(submodule)
);
if let &mut Some(ref mut module) = &mut self.module { if let &mut Some(ref mut module) = &mut self.module {
module.remove_module(module_name, &submodule); module.remove_module(module_name, &submodule);
unwind_protect!(module.use_module(code_repo, flags, &submodule), unwind_protect!(
wam_indices.insert_module(submodule)); module.use_module(code_repo, flags, &submodule),
wam_indices.insert_module(submodule)
);
} else { } else {
submodule.inserted_expansions = true; submodule.inserted_expansions = true;
wam_indices.remove_module(clause_name!("user"), &submodule); wam_indices.remove_module(clause_name!("user"), &submodule);
@@ -489,21 +533,29 @@ impl ListingCompiler {
} }
} }
fn use_qualified_module(&mut self, submodule: ClauseName, code_repo: &mut CodeRepo, fn use_qualified_module(
flags: MachineFlags, exports: &Vec<PredicateKey>, &mut self,
wam_indices: &mut IndexStore, indices: &mut IndexStore) submodule: ClauseName,
-> Result<(), SessionError> code_repo: &mut CodeRepo,
{ flags: MachineFlags,
exports: &Vec<PredicateKey>,
wam_indices: &mut IndexStore,
indices: &mut IndexStore,
) -> Result<(), SessionError> {
let module_name = self.get_module_name(); let module_name = self.get_module_name();
if let Some(mut submodule) = wam_indices.take_module(submodule) { if let Some(mut submodule) = wam_indices.take_module(submodule) {
unwind_protect!(indices.use_qualified_module(code_repo, flags, &submodule, exports), unwind_protect!(
wam_indices.insert_module(submodule)); indices.use_qualified_module(code_repo, flags, &submodule, exports),
wam_indices.insert_module(submodule)
);
if let &mut Some(ref mut module) = &mut self.module { if let &mut Some(ref mut module) = &mut self.module {
module.remove_module(module_name, &submodule); module.remove_module(module_name, &submodule);
unwind_protect!(module.use_qualified_module(code_repo, flags, &submodule, exports), unwind_protect!(
wam_indices.insert_module(submodule)); module.use_qualified_module(code_repo, flags, &submodule, exports),
wam_indices.insert_module(submodule)
);
} else { } else {
submodule.inserted_expansions = true; submodule.inserted_expansions = true;
wam_indices.remove_module(clause_name!("user"), &submodule); wam_indices.remove_module(clause_name!("user"), &submodule);
@@ -517,29 +569,39 @@ impl ListingCompiler {
#[inline] #[inline]
fn get_module_name(&self) -> ClauseName { fn get_module_name(&self) -> ClauseName {
self.module.as_ref() self.module
.as_ref()
.map(|module| module.module_decl.name.clone()) .map(|module| module.module_decl.name.clone())
.unwrap_or(ClauseName::BuiltIn("user")) .unwrap_or(ClauseName::BuiltIn("user"))
} }
pub(crate) pub(crate) fn generate_code(
fn generate_code(&mut self, decls: Vec<PredicateCompileQueue>, wam: &Machine, &mut self,
code_dir: &mut CodeDir, code_offset: usize) decls: Vec<PredicateCompileQueue>,
-> Result<Code, SessionError> wam: &Machine,
{ code_dir: &mut CodeDir,
code_offset: usize,
) -> Result<Code, SessionError> {
let mut code = vec![]; let mut code = vec![];
for (decl, queue) in decls { for (decl, queue) in decls {
let (name, arity) = decl.predicate_indicator().ok_or(SessionError::NamelessEntry)?; let (name, arity) = decl
.predicate_indicator()
.ok_or(SessionError::NamelessEntry)?;
let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity)); let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
let p = code.len() + wam.code_repo.code.len() + code_offset; let p = code.len() + wam.code_repo.code.len() + code_offset;
let mut decl_code = compile_relation(&TopLevel::Predicate(decl), non_counted_bt, let mut decl_code = compile_relation(
wam.machine_flags())?; &TopLevel::Predicate(decl),
non_counted_bt,
wam.machine_flags(),
)?;
compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?; compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
let idx = code_dir.entry((name.clone(), arity)).or_insert(CodeIndex::default()); let idx = code_dir
.entry((name.clone(), arity))
.or_insert(CodeIndex::default());
set_code_index!(idx, IndexPtr::Index(p), self.get_module_name()); set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
self.localize_self_calls(name, arity, &mut decl_code, p); self.localize_self_calls(name, arity, &mut decl_code, p);
@@ -553,17 +615,25 @@ impl ListingCompiler {
self.non_counted_bt_preds.insert((name, arity)); self.non_counted_bt_preds.insert((name, arity));
} }
fn add_term_dir_terms(&mut self, hook: CompileTimeHook, code_repo: &mut CodeRepo, fn add_term_dir_terms(
key: PredicateKey, clause: PredicateClause, queue: VecDeque<TopLevel>) &mut self,
-> (usize, usize) hook: CompileTimeHook,
{ code_repo: &mut CodeRepo,
let preds = code_repo.term_dir.entry(key.clone()) key: PredicateKey,
clause: PredicateClause,
queue: VecDeque<TopLevel>,
) -> (usize, usize) {
let preds = code_repo
.term_dir
.entry(key.clone())
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
let (mut len, mut queue_len) = ((preds.0).0.len(), preds.1.len()); let (mut len, mut queue_len) = ((preds.0).0.len(), preds.1.len());
if self.module.is_some() && hook.has_module_scope() { if self.module.is_some() && hook.has_module_scope() {
let module_preds = self.user_term_dir.entry(key.clone()) let module_preds = self
.user_term_dir
.entry(key.clone())
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
if let Some(ref mut module) = &mut self.module { if let Some(ref mut module) = &mut self.module {
@@ -576,7 +646,9 @@ impl ListingCompiler {
(preds.0).0.extend((module_preds.0).0.iter().cloned()); (preds.0).0.extend((module_preds.0).0.iter().cloned());
preds.1.extend(module_preds.1.iter().cloned()); preds.1.extend(module_preds.1.iter().cloned());
} else { } else {
let module_preds = self.user_term_dir.entry(key.clone()) let module_preds = self
.user_term_dir
.entry(key.clone())
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
len += 1; len += 1;
@@ -592,38 +664,56 @@ impl ListingCompiler {
(len, queue_len) (len, queue_len)
} }
fn process_decl(&mut self, decl: Declaration, wam: &mut Machine, indices: &mut IndexStore, fn process_decl(
flags: MachineFlags) &mut self,
-> Result<(), SessionError> decl: Declaration,
{ wam: &mut Machine,
indices: &mut IndexStore,
flags: MachineFlags,
) -> Result<(), SessionError> {
match decl { match decl {
Declaration::EndOfFile => Ok(()), Declaration::EndOfFile => Ok(()),
Declaration::Hook(hook, clause, queue) => { Declaration::Hook(hook, clause, queue) => {
let key = (hook.name(), hook.arity()); let key = (hook.name(), hook.arity());
let (len, queue_len) = self.add_term_dir_terms(hook, &mut wam.code_repo, let (len, queue_len) =
key.clone(), clause, queue); self.add_term_dir_terms(hook, &mut wam.code_repo, key.clone(), clause, queue);
let result = wam.code_repo.compile_hook(hook, flags).map_err(SessionError::from); let result = wam
.code_repo
.compile_hook(hook, flags)
.map_err(SessionError::from);
wam.code_repo.truncate_terms(key, len, queue_len); wam.code_repo.truncate_terms(key, len, queue_len);
result result
}, }
Declaration::NonCountedBacktracking(name, arity) => Declaration::NonCountedBacktracking(name, arity) => {
Ok(self.add_non_counted_bt_flag(name, arity)), Ok(self.add_non_counted_bt_flag(name, arity))
}
Declaration::Op(op_decl) => { Declaration::Op(op_decl) => {
let spec = get_desc(op_decl.name(), composite_op!(self.module.is_some(), let spec = get_desc(
op_decl.name(),
composite_op!(
self.module.is_some(),
&wam.indices.op_dir, &wam.indices.op_dir,
&mut indices.op_dir)); &mut indices.op_dir
),
);
op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir) op_decl.submit(self.get_module_name(), spec, &mut indices.op_dir)
}, }
Declaration::UseModule(ModuleSource::Library(name)) => Declaration::UseModule(ModuleSource::Library(name)) => {
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
indices), }
Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => Declaration::UseQualifiedModule(ModuleSource::Library(name), exports) => self
self.use_qualified_module(name, &mut wam.code_repo, flags, &exports, .use_qualified_module(
&mut wam.indices, indices), name,
Declaration::Module(module_decl) => &mut wam.code_repo,
flags,
&exports,
&mut wam.indices,
indices,
),
Declaration::Module(module_decl) => {
if self.module.is_none() { if self.module.is_none() {
let module_name = module_decl.name.clone(); let module_name = module_decl.name.clone();
let atom_tbl = TabledData::new(module_name.to_rc()); let atom_tbl = TabledData::new(module_name.to_rc());
@@ -631,38 +721,53 @@ impl ListingCompiler {
Ok(self.module = Some(Module::new(module_decl, atom_tbl))) Ok(self.module = Some(Module::new(module_decl, atom_tbl)))
} else { } else {
Err(SessionError::from(ParserError::InvalidModuleDecl)) Err(SessionError::from(ParserError::InvalidModuleDecl))
}, }
}
Declaration::UseModule(ModuleSource::File(filename)) => { Declaration::UseModule(ModuleSource::File(filename)) => {
let name = load_module_from_file(wam, filename.as_str())?; let name = load_module_from_file(wam, filename.as_str())?;
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices) self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
}, }
Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => { Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
let name = load_module_from_file(wam, filename.as_str())?; let name = load_module_from_file(wam, filename.as_str())?;
self.use_qualified_module(name, &mut wam.code_repo, flags, &exports, self.use_qualified_module(
&mut wam.indices, indices) name,
}, &mut wam.code_repo,
Declaration::Dynamic(..) => Ok(()) flags,
&exports,
&mut wam.indices,
indices,
)
}
Declaration::Dynamic(..) => Ok(()),
} }
} }
fn process_and_commit_decl<R: Read>(&mut self, decl: Declaration, fn process_and_commit_decl<R: Read>(
&mut self,
decl: Declaration,
worker: &mut TopLevelBatchWorker<R>, worker: &mut TopLevelBatchWorker<R>,
indices: &mut IndexStore, flags: MachineFlags) indices: &mut IndexStore,
-> Result<(), SessionError> flags: MachineFlags,
{ ) -> Result<(), SessionError> {
let mut update_expansion_lengths = false; let mut update_expansion_lengths = false;
match &decl { match &decl {
&Declaration::Dynamic(ref name, arity) => { &Declaration::Dynamic(ref name, arity) => {
worker.dynamic_clause_map.entry((name.clone(), arity)).or_insert(vec![]); worker
}, .dynamic_clause_map
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() => .entry((name.clone(), arity))
worker.term_stream.incr_expansion_lens(hook.user_scope(), 1, queue.len()), .or_insert(vec![]);
&Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() => }
worker.term_stream.incr_expansion_lens(hook, 1, queue.len()), &Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
.term_stream
.incr_expansion_lens(hook.user_scope(), 1, queue.len()),
&Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() => {
worker.term_stream.incr_expansion_lens(hook, 1, queue.len())
}
&Declaration::UseModule(ModuleSource::File(_)) &Declaration::UseModule(ModuleSource::File(_))
| &Declaration::UseQualifiedModule(ModuleSource::File(_), _) => | &Declaration::UseQualifiedModule(ModuleSource::File(_), _) => {
update_expansion_lengths = true, update_expansion_lengths = true
}
_ => {} _ => {}
}; };
@@ -675,11 +780,12 @@ impl ListingCompiler {
result result
} }
pub(crate) pub(crate) fn gather_items<R: Read>(
fn gather_items<R: Read>(&mut self, wam: &mut Machine, mut src: ParsingStream<R>, &mut self,
indices: &mut IndexStore) wam: &mut Machine,
-> Result<GatherResult, SessionError> mut src: ParsingStream<R>,
{ indices: &mut IndexStore,
) -> Result<GatherResult, SessionError> {
let flags = wam.machine_flags(); let flags = wam.machine_flags();
let atom_tbl = indices.atom_tbl.clone(); let atom_tbl = indices.atom_tbl.clone();
let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags, wam); let mut worker = TopLevelBatchWorker::new(&mut src, atom_tbl.clone(), flags, wam);
@@ -712,12 +818,11 @@ impl ListingCompiler {
dynamic_clause_map: worker.dynamic_clause_map, dynamic_clause_map: worker.dynamic_clause_map,
toplevel_results, toplevel_results,
toplevel_indices, toplevel_indices,
addition_results addition_results,
}) })
} }
fn drop_expansions(&self, flags: MachineFlags, code_repo: &mut CodeRepo) fn drop_expansions(&self, flags: MachineFlags, code_repo: &mut CodeRepo) {
{
let (te_len, te_queue_len) = self.orig_term_expansion_lens; let (te_len, te_queue_len) = self.orig_term_expansion_lens;
let (ge_len, ge_queue_len) = self.orig_goal_expansion_lens; let (ge_len, ge_queue_len) = self.orig_goal_expansion_lens;
@@ -729,15 +834,24 @@ impl ListingCompiler {
} }
} }
fn compile_work_impl(compiler: &mut ListingCompiler, wam: &mut Machine, fn compile_work_impl(
mut indices: IndexStore, mut results: GatherResult) compiler: &mut ListingCompiler,
-> EvalSession wam: &mut Machine,
{ mut indices: IndexStore,
let module_code = try_eval_session!(compiler.generate_code(results.worker_results, wam, mut results: GatherResult,
&mut indices.code_dir, 0)); ) -> EvalSession {
let toplvl_code = try_eval_session!(compiler.generate_code(results.toplevel_results, wam, let module_code = try_eval_session!(compiler.generate_code(
results.worker_results,
wam,
&mut indices.code_dir,
0
));
let toplvl_code = try_eval_session!(compiler.generate_code(
results.toplevel_results,
wam,
&mut results.toplevel_indices.code_dir, &mut results.toplevel_indices.code_dir,
module_code.len())); module_code.len()
));
if let Some(ref mut module) = &mut compiler.module { if let Some(ref mut module) = &mut compiler.module {
module.user_term_expansions = results.addition_results.take_term_expansions(); module.user_term_expansions = results.addition_results.take_term_expansions();
@@ -746,32 +860,44 @@ fn compile_work_impl(compiler: &mut ListingCompiler, wam: &mut Machine,
let flags = wam.machine_flags(); let flags = wam.machine_flags();
try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags)); try_eval_session!(wam
try_eval_session!(wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags)); .code_repo
.compile_hook(CompileTimeHook::UserTermExpansion, flags));
try_eval_session!(wam
.code_repo
.compile_hook(CompileTimeHook::UserGoalExpansion, flags));
if let Some(module) = compiler.module.take() { if let Some(module) = compiler.module.take() {
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len() + toplvl_code.len()); let mut clause_code_generator =
ClauseCodeGenerator::new(module_code.len() + toplvl_code.len());
try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices)); try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices));
try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map, try_eval_session!(
wam)); clause_code_generator.generate_clause_code(results.dynamic_clause_map, wam)
);
add_module_code(wam, module, module_code, indices); add_module_code(wam, module, module_code, indices);
add_toplevel_code(wam, toplvl_code, results.toplevel_indices); add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
clause_code_generator.add_clause_code(wam); clause_code_generator.add_clause_code(wam);
} else { } else {
try_eval_session!(add_non_module_code(wam, results.dynamic_clause_map, module_code, try_eval_session!(add_non_module_code(
indices)); wam,
results.dynamic_clause_map,
module_code,
indices
));
} }
EvalSession::EntrySuccess EvalSession::EntrySuccess
} }
fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine, fn compile_work<R: Read>(
src: ParsingStream<R>, mut indices: IndexStore) compiler: &mut ListingCompiler,
-> EvalSession wam: &mut Machine,
{ src: ParsingStream<R>,
mut indices: IndexStore,
) -> EvalSession {
let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices)); let results = try_eval_session!(compiler.gather_items(wam, src, &mut indices));
compile_work_impl(compiler, wam, indices, results) compile_work_impl(compiler, wam, indices, results)
} }
@@ -779,9 +905,10 @@ fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine,
/* This is a truncated version of compile_user_module, used for /* This is a truncated version of compile_user_module, used for
compiling code composing special forms, ie. the code that calls compiling code composing special forms, ie. the code that calls
M:verify_attributes on attributed variables. */ M:verify_attributes on attributed variables. */
pub fn compile_special_form<R: Read>(wam: &mut Machine, src: ParsingStream<R>) pub fn compile_special_form<R: Read>(
-> Result<Code, SessionError> wam: &mut Machine,
{ src: ParsingStream<R>,
) -> Result<Code, SessionError> {
let mut indices = default_index_store!(wam.indices.atom_tbl.clone()); let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
setup_indices(wam, clause_name!("builtins"), &mut indices)?; setup_indices(wam, clause_name!("builtins"), &mut indices)?;
@@ -792,25 +919,27 @@ pub fn compile_special_form<R: Read>(wam: &mut Machine, src: ParsingStream<R>)
} }
#[inline] #[inline]
pub pub fn compile_listing<R: Read>(
fn compile_listing<R: Read>(wam: &mut Machine, src: ParsingStream<R>, indices: IndexStore) wam: &mut Machine,
-> EvalSession src: ParsingStream<R>,
{ indices: IndexStore,
) -> EvalSession {
let mut compiler = ListingCompiler::new(&wam.code_repo); let mut compiler = ListingCompiler::new(&wam.code_repo);
match compile_work(&mut compiler, wam, src, indices) { match compile_work(&mut compiler, wam, src, indices) {
EvalSession::Error(e) => { EvalSession::Error(e) => {
compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo); compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo);
EvalSession::Error(e) EvalSession::Error(e)
}, }
result => result result => result,
} }
} }
pub(super) pub(super) fn setup_indices(
fn setup_indices(wam: &mut Machine, module: ClauseName, indices: &mut IndexStore) wam: &mut Machine,
-> Result<(), SessionError> module: ClauseName,
{ indices: &mut IndexStore,
) -> Result<(), SessionError> {
if let Some(module) = wam.indices.take_module(module) { if let Some(module) = wam.indices.take_module(module) {
let flags = wam.machine_flags(); let flags = wam.machine_flags();
let result = indices.use_module(&mut wam.code_repo, flags, &module); let result = indices.use_module(&mut wam.code_repo, flags, &module);

View File

@@ -5,8 +5,7 @@ use std::ops::IndexMut;
type Trail = Vec<(Ref, HeapCellValue)>; type Trail = Vec<(Ref, HeapCellValue)>;
pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue> pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
{
fn threshold(&self) -> usize; fn threshold(&self) -> usize;
fn push(&mut self, HeapCellValue); fn push(&mut self, HeapCellValue);
fn store(&self, Addr) -> Addr; fn store(&self, Addr) -> Addr;
@@ -14,9 +13,7 @@ pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
fn stack(&mut self) -> &mut AndStack; fn stack(&mut self) -> &mut AndStack;
} }
pub(crate) pub(crate) fn copy_term<T: CopierTarget>(target: T, addr: Addr) {
fn copy_term<T: CopierTarget>(target: T, addr: Addr)
{
let mut copy_term_state = CopyTermState::new(target); let mut copy_term_state = CopyTermState::new(target);
copy_term_state.copy_term_impl(addr); copy_term_state.copy_term_impl(addr);
} }
@@ -25,7 +22,7 @@ struct CopyTermState<T: CopierTarget> {
trail: Trail, trail: Trail,
scan: usize, scan: usize,
old_h: usize, old_h: usize,
target: T target: T,
} }
impl<T: CopierTarget> CopyTermState<T> { impl<T: CopierTarget> CopyTermState<T> {
@@ -34,7 +31,7 @@ impl<T: CopierTarget> CopyTermState<T> {
trail: vec![], trail: vec![],
scan: 0, scan: 0,
old_h: target.threshold(), old_h: target.threshold(),
target target,
} }
} }
@@ -44,24 +41,28 @@ impl<T: CopierTarget> CopyTermState<T> {
&mut self.target[scan] &mut self.target[scan]
} }
fn reinstantiate_var(&mut self, addr: Addr, threshold: usize) fn reinstantiate_var(&mut self, addr: Addr, threshold: usize) {
{
match addr { match addr {
Addr::HeapCell(h) => { Addr::HeapCell(h) => {
self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold)); self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold)); self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
self.trail.push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h)))); self.trail
}, .push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h))));
}
Addr::StackCell(fr, sc) => { Addr::StackCell(fr, sc) => {
self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold)); self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
self.target.stack()[fr][sc] = Addr::HeapCell(threshold); self.target.stack()[fr][sc] = Addr::HeapCell(threshold);
self.trail.push((Ref::StackCell(fr, sc), HeapCellValue::Addr(Addr::StackCell(fr, sc)))); self.trail.push((
}, Ref::StackCell(fr, sc),
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
));
}
Addr::AttrVar(h) => { Addr::AttrVar(h) => {
self.target[threshold] = HeapCellValue::Addr(Addr::AttrVar(threshold)); self.target[threshold] = HeapCellValue::Addr(Addr::AttrVar(threshold));
self.target[h] = HeapCellValue::Addr(Addr::AttrVar(threshold)); self.target[h] = HeapCellValue::Addr(Addr::AttrVar(threshold));
self.trail.push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h)))); self.trail
}, .push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h))));
}
_ => {} _ => {}
} }
} }
@@ -93,16 +94,19 @@ impl<T: CopierTarget> CopyTermState<T> {
let rd = self.target.store(self.target.deref(ra)); let rd = self.target.store(self.target.deref(ra));
match rd.clone() { match rd.clone() {
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
self.target[threshold] = HeapCellValue::Addr(rd), self.target[threshold] = HeapCellValue::Addr(rd)
ra @ Addr::AttrVar(_) | ra @ Addr::HeapCell(..) | ra @ Addr::StackCell(..) => }
ra @ Addr::AttrVar(_) | ra @ Addr::HeapCell(..) | ra @ Addr::StackCell(..) => {
if ra == rd { if ra == rd {
self.reinstantiate_var(ra, threshold); self.reinstantiate_var(ra, threshold);
} else { } else {
self.target[threshold] = HeapCellValue::Addr(ra); self.target[threshold] = HeapCellValue::Addr(ra);
}, }
}
_ => { _ => {
self.trail.push((Ref::HeapCell(addr), self.target[addr].clone())); self.trail
.push((Ref::HeapCell(addr), self.target[addr].clone()));
self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold)) self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold))
} }
}; };
@@ -120,23 +124,24 @@ impl<T: CopierTarget> CopyTermState<T> {
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => { Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
*self.value_at_scan() = HeapCellValue::Addr(rd); *self.value_at_scan() = HeapCellValue::Addr(rd);
self.scan += 1; self.scan += 1;
}, }
Addr::AttrVar(h) if addr == rd => { Addr::AttrVar(h) if addr == rd => {
let threshold = self.target.threshold(); let threshold = self.target.threshold();
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold))); self.target
.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
let list_val = self.target[h + 1].clone(); let list_val = self.target[h + 1].clone();
self.target.push(list_val); self.target.push(list_val);
self.reinstantiate_var(addr, threshold); self.reinstantiate_var(addr, threshold);
*self.value_at_scan() = HeapCellValue::Addr(Addr::AttrVar(threshold)); *self.value_at_scan() = HeapCellValue::Addr(Addr::AttrVar(threshold));
}, }
_ if addr == rd => { _ if addr == rd => {
let scan = self.scan; let scan = self.scan;
self.reinstantiate_var(addr, scan); self.reinstantiate_var(addr, scan);
self.scan += 1; self.scan += 1;
}, }
_ => *self.value_at_scan() = HeapCellValue::Addr(rd) _ => *self.value_at_scan() = HeapCellValue::Addr(rd),
} }
} }
@@ -148,18 +153,22 @@ impl<T: CopierTarget> CopyTermState<T> {
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold)); *self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold)); self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold));
self.trail.push((Ref::HeapCell(addr), self.trail.push((
HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()))); Ref::HeapCell(addr),
HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()),
));
self.target.push(HeapCellValue::NamedStr(arity, name, fixity)); self.target
.push(HeapCellValue::NamedStr(arity, name, fixity));
for i in 0..arity { for i in 0..arity {
let hcv = self.target[addr + 1 + i].clone(); let hcv = self.target[addr + 1 + i].clone();
self.target.push(hcv); self.target.push(hcv);
} }
}, }
HeapCellValue::Addr(Addr::Str(addr)) => HeapCellValue::Addr(Addr::Str(addr)) => {
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr)), *self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
}
_ => {} _ => {}
} }
@@ -172,21 +181,15 @@ impl<T: CopierTarget> CopyTermState<T> {
while self.scan < self.target.threshold() { while self.scan < self.target.threshold() {
match self.value_at_scan().clone() { match self.value_at_scan().clone() {
HeapCellValue::NamedStr(..) => HeapCellValue::NamedStr(..) => self.scan += 1,
self.scan += 1, HeapCellValue::Addr(addr) => match addr {
HeapCellValue::Addr(addr) => Addr::Lis(addr) => self.copy_list(addr),
match addr {
Addr::Lis(addr) =>
self.copy_list(addr),
addr @ Addr::AttrVar(_) addr @ Addr::AttrVar(_)
| addr @ Addr::HeapCell(_) | addr @ Addr::HeapCell(_)
| addr @ Addr::StackCell(..) => | addr @ Addr::StackCell(..) => self.copy_var(addr),
self.copy_var(addr), Addr::Str(addr) => self.copy_structure(addr),
Addr::Str(addr) => Addr::Con(_) | Addr::DBRef(_) => self.scan += 1,
self.copy_structure(addr), },
Addr::Con(_) | Addr::DBRef(_) =>
self.scan += 1
}
} }
} }
@@ -196,10 +199,8 @@ impl<T: CopierTarget> CopyTermState<T> {
fn unwind_trail(&mut self) { fn unwind_trail(&mut self) {
for (r, value) in self.trail.drain(0..) { for (r, value) in self.trail.drain(0..) {
match r { match r {
Ref::AttrVar(h) | Ref::HeapCell(h) => Ref::AttrVar(h) | Ref::HeapCell(h) => self.target[h] = value,
self.target[h] = value, Ref::StackCell(fr, sc) => self.target.stack()[fr][sc] = value.as_addr(0),
Ref::StackCell(fr, sc) =>
self.target.stack()[fr][sc] = value.as_addr(0)
} }
} }
} }

View File

@@ -1,24 +1,26 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use prolog::heap_print::*; use prolog::heap_print::*;
use prolog::machine::*;
use prolog::machine::compile::*; use prolog::machine::compile::*;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::machine::*;
use std::io::Read; use std::io::Read;
impl Machine { impl Machine {
pub(super) pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
match name { match name {
&ClauseName::User(ref rc) => rc.table.clone(), &ClauseName::User(ref rc) => rc.table.clone(),
_ => self.indices.atom_tbl() _ => self.indices.atom_tbl(),
} }
} }
fn compile_into_machine<R: Read>(&mut self, src: ParsingStream<R>, name: ClauseName, arity: usize) fn compile_into_machine<R: Read>(
-> EvalSession &mut self,
{ src: ParsingStream<R>,
name: ClauseName,
arity: usize,
) -> EvalSession {
match name.owning_module().as_str() { match name.owning_module().as_str() {
"user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() { "user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() {
Some(idx) => { Some(idx) => {
@@ -26,37 +28,38 @@ impl Machine {
match module.as_str() { match module.as_str() {
"user" => compile_user_module(self, src), "user" => compile_user_module(self, src),
_ => compile_into_module(self, module, src, name) _ => compile_into_module(self, module, src, name),
} }
}
None => compile_user_module(self, src),
}, },
None => compile_user_module(self, src) _ => compile_into_module(self, name.owning_module(), src, name),
},
_ => compile_into_module(self, name.owning_module(), src, name)
} }
} }
fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey {
{
let name = self.machine_st[name].clone(); let name = self.machine_st[name].clone();
let arity = self.machine_st[arity].clone(); let arity = self.machine_st[arity].clone();
let name = match self.machine_st.store(self.machine_st.deref(name)) { let name = match self.machine_st.store(self.machine_st.deref(name)) {
Addr::Con(Constant::Atom(name, _)) => name, Addr::Con(Constant::Atom(name, _)) => name,
_ => unreachable!() _ => unreachable!(),
}; };
let arity = match self.machine_st.store(self.machine_st.deref(arity)) { let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
Addr::Con(Constant::Integer(arity)) => Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
arity.to_usize().unwrap(), _ => unreachable!(),
_ => unreachable!()
}; };
(name, arity) (name, arity)
} }
fn print_new_dynamic_clause(&self, addrs: VecDeque<Addr>, name: ClauseName, arity: usize) fn print_new_dynamic_clause(
-> String &self,
{ addrs: VecDeque<Addr>,
name: ClauseName,
arity: usize,
) -> String {
let mut output = PrinterOutputter::new(); let mut output = PrinterOutputter::new();
output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity).as_str()); output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity).as_str());
@@ -71,8 +74,7 @@ impl Machine {
output.result() output.result()
} }
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
{
let (name, arity) = self.get_predicate_key(name, arity); let (name, arity) = self.get_predicate_key(name, arity);
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
@@ -80,27 +82,26 @@ impl Machine {
} }
self.indices.remove_code_index((name.clone(), arity)); self.indices.remove_code_index((name.clone(), arity));
self.indices.remove_clause_subsection(name.owning_module(), name, arity); self.indices
.remove_clause_subsection(name.owning_module(), name, arity);
} }
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) {
{
let (name, arity) = self.get_predicate_key(name, arity); let (name, arity) = self.get_predicate_key(name, arity);
let module_addr = self.machine_st[module].clone(); let module_addr = self.machine_st[module].clone();
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) { let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
Addr::Con(Constant::Atom(module, _)) => Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
match self.indices.modules.get_mut(&module) {
Some(ref mut module) => { Some(ref mut module) => {
module.code_dir.remove(&(name.clone(), arity)); module.code_dir.remove(&(name.clone(), arity));
module.module_decl.name.clone() module.module_decl.name.clone()
}, }
_ => { _ => {
self.machine_st.fail = true; self.machine_st.fail = true;
return; return;
} }
}, },
_ => unreachable!() _ => unreachable!(),
}; };
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) { if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
@@ -110,12 +111,17 @@ impl Machine {
} }
self.indices.remove_code_index((name.clone(), arity)); self.indices.remove_code_index((name.clone(), arity));
self.indices.remove_clause_subsection(module_name, name, arity); self.indices
.remove_clause_subsection(module_name, name, arity);
} }
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName, fn handle_eval_result_from_dynamic_compile(
arity: usize, src: ClauseName) &mut self,
{ pred_str: String,
name: ClauseName,
arity: usize,
src: ClauseName,
) {
let machine_st = mem::replace(&mut self.machine_st, MachineState::new()); let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
let result = self.compile_into_machine(parsing_stream(pred_str.as_bytes()), name, arity); let result = self.compile_into_machine(parsing_stream(pred_str.as_bytes()), name, arity);
@@ -131,9 +137,12 @@ impl Machine {
} }
} }
fn recompile_dynamic_predicate_impl(&mut self, place: DynamicAssertPlace, name: ClauseName, fn recompile_dynamic_predicate_impl(
arity: usize) &mut self,
{ place: DynamicAssertPlace,
name: ClauseName,
arity: usize,
) {
let stub = MachineError::functor_stub(place.predicate_name(), 1); let stub = MachineError::functor_stub(place.predicate_name(), 1);
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) { let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
Ok(addrs) => { Ok(addrs) => {
@@ -142,26 +151,23 @@ impl Machine {
place.push_to_queue(&mut addrs, added_clause); place.push_to_queue(&mut addrs, added_clause);
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
}, }
Err(err) => Err(err) => return self.machine_st.throw_exception(err),
return self.machine_st.throw_exception(err)
}; };
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name()); self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name());
} }
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
{
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) { let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
Addr::Con(Constant::Atom(module, _)) => Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
match self.indices.modules.get(&module) {
Some(ref module) => module.atom_tbl.clone(), Some(ref module) => module.atom_tbl.clone(),
None => { None => {
self.machine_st.fail = true; self.machine_st.fail = true;
return false; return false;
} }
}, },
_ => unreachable!() _ => unreachable!(),
}; };
if let &mut ClauseName::User(ref mut rc) = name { if let &mut ClauseName::User(ref mut rc) = name {
@@ -171,8 +177,7 @@ impl Machine {
true true
} }
fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace) fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace) {
{
let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4)); let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
let module_addr = self.machine_st[temp_v!(5)].clone(); let module_addr = self.machine_st[temp_v!(5)].clone();
@@ -181,18 +186,16 @@ impl Machine {
} }
} }
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace) fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace) {
{
let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4)); let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
self.recompile_dynamic_predicate_impl(place, name, arity); self.recompile_dynamic_predicate_impl(place, name, arity);
} }
fn retract_from_dynamic_predicate_in_module(&mut self) fn retract_from_dynamic_predicate_in_module(&mut self) {
{
let index = self.machine_st[temp_v!(3)].clone(); let index = self.machine_st[temp_v!(3)].clone();
let index = match self.machine_st.store(self.machine_st.deref(index)) { let index = match self.machine_st.store(self.machine_st.deref(index)) {
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(), Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
_ => unreachable!() _ => unreachable!(),
}; };
let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2)); let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
@@ -206,28 +209,29 @@ impl Machine {
addrs.remove(index); addrs.remove(index);
if addrs.is_empty() { if addrs.is_empty() {
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(5));
temp_v!(5));
return; return;
} }
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
}, }
Err(err) => Err(err) => return self.machine_st.throw_exception(err),
return self.machine_st.throw_exception(err)
}; };
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, self.handle_eval_result_from_dynamic_compile(
clause_name!("retract")); pred_str,
name,
arity,
clause_name!("retract"),
);
} }
} }
fn retract_from_dynamic_predicate(&mut self) fn retract_from_dynamic_predicate(&mut self) {
{
let index = self.machine_st[temp_v!(3)].clone(); let index = self.machine_st[temp_v!(3)].clone();
let index = match self.machine_st.store(self.machine_st.deref(index)) { let index = match self.machine_st.store(self.machine_st.deref(index)) {
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(), Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
_ => unreachable!() _ => unreachable!(),
}; };
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2)); let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
@@ -244,31 +248,36 @@ impl Machine {
} }
self.print_new_dynamic_clause(addrs, name.clone(), arity) self.print_new_dynamic_clause(addrs, name.clone(), arity)
}, }
Err(err) => Err(err) => return self.machine_st.throw_exception(err),
return self.machine_st.throw_exception(err)
}; };
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, self.handle_eval_result_from_dynamic_compile(
clause_name!("retract")); pred_str,
name,
arity,
clause_name!("retract"),
);
} }
pub(super) pub(super) fn dynamic_transaction(
fn dynamic_transaction(&mut self, trans_type: DynamicTransactionType, p: LocalCodePtr) &mut self,
{ trans_type: DynamicTransactionType,
p: LocalCodePtr,
) {
match trans_type { match trans_type {
DynamicTransactionType::Abolish => DynamicTransactionType::Abolish => self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)), DynamicTransactionType::Assert(place) => self.recompile_dynamic_predicate(place),
DynamicTransactionType::Assert(place) => DynamicTransactionType::ModuleAbolish => {
self.recompile_dynamic_predicate(place), self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3))
DynamicTransactionType::ModuleAbolish => }
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3)), DynamicTransactionType::ModuleAssert(place) => {
DynamicTransactionType::ModuleAssert(place) => self.recompile_dynamic_predicate_in_module(place)
self.recompile_dynamic_predicate_in_module(place), }
DynamicTransactionType::ModuleRetract => DynamicTransactionType::ModuleRetract => {
self.retract_from_dynamic_predicate_in_module(), self.retract_from_dynamic_predicate_in_module()
DynamicTransactionType::Retract => }
self.retract_from_dynamic_predicate() DynamicTransactionType::Retract => self.retract_from_dynamic_predicate(),
} }
self.machine_st.p = CodePtr::Local(p); self.machine_st.p = CodePtr::Local(p);

View File

@@ -12,8 +12,10 @@ pub struct Heap {
impl Heap { impl Heap {
pub fn with_capacity(cap: usize) -> Self { pub fn with_capacity(cap: usize) -> Self {
Heap { heap: Vec::with_capacity(cap), Heap {
h: 0 } heap: Vec::with_capacity(cap),
h: 0,
}
} }
#[inline] #[inline]
@@ -29,7 +31,7 @@ impl Heap {
Heap { Heap {
heap: mem::replace(&mut self.heap, vec![]), heap: mem::replace(&mut self.heap, vec![]),
h h,
} }
} }

View File

@@ -10,63 +10,115 @@ pub(crate) type MachineStub = Vec<HeapCellValue>;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum ErrorProvenance { enum ErrorProvenance {
Constructed, // if constructed, offset the addresses. Constructed, // if constructed, offset the addresses.
Received // otherwise, preserve the addresses. Received, // otherwise, preserve the addresses.
} }
pub(super) struct MachineError { pub(super) struct MachineError {
stub: MachineStub, stub: MachineStub,
location: Option<(usize, usize)>, // line_num, col_num location: Option<(usize, usize)>, // line_num, col_num
from: ErrorProvenance from: ErrorProvenance,
} }
impl MachineError { impl MachineError {
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub { pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None))); let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
functor!("/", 2, [name, heap_integer!(Integer::from(arity))], SharedOpDesc::new(400, YFX)) functor!(
"/",
2,
[name, heap_integer!(Integer::from(arity))],
SharedOpDesc::new(400, YFX)
)
} }
pub(super) fn evaluation_error(eval_error: EvalError) -> Self { pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]); let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
MachineError { stub, location: None, from: ErrorProvenance::Received } MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
} }
pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self { pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()), let stub = functor!(
HeapCellValue::Addr(culprit)]); "type_error",
2,
[
heap_atom!(valid_type.as_str()),
HeapCellValue::Addr(culprit)
]
);
MachineError { stub, location: None, from: ErrorProvenance::Received } MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
} }
pub(super) pub(super) fn module_resolution_error(
fn module_resolution_error(h: usize, mod_name: ClauseName, name: ClauseName, arity: usize) -> Self h: usize,
{ mod_name: ClauseName,
name: ClauseName,
arity: usize,
) -> Self {
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None))); let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None)));
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None))); let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
let mut stub = functor!("evaluation_error", 1, [HeapCellValue::Addr(Addr::HeapCell(h + 2))]); let mut stub = functor!(
"evaluation_error",
1,
[HeapCellValue::Addr(Addr::HeapCell(h + 2))]
);
stub.append(&mut functor!("/", 2, [HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)), stub.append(&mut functor!(
heap_integer!(Integer::from(arity))], "/",
SharedOpDesc::new(400, YFX))); 2,
stub.append(&mut functor!(":", 2, [mod_name, name], SharedOpDesc::new(600, XFY))); [
HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
heap_integer!(Integer::from(arity))
],
SharedOpDesc::new(400, YFX)
));
stub.append(&mut functor!(
":",
2,
[mod_name, name],
SharedOpDesc::new(600, XFY)
));
MachineError { stub, location: None, from: ErrorProvenance::Constructed } MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
} }
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self {
{
match err { match err {
ExistenceError::Procedure(name, arity) => { ExistenceError::Procedure(name, arity) => {
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]); let mut stub = functor!(
"existence_error",
2,
[heap_atom!("procedure"), heap_str!(3 + h)]
);
stub.append(&mut Self::functor_stub(name, arity)); stub.append(&mut Self::functor_stub(name, arity));
MachineError { stub, location: None, from: ErrorProvenance::Constructed } MachineError {
}, stub,
location: None,
from: ErrorProvenance::Constructed,
}
}
ExistenceError::Module(name) => { ExistenceError::Module(name) => {
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None))); let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
let stub = functor!("existence_error", 2, [heap_atom!("module"), name]); let stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
MachineError { stub, location: None, from: ErrorProvenance::Constructed } MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
} }
} }
} }
@@ -75,31 +127,37 @@ impl MachineError {
match err { match err {
SessionError::ParserError(err) => Self::syntax_error(h, err), SessionError::ParserError(err) => Self::syntax_error(h, err),
SessionError::CannotOverwriteBuiltIn(pred_str) SessionError::CannotOverwriteBuiltIn(pred_str)
| SessionError::CannotOverwriteImport(pred_str) => | SessionError::CannotOverwriteImport(pred_str) => {
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str), Self::permission_error(PermissionError::Modify, "private_procedure", pred_str)
SessionError::InvalidFileName(filename) => }
Self::existence_error(h, ExistenceError::Module(filename)), SessionError::InvalidFileName(filename) => {
SessionError::ModuleDoesNotContainExport => Self::existence_error(h, ExistenceError::Module(filename))
Self::permission_error(PermissionError::Access, }
SessionError::ModuleDoesNotContainExport => Self::permission_error(
PermissionError::Access,
"private_procedure", "private_procedure",
clause_name!("module_does_not_contain_claimed_export")), clause_name!("module_does_not_contain_claimed_export"),
SessionError::ModuleNotFound => ),
Self::permission_error(PermissionError::Access, SessionError::ModuleNotFound => Self::permission_error(
PermissionError::Access,
"private_procedure", "private_procedure",
clause_name!("module_does_not_exist")), clause_name!("module_does_not_exist"),
SessionError::NoModuleDeclaration(name) => ),
Self::existence_error(h, ExistenceError::Module(name)), SessionError::NoModuleDeclaration(name) => {
SessionError::OpIsInfixAndPostFix(op) => Self::existence_error(h, ExistenceError::Module(name))
Self::permission_error(PermissionError::Create, }
"operator", SessionError::OpIsInfixAndPostFix(op) => {
op), Self::permission_error(PermissionError::Create, "operator", op)
_ => unreachable!() }
_ => unreachable!(),
} }
} }
pub(super) pub(super) fn permission_error(
fn permission_error(err: PermissionError, index_str: &'static str, pred_str: ClauseName) -> Self err: PermissionError,
{ index_str: &'static str,
pred_str: ClauseName,
) -> Self {
let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None))); let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None)));
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), pred_str]; let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), pred_str];
@@ -107,22 +165,33 @@ impl MachineError {
stub.extend(err.into_iter()); stub.extend(err.into_iter());
MachineError { stub, location: None, from: ErrorProvenance::Constructed } MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
} }
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self { fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
match err { match err {
ArithmeticError::UninstantiatedVar => ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
Self::instantiation_error(),
ArithmeticError::NonEvaluableFunctor(name, arity) => { ArithmeticError::NonEvaluableFunctor(name, arity) => {
let name = HeapCellValue::Addr(Addr::Con(name)); let name = HeapCellValue::Addr(Addr::Con(name));
let culprit = functor!("/", 2, [name, heap_integer!(Integer::from(arity))], let culprit = functor!(
SharedOpDesc::new(400, YFX)); "/",
2,
[name, heap_integer!(Integer::from(arity))],
SharedOpDesc::new(400, YFX)
);
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub; let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
stub.extend(culprit.into_iter()); stub.extend(culprit.into_iter());
MachineError { stub, location: None, from: ErrorProvenance::Constructed } MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
}
} }
} }
} }
@@ -143,36 +212,53 @@ impl MachineError {
stub.extend(err.into_iter()); stub.extend(err.into_iter());
MachineError { stub, location, from: ErrorProvenance::Constructed } MachineError {
stub,
location,
from: ErrorProvenance::Constructed,
}
} }
pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self { pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self {
let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()), let stub = functor!(
HeapCellValue::Addr(culprit)]); "domain_error",
MachineError { stub, location: None, from: ErrorProvenance::Received } 2,
[heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
} }
pub(super) fn instantiation_error() -> Self { pub(super) fn instantiation_error() -> Self {
let stub = functor!("instantiation_error"); let stub = functor!("instantiation_error");
MachineError { stub, location: None, from: ErrorProvenance::Received } MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
} }
pub(super) fn representation_error(flag: RepFlag) -> Self { pub(super) fn representation_error(flag: RepFlag) -> Self {
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]); let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
MachineError { stub, location: None, from: ErrorProvenance::Received } MachineError {
stub,
location: None,
from: ErrorProvenance::Received,
}
} }
fn into_iter(self, offset: usize) -> Box<Iterator<Item = HeapCellValue>> { fn into_iter(self, offset: usize) -> Box<Iterator<Item = HeapCellValue>> {
match self.from { match self.from {
ErrorProvenance::Constructed => ErrorProvenance::Constructed => {
Box::new(self.stub.into_iter().map(move |hcv| { Box::new(self.stub.into_iter().map(move |hcv| match hcv {
match hcv {
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr + offset), HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr + offset),
hcv => hcv hcv => hcv,
}))
} }
})), ErrorProvenance::Received => Box::new(self.stub.into_iter()),
ErrorProvenance::Received =>
Box::new(self.stub.into_iter())
} }
} }
@@ -193,7 +279,7 @@ impl PermissionError {
match self { match self {
PermissionError::Access => "access", PermissionError::Access => "access",
PermissionError::Create => "create", PermissionError::Create => "create",
PermissionError::Modify => "modify" PermissionError::Modify => "modify",
} }
} }
} }
@@ -246,13 +332,13 @@ impl ValidType {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum DomainError { pub enum DomainError {
NotLessThanZero NotLessThanZero,
} }
impl DomainError { impl DomainError {
pub fn as_str(self) -> &'static str { pub fn as_str(self) -> &'static str {
match self { match self {
DomainError::NotLessThanZero => "not_less_than_zero" DomainError::NotLessThanZero => "not_less_than_zero",
} }
} }
} }
@@ -308,7 +394,7 @@ pub(super) enum CycleSearchResult {
PartialList(usize, usize), // the list length (up to max), and an offset into the heap. PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
ProperList(usize), // the list length. ProperList(usize), // the list length.
String(usize, StringList), // the number of elements iterated, the string tail. String(usize, StringList), // the number of elements iterated, the string tail.
UntouchedList(usize) // the address of an uniterated Addr::Lis(address). UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
} }
impl MachineState { impl MachineState {
@@ -319,17 +405,20 @@ impl MachineState {
let sorted = self.store(self.deref(self[temp_v!(2)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(list.clone()) { match self.detect_cycles(list.clone()) {
CycleSearchResult::PartialList(..) => CycleSearchResult::PartialList(..) => {
return Err(self.error_form(MachineError::instantiation_error(), stub)), return Err(self.error_form(MachineError::instantiation_error(), stub))
CycleSearchResult::NotList => }
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)), CycleSearchResult::NotList => {
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
}
_ => {} _ => {}
}; };
match self.detect_cycles(sorted.clone()) { match self.detect_cycles(sorted.clone()) {
CycleSearchResult::NotList if !sorted.is_ref() => CycleSearchResult::NotList if !sorted.is_ref() => {
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub)), Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
_ => Ok(()) }
_ => Ok(()),
} }
} }
@@ -337,8 +426,9 @@ impl MachineState {
let stub = MachineError::functor_stub(clause_name!("keysort"), 2); let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
match self.detect_cycles(list.clone()) { match self.detect_cycles(list.clone()) {
CycleSearchResult::NotList if !list.is_ref() => CycleSearchResult::NotList if !list.is_ref() => {
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)), Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
}
_ => { _ => {
let mut addr = list; let mut addr = list;
@@ -349,12 +439,18 @@ impl MachineState {
match self.heap[new_l].clone() { match self.heap[new_l].clone() {
HeapCellValue::Addr(Addr::Str(l)) => new_l = l, HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
HeapCellValue::NamedStr(2, ref name, Some(_)) HeapCellValue::NamedStr(2, ref name, Some(_))
if name.as_str() == "-" => break, if name.as_str() == "-" =>
{
break
}
HeapCellValue::Addr(Addr::HeapCell(_)) => break, HeapCellValue::Addr(Addr::HeapCell(_)) => break,
HeapCellValue::Addr(Addr::StackCell(..)) => break, HeapCellValue::Addr(Addr::StackCell(..)) => break,
_ => return Err(self.error_form(MachineError::type_error(ValidType::Pair, _ => {
Addr::HeapCell(l)), return Err(self.error_form(
stub)) MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
stub,
))
}
}; };
} }
@@ -373,11 +469,13 @@ impl MachineState {
let sorted = self.store(self.deref(self[temp_v!(2)].clone())); let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
match self.detect_cycles(pairs.clone()) { match self.detect_cycles(pairs.clone()) {
CycleSearchResult::PartialList(..) => CycleSearchResult::PartialList(..) => {
Err(self.error_form(MachineError::instantiation_error(), stub)), Err(self.error_form(MachineError::instantiation_error(), stub))
CycleSearchResult::NotList => }
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub)), CycleSearchResult::NotList => {
_ => Ok(()) Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
}
_ => Ok(()),
}?; }?;
self.check_for_list_pairs(sorted) self.check_for_list_pairs(sorted)
@@ -388,18 +486,25 @@ impl MachineState {
let err_len = err.len(); let err_len = err.len();
let h = self.heap.h; let h = self.heap.h;
let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None), let mut stub = vec![
HeapCellValue::NamedStr(2, clause_name!("error"), None),
HeapCellValue::Addr(Addr::HeapCell(h + 3)), HeapCellValue::Addr(Addr::HeapCell(h + 3)),
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len))]; HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len)),
];
stub.extend(err.into_iter(3)); stub.extend(err.into_iter(3));
if let Some((line_num, _)) = location { if let Some((line_num, _)) = location {
let colon_op_desc = Some(SharedOpDesc::new(600, XFY)); let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
stub.extend(vec![HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc), stub.extend(
vec![
HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)), HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
heap_integer!(Integer::from(line_num))].into_iter()); heap_integer!(Integer::from(line_num)),
]
.into_iter(),
);
} }
stub.extend(src.into_iter()); stub.extend(src.into_iter());
@@ -423,7 +528,7 @@ impl MachineState {
pub enum ExistenceError { pub enum ExistenceError {
Module(ClauseName), Module(ClauseName),
Procedure(ClauseName, usize) Procedure(ClauseName, usize),
} }
pub enum SessionError { pub enum SessionError {
@@ -436,7 +541,7 @@ pub enum SessionError {
NoModuleDeclaration(ClauseName), NoModuleDeclaration(ClauseName),
OpIsInfixAndPostFix(ClauseName), OpIsInfixAndPostFix(ClauseName),
ParserError(ParserError), ParserError(ParserError),
UserPrompt UserPrompt,
} }
pub enum EvalSession { pub enum EvalSession {

View File

@@ -22,7 +22,13 @@ pub type OssifiedOpDir = BTreeMap<OrderedOpDirKey, (usize, Specifier)>;
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum DBRef { pub enum DBRef {
NamedPred(ClauseName, usize, Option<SharedOpDesc>), NamedPred(ClauseName, usize, Option<SharedOpDesc>),
Op(usize, Specifier, ClauseName, Rc<OssifiedOpDir>, SharedOpDesc) Op(
usize,
Specifier,
ClauseName,
Rc<OssifiedOpDir>,
SharedOpDesc,
),
} }
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
@@ -33,14 +39,14 @@ pub enum Addr {
Lis(usize), Lis(usize),
HeapCell(usize), HeapCell(usize),
StackCell(usize, usize), StackCell(usize, usize),
Str(usize) Str(usize),
} }
#[derive(Clone, Copy, Hash, Eq, PartialEq)] #[derive(Clone, Copy, Hash, Eq, PartialEq)]
pub enum Ref { pub enum Ref {
AttrVar(usize), AttrVar(usize),
HeapCell(usize), HeapCell(usize),
StackCell(usize, usize) StackCell(usize, usize),
} }
impl Ref { impl Ref {
@@ -48,7 +54,7 @@ impl Ref {
match self { match self {
Ref::AttrVar(h) => Addr::AttrVar(h), Ref::AttrVar(h) => Addr::AttrVar(h),
Ref::HeapCell(h) => Addr::HeapCell(h), Ref::HeapCell(h) => Addr::HeapCell(h),
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
} }
} }
} }
@@ -63,11 +69,9 @@ impl PartialEq<Ref> for Addr {
impl PartialOrd<Ref> for Addr { impl PartialOrd<Ref> for Addr {
fn partial_cmp(&self, r: &Ref) -> Option<Ordering> { fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
match self { match self {
&Addr::StackCell(fr, sc) => &Addr::StackCell(fr, sc) => match *r {
match *r { Ref::AttrVar(_) | Ref::HeapCell(_) => Some(Ordering::Greater),
Ref::AttrVar(_) | Ref::HeapCell(_) => Ref::StackCell(fr1, sc1) => {
Some(Ordering::Greater),
Ref::StackCell(fr1, sc1) =>
if fr1 < fr || (fr1 == fr && sc1 < sc) { if fr1 < fr || (fr1 == fr && sc1 < sc) {
Some(Ordering::Greater) Some(Ordering::Greater)
} else if fr1 == fr && sc1 == sc { } else if fr1 == fr && sc1 == sc {
@@ -75,13 +79,13 @@ impl PartialOrd<Ref> for Addr {
} else { } else {
Some(Ordering::Less) Some(Ordering::Less)
} }
}
}, },
&Addr::HeapCell(h) | &Addr::AttrVar(h) => &Addr::HeapCell(h) | &Addr::AttrVar(h) => match r {
match r {
&Ref::StackCell(..) => Some(Ordering::Less), &Ref::StackCell(..) => Some(Ordering::Less),
&Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1) &Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1),
}, },
_ => None _ => None,
} }
} }
} }
@@ -90,7 +94,7 @@ impl Addr {
pub fn is_ref(&self) -> bool { pub fn is_ref(&self) -> bool {
match self { match self {
&Addr::AttrVar(_) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true, &Addr::AttrVar(_) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
_ => false _ => false,
} }
} }
@@ -99,14 +103,14 @@ impl Addr {
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)), &Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)), &Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)), &Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
_ => None _ => None,
} }
} }
pub fn is_protected(&self, e: usize) -> bool { pub fn is_protected(&self, e: usize) -> bool {
match self { match self {
&Addr::StackCell(addr, _) if addr >= e => false, &Addr::StackCell(addr, _) if addr >= e => false,
_ => true _ => true,
} }
} }
} }
@@ -120,7 +124,7 @@ impl Add<usize> for Addr {
Addr::AttrVar(h) => Addr::AttrVar(h + rhs), Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs), Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
Addr::Str(s) => Addr::Str(s + rhs), Addr::Str(s) => Addr::Str(s + rhs),
_ => self _ => self,
} }
} }
} }
@@ -135,7 +139,7 @@ impl Sub<i64> for Addr {
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize), Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize), Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize), Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
_ => self _ => self,
} }
} else { } else {
self.sub(rhs as usize) self.sub(rhs as usize)
@@ -152,7 +156,7 @@ impl Sub<usize> for Addr {
Addr::AttrVar(h) => Addr::AttrVar(h - rhs), Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
Addr::HeapCell(h) => Addr::HeapCell(h - rhs), Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
Addr::Str(s) => Addr::Str(s - rhs), Addr::Str(s) => Addr::Str(s - rhs),
_ => self _ => self,
} }
} }
} }
@@ -168,7 +172,7 @@ impl From<Ref> for Addr {
match r { match r {
Ref::AttrVar(h) => Addr::AttrVar(h), Ref::AttrVar(h) => Addr::AttrVar(h),
Ref::HeapCell(h) => Addr::HeapCell(h), Ref::HeapCell(h) => Addr::HeapCell(h),
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc) Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
} }
} }
} }
@@ -176,7 +180,7 @@ impl From<Ref> for Addr {
#[derive(Clone)] #[derive(Clone)]
pub enum TrailRef { pub enum TrailRef {
Ref(Ref), Ref(Ref),
AttrVarLink(usize, Addr) AttrVarLink(usize, Addr),
} }
impl From<Ref> for TrailRef { impl From<Ref> for TrailRef {
@@ -195,7 +199,7 @@ impl HeapCellValue {
pub fn as_addr(&self, focus: usize) -> Addr { pub fn as_addr(&self, focus: usize) -> Addr {
match self { match self {
&HeapCellValue::Addr(ref a) => a.clone(), &HeapCellValue::Addr(ref a) => a.clone(),
&HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus) &HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus),
} }
} }
} }
@@ -229,14 +233,17 @@ impl CodeIndex {
pub fn local(&self) -> Option<usize> { pub fn local(&self) -> Option<usize> {
match self.0.borrow().0 { match self.0.borrow().0 {
IndexPtr::Index(i) => Some(i), IndexPtr::Index(i) => Some(i),
_ => None _ => None,
} }
} }
} }
impl Default for CodeIndex { impl Default for CodeIndex {
fn default() -> Self { fn default() -> Self {
CodeIndex(Rc::new(RefCell::new((IndexPtr::Undefined, clause_name!(""))))) CodeIndex(Rc::new(RefCell::new((
IndexPtr::Undefined,
clause_name!(""),
))))
} }
} }
@@ -248,7 +255,8 @@ impl From<(usize, ClauseName)> for CodeIndex {
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum DynamicAssertPlace { pub enum DynamicAssertPlace {
Back, Front Back,
Front,
} }
impl DynamicAssertPlace { impl DynamicAssertPlace {
@@ -256,7 +264,7 @@ impl DynamicAssertPlace {
pub fn predicate_name(self) -> ClauseName { pub fn predicate_name(self) -> ClauseName {
match self { match self {
DynamicAssertPlace::Back => clause_name!("assertz"), DynamicAssertPlace::Back => clause_name!("assertz"),
DynamicAssertPlace::Front => clause_name!("asserta") DynamicAssertPlace::Front => clause_name!("asserta"),
} }
} }
@@ -264,7 +272,7 @@ impl DynamicAssertPlace {
pub fn push_to_queue(self, addrs: &mut VecDeque<Addr>, new_addr: Addr) { pub fn push_to_queue(self, addrs: &mut VecDeque<Addr>, new_addr: Addr) {
match self { match self {
DynamicAssertPlace::Back => addrs.push_back(new_addr), DynamicAssertPlace::Back => addrs.push_back(new_addr),
DynamicAssertPlace::Front => addrs.push_front(new_addr) DynamicAssertPlace::Front => addrs.push_front(new_addr),
} }
} }
} }
@@ -276,13 +284,13 @@ pub enum DynamicTransactionType {
ModuleAbolish, ModuleAbolish,
ModuleAssert(DynamicAssertPlace), ModuleAssert(DynamicAssertPlace),
ModuleRetract, ModuleRetract,
Retract // dynamic index of the clause to remove. Retract, // dynamic index of the clause to remove.
} }
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr { pub enum REPLCodePtr {
CompileBatch, CompileBatch,
SubmitQueryAndPrintResults SubmitQueryAndPrintResults,
} }
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
@@ -292,7 +300,7 @@ pub enum CodePtr {
Local(LocalCodePtr), Local(LocalCodePtr),
DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer. DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer. REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
VerifyAttrInterrupt(usize) // location of the verify attribute interrupt code in the CodeDir. VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
} }
impl CodePtr { impl CodePtr {
@@ -302,8 +310,7 @@ impl CodePtr {
| &CodePtr::CallN(_, ref local) | &CodePtr::CallN(_, ref local)
| &CodePtr::Local(ref local) => local.clone(), | &CodePtr::Local(ref local) => local.clone(),
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p), &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
&CodePtr::REPL(_, p) &CodePtr::REPL(_, p) | &CodePtr::DynamicTransaction(_, p) => p,
| &CodePtr::DynamicTransaction(_, p) => p
} }
} }
} }
@@ -314,7 +321,7 @@ pub enum LocalCodePtr {
InSituDirEntry(usize), InSituDirEntry(usize),
TopLevel(usize, usize), // chunk_num, offset. TopLevel(usize, usize), // chunk_num, offset.
UserGoalExpansion(usize), UserGoalExpansion(usize),
UserTermExpansion(usize) UserTermExpansion(usize),
} }
impl LocalCodePtr { impl LocalCodePtr {
@@ -330,7 +337,7 @@ impl PartialOrd<CodePtr> for CodePtr {
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> { fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
match (self, other) { match (self, other) {
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2), (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
_ => Some(Ordering::Greater) _ => Some(Ordering::Greater),
} }
} }
} }
@@ -342,11 +349,11 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
| (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2)) | (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2))
| (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2)) | (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2))
| (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2)) | (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2))
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => | (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
p1.partial_cmp(p2), p1.partial_cmp(p2)
(_, &LocalCodePtr::TopLevel(_, _)) => }
Some(Ordering::Less), (_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
_ => Some(Ordering::Greater) _ => Some(Ordering::Greater),
} }
} }
} }
@@ -384,7 +391,7 @@ impl AddAssign<usize> for LocalCodePtr {
| &mut LocalCodePtr::UserGoalExpansion(ref mut p) | &mut LocalCodePtr::UserGoalExpansion(ref mut p)
| &mut LocalCodePtr::UserTermExpansion(ref mut p) | &mut LocalCodePtr::UserTermExpansion(ref mut p)
| &mut LocalCodePtr::DirEntry(ref mut p) | &mut LocalCodePtr::DirEntry(ref mut p)
| &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs | &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs,
} }
} }
} }
@@ -398,7 +405,9 @@ impl Add<usize> for CodePtr {
| p @ CodePtr::VerifyAttrInterrupt(_) | p @ CodePtr::VerifyAttrInterrupt(_)
| p @ CodePtr::DynamicTransaction(..) => p, | p @ CodePtr::DynamicTransaction(..) => p,
CodePtr::Local(local) => CodePtr::Local(local + rhs), CodePtr::Local(local) => CodePtr::Local(local + rhs),
CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs) CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => {
CodePtr::Local(local + rhs)
}
} }
} }
} }
@@ -406,9 +415,9 @@ impl Add<usize> for CodePtr {
impl AddAssign<usize> for CodePtr { impl AddAssign<usize> for CodePtr {
fn add_assign(&mut self, rhs: usize) { fn add_assign(&mut self, rhs: usize) {
match self { match self {
&mut CodePtr::VerifyAttrInterrupt(_) => {}, &mut CodePtr::VerifyAttrInterrupt(_) => {}
&mut CodePtr::Local(ref mut local) => *local += rhs, &mut CodePtr::Local(ref mut local) => *local += rhs,
_ => *self = CodePtr::Local(self.local() + rhs) _ => *self = CodePtr::Local(self.local() + rhs),
} }
} }
} }
@@ -423,7 +432,9 @@ pub struct DynamicPredicateInfo {
impl Default for DynamicPredicateInfo { impl Default for DynamicPredicateInfo {
fn default() -> Self { fn default() -> Self {
DynamicPredicateInfo { clauses_subsection_p: 0 } DynamicPredicateInfo {
clauses_subsection_p: 0,
}
} }
} }
@@ -444,42 +455,41 @@ pub struct IndexStore {
} }
impl IndexStore { impl IndexStore {
pub fn predicate_exists(&self, name: ClauseName, module: ClauseName, arity: usize, pub fn predicate_exists(
op_spec: Option<SharedOpDesc>) &self,
-> bool name: ClauseName,
{ module: ClauseName,
arity: usize,
op_spec: Option<SharedOpDesc>,
) -> bool {
match self.modules.get(&module) { match self.modules.get(&module) {
Some(module) => Some(module) => match ClauseType::from(name, arity, op_spec) {
match ClauseType::from(name, arity, op_spec) { ClauseType::Named(name, arity, _) => module.code_dir.contains_key(&(name, arity)),
ClauseType::Named(name, arity, _) => ClauseType::Op(name, spec, ..) => {
module.code_dir.contains_key(&(name, arity)), module.code_dir.contains_key(&(name, spec.arity()))
ClauseType::Op(name, spec, ..) =>
module.code_dir.contains_key(&(name, spec.arity())),
_ =>
true
},
None =>
match ClauseType::from(name, arity, op_spec) {
ClauseType::Named(name, arity, _) =>
self.code_dir.contains_key(&(name, arity)),
ClauseType::Op(name, spec, ..) =>
self.code_dir.contains_key(&(name, spec.arity())),
_ =>
true
} }
_ => true,
},
None => match ClauseType::from(name, arity, op_spec) {
ClauseType::Named(name, arity, _) => self.code_dir.contains_key(&(name, arity)),
ClauseType::Op(name, spec, ..) => self.code_dir.contains_key(&(name, spec.arity())),
_ => true,
},
} }
} }
#[inline] #[inline]
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
{
self.dynamic_code_dir.remove(&(module, name, arity)); self.dynamic_code_dir.remove(&(module, name, arity));
} }
#[inline] #[inline]
pub fn get_clause_subsection(&self, module: ClauseName, name: ClauseName, arity: usize) pub fn get_clause_subsection(
-> Option<DynamicPredicateInfo> &self,
{ module: ClauseName,
name: ClauseName,
arity: usize,
) -> Option<DynamicPredicateInfo> {
self.dynamic_code_dir.get(&(module, name, arity)).cloned() self.dynamic_code_dir.get(&(module, name, arity)).cloned()
} }
@@ -518,9 +528,14 @@ impl IndexStore {
} }
#[inline] #[inline]
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex> fn get_internal(
{ &self,
self.modules.get(&in_mod) name: ClauseName,
arity: usize,
in_mod: ClauseName,
) -> Option<CodeIndex> {
self.modules
.get(&in_mod)
.and_then(|ref module| module.code_dir.get(&(name, arity))) .and_then(|ref module| module.code_dir.get(&(name, arity)))
.cloned() .cloned()
} }
@@ -531,8 +546,12 @@ impl IndexStore {
let non_iso = clause_name!("non_iso"); let non_iso = clause_name!("non_iso");
let r_w_h = self.get_internal(r_w_h, 0, non_iso.clone()).and_then(|item| item.local()); let r_w_h = self
let r_wo_h = self.get_internal(r_wo_h, 1, non_iso).and_then(|item| item.local()); .get_internal(r_w_h, 0, non_iso.clone())
.and_then(|item| item.local());
let r_wo_h = self
.get_internal(r_wo_h, 1, non_iso)
.and_then(|item| item.local());
if let Some(r_w_h) = r_w_h { if let Some(r_w_h) = r_w_h {
if let Some(r_wo_h) = r_wo_h { if let Some(r_wo_h) = r_wo_h {
@@ -552,36 +571,38 @@ pub enum CompileTimeHook {
GoalExpansion, GoalExpansion,
TermExpansion, TermExpansion,
UserGoalExpansion, UserGoalExpansion,
UserTermExpansion UserTermExpansion,
} }
impl CompileTimeHook { impl CompileTimeHook {
pub fn name(self) -> ClauseName { pub fn name(self) -> ClauseName {
match self { match self {
CompileTimeHook::UserGoalExpansion CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
| CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"), clause_name!("goal_expansion")
CompileTimeHook::UserTermExpansion }
| CompileTimeHook::TermExpansion => clause_name!("term_expansion") CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
clause_name!("term_expansion")
}
} }
} }
#[inline] #[inline]
pub fn arity(self) -> usize { pub fn arity(self) -> usize {
match self { match self {
CompileTimeHook::UserGoalExpansion CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => 2,
| CompileTimeHook::GoalExpansion => 2, CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => 2,
CompileTimeHook::UserTermExpansion
| CompileTimeHook::TermExpansion => 2
} }
} }
#[inline] #[inline]
pub fn user_scope(self) -> Self { pub fn user_scope(self) -> Self {
match self { match self {
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
CompileTimeHook::UserGoalExpansion, CompileTimeHook::UserGoalExpansion
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => }
CompileTimeHook::UserTermExpansion, CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
CompileTimeHook::UserTermExpansion
}
} }
} }
@@ -589,30 +610,31 @@ impl CompileTimeHook {
pub fn has_module_scope(self) -> bool { pub fn has_module_scope(self) -> bool {
match self { match self {
CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false, CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false,
_ => true _ => true,
} }
} }
} }
pub enum RefOrOwned<'a, T: 'a> { pub enum RefOrOwned<'a, T: 'a> {
Borrowed(&'a T), Borrowed(&'a T),
Owned(T) Owned(T),
} }
impl<'a, T> RefOrOwned<'a, T> { impl<'a, T> RefOrOwned<'a, T> {
pub fn as_ref(&'a self) -> &'a T { pub fn as_ref(&'a self) -> &'a T {
match self { match self {
&RefOrOwned::Borrowed(r) => r, &RefOrOwned::Borrowed(r) => r,
&RefOrOwned::Owned(ref r) => r &RefOrOwned::Owned(ref r) => r,
} }
} }
pub fn to_owned(self) -> T pub fn to_owned(self) -> T
where T: Clone where
T: Clone,
{ {
match self { match self {
RefOrOwned::Borrowed(item) => item.clone(), RefOrOwned::Borrowed(item) => item.clone(),
RefOrOwned::Owned(item) => item RefOrOwned::Owned(item) => item,
} }
} }
} }

View File

@@ -17,7 +17,7 @@ use prolog::rug::Integer;
use downcast::Any; use downcast::Any;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::io::{Write, stdout}; use std::io::{stdout, Write};
use std::mem; use std::mem;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
@@ -28,7 +28,10 @@ pub(super) struct Ball {
impl Ball { impl Ball {
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
Ball { boundary: 0, stub: MachineStub::new() } Ball {
boundary: 0,
stub: MachineStub::new(),
}
} }
pub(super) fn reset(&mut self) { pub(super) fn reset(&mut self) {
@@ -42,13 +45,13 @@ impl Ball {
Ball { Ball {
boundary, boundary,
stub: mem::replace(&mut self.stub, vec![]) stub: mem::replace(&mut self.stub, vec![]),
} }
} }
} }
pub(super) struct CopyTerm<'a> { pub(super) struct CopyTerm<'a> {
state: &'a mut MachineState state: &'a mut MachineState,
} }
impl<'a> CopyTerm<'a> { impl<'a> CopyTerm<'a> {
@@ -102,10 +105,18 @@ pub(super) struct CopyBallTerm<'a> {
} }
impl<'a> CopyBallTerm<'a> { impl<'a> CopyBallTerm<'a> {
pub(super) fn new(and_stack: &'a mut AndStack, heap: &'a mut Heap, stub: &'a mut MachineStub) -> Self pub(super) fn new(
{ and_stack: &'a mut AndStack,
heap: &'a mut Heap,
stub: &'a mut MachineStub,
) -> Self {
let hb = heap.len(); let hb = heap.len();
CopyBallTerm { and_stack, heap, heap_boundary: hb, stub } CopyBallTerm {
and_stack,
heap,
heap_boundary: hb,
stub,
}
} }
} }
@@ -145,15 +156,15 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
fn store(&self, addr: Addr) -> Addr { fn store(&self, addr: Addr) -> Addr {
match addr { match addr {
Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary => Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary => {
self.heap[h].as_addr(h), self.heap[h].as_addr(h)
}
Addr::HeapCell(h) | Addr::AttrVar(h) => { Addr::HeapCell(h) | Addr::AttrVar(h) => {
let index = h - self.heap_boundary; let index = h - self.heap_boundary;
self.stub[index].as_addr(h) self.stub[index].as_addr(h)
}, }
Addr::StackCell(fr, sc) => Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),
self.and_stack[fr][sc].clone(), addr => addr,
addr => addr
} }
} }
@@ -167,7 +178,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
} }
return addr; return addr;
}; }
} }
fn stack(&mut self) -> &mut AndStack { fn stack(&mut self) -> &mut AndStack {
@@ -206,7 +217,7 @@ pub type Registers = Vec<Addr>;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub(super) enum MachineMode { pub(super) enum MachineMode {
Read, Read,
Write Write,
} }
pub struct MachineState { pub struct MachineState {
@@ -235,97 +246,85 @@ pub struct MachineState {
pub(super) interms: Vec<Number>, // intermediate numbers. pub(super) interms: Vec<Number>, // intermediate numbers.
pub(super) last_call: bool, pub(super) last_call: bool,
pub(crate) heap_locs: HeapVarDict, pub(crate) heap_locs: HeapVarDict,
pub(crate) flags: MachineFlags pub(crate) flags: MachineFlags,
} }
impl MachineState { impl MachineState {
pub(super) pub(super) fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError>
{
let mut chars = String::new(); let mut chars = String::new();
let mut iter = addrs.iter(); let mut iter = addrs.iter();
while let Some(addr) = iter.next() { while let Some(addr) = iter.next() {
match addr { match addr {
&Addr::Con(Constant::String(ref s)) &Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() => {
if self.flags.double_quotes.is_chars() => {
chars += s.borrow().as_str(); chars += s.borrow().as_str();
if iter.next().is_some() { if iter.next().is_some() {
return Err(MachineError::type_error(ValidType::Character, addr.clone())); return Err(MachineError::type_error(ValidType::Character, addr.clone()));
} }
}, }
&Addr::Con(Constant::Char(c)) => &Addr::Con(Constant::Char(c)) => chars.push(c),
chars.push(c), &Addr::Con(Constant::Atom(ref name, _)) if name.as_str().len() == 1 => {
&Addr::Con(Constant::Atom(ref name, _))
if name.as_str().len() == 1 => {
chars += name.as_str(); chars += name.as_str();
}, }
_ => _ => return Err(MachineError::type_error(ValidType::Character, addr.clone())),
return Err(MachineError::type_error(ValidType::Character, addr.clone()))
} }
} }
Ok(chars) Ok(chars)
} }
pub(super) pub(super) fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError> {
fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError>
{
let mut codes = vec![]; let mut codes = vec![];
let mut iter = addrs.iter(); let mut iter = addrs.iter();
while let Some(addr) = iter.next() { while let Some(addr) = iter.next() {
match addr { match addr {
&Addr::Con(Constant::String(ref s)) &Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_codes() => {
if self.flags.double_quotes.is_codes() => {
codes.extend(s.borrow().chars().map(|c| c as u8)); codes.extend(s.borrow().chars().map(|c| c as u8));
if iter.next().is_some() { if iter.next().is_some() {
return Err(MachineError::representation_error(RepFlag::CharacterCode)); return Err(MachineError::representation_error(RepFlag::CharacterCode));
} }
}, }
&Addr::Con(Constant::CharCode(c)) => &Addr::Con(Constant::CharCode(c)) => codes.push(c),
codes.push(c), &Addr::Con(Constant::Integer(ref n)) => {
&Addr::Con(Constant::Integer(ref n)) =>
if let Some(c) = n.to_u8() { if let Some(c) = n.to_u8() {
codes.push(c); codes.push(c);
} else { } else {
return Err(MachineError::representation_error(RepFlag::CharacterCode)); return Err(MachineError::representation_error(RepFlag::CharacterCode));
}, }
_ => }
return Err(MachineError::representation_error(RepFlag::CharacterCode)) _ => return Err(MachineError::representation_error(RepFlag::CharacterCode)),
} }
} }
Ok(codes) Ok(codes)
} }
fn call_at_index(&mut self, arity: usize, p: usize) fn call_at_index(&mut self, arity: usize, p: usize) {
{
self.cp.assign_if_local(self.p.clone() + 1); self.cp.assign_if_local(self.p.clone() + 1);
self.num_of_args = arity; self.num_of_args = arity;
self.b0 = self.b; self.b0 = self.b;
self.p = dir_entry!(p); self.p = dir_entry!(p);
} }
pub(super) pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
fn execute_at_index(&mut self, arity: usize, p: usize)
{
self.num_of_args = arity; self.num_of_args = arity;
self.b0 = self.b; self.b0 = self.b;
self.p = dir_entry!(p); self.p = dir_entry!(p);
} }
pub(super) pub(super) fn module_lookup(
fn module_lookup(&mut self, indices: &IndexStore, key: PredicateKey, module_name: ClauseName, &mut self,
last_call: bool) indices: &IndexStore,
-> CallResult key: PredicateKey,
{ module_name: ClauseName,
last_call: bool,
) -> CallResult {
let (name, arity) = key; let (name, arity) = key;
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
{
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 { if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
if last_call { if last_call {
self.execute_at_index(arity, compiled_tl_index); self.execute_at_index(arity, compiled_tl_index);
@@ -345,25 +344,29 @@ impl MachineState {
} }
} }
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<usize> fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<usize> {
{
match indices.in_situ_code_dir.get(&(name.clone(), arity)) { match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
Some(p) => Some(*p), Some(p) => Some(*p),
None => match indices.code_dir.get(&(name, arity)) { None => match indices.code_dir.get(&(name, arity)) {
Some(ref idx) => if let &IndexPtr::Index(p) = &idx.0.borrow().0 { Some(ref idx) => {
if let &IndexPtr::Index(p) = &idx.0.borrow().0 {
Some(p) Some(p)
} else { } else {
None None
},
_ => None
} }
} }
_ => None,
},
}
} }
fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize, fn try_in_situ(
indices: &IndexStore, last_call: bool) machine_st: &mut MachineState,
-> CallResult name: ClauseName,
{ arity: usize,
indices: &IndexStore,
last_call: bool,
) -> CallResult {
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) { if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
if last_call { if last_call {
machine_st.execute_at_index(arity, p); machine_st.execute_at_index(arity, p);
@@ -385,8 +388,7 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>; pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
pub(crate) trait CallPolicy: Any { pub(crate) trait CallPolicy: Any {
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
let b = machine_st.b - 1; let b = machine_st.b - 1;
let n = machine_st.or_stack[b].num_args(); let n = machine_st.or_stack[b].num_args();
@@ -418,7 +420,10 @@ pub(crate) trait CallPolicy: Any {
machine_st.heap.truncate(machine_st.or_stack[b].h); machine_st.heap.truncate(machine_st.or_stack[b].h);
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b; let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b); machine_st
.attr_var_init
.attr_var_queue
.truncate(attr_var_init_b);
machine_st.hb = machine_st.heap.h; machine_st.hb = machine_st.heap.h;
machine_st.p += 1; machine_st.p += 1;
@@ -426,8 +431,7 @@ pub(crate) trait CallPolicy: Any {
Ok(()) Ok(())
} }
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
let b = machine_st.b - 1; let b = machine_st.b - 1;
let n = machine_st.or_stack[b].num_args(); let n = machine_st.or_stack[b].num_args();
@@ -459,7 +463,10 @@ pub(crate) trait CallPolicy: Any {
machine_st.heap.truncate(machine_st.or_stack[b].h); machine_st.heap.truncate(machine_st.or_stack[b].h);
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b; let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b); machine_st
.attr_var_init
.attr_var_queue
.truncate(attr_var_init_b);
machine_st.hb = machine_st.heap.h; machine_st.hb = machine_st.heap.h;
machine_st.p += offset; machine_st.p += offset;
@@ -467,8 +474,7 @@ pub(crate) trait CallPolicy: Any {
Ok(()) Ok(())
} }
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
let b = machine_st.b - 1; let b = machine_st.b - 1;
let n = machine_st.or_stack[b].num_args(); let n = machine_st.or_stack[b].num_args();
@@ -498,7 +504,10 @@ pub(crate) trait CallPolicy: Any {
machine_st.heap.truncate(machine_st.or_stack[b].h); machine_st.heap.truncate(machine_st.or_stack[b].h);
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b; let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b); machine_st
.attr_var_init
.attr_var_queue
.truncate(attr_var_init_b);
machine_st.b = machine_st.or_stack[b].b; machine_st.b = machine_st.or_stack[b].b;
machine_st.or_stack.truncate(machine_st.b); machine_st.or_stack.truncate(machine_st.b);
@@ -509,8 +518,7 @@ pub(crate) trait CallPolicy: Any {
Ok(()) Ok(())
} }
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult {
{
let b = machine_st.b - 1; let b = machine_st.b - 1;
let n = machine_st.or_stack[b].num_args(); let n = machine_st.or_stack[b].num_args();
@@ -540,7 +548,10 @@ pub(crate) trait CallPolicy: Any {
machine_st.heap.truncate(machine_st.or_stack[b].h); machine_st.heap.truncate(machine_st.or_stack[b].h);
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b; let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b); machine_st
.attr_var_init
.attr_var_queue
.truncate(attr_var_init_b);
machine_st.b = machine_st.or_stack[b].b; machine_st.b = machine_st.or_stack[b].b;
machine_st.or_stack.truncate(machine_st.b); machine_st.or_stack.truncate(machine_st.b);
@@ -551,10 +562,14 @@ pub(crate) trait CallPolicy: Any {
Ok(()) Ok(())
} }
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, fn context_call(
arity: usize, idx: CodeIndex, indices: &mut IndexStore) &mut self,
-> CallResult machine_st: &mut MachineState,
{ name: ClauseName,
arity: usize,
idx: CodeIndex,
indices: &mut IndexStore,
) -> CallResult {
if machine_st.last_call { if machine_st.last_call {
self.try_execute(machine_st, name, arity, idx, indices) self.try_execute(machine_st, name, arity, idx, indices)
} else { } else {
@@ -562,48 +577,59 @@ pub(crate) trait CallPolicy: Any {
} }
} }
fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, fn try_call(
idx: CodeIndex, indices: &IndexStore) &mut self,
-> CallResult machine_st: &mut MachineState,
{ name: ClauseName,
arity: usize,
idx: CodeIndex,
indices: &IndexStore,
) -> CallResult {
match idx.0.borrow().0 { match idx.0.borrow().0 {
IndexPtr::Undefined => IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, false),
return try_in_situ(machine_st, name, arity, indices, false), IndexPtr::Index(compiled_tl_index) => {
IndexPtr::Index(compiled_tl_index) =>
machine_st.call_at_index(arity, compiled_tl_index) machine_st.call_at_index(arity, compiled_tl_index)
} }
}
Ok(()) Ok(())
} }
fn try_execute(&mut self, machine_st: &mut MachineState, name: ClauseName, fn try_execute(
arity: usize, idx: CodeIndex, indices: &IndexStore) &mut self,
-> CallResult machine_st: &mut MachineState,
{ name: ClauseName,
arity: usize,
idx: CodeIndex,
indices: &IndexStore,
) -> CallResult {
match idx.0.borrow().0 { match idx.0.borrow().0 {
IndexPtr::Undefined => IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, true),
return try_in_situ(machine_st, name, arity, indices, true), IndexPtr::Index(compiled_tl_index) => {
IndexPtr::Index(compiled_tl_index) =>
machine_st.execute_at_index(arity, compiled_tl_index) machine_st.execute_at_index(arity, compiled_tl_index)
} }
}
Ok(()) Ok(())
} }
fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, fn call_builtin(
indices: &mut IndexStore, parsing_stream: &mut PrologStream) &mut self,
-> CallResult machine_st: &mut MachineState,
{ ct: &BuiltInClauseType,
indices: &mut IndexStore,
parsing_stream: &mut PrologStream,
) -> CallResult {
match ct { match ct {
&BuiltInClauseType::AcyclicTerm => { &BuiltInClauseType::AcyclicTerm => {
let addr = machine_st[temp_v!(1)].clone(); let addr = machine_st[temp_v!(1)].clone();
machine_st.fail = machine_st.is_cyclic_term(addr); machine_st.fail = machine_st.is_cyclic_term(addr);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Arg => { &BuiltInClauseType::Arg => {
machine_st.try_arg()?; machine_st.try_arg()?;
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Compare => { &BuiltInClauseType::Compare => {
let a1 = machine_st[temp_v!(1)].clone(); let a1 = machine_st[temp_v!(1)].clone();
let a2 = machine_st[temp_v!(2)].clone(); let a2 = machine_st[temp_v!(2)].clone();
@@ -613,11 +639,11 @@ pub(crate) trait CallPolicy: Any {
Ordering::Greater => { Ordering::Greater => {
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir); let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
Addr::Con(Constant::Atom(clause_name!(">"), spec)) Addr::Con(Constant::Atom(clause_name!(">"), spec))
}, }
Ordering::Equal => { Ordering::Equal => {
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir); let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
Addr::Con(Constant::Atom(clause_name!("="), spec)) Addr::Con(Constant::Atom(clause_name!("="), spec))
}, }
Ordering::Less => { Ordering::Less => {
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir); let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
Addr::Con(Constant::Atom(clause_name!("<"), spec)) Addr::Con(Constant::Atom(clause_name!("<"), spec))
@@ -626,29 +652,29 @@ pub(crate) trait CallPolicy: Any {
machine_st.unify(a1, c); machine_st.unify(a1, c);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::CompareTerm(qt) => { &BuiltInClauseType::CompareTerm(qt) => {
machine_st.compare_term(qt); machine_st.compare_term(qt);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::CyclicTerm => { &BuiltInClauseType::CyclicTerm => {
let addr = machine_st[temp_v!(1)].clone(); let addr = machine_st[temp_v!(1)].clone();
machine_st.fail = !machine_st.is_cyclic_term(addr); machine_st.fail = !machine_st.is_cyclic_term(addr);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Nl => { &BuiltInClauseType::Nl => {
let mut stdout = stdout(); let mut stdout = stdout();
write!(stdout, "\n\r").unwrap(); write!(stdout, "\n\r").unwrap();
stdout.flush().unwrap(); stdout.flush().unwrap();
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Read => { &BuiltInClauseType::Read => {
match machine_st.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) { match machine_st.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) {
Ok(offset) => { Ok(offset) => {
let addr = machine_st[temp_v!(1)].clone(); let addr = machine_st[temp_v!(1)].clone();
machine_st.unify(addr, Addr::HeapCell(offset.heap_loc)); machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
}, }
Err(e) => { Err(e) => {
let h = machine_st.heap.h; let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("read"), 1); let stub = MachineError::functor_stub(clause_name!("read"), 1);
@@ -660,23 +686,23 @@ pub(crate) trait CallPolicy: Any {
}; };
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::CopyTerm => { &BuiltInClauseType::CopyTerm => {
machine_st.copy_term(); machine_st.copy_term();
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Eq => { &BuiltInClauseType::Eq => {
machine_st.fail = machine_st.eq_test(); machine_st.fail = machine_st.eq_test();
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Ground => { &BuiltInClauseType::Ground => {
machine_st.fail = machine_st.ground_test(); machine_st.fail = machine_st.ground_test();
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Functor => { &BuiltInClauseType::Functor => {
machine_st.try_functor(&indices)?; machine_st.try_functor(&indices)?;
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::NotEq => { &BuiltInClauseType::NotEq => {
let a1 = machine_st[temp_v!(1)].clone(); let a1 = machine_st[temp_v!(1)].clone();
let a2 = machine_st[temp_v!(2)].clone(); let a2 = machine_st[temp_v!(2)].clone();
@@ -688,7 +714,7 @@ pub(crate) trait CallPolicy: Any {
}; };
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::PartialString => { &BuiltInClauseType::PartialString => {
let s = machine_st.try_string_list(temp_v!(1))?; let s = machine_st.try_string_list(temp_v!(1))?;
let a2 = machine_st[temp_v!(2)].clone(); let a2 = machine_st[temp_v!(2)].clone();
@@ -697,7 +723,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.write_constant_to_var(a2, Constant::String(s)); machine_st.write_constant_to_var(a2, Constant::String(s));
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Sort => { &BuiltInClauseType::Sort => {
machine_st.check_sort_errors()?; machine_st.check_sort_errors()?;
@@ -713,7 +739,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.unify(r2, heap_addr); machine_st.unify(r2, heap_addr);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::KeySort => { &BuiltInClauseType::KeySort => {
machine_st.check_keysort_errors()?; machine_st.check_keysort_errors()?;
@@ -735,38 +761,46 @@ pub(crate) trait CallPolicy: Any {
machine_st.unify(r2, heap_addr); machine_st.unify(r2, heap_addr);
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
&BuiltInClauseType::Is(r, ref at) => { &BuiltInClauseType::Is(r, ref at) => {
let a1 = machine_st[r].clone(); let a1 = machine_st[r].clone();
let a2 = machine_st.get_number(at)?; let a2 = machine_st.get_number(at)?;
machine_st.unify(a1, Addr::Con(a2.to_constant())); machine_st.unify(a1, Addr::Con(a2.to_constant()));
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
}, }
} }
} }
fn compile_hook(&mut self, machine_st: &mut MachineState, hook: &CompileTimeHook) -> CallResult fn compile_hook(
{ &mut self,
machine_st: &mut MachineState,
hook: &CompileTimeHook,
) -> CallResult {
machine_st.cp = LocalCodePtr::TopLevel(0, 0); machine_st.cp = LocalCodePtr::TopLevel(0, 0);
machine_st.num_of_args = hook.arity(); machine_st.num_of_args = hook.arity();
machine_st.b0 = machine_st.b; machine_st.b0 = machine_st.b;
machine_st.p = match hook { machine_st.p = match hook {
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
CodePtr::Local(LocalCodePtr::UserTermExpansion(0)), CodePtr::Local(LocalCodePtr::UserTermExpansion(0))
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => }
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
CodePtr::Local(LocalCodePtr::UserGoalExpansion(0)) CodePtr::Local(LocalCodePtr::UserGoalExpansion(0))
}
}; };
Ok(()) Ok(())
} }
fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore, fn call_n(
parsing_stream: &mut PrologStream) &mut self,
-> CallResult machine_st: &mut MachineState,
{ arity: usize,
indices: &mut IndexStore,
parsing_stream: &mut PrologStream,
) -> CallResult {
if let Some((name, arity)) = machine_st.setup_call_n(arity) { if let Some((name, arity)) = machine_st.setup_call_n(arity) {
match ClauseType::from(name.clone(), arity, None) { match ClauseType::from(name.clone(), arity, None) {
ClauseType::CallN => { ClauseType::CallN => {
@@ -777,18 +811,18 @@ pub(crate) trait CallPolicy: Any {
} }
machine_st.p = CodePtr::CallN(arity, machine_st.p.local()); machine_st.p = CodePtr::CallN(arity, machine_st.p.local());
}, }
ClauseType::BuiltIn(built_in) => { ClauseType::BuiltIn(built_in) => {
machine_st.setup_built_in_call(built_in.clone()); machine_st.setup_built_in_call(built_in.clone());
self.call_builtin(machine_st, &built_in, indices, parsing_stream)?; self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
}, }
ClauseType::Inlined(inlined) => { ClauseType::Inlined(inlined) => {
machine_st.execute_inlined(&inlined); machine_st.execute_inlined(&inlined);
if machine_st.last_call { if machine_st.last_call {
machine_st.p = CodePtr::Local(machine_st.cp); machine_st.p = CodePtr::Local(machine_st.cp);
} }
}, }
ClauseType::Op(..) | ClauseType::Named(..) => { ClauseType::Op(..) | ClauseType::Named(..) => {
let module = name.owning_module(); let module = name.owning_module();
@@ -799,17 +833,17 @@ pub(crate) trait CallPolicy: Any {
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1); let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
let key = ExistenceError::Procedure(name, arity); let key = ExistenceError::Procedure(name, arity);
return Err(machine_st.error_form(MachineError::existence_error(h, key), return Err(
stub)); machine_st.error_form(MachineError::existence_error(h, key), stub)
);
}
} }
},
ClauseType::Hook(_) | ClauseType::System(_) => { ClauseType::Hook(_) | ClauseType::System(_) => {
let name = Addr::Con(Constant::Atom(name, None)); let name = Addr::Con(Constant::Atom(name, None));
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1); let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
return Err(machine_st.error_form(MachineError::type_error(ValidType::Callable, return Err(machine_st
name), .error_form(MachineError::type_error(ValidType::Callable, name), stub));
stub));
} }
}; };
} }
@@ -819,51 +853,60 @@ pub(crate) trait CallPolicy: Any {
} }
impl CallPolicy for CWILCallPolicy { impl CallPolicy for CWILCallPolicy {
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, fn context_call(
arity: usize, idx: CodeIndex, indices: &mut IndexStore) &mut self,
-> CallResult machine_st: &mut MachineState,
{ name: ClauseName,
self.prev_policy.context_call(machine_st, name, arity, idx, indices)?; arity: usize,
idx: CodeIndex,
indices: &mut IndexStore,
) -> CallResult {
self.prev_policy
.context_call(machine_st, name, arity, idx, indices)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
self.prev_policy.retry_me_else(machine_st, offset)?; self.prev_policy.retry_me_else(machine_st, offset)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
self.prev_policy.retry(machine_st, offset)?; self.prev_policy.retry(machine_st, offset)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult {
{
self.prev_policy.trust_me(machine_st)?; self.prev_policy.trust_me(machine_st)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
{
self.prev_policy.trust(machine_st, offset)?; self.prev_policy.trust(machine_st, offset)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, fn call_builtin(
indices: &mut IndexStore, parsing_stream: &mut PrologStream) &mut self,
-> CallResult machine_st: &mut MachineState,
{ ct: &BuiltInClauseType,
self.prev_policy.call_builtin(machine_st, ct, indices, parsing_stream)?; indices: &mut IndexStore,
parsing_stream: &mut PrologStream,
) -> CallResult {
self.prev_policy
.call_builtin(machine_st, ct, indices, parsing_stream)?;
self.increment(machine_st) self.increment(machine_st)
} }
fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore, fn call_n(
parsing_stream: &mut PrologStream) &mut self,
-> CallResult machine_st: &mut MachineState,
{ arity: usize,
self.prev_policy.call_n(machine_st, arity, indices, parsing_stream)?; indices: &mut IndexStore,
parsing_stream: &mut PrologStream,
) -> CallResult {
self.prev_policy
.call_n(machine_st, arity, indices, parsing_stream)?;
self.increment(machine_st) self.increment(machine_st)
} }
} }
@@ -878,19 +921,20 @@ pub(crate) struct CWILCallPolicy {
pub(crate) prev_policy: Box<CallPolicy>, pub(crate) prev_policy: Box<CallPolicy>,
count: Integer, count: Integer,
limits: Vec<(Integer, usize)>, limits: Vec<(Integer, usize)>,
inference_limit_exceeded: bool inference_limit_exceeded: bool,
} }
impl CWILCallPolicy { impl CWILCallPolicy {
pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>) pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>) {
{
let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {}); let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
mem::swap(&mut prev_policy, policy); mem::swap(&mut prev_policy, policy);
let new_policy = CWILCallPolicy { prev_policy, let new_policy = CWILCallPolicy {
prev_policy,
count: Integer::from(0), count: Integer::from(0),
limits: vec![], limits: vec![],
inference_limit_exceeded: false }; inference_limit_exceeded: false,
};
*policy = Box::new(new_policy); *policy = Box::new(new_policy);
} }
@@ -902,8 +946,11 @@ impl CWILCallPolicy {
if let Some(&(ref limit, bp)) = self.limits.last() { if let Some(&(ref limit, bp)) = self.limits.last() {
if self.count == *limit { if self.count == *limit {
self.inference_limit_exceeded = true; self.inference_limit_exceeded = true;
return Err(functor!("inference_limit_exceeded", 1, return Err(functor!(
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))])); "inference_limit_exceeded",
1,
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
));
} else { } else {
self.count += 1; self.count += 1;
} }
@@ -916,8 +963,8 @@ impl CWILCallPolicy {
limit += &self.count; limit += &self.count;
match self.limits.last().cloned() { match self.limits.last().cloned() {
Some((ref inner_limit, _)) if *inner_limit <= limit => {}, Some((ref inner_limit, _)) if *inner_limit <= limit => {}
_ => self.limits.push((limit, b)) _ => self.limits.push((limit, b)),
}; };
&self.count &self.count
@@ -987,12 +1034,16 @@ pub(crate) struct SCCCutPolicy {
// locations of cleaners, cut points, the previous block // locations of cleaners, cut points, the previous block
cont_pts: Vec<(Addr, usize, usize)>, cont_pts: Vec<(Addr, usize, usize)>,
r_c_w_h: usize, r_c_w_h: usize,
r_c_wo_h: usize r_c_wo_h: usize,
} }
impl SCCCutPolicy { impl SCCCutPolicy {
pub(crate) fn new(r_c_w_h: usize, r_c_wo_h: usize) -> Self { pub(crate) fn new(r_c_w_h: usize, r_c_wo_h: usize) -> Self {
SCCCutPolicy { cont_pts: vec![], r_c_w_h, r_c_wo_h } SCCCutPolicy {
cont_pts: vec![],
r_c_w_h,
r_c_wo_h,
}
} }
pub(crate) fn out_of_cont_pts(&self) -> bool { pub(crate) fn out_of_cont_pts(&self) -> bool {

File diff suppressed because it is too large Load Diff

View File

@@ -7,29 +7,30 @@ use prolog::forms::*;
use prolog::heap_print::*; use prolog::heap_print::*;
use prolog::instructions::*; use prolog::instructions::*;
use prolog::read::*; use prolog::read::*;
use prolog::write::{ContinueResult, next_keypress}; use prolog::write::{next_keypress, ContinueResult};
pub mod machine_indices;
pub mod heap;
mod and_stack; mod and_stack;
mod or_stack;
mod attributed_variables; mod attributed_variables;
pub(super) mod code_repo;
pub mod compile;
mod copier; mod copier;
mod dynamic_database; mod dynamic_database;
pub mod heap;
pub mod machine_errors; pub mod machine_errors;
pub mod toplevel; pub mod machine_indices;
pub mod compile;
pub(super) mod code_repo;
pub mod modules;
pub(super) mod machine_state; pub(super) mod machine_state;
pub mod modules;
mod or_stack;
pub(super) mod term_expansion; pub(super) mod term_expansion;
pub mod toplevel;
#[macro_use] mod machine_state_impl; #[macro_use]
mod machine_state_impl;
mod system_calls; mod system_calls;
use prolog::machine::attributed_variables::*; use prolog::machine::attributed_variables::*;
use prolog::machine::compile::*;
use prolog::machine::code_repo::*; use prolog::machine::code_repo::*;
use prolog::machine::compile::*;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::*; use prolog::machine::machine_state::*;
@@ -40,13 +41,13 @@ use prolog::read::PrologStream;
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::io::{Read, Write, stdout};
use std::fs::File; use std::fs::File;
use std::io::{stdout, Read, Write};
use std::mem; use std::mem;
use std::ops::Index; use std::ops::Index;
use std::rc::Rc; use std::rc::Rc;
use termion::raw::{IntoRawMode}; use termion::raw::IntoRawMode;
pub struct MachinePolicies { pub struct MachinePolicies {
call_policy: Box<CallPolicy>, call_policy: Box<CallPolicy>,
@@ -69,7 +70,7 @@ pub struct Machine {
pub(super) indices: IndexStore, pub(super) indices: IndexStore,
pub(super) code_repo: CodeRepo, pub(super) code_repo: CodeRepo,
pub(super) toplevel_idx: usize, pub(super) toplevel_idx: usize,
pub(super) prolog_stream: ParsingStream<Box<Read>> pub(super) prolog_stream: ParsingStream<Box<Read>>,
} }
impl Index<LocalCodePtr> for CodeRepo { impl Index<LocalCodePtr> for CodeRepo {
@@ -103,23 +104,21 @@ impl SubModuleUser for IndexStore {
&mut self.op_dir &mut self.op_dir
} }
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
{
match module.as_str() { match module.as_str() {
"user" | "builtin" => self.code_dir.get(&key).cloned(), "user" | "builtin" => self.code_dir.get(&key).cloned(),
_ => self.modules.get(&module).and_then(|ref module| { _ => self
module.code_dir.get(&key).cloned().map(CodeIndex::from) .modules
}) .get(&module)
.and_then(|ref module| module.code_dir.get(&key).cloned().map(CodeIndex::from)),
} }
} }
fn remove_code_index(&mut self, key: PredicateKey) fn remove_code_index(&mut self, key: PredicateKey) {
{
self.code_dir.remove(&key); self.code_dir.remove(&key);
} }
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
{
if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) { if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
if !code_idx.is_undefined() { if !code_idx.is_undefined() {
println!("warning: overwriting {}/{}", &name, arity); println!("warning: overwriting {}/{}", &name, arity);
@@ -133,21 +132,31 @@ impl SubModuleUser for IndexStore {
self.code_dir.insert((name, arity), idx); self.code_dir.insert((name, arity), idx);
} }
fn use_qualified_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags, fn use_qualified_module(
submodule: &Module, exports: &Vec<PredicateKey>) &mut self,
-> Result<(), SessionError> code_repo: &mut CodeRepo,
{ flags: MachineFlags,
submodule: &Module,
exports: &Vec<PredicateKey>,
) -> Result<(), SessionError> {
use_qualified_module(self, submodule, exports)?; use_qualified_module(self, submodule, exports)?;
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from) submodule
.dump_expansions(code_repo, flags)
.map_err(SessionError::from)
} }
fn use_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags, submodule: &Module) fn use_module(
-> Result<(), SessionError> &mut self,
{ code_repo: &mut CodeRepo,
flags: MachineFlags,
submodule: &Module,
) -> Result<(), SessionError> {
use_module(self, submodule)?; use_module(self, submodule)?;
if !submodule.inserted_expansions { if !submodule.inserted_expansions {
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from) submodule
.dump_expansions(code_repo, flags)
.map_err(SessionError::from)
} else { } else {
Ok(()) Ok(())
} }
@@ -166,16 +175,16 @@ impl Machine {
Ok(code) => { Ok(code) => {
self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len(); self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len();
self.code_repo.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
}, }
Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS") Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
} }
match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes())) { match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes())) {
Ok(code) => { Ok(code) => {
self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len(); self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len();
self.code_repo.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
}, }
Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS") Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS"),
} }
} }
@@ -187,7 +196,7 @@ impl Machine {
fn compile_scryerrc(&mut self) { fn compile_scryerrc(&mut self) {
let mut path = match dirs::home_dir() { let mut path = match dirs::home_dir() {
Some(path) => path, Some(path) => path,
None => return None => return,
}; };
path.push(".scryerrc"); path.push(".scryerrc");
@@ -195,7 +204,7 @@ impl Machine {
if path.is_file() { if path.is_file() {
let file_src = match File::open(&path) { let file_src = match File::open(&path) {
Ok(file_handle) => parsing_stream(file_handle), Ok(file_handle) => parsing_stream(file_handle),
Err(_) => return Err(_) => return,
}; };
compile_user_module(self, file_src); compile_user_module(self, file_src);
@@ -221,13 +230,16 @@ impl Machine {
indices: IndexStore::new(), indices: IndexStore::new(),
code_repo: CodeRepo::new(), code_repo: CodeRepo::new(),
toplevel_idx: 0, toplevel_idx: 0,
prolog_stream prolog_stream,
}; };
let atom_tbl = wam.indices.atom_tbl.clone(); let atom_tbl = wam.indices.atom_tbl.clone();
compile_listing(&mut wam, parsing_stream(BUILTINS.as_bytes()), compile_listing(
default_index_store!(atom_tbl.clone())); &mut wam,
parsing_stream(BUILTINS.as_bytes()),
default_index_store!(atom_tbl.clone()),
);
wam.compile_special_forms(); wam.compile_special_forms();
wam.compile_top_level(); wam.compile_top_level();
@@ -246,11 +258,10 @@ impl Machine {
self.machine_st.flags self.machine_st.flags
} }
pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError> pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError> {
{
for (key, idx) in &indices.code_dir { for (key, idx) in &indices.code_dir {
match ClauseType::from(key.0.clone(), key.1, None) { match ClauseType::from(key.0.clone(), key.1, None) {
ClauseType::Named(..) | ClauseType::Op(..) => {}, ClauseType::Named(..) | ClauseType::Op(..) => {}
_ => { _ => {
// ensure we don't try to overwrite the name/arity of a builtin. // ensure we don't try to overwrite the name/arity of a builtin.
let err_str = format!("{}/{}", key.0, key.1); let err_str = format!("{}/{}", key.0, key.1);
@@ -269,8 +280,12 @@ impl Machine {
} }
if existing_idx.module_name() != idx.module_name() { if existing_idx.module_name() != idx.module_name() {
let err_str = format!("{}/{} from module {}", key.0, key.1, let err_str = format!(
existing_idx.module_name().as_str()); "{}/{} from module {}",
key.0,
key.1,
existing_idx.module_name().as_str()
);
let err_str = clause_name!(err_str, self.indices.atom_tbl()); let err_str = clause_name!(err_str, self.indices.atom_tbl());
return Err(SessionError::CannotOverwriteImport(err_str)); return Err(SessionError::CannotOverwriteImport(err_str));
@@ -282,8 +297,7 @@ impl Machine {
Ok(()) Ok(())
} }
pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) {
{
// error detection has finished, so update the master index of keys. // error detection has finished, so update the master index of keys.
for (key, idx) in code_dir { for (key, idx) in code_dir {
if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) { if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) {
@@ -309,12 +323,13 @@ impl Machine {
#[inline] #[inline]
pub fn add_module(&mut self, module: Module, code: Code) { pub fn add_module(&mut self, module: Module, code: Code) {
self.indices.modules.insert(module.module_decl.name.clone(), module); self.indices
.modules
.insert(module.module_decl.name.clone(), module);
self.code_repo.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
} }
pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession {
{
self.code_repo.cached_query = code; self.code_repo.cached_query = code;
self.run_query(&alloc_locs); self.run_query(&alloc_locs);
@@ -336,8 +351,7 @@ impl Machine {
return; return;
} }
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
{
match code_ptr { match code_ptr {
REPLCodePtr::CompileBatch => { REPLCodePtr::CompileBatch => {
#[cfg(feature = "readline_rs_compat")] #[cfg(feature = "readline_rs_compat")]
@@ -352,7 +366,7 @@ impl Machine {
EvalSession::Error(e) => self.throw_session_error(e, (clause_name!("repl"), 0)), EvalSession::Error(e) => self.throw_session_error(e, (clause_name!("repl"), 0)),
_ => {} _ => {}
}; };
}, }
REPLCodePtr::SubmitQueryAndPrintResults => { REPLCodePtr::SubmitQueryAndPrintResults => {
let term = self.machine_st[temp_v!(1)].clone(); let term = self.machine_st[temp_v!(1)].clone();
let stub = MachineError::functor_stub(clause_name!("repl"), 0); let stub = MachineError::functor_stub(clause_name!("repl"), 0);
@@ -364,16 +378,18 @@ impl Machine {
for addr in addrs { for addr in addrs {
match addr { match addr {
Addr::Str(s) => { Addr::Str(s) => {
let var_atom = match self.machine_st.heap[s+1].as_addr(s+1) { let var_atom = match self.machine_st.heap[s + 1].as_addr(s + 1)
Addr::Con(Constant::Atom(var_atom, _)) => {
Rc::new(var_atom.to_string()), Addr::Con(Constant::Atom(var_atom, _)) => {
_ => unreachable!() Rc::new(var_atom.to_string())
}
_ => unreachable!(),
}; };
let var_addr = self.machine_st.heap[s + 2].as_addr(s + 2); let var_addr = self.machine_st.heap[s + 2].as_addr(s + 2);
var_dict.insert(var_atom, var_addr); var_dict.insert(var_atom, var_addr);
}, }
_ => unreachable!() _ => unreachable!(),
}; };
} }
@@ -381,7 +397,7 @@ impl Machine {
let term_output = self.machine_st.print_query(term, &self.indices.op_dir); let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
term_output.result() term_output.result()
}, }
Err(err_stub) => { Err(err_stub) => {
self.machine_st.throw_exception(err_stub); self.machine_st.throw_exception(err_stub);
return; return;
@@ -395,7 +411,7 @@ impl Machine {
let result = match stream_to_toplevel(stream, self) { let result = match stream_to_toplevel(stream, self) {
Ok(packet) => compile_term(self, packet), Ok(packet) => compile_term(self, packet),
Err(e) => EvalSession::from(e) Err(e) => EvalSession::from(e),
}; };
self.handle_eval_session(result, snapshot); self.handle_eval_session(result, snapshot);
@@ -419,8 +435,7 @@ impl Machine {
fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) { fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) {
match result { match result {
EvalSession::InitialQuerySuccess(alloc_locs) => EvalSession::InitialQuerySuccess(alloc_locs) => loop {
loop {
let bindings = { let bindings = {
let output = PrinterOutputter::new(); let output = PrinterOutputter::new();
self.toplevel_heap_view(output).result() self.toplevel_heap_view(output).result()
@@ -430,7 +445,11 @@ impl Machine {
if !(self.machine_st.b > 0) { if !(self.machine_st.b > 0) {
if bindings.is_empty() { if bindings.is_empty() {
let space = if requires_space(&attr_goals, ".") { " " } else { "" }; let space = if requires_space(&attr_goals, ".") {
" "
} else {
""
};
if !attr_goals.is_empty() { if !attr_goals.is_empty() {
println!("{}{}.", attr_goals, space); println!("{}{}.", attr_goals, space);
@@ -465,7 +484,7 @@ impl Machine {
ContinueResult::ContinueQuery => { ContinueResult::ContinueQuery => {
write!(raw_stdout, " ;\r\n").unwrap(); write!(raw_stdout, " ;\r\n").unwrap();
self.continue_query(&alloc_locs) self.continue_query(&alloc_locs)
}, }
ContinueResult::Conclude => { ContinueResult::Conclude => {
write!(raw_stdout, " ...\r\n").unwrap(); write!(raw_stdout, " ...\r\n").unwrap();
self.machine_st.absorb_snapshot(snapshot); self.machine_st.absorb_snapshot(snapshot);
@@ -476,7 +495,7 @@ impl Machine {
let mut raw_stdout = stdout().into_raw_mode().unwrap(); let mut raw_stdout = stdout().into_raw_mode().unwrap();
match result { match result {
EvalSession::QueryFailure => EvalSession::QueryFailure => {
if self.machine_st.ball.stub.len() > 0 { if self.machine_st.ball.stub.len() > 0 {
self.propagate_exception_to_toplevel(snapshot); self.propagate_exception_to_toplevel(snapshot);
return; return;
@@ -486,12 +505,13 @@ impl Machine {
self.machine_st.absorb_snapshot(snapshot); self.machine_st.absorb_snapshot(snapshot);
return; return;
}, }
}
EvalSession::Error(err) => { EvalSession::Error(err) => {
self.machine_st.absorb_snapshot(snapshot); self.machine_st.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0)); self.throw_session_error(err, (clause_name!("repl"), 0));
return; return;
}, }
_ => {} _ => {}
} }
} else { } else {
@@ -499,9 +519,17 @@ impl Machine {
write!(raw_stdout, "true.\r\n").unwrap(); write!(raw_stdout, "true.\r\n").unwrap();
} else { } else {
let space = if !attr_goals.is_empty() { let space = if !attr_goals.is_empty() {
if requires_space(&attr_goals, ".") { " " } else { "" } if requires_space(&attr_goals, ".") {
" "
} else { } else {
if requires_space(&bindings, ".") { " " } else { "" } ""
}
} else {
if requires_space(&bindings, ".") {
" "
} else {
""
}
}; };
write!(raw_stdout, "{}.\r\n", space).unwrap(); write!(raw_stdout, "{}.\r\n", space).unwrap();
@@ -514,22 +542,21 @@ impl Machine {
self.machine_st.absorb_snapshot(snapshot); self.machine_st.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0)); self.throw_session_error(err, (clause_name!("repl"), 0));
return; return;
}, }
EvalSession::QueryFailure => EvalSession::QueryFailure => {
if self.machine_st.ball.stub.len() > 0 { if self.machine_st.ball.stub.len() > 0 {
return self.propagate_exception_to_toplevel(snapshot); return self.propagate_exception_to_toplevel(snapshot);
} else { } else {
println!("false."); println!("false.");
}, }
}
_ => {} _ => {}
} }
self.machine_st.absorb_snapshot(snapshot); self.machine_st.absorb_snapshot(snapshot);
} }
pub(super) pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) {
fn run_query(&mut self, alloc_locs: &AllocVarDict)
{
let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query()); let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query());
while self.machine_st.p < end_ptr { while self.machine_st.p < end_ptr {
@@ -538,20 +565,23 @@ impl Machine {
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => { &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
self.machine_st.record_var_places(cn, alloc_locs); self.machine_st.record_var_places(cn, alloc_locs);
cn += 1; cn += 1;
}, }
_ => {} _ => {}
} }
self.machine_st.p = top_level_code_ptr!(cn, p); self.machine_st.p = top_level_code_ptr!(cn, p);
} }
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo, self.machine_st.query_stepper(
&mut self.prolog_stream); &mut self.indices,
&mut self.policies,
&mut self.code_repo,
&mut self.prolog_stream,
);
match self.machine_st.p { match self.machine_st.p {
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}, CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}
CodePtr::REPL(code_ptr, p) => CodePtr::REPL(code_ptr, p) => self.handle_toplevel_command(code_ptr, p),
self.handle_toplevel_command(code_ptr, p),
CodePtr::DynamicTransaction(trans_type, p) => { CodePtr::DynamicTransaction(trans_type, p) => {
// self.code_repo.cached_query is about to be overwritten by the term expander, // self.code_repo.cached_query is about to be overwritten by the term expander,
// so hold onto it locally and restore it after the compiler has finished. // so hold onto it locally and restore it after the compiler has finished.
@@ -569,7 +599,7 @@ impl Machine {
} }
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
}, }
_ => { _ => {
if self.machine_st.heap_locs.is_empty() { if self.machine_st.heap_locs.is_empty() {
self.machine_st.record_var_places(0, alloc_locs); self.machine_st.record_var_places(0, alloc_locs);
@@ -581,8 +611,7 @@ impl Machine {
} }
} }
pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession {
{
if !self.or_stack_is_empty() { if !self.or_stack_is_empty() {
let b = self.machine_st.b - 1; let b = self.machine_st.b - 1;
self.machine_st.p = self.machine_st.or_stack[b].bp.clone(); self.machine_st.p = self.machine_st.or_stack[b].bp.clone();
@@ -605,15 +634,17 @@ impl Machine {
} }
pub fn toplevel_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter pub fn toplevel_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where Outputter: HCValueOutputter where
Outputter: HCValueOutputter,
{ {
let mut sorted_vars: Vec<_> = self.machine_st.heap_locs.iter().collect(); let mut sorted_vars: Vec<_> = self.machine_st.heap_locs.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0); sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars { for (var, addr) in sorted_vars {
let addr = self.machine_st.store(self.machine_st.deref(addr.clone())); let addr = self.machine_st.store(self.machine_st.deref(addr.clone()));
output = self.machine_st.print_var_eq(var.clone(), addr, &self.indices.op_dir, output = self
output); .machine_st
.print_var_eq(var.clone(), addr, &self.indices.op_dir, output);
} }
output output
@@ -621,14 +652,19 @@ impl Machine {
#[cfg(test)] #[cfg(test)]
pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where Outputter: HCValueOutputter where
Outputter: HCValueOutputter,
{ {
let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = self.machine_st.heap_locs.iter().collect(); let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = self.machine_st.heap_locs.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0); sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars { for (var, addr) in sorted_vars {
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), &self.indices.op_dir, output = self.machine_st.print_var_eq(
output); var.clone(),
addr.clone(),
&self.indices.op_dir,
output,
);
} }
output output
@@ -640,18 +676,18 @@ impl Machine {
} }
impl MachineState { impl MachineState {
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict) fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict) {
{
for (var, var_data) in alloc_locs { for (var, var_data) in alloc_locs {
match var_data { match var_data {
&VarData::Perm(p) if p > 0 => &VarData::Perm(p) if p > 0 => {
if !self.heap_locs.contains_key(var) { if !self.heap_locs.contains_key(var) {
let e = self.e; let e = self.e;
let r = var_data.as_reg_type().reg_num(); let r = var_data.as_reg_type().reg_num();
let addr = self.and_stack[e][r].clone(); let addr = self.and_stack[e][r].clone();
self.heap_locs.insert(var.clone(), addr); self.heap_locs.insert(var.clone(), addr);
}, }
}
&VarData::Temp(cn, _, _) if cn == chunk_num => { &VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type(); let r = var_data.as_reg_type();
@@ -659,18 +695,19 @@ impl MachineState {
let addr = self[r].clone(); let addr = self[r].clone();
self.heap_locs.insert(var.clone(), addr); self.heap_locs.insert(var.clone(), addr);
} }
}, }
_ => {} _ => {}
} }
} }
} }
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
{
let flags = self.flags; let flags = self.flags;
let mut output = { let mut output = {
self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom }; self.flags = MachineFlags {
double_quotes: DoubleQuotes::Atom,
};
let output = PrinterOutputter::new(); let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
@@ -689,28 +726,38 @@ impl MachineState {
output output
} }
fn dispatch_instr(&mut self, instr: &Line, indices: &mut IndexStore, policies: &mut MachinePolicies, fn dispatch_instr(
code_repo: &CodeRepo, prolog_stream: &mut PrologStream) &mut self,
{ instr: &Line,
indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
prolog_stream: &mut PrologStream,
) {
match instr { match instr {
&Line::Arithmetic(ref arith_instr) => &Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
self.execute_arith_instr(arith_instr), &Line::Choice(ref choice_instr) => {
&Line::Choice(ref choice_instr) => self.execute_choice_instr(choice_instr, &mut policies.call_policy)
self.execute_choice_instr(choice_instr, &mut policies.call_policy), }
&Line::Cut(ref cut_instr) => &Line::Cut(ref cut_instr) => {
self.execute_cut_instr(cut_instr, &mut policies.cut_policy), self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
&Line::Control(ref control_instr) => }
self.execute_ctrl_instr(indices, code_repo, &mut policies.call_policy, &Line::Control(ref control_instr) => self.execute_ctrl_instr(
&mut policies.cut_policy, prolog_stream, indices,
control_instr), code_repo,
&mut policies.call_policy,
&mut policies.cut_policy,
prolog_stream,
control_instr,
),
&Line::Fact(ref fact_instr) => { &Line::Fact(ref fact_instr) => {
self.execute_fact_instr(&fact_instr); self.execute_fact_instr(&fact_instr);
self.p += 1; self.p += 1;
}, }
&Line::Indexing(ref indexing_instr) => &Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
self.execute_indexing_instr(&indexing_instr), &Line::IndexedChoice(ref choice_instr) => {
&Line::IndexedChoice(ref choice_instr) => self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy), }
&Line::Query(ref query_instr) => { &Line::Query(ref query_instr) => {
self.execute_query_instr(&query_instr); self.execute_query_instr(&query_instr);
self.p += 1; self.p += 1;
@@ -718,19 +765,22 @@ impl MachineState {
} }
} }
fn execute_instr(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, fn execute_instr(
code_repo: &CodeRepo, prolog_stream: &mut PrologStream) &mut self,
{ indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &CodeRepo,
prolog_stream: &mut PrologStream,
) {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) { let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
Some(instr) => instr, Some(instr) => instr,
None => return None => return,
}; };
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream); self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
} }
fn backtrack(&mut self) fn backtrack(&mut self) {
{
if self.b > 0 { if self.b > 0 {
let b = self.b - 1; let b = self.b - 1;
@@ -749,27 +799,23 @@ impl MachineState {
fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool { fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool {
match self.p { match self.p {
CodePtr::Local(LocalCodePtr::DirEntry(p)) CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < code_repo.code.len() => {}
if p < code_repo.code.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) CodePtr::Local(LocalCodePtr::UserTermExpansion(p))
if p < code_repo.term_expanders.len() => {}, if p < code_repo.term_expanders.len() => {}
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.fail = true,
self.fail = true,
CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) CodePtr::Local(LocalCodePtr::UserGoalExpansion(p))
if p < code_repo.goal_expanders.len() => {}, if p < code_repo.goal_expanders.len() => {}
CodePtr::Local(LocalCodePtr::UserGoalExpansion(_)) => CodePtr::Local(LocalCodePtr::UserGoalExpansion(_)) => self.fail = true,
self.fail = true, CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) if p < code_repo.in_situ_code.len() => {
CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) }
if p < code_repo.in_situ_code.len() => {}, CodePtr::Local(_) | CodePtr::REPL(..) => return false,
CodePtr::Local(_) | CodePtr::REPL(..) =>
return false,
CodePtr::DynamicTransaction(..) => { CodePtr::DynamicTransaction(..) => {
// prevent use of dynamic transactions from // prevent use of dynamic transactions from
// succeeding in expansions. self.fail will be toggled // succeeding in expansions. self.fail will be toggled
// back to false later. // back to false later.
self.fail = true; self.fail = true;
return false; return false;
}, }
_ => {} _ => {}
} }
@@ -777,10 +823,13 @@ impl MachineState {
} }
// return true iff verify_attr_interrupt is called. // return true iff verify_attr_interrupt is called.
fn verify_attr_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, fn verify_attr_stepper(
code_repo: &mut CodeRepo, prolog_stream: &mut PrologStream) &mut self,
-> bool indices: &mut IndexStore,
{ policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
prolog_stream: &mut PrologStream,
) -> bool {
loop { loop {
let instr = match code_repo.lookup_instr(self.last_call, &self.p) { let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
Some(instr) => { Some(instr) => {
@@ -791,8 +840,8 @@ impl MachineState {
self.run_verify_attr_interrupt(cp); self.run_verify_attr_interrupt(cp);
return true; return true;
} }
}, }
None => return false None => return false,
}; };
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream); self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
@@ -814,9 +863,13 @@ impl MachineState {
self.verify_attr_interrupt(p); self.verify_attr_interrupt(p);
} }
fn query_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies, fn query_stepper(
code_repo: &mut CodeRepo, prolog_stream: &mut PrologStream) &mut self,
{ indices: &mut IndexStore,
policies: &mut MachinePolicies,
code_repo: &mut CodeRepo,
prolog_stream: &mut PrologStream,
) {
loop { loop {
self.execute_instr(indices, policies, code_repo, prolog_stream); self.execute_instr(indices, policies, code_repo, prolog_stream);
@@ -836,8 +889,8 @@ impl MachineState {
let cp = self.p.local(); let cp = self.p.local();
self.run_verify_attr_interrupt(cp); self.run_verify_attr_interrupt(cp);
} }
}, }
_ => _ => {
if !self.check_machine_index(code_repo) { if !self.check_machine_index(code_repo) {
break; break;
} }
@@ -845,3 +898,4 @@ impl MachineState {
} }
} }
} }
}

View File

@@ -6,37 +6,50 @@ use prolog::machine::code_repo::*;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use std::collections::{VecDeque}; use std::collections::VecDeque;
// Module's and related types are defined in forms. // Module's and related types are defined in forms.
impl Module { impl Module {
pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self { pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self {
Module { module_decl, atom_tbl, Module {
module_decl,
atom_tbl,
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])), user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])), user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
term_expansions: (Predicate::new(), VecDeque::from(vec![])), term_expansions: (Predicate::new(), VecDeque::from(vec![])),
goal_expansions: (Predicate::new(), VecDeque::from(vec![])), goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
code_dir: CodeDir::new(), code_dir: CodeDir::new(),
op_dir: default_op_dir(), op_dir: default_op_dir(),
inserted_expansions: false } inserted_expansions: false,
}
} }
pub fn dump_expansions(&self, code_repo: &mut CodeRepo, flags: MachineFlags) pub fn dump_expansions(
-> Result<(), ParserError> &self,
code_repo: &mut CodeRepo,
flags: MachineFlags,
) -> Result<(), ParserError> {
{ {
{ let te = code_repo
let te = code_repo.term_dir.entry((clause_name!("term_expansion"), 2)) .term_dir
.entry((clause_name!("term_expansion"), 2))
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
(te.0).0.extend((self.user_term_expansions.0).0.iter().cloned()); (te.0)
.0
.extend((self.user_term_expansions.0).0.iter().cloned());
te.1.extend(self.user_term_expansions.1.iter().cloned()); te.1.extend(self.user_term_expansions.1.iter().cloned());
} }
{ {
let ge = code_repo.term_dir.entry((clause_name!("goal_expansion"), 2)) let ge = code_repo
.term_dir
.entry((clause_name!("goal_expansion"), 2))
.or_insert((Predicate::new(), VecDeque::from(vec![]))); .or_insert((Predicate::new(), VecDeque::from(vec![])));
(ge.0).0.extend((self.user_goal_expansions.0).0.iter().cloned()); (ge.0)
.0
.extend((self.user_goal_expansions.0).0.iter().cloned());
ge.1.extend(self.user_goal_expansions.1.iter().cloned()); ge.1.extend(self.user_goal_expansions.1.iter().cloned());
} }
@@ -46,14 +59,17 @@ impl Module {
Ok(()) Ok(())
} }
pub fn add_module_expansion_record(&mut self, hook: CompileTimeHook, clause: PredicateClause, pub fn add_module_expansion_record(
queue: VecDeque<TopLevel>) &mut self,
{ hook: CompileTimeHook,
clause: PredicateClause,
queue: VecDeque<TopLevel>,
) {
match hook { match hook {
CompileTimeHook::TermExpansion | CompileTimeHook::UserTermExpansion => { CompileTimeHook::TermExpansion | CompileTimeHook::UserTermExpansion => {
(self.term_expansions.0).0.push(clause); (self.term_expansions.0).0.push(clause);
self.term_expansions.1.extend(queue.into_iter()); self.term_expansions.1.extend(queue.into_iter());
}, }
CompileTimeHook::GoalExpansion | CompileTimeHook::UserGoalExpansion => { CompileTimeHook::GoalExpansion | CompileTimeHook::UserGoalExpansion => {
(self.goal_expansions.0).0.push(clause); (self.goal_expansions.0).0.push(clause);
self.goal_expansions.1.extend(queue.into_iter()); self.goal_expansions.1.extend(queue.into_iter());
@@ -62,8 +78,7 @@ impl Module {
} }
} }
pub trait SubModuleUser pub trait SubModuleUser {
{
fn atom_tbl(&self) -> TabledData<Atom>; fn atom_tbl(&self) -> TabledData<Atom>;
fn op_dir(&mut self) -> &mut OpDir; fn op_dir(&mut self) -> &mut OpDir;
fn remove_code_index(&mut self, PredicateKey); fn remove_code_index(&mut self, PredicateKey);
@@ -71,13 +86,13 @@ pub trait SubModuleUser
fn insert_dir_entry(&mut self, ClauseName, usize, CodeIndex); fn insert_dir_entry(&mut self, ClauseName, usize, CodeIndex);
fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName> fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName> {
{ self.op_dir()
self.op_dir().get(&(name, fixity)).map(|op_val| op_val.owning_module()) .get(&(name, fixity))
.map(|op_val| op_val.owning_module())
} }
fn remove_module(&mut self, mod_name: ClauseName, module: &Module) fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
{
for (name, arity) in module.module_decl.exports.iter().cloned() { for (name, arity) in module.module_decl.exports.iter().cloned() {
let name = name.defrock_brackets(); let name = name.defrock_brackets();
@@ -91,15 +106,13 @@ pub trait SubModuleUser
// remove or respecify ops. // remove or respecify ops.
if arity == 2 { if arity == 2 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
{
if mod_name == module.module_decl.name { if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::In)); self.op_dir().remove(&(name.clone(), Fixity::In));
} }
} }
} else if arity == 1 { } else if arity == 1 {
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
{
if mod_name == module.module_decl.name { if mod_name == module.module_decl.name {
self.op_dir().remove(&(name.clone(), Fixity::Pre)); self.op_dir().remove(&(name.clone(), Fixity::Pre));
} }
@@ -112,15 +125,14 @@ pub trait SubModuleUser
} }
} }
} }
}, }
_ => {} _ => {}
}; };
} }
} }
// returns true on successful import. // returns true on successful import.
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
{
let name = name.defrock_brackets(); let name = name.defrock_brackets();
let mut found_op = false; let mut found_op = false;
@@ -153,17 +165,30 @@ pub trait SubModuleUser
} }
} }
fn use_qualified_module(&mut self, &mut CodeRepo, MachineFlags, &Module, &Vec<PredicateKey>) fn use_qualified_module(
-> Result<(), SessionError>; &mut self,
&mut CodeRepo,
MachineFlags,
&Module,
&Vec<PredicateKey>,
) -> Result<(), SessionError>;
fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) -> Result<(), SessionError>; fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) -> Result<(), SessionError>;
} }
pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>) pub fn use_qualified_module<User>(
-> Result<(), SessionError> user: &mut User,
where User: SubModuleUser submodule: &Module,
exports: &Vec<PredicateKey>,
) -> Result<(), SessionError>
where
User: SubModuleUser,
{ {
for (name, arity) in exports.iter().cloned() { for (name, arity) in exports.iter().cloned() {
if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { if !submodule
.module_decl
.exports
.contains(&(name.clone(), arity))
{
continue; continue;
} }
@@ -175,9 +200,10 @@ pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports:
Ok(()) Ok(())
} }
pub fn use_module<User: SubModuleUser>(user: &mut User, submodule: &Module) pub fn use_module<User: SubModuleUser>(
-> Result<(), SessionError> user: &mut User,
{ submodule: &Module,
) -> Result<(), SessionError> {
for (name, arity) in submodule.module_decl.exports.iter().cloned() { for (name, arity) in submodule.module_decl.exports.iter().cloned() {
if !user.import_decl(name, arity, submodule) { if !user.import_decl(name, arity, submodule) {
return Err(SessionError::ModuleDoesNotContainExport); return Err(SessionError::ModuleDoesNotContainExport);
@@ -208,31 +234,53 @@ impl SubModuleUser for Module {
self.code_dir.insert((name, arity), idx); self.code_dir.insert((name, arity), idx);
} }
fn use_qualified_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module, fn use_qualified_module(
exports: &Vec<PredicateKey>) &mut self,
-> Result<(), SessionError> _: &mut CodeRepo,
{ _: MachineFlags,
submodule: &Module,
exports: &Vec<PredicateKey>,
) -> Result<(), SessionError> {
use_qualified_module(self, submodule, exports)?; use_qualified_module(self, submodule, exports)?;
(self.user_term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); (self.user_term_expansions.0)
self.user_term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); .0
.extend((submodule.term_expansions.0).0.iter().cloned());
self.user_term_expansions
.1
.extend(submodule.term_expansions.1.iter().cloned());
(self.user_goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); (self.user_goal_expansions.0)
self.user_goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned()); .0
.extend((submodule.goal_expansions.0).0.iter().cloned());
self.user_goal_expansions
.1
.extend(submodule.goal_expansions.1.iter().cloned());
Ok(()) Ok(())
} }
fn use_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module) fn use_module(
-> Result<(), SessionError> &mut self,
{ _: &mut CodeRepo,
_: MachineFlags,
submodule: &Module,
) -> Result<(), SessionError> {
use_module(self, submodule)?; use_module(self, submodule)?;
(self.user_term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned()); (self.user_term_expansions.0)
self.user_term_expansions.1.extend(submodule.term_expansions.1.iter().cloned()); .0
.extend((submodule.term_expansions.0).0.iter().cloned());
self.user_term_expansions
.1
.extend(submodule.term_expansions.1.iter().cloned());
(self.user_goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned()); (self.user_goal_expansions.0)
self.user_goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned()); .0
.extend((submodule.goal_expansions.0).0.iter().cloned());
self.user_goal_expansions
.1
.extend(submodule.goal_expansions.1.iter().cloned());
Ok(()) Ok(())
} }

View File

@@ -15,11 +15,12 @@ pub struct Frame {
pub pstr_tr: usize, pub pstr_tr: usize,
pub h: usize, pub h: usize,
pub b0: usize, pub b0: usize,
args: Vec<Addr> args: Vec<Addr>,
} }
impl Frame { impl Frame {
fn new(global_index: usize, fn new(
global_index: usize,
e: usize, e: usize,
cp: LocalCodePtr, cp: LocalCodePtr,
attr_var_init_b: usize, attr_var_init_b: usize,
@@ -29,9 +30,8 @@ impl Frame {
pstr_tr: usize, pstr_tr: usize,
h: usize, h: usize,
b0: usize, b0: usize,
n: usize) n: usize,
-> Self ) -> Self {
{
Frame { Frame {
global_index, global_index,
e, e,
@@ -43,7 +43,7 @@ impl Frame {
pstr_tr, pstr_tr,
h, h,
b0, b0,
args: vec![Addr::HeapCell(0); n] args: vec![Addr::HeapCell(0); n],
} }
} }
@@ -59,7 +59,8 @@ impl OrStack {
OrStack(Vec::new()) OrStack(Vec::new())
} }
pub fn push(&mut self, pub fn push(
&mut self,
global_index: usize, global_index: usize,
e: usize, e: usize,
cp: LocalCodePtr, cp: LocalCodePtr,
@@ -70,9 +71,21 @@ impl OrStack {
pstr_tr: usize, pstr_tr: usize,
h: usize, h: usize,
b0: usize, b0: usize,
n: usize) n: usize,
{ ) {
self.0.push(Frame::new(global_index, e, cp, attr_var_init_b, b, bp, tr, pstr_tr, h, b0, n)); self.0.push(Frame::new(
global_index,
e,
cp,
attr_var_init_b,
b,
bp,
tr,
pstr_tr,
h,
b0,
n,
));
} }
#[inline] #[inline]

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use prolog_parser::parser::*; use prolog_parser::parser::*;
use prolog::machine::*;
use prolog::machine::machine_indices::HeapCellValue; use prolog::machine::machine_indices::HeapCellValue;
use prolog::rug::Integer; use prolog::machine::*;
use prolog::rug::ops::Pow; use prolog::rug::ops::Pow;
use prolog::rug::Integer;
use std::cell::Cell; use std::cell::Cell;
use std::collections::VecDeque; use std::collections::VecDeque;
@@ -12,8 +12,7 @@ use std::io::Read;
use std::iter::Rev; use std::iter::Rev;
use std::vec::IntoIter; use std::vec::IntoIter;
fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> {
{
if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term { if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term {
if name.as_str() == s && subterms.len() == 2 { if name.as_str() == s && subterms.len() == 2 {
let snd = *subterms.pop().unwrap(); let snd = *subterms.pop().unwrap();
@@ -26,8 +25,7 @@ fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)>
None None
} }
pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term> pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term> {
{
let mut terms = vec![]; let mut terms = vec![];
while let Some((fst, snd)) = unfold_by_str_once(&mut term, s) { while let Some((fst, snd)) = unfold_by_str_once(&mut term, s) {
@@ -40,20 +38,22 @@ pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term>
} }
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
where I: DoubleEndedIterator<Item=Term> where
I: DoubleEndedIterator<Item = Term>,
{ {
for prec in terms.rev() { for prec in terms.rev() {
term = Term::Clause(Cell::default(), sym.clone(), term = Term::Clause(
Cell::default(),
sym.clone(),
vec![Box::new(prec), Box::new(term)], vec![Box::new(prec), Box::new(term)],
None); None,
);
} }
term term
} }
fn extract_from_list(head: Box<Term>, tail: Box<Term>) fn extract_from_list(head: Box<Term>, tail: Box<Term>) -> Result<Rev<IntoIter<Term>>, ParserError> {
-> Result<Rev<IntoIter<Term>>, ParserError>
{
let mut terms = vec![*head]; let mut terms = vec![*head];
let mut tail = *tail; let mut tail = *tail;
@@ -81,7 +81,7 @@ pub struct TermStream<'a, R: Read> {
pub struct ExpansionAdditionResult { pub struct ExpansionAdditionResult {
term_expansion_additions: (Predicate, VecDeque<TopLevel>), term_expansion_additions: (Predicate, VecDeque<TopLevel>),
goal_expansion_additions: (Predicate, VecDeque<TopLevel>) goal_expansion_additions: (Predicate, VecDeque<TopLevel>),
} }
impl ExpansionAdditionResult { impl ExpansionAdditionResult {
@@ -109,17 +109,24 @@ impl<'a, R: Read> Drop for TermStream<'a, R> {
} }
impl<'a, R: Read> TermStream<'a, R> { impl<'a, R: Read> TermStream<'a, R> {
pub fn new(src: &'a mut ParsingStream<R>, atom_tbl: TabledData<Atom>, flags: MachineFlags, wam: &'a mut Machine) pub fn new(
-> Self src: &'a mut ParsingStream<R>,
{ atom_tbl: TabledData<Atom>,
flags: MachineFlags,
wam: &'a mut Machine,
) -> Self {
TermStream { TermStream {
stack: Vec::new(), stack: Vec::new(),
term_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("term_expansion"), 2)), term_expansion_lens: wam
goal_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("goal_expansion"), 2)), .code_repo
.term_dir_entry_len((clause_name!("term_expansion"), 2)),
goal_expansion_lens: wam
.code_repo
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
wam, wam,
parser: Parser::new(src, atom_tbl, flags), parser: Parser::new(src, atom_tbl, flags),
in_module: false, in_module: false,
flags flags,
} }
} }
@@ -134,11 +141,11 @@ impl<'a, R: Read> TermStream<'a, R> {
CompileTimeHook::UserTermExpansion => { CompileTimeHook::UserTermExpansion => {
self.term_expansion_lens.0 += len; self.term_expansion_lens.0 += len;
self.term_expansion_lens.1 += queue_len; self.term_expansion_lens.1 += queue_len;
}, }
CompileTimeHook::UserGoalExpansion => { CompileTimeHook::UserGoalExpansion => {
self.goal_expansion_lens.0 += len; self.goal_expansion_lens.0 += len;
self.goal_expansion_lens.1 += queue_len; self.goal_expansion_lens.1 += queue_len;
}, }
_ => {} _ => {}
} }
} }
@@ -169,27 +176,34 @@ impl<'a, R: Read> TermStream<'a, R> {
Ok(self.stack.is_empty() && self.parser.eof()?) Ok(self.stack.is_empty() && self.parser.eof()?)
} }
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
{
let te_len = self.term_expansion_lens.0; let te_len = self.term_expansion_lens.0;
let te_queue_len = self.term_expansion_lens.1; let te_queue_len = self.term_expansion_lens.1;
let ge_len = self.goal_expansion_lens.0; let ge_len = self.goal_expansion_lens.0;
let ge_queue_len = self.goal_expansion_lens.1; let ge_queue_len = self.goal_expansion_lens.1;
let term_expansion_additions = let term_expansion_additions = self.wam.code_repo.truncate_terms(
self.wam.code_repo.truncate_terms((clause_name!("term_expansion"), 2), (clause_name!("term_expansion"), 2),
te_len, te_queue_len); te_len,
let goal_expansion_additions = te_queue_len,
self.wam.code_repo.truncate_terms((clause_name!("goal_expansion"), 2), );
ge_len, ge_queue_len); let goal_expansion_additions = self.wam.code_repo.truncate_terms(
(clause_name!("goal_expansion"), 2),
ge_len,
ge_queue_len,
);
self.wam.code_repo.compile_hook(CompileTimeHook::TermExpansion, self.flags)?; self.wam
self.wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?; .code_repo
.compile_hook(CompileTimeHook::TermExpansion, self.flags)?;
self.wam
.code_repo
.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?;
Ok(ExpansionAdditionResult { Ok(ExpansionAdditionResult {
term_expansion_additions, term_expansion_additions,
goal_expansion_additions goal_expansion_additions,
}) })
} }
@@ -198,34 +212,37 @@ impl<'a, R: Read> TermStream<'a, R> {
Term::Cons(_, head, tail) => { Term::Cons(_, head, tail) => {
let iter = extract_from_list(head, tail)?; let iter = extract_from_list(head, tail)?;
Ok(self.stack.extend(iter)) Ok(self.stack.extend(iter))
}, }
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Ok(self.stack.push(term)),
Ok(self.stack.push(term)), _ => Err(ParserError::ExpectedTopLevelTerm),
_ =>
Err(ParserError::ExpectedTopLevelTerm)
} }
} }
fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result<Term, ParserError> fn parse_expansion_output(
{ &self,
term_string: &str,
op_dir: &OpDir,
) -> Result<Term, ParserError> {
let mut stream = parsing_stream(term_string.trim().as_bytes()); let mut stream = parsing_stream(term_string.trim().as_bytes());
let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags); let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags);
parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir, op_dir)) parser.read_term(composite_op!(
self.in_module,
&self.wam.indices.op_dir,
op_dir
))
} }
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
{
let mut machine_st = MachineState::new(); let mut machine_st = MachineState::new();
loop { loop {
while let Some(term) = self.stack.pop() { while let Some(term) = self.stack.pop() {
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
{
Some(term_string) => { Some(term_string) => {
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?; let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
self.enqueue_term(term)? self.enqueue_term(term)?
}, }
None => { None => {
let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?; let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?;
return Ok(term); return Ok(term);
@@ -234,16 +251,21 @@ impl<'a, R: Read> TermStream<'a, R> {
} }
self.parser.reset(); self.parser.reset();
let term = self.parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir, let term = self.parser.read_term(composite_op!(
op_dir))?; self.in_module,
&self.wam.indices.op_dir,
op_dir
))?;
self.stack.push(term); self.stack.push(term);
} }
} }
pub(crate) pub(crate) fn run_goal_expanders(
fn run_goal_expanders(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, term: Term) &mut self,
-> Result<Term, ParserError> machine_st: &mut MachineState,
{ op_dir: &OpDir,
term: Term,
) -> Result<Term, ParserError> {
match term { match term {
Term::Clause(cell, name, mut terms, arity) => { Term::Clause(cell, name, mut terms, arity) => {
let mut new_terms = { let mut new_terms = {
@@ -251,45 +273,50 @@ impl<'a, R: Read> TermStream<'a, R> {
(":-", 2) => { (":-", 2) => {
let comma_term = *terms.pop().unwrap(); let comma_term = *terms.pop().unwrap();
unfold_by_str(comma_term, ",") unfold_by_str(comma_term, ",")
}, }
("?-", 1) => unfold_by_str(*terms.pop().unwrap(), ","), ("?-", 1) => unfold_by_str(*terms.pop().unwrap(), ","),
_ => return Ok(Term::Clause(cell, name, terms, arity)) _ => return Ok(Term::Clause(cell, name, terms, arity)),
}; };
self.expand_goals(machine_st, op_dir, VecDeque::from(old_terms))? self.expand_goals(machine_st, op_dir, VecDeque::from(old_terms))?
}; };
let initial_term = new_terms.pop().unwrap(); let initial_term = new_terms.pop().unwrap();
terms.push(Box::new(fold_by_str(new_terms.into_iter(), initial_term, terms.push(Box::new(fold_by_str(
clause_name!(",")))); new_terms.into_iter(),
initial_term,
clause_name!(","),
)));
Ok(Term::Clause(cell, name, terms, arity)) Ok(Term::Clause(cell, name, terms, arity))
}, }
_ => _ => Ok(term),
Ok(term)
} }
} }
fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, mut terms: VecDeque<Term>) fn expand_goals(
-> Result<Vec<Term>, ParserError> &mut self,
{ machine_st: &mut MachineState,
op_dir: &OpDir,
mut terms: VecDeque<Term>,
) -> Result<Vec<Term>, ParserError> {
let mut results = vec![]; let mut results = vec![];
while let Some(term) = terms.pop_front() { while let Some(term) = terms.pop_front() {
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) {
{
Some(term_string) => { Some(term_string) => {
println!("trying to goal expand {}", term_string); println!("trying to goal expand {}", term_string);
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?; let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
match term { match term {
Term::Cons(_, head, tail) => Term::Cons(_, head, tail) => {
for term in extract_from_list(head, tail)? { for term in extract_from_list(head, tail)? {
terms.push_front(term); terms.push_front(term);
}, }
term => terms.push_front(term) }
term => terms.push_front(term),
}; };
}, }
None => results.push(term) None => results.push(term),
} }
} }
@@ -298,9 +325,7 @@ impl<'a, R: Read> TermStream<'a, R> {
} }
impl MachineState { impl MachineState {
pub(super) pub(super) fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
{
let output = PrinterOutputter::new(); let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
let mut max_var_length = 0; let mut max_var_length = 0;
@@ -327,9 +352,12 @@ impl MachineState {
output output
} }
fn try_expand_term(&mut self, wam: &mut Machine, term: &Term, hook: CompileTimeHook) fn try_expand_term(
-> Option<String> &mut self,
{ wam: &mut Machine,
term: &Term,
hook: CompileTimeHook,
) -> Option<String> {
let term_write_result = write_term_to_heap(term, self); let term_write_result = write_term_to_heap(term, self);
let h = self.heap.h; let h = self.heap.h;
@@ -340,7 +368,12 @@ impl MachineState {
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)]; let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
wam.code_repo.cached_query = code; wam.code_repo.cached_query = code;
self.query_stepper(&mut wam.indices, &mut wam.policies, &mut wam.code_repo, &mut readline::input_stream()); self.query_stepper(
&mut wam.indices,
&mut wam.policies,
&mut wam.code_repo,
&mut readline::input_stream(),
);
if self.fail { if self.fail {
self.reset(); self.reset();

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +1,40 @@
macro_rules! interm { macro_rules! interm {
($n: expr) => ( ($n: expr) => {
ArithmeticTerm::Interm($n) ArithmeticTerm::Interm($n)
) };
} }
macro_rules! heap_str { macro_rules! heap_str {
($s:expr) => ( ($s:expr) => {
HeapCellValue::Addr(Addr::Str($s)) HeapCellValue::Addr(Addr::Str($s))
) };
} }
macro_rules! heap_integer { macro_rules! heap_integer {
($i:expr) => ( ($i:expr) => {
HeapCellValue::Addr(Addr::Con(Constant::Integer($i))) HeapCellValue::Addr(Addr::Con(Constant::Integer($i)))
) };
} }
macro_rules! heap_cell { macro_rules! heap_cell {
($i:expr) => ( ($i:expr) => {
HeapCellValue::Addr(Addr::HeapCell($i)) HeapCellValue::Addr(Addr::HeapCell($i))
) };
} }
macro_rules! heap_con { macro_rules! heap_con {
($i:expr) => ( ($i:expr) => {
HeapCellValue::Addr(Addr::Con($i)) HeapCellValue::Addr(Addr::Con($i))
) };
} }
macro_rules! heap_atom { macro_rules! heap_atom {
($name:expr) => ( ($name:expr) => {
HeapCellValue::Addr(Addr::Con(atom!($name))) HeapCellValue::Addr(Addr::Con(atom!($name)))
); };
($name:expr, $tbl:expr) => ( ($name:expr, $tbl:expr) => {
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl))) HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
) };
} }
macro_rules! functor { macro_rules! functor {
@@ -53,140 +53,151 @@ macro_rules! functor {
} }
macro_rules! is_atom { macro_rules! is_atom {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0)
) };
} }
macro_rules! is_atomic { macro_rules! is_atomic {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtomic($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtomic($r)), 1, 0)
) };
} }
macro_rules! is_integer { macro_rules! is_integer {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsInteger($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsInteger($r)), 1, 0)
) };
} }
macro_rules! is_compound { macro_rules! is_compound {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsCompound($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsCompound($r)), 1, 0)
) };
} }
macro_rules! is_float { macro_rules! is_float {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsFloat($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsFloat($r)), 1, 0)
) };
} }
macro_rules! is_rational { macro_rules! is_rational {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsRational($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsRational($r)), 1, 0)
) };
} }
macro_rules! is_nonvar { macro_rules! is_nonvar {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsNonVar($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsNonVar($r)), 1, 0)
) };
} }
macro_rules! is_string { macro_rules! is_string {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsString($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsString($r)), 1, 0)
) };
} }
macro_rules! is_var { macro_rules! is_var {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0) call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0)
) };
} }
macro_rules! is_partial_string { macro_rules! is_partial_string {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::Inlined(InlinedClauseType::IsPartialString($r)), 1, 0) call_clause!(
ClauseType::Inlined(InlinedClauseType::IsPartialString($r)),
1,
0
) )
};
} }
macro_rules! call_clause { macro_rules! call_clause {
($ct:expr, $arity:expr, $pvs:expr) => ( ($ct:expr, $arity:expr, $pvs:expr) => {
Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, false, false)) Line::Control(ControlInstruction::CallClause(
); $ct, $arity, $pvs, false, false,
($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => ( ))
Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, $lco, false)) };
) ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, $lco, false,
))
};
} }
macro_rules! call_clause_by_default { macro_rules! call_clause_by_default {
($ct:expr, $arity:expr, $pvs:expr) => ( ($ct:expr, $arity:expr, $pvs:expr) => {
Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, false, true)) Line::Control(ControlInstruction::CallClause(
); $ct, $arity, $pvs, false, true,
($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => ( ))
Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, $lco, true)) };
) ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
Line::Control(ControlInstruction::CallClause(
$ct, $arity, $pvs, $lco, true,
))
};
} }
macro_rules! proceed { macro_rules! proceed {
() => ( () => {
Line::Control(ControlInstruction::Proceed) Line::Control(ControlInstruction::Proceed)
) };
} }
macro_rules! is_call { macro_rules! is_call {
($r:expr, $at:expr) => ( ($r:expr, $at:expr) => {
call_clause!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0) call_clause!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
) };
} }
macro_rules! is_call_by_default { macro_rules! is_call_by_default {
($r:expr, $at:expr) => ( ($r:expr, $at:expr) => {
call_clause_by_default!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0) call_clause_by_default!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
) };
} }
macro_rules! set_cp { macro_rules! set_cp {
($r:expr) => ( ($r:expr) => {
call_clause!(ClauseType::System(SystemClauseType::SetCutPoint($r)), 1, 0) call_clause!(ClauseType::System(SystemClauseType::SetCutPoint($r)), 1, 0)
) };
} }
macro_rules! succeed { macro_rules! succeed {
() => ( () => {
call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0) call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0)
) };
} }
macro_rules! fail { macro_rules! fail {
() => ( () => {
call_clause!(ClauseType::System(SystemClauseType::Fail), 0, 0) call_clause!(ClauseType::System(SystemClauseType::Fail), 0, 0)
) };
} }
macro_rules! compare_number_instr { macro_rules! compare_number_instr {
($cmp: expr, $at_1: expr, $at_2: expr) => {{ ($cmp: expr, $at_1: expr, $at_2: expr) => {{
let ct = ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp, $at_1, $at_2)); let ct = ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp, $at_1, $at_2));
call_clause!(ct, 2, 0) call_clause!(ct, 2, 0)
}} }};
} }
macro_rules! jmp_call { macro_rules! jmp_call {
($arity:expr, $offset:expr, $pvs:expr) => ( ($arity:expr, $offset:expr, $pvs:expr) => {
Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false)) Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false))
) };
} }
macro_rules! try_eval_session { macro_rules! try_eval_session {
($e:expr) => ( ($e:expr) => {
match $e { match $e {
Ok(result) => result, Ok(result) => result,
Err(e) => return EvalSession::from(e) Err(e) => return EvalSession::from(e),
} }
) };
} }
macro_rules! return_from_clause { macro_rules! return_from_clause {
($lco:expr, $machine_st:expr) => {{ ($lco:expr, $machine_st:expr) => {{
@@ -201,19 +212,19 @@ macro_rules! return_from_clause {
} }
Ok(()) Ok(())
}} }};
} }
macro_rules! dir_entry { macro_rules! dir_entry {
($idx:expr) => ( ($idx:expr) => {
CodePtr::Local(LocalCodePtr::DirEntry($idx)) CodePtr::Local(LocalCodePtr::DirEntry($idx))
) };
} }
macro_rules! in_situ_dir_entry { macro_rules! in_situ_dir_entry {
($idx:expr) => ( ($idx:expr) => {
CodePtr::Local(LocalCodePtr::InSituDirEntry($idx)) CodePtr::Local(LocalCodePtr::InSituDirEntry($idx))
) };
} }
macro_rules! set_code_index { macro_rules! set_code_index {
@@ -222,64 +233,69 @@ macro_rules! set_code_index {
idx.0 = $ip; idx.0 = $ip;
idx.1 = $mod_name.clone(); idx.1 = $mod_name.clone();
}} }};
} }
macro_rules! index_store { macro_rules! index_store {
($atom_tbl:expr, $code_dir:expr, $op_dir:expr, $modules:expr) => ( ($atom_tbl:expr, $code_dir:expr, $op_dir:expr, $modules:expr) => {
IndexStore { atom_tbl: $atom_tbl, IndexStore {
atom_tbl: $atom_tbl,
code_dir: $code_dir, code_dir: $code_dir,
dynamic_code_dir: DynamicCodeDir::new(), dynamic_code_dir: DynamicCodeDir::new(),
global_variables: GlobalVarDir::new(), global_variables: GlobalVarDir::new(),
in_situ_code_dir: InSituCodeDir::new(), in_situ_code_dir: InSituCodeDir::new(),
op_dir: $op_dir, op_dir: $op_dir,
modules: $modules } modules: $modules,
) }
};
} }
macro_rules! default_index_store { macro_rules! default_index_store {
($atom_tbl:expr) => ( ($atom_tbl:expr) => {
index_store!($atom_tbl, CodeDir::new(), default_op_dir(), IndexMap::new()) index_store!($atom_tbl, CodeDir::new(), default_op_dir(), IndexMap::new())
) };
} }
macro_rules! put_constant { macro_rules! put_constant {
($lvl:expr, $cons:expr, $r:expr) => ( ($lvl:expr, $cons:expr, $r:expr) => {
QueryInstruction::PutConstant($lvl, $cons, $r) QueryInstruction::PutConstant($lvl, $cons, $r)
) };
} }
macro_rules! top_level_code_ptr { macro_rules! top_level_code_ptr {
($p:expr, $q_sz:expr) => ( ($p:expr, $q_sz:expr) => {
CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz)) CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz))
) };
} }
macro_rules! get_level_and_unify { macro_rules! get_level_and_unify {
($r: expr) => ( ($r: expr) => {
Line::Cut(CutInstruction::GetLevelAndUnify($r)) Line::Cut(CutInstruction::GetLevelAndUnify($r))
) };
} }
macro_rules! unwind_protect { macro_rules! unwind_protect {
($e: expr, $protected: expr) => ( ($e: expr, $protected: expr) => {
match $e { match $e {
Err(e) => { $protected; return Err(e); }, Err(e) => {
$protected;
return Err(e);
}
_ => {} _ => {}
} }
) };
} }
macro_rules! discard_result { macro_rules! discard_result {
($f: expr) => ( ($f: expr) => {
match $f { match $f {
_ => () _ => (),
} }
) };
} }
macro_rules! ar_reg { macro_rules! ar_reg {
($r: expr) => ( ($r: expr) => {
ArithmeticTerm::Reg($r) ArithmeticTerm::Reg($r)
) };
} }

View File

@@ -3,20 +3,22 @@ extern crate ordered_float;
extern crate prolog_parser; extern crate prolog_parser;
extern crate rug; extern crate rug;
#[macro_use] mod macros; #[macro_use]
pub mod instructions; mod macros;
mod clause_types; mod clause_types;
#[macro_use] mod allocator; pub mod instructions;
mod fixtures; #[macro_use]
pub mod machine; mod allocator;
mod forms;
mod arithmetic; mod arithmetic;
mod codegen; mod codegen;
mod debray_allocator; mod debray_allocator;
mod fixtures;
mod forms;
mod heap_iter; mod heap_iter;
mod indexing;
pub mod write;
mod iterators;
pub mod heap_print; pub mod heap_print;
mod targets; mod indexing;
mod iterators;
pub mod machine;
pub mod read; pub mod read;
mod targets;
pub mod write;

View File

@@ -26,8 +26,7 @@ impl<'a> TermRef<'a> {
pub type PrologStream = ParsingStream<Box<Read>>; pub type PrologStream = ParsingStream<Box<Read>>;
#[cfg(feature = "readline_rs_compat")] #[cfg(feature = "readline_rs_compat")]
pub mod readline pub mod readline {
{
use prolog_parser::ast::*; use prolog_parser::ast::*;
use readline_rs_compat::readline::*; use readline_rs_compat::readline::*;
use std::io::{Error, Read}; use std::io::{Error, Read};
@@ -35,11 +34,11 @@ pub mod readline
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum LineMode { pub enum LineMode {
Single, Single,
Multi Multi,
} }
pub struct ReadlineStream { pub struct ReadlineStream {
pending_input: String pending_input: String,
} }
impl ReadlineStream { impl ReadlineStream {
@@ -53,8 +52,8 @@ pub mod readline
Some(text) => { Some(text) => {
self.pending_input += &text; self.pending_input += &text;
Ok(self.write_to_buf(buf)) Ok(self.write_to_buf(buf))
}, }
None => Err(Error::last_os_error()) None => Err(Error::last_os_error()),
} }
} }
@@ -144,13 +143,12 @@ pub mod readline
} }
#[cfg(not(feature = "readline_rs_compat"))] #[cfg(not(feature = "readline_rs_compat"))]
pub mod readline pub mod readline {
{
use prolog_parser::ast::*; use prolog_parser::ast::*;
use std::io::{BufReader, Read, Stdin, stdin}; use std::io::{stdin, BufReader, Read, Stdin};
struct StdinWrapper { struct StdinWrapper {
buf: BufReader<Stdin> buf: BufReader<Stdin>,
} }
impl Read for StdinWrapper { impl Read for StdinWrapper {
@@ -161,15 +159,20 @@ pub mod readline
#[inline] #[inline]
pub fn input_stream() -> ::PrologStream { pub fn input_stream() -> ::PrologStream {
let reader: Box<Read> = Box::new(StdinWrapper { buf: BufReader::new(stdin()) }); let reader: Box<Read> = Box::new(StdinWrapper {
buf: BufReader::new(stdin()),
});
parsing_stream(reader) parsing_stream(reader)
} }
} }
impl MachineState { impl MachineState {
pub fn read(&mut self, inner: &mut PrologStream, atom_tbl: TabledData<Atom>, op_dir: &OpDir) pub fn read(
-> Result<TermWriteResult, ParserError> &mut self,
{ inner: &mut PrologStream,
atom_tbl: TabledData<Atom>,
op_dir: &OpDir,
) -> Result<TermWriteResult, ParserError> {
let mut parser = Parser::new(inner, atom_tbl, self.flags); let mut parser = Parser::new(inner, atom_tbl, self.flags);
let term = parser.read_term(composite_op!(op_dir))?; let term = parser.read_term(composite_op!(op_dir))?;
@@ -182,8 +185,12 @@ fn push_stub_addr(machine_st: &mut MachineState) {
machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
} }
fn modify_head_of_queue(machine_st: &mut MachineState, queue: &mut SubtermDeque, term: TermRef, h: usize) fn modify_head_of_queue(
{ machine_st: &mut MachineState,
queue: &mut SubtermDeque,
term: TermRef,
h: usize,
) {
if let Some((arity, site_h)) = queue.pop_front() { if let Some((arity, site_h)) = queue.pop_front() {
machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h)); machine_st.heap[site_h] = HeapCellValue::Addr(term.as_addr(h));
@@ -198,9 +205,7 @@ pub struct TermWriteResult {
pub(crate) var_dict: HeapVarDict, pub(crate) var_dict: HeapVarDict,
} }
pub(crate) pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult
{
let heap_loc = machine_st.heap.h; let heap_loc = machine_st.heap.h;
let mut queue = SubtermDeque::new(); let mut queue = SubtermDeque::new();
@@ -220,7 +225,7 @@ fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteRe
if let Level::Root = lvl { if let Level::Root = lvl {
continue; continue;
} }
}, }
&TermRef::Clause(lvl, _, ref ct, subterms) => { &TermRef::Clause(lvl, _, ref ct, subterms) => {
queue.push_back((subterms.len(), h + 1)); queue.push_back((subterms.len(), h + 1));
let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec()); let named = HeapCellValue::NamedStr(subterms.len(), ct.name(), ct.spec());
@@ -234,11 +239,13 @@ fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteRe
if let Level::Root = lvl { if let Level::Root = lvl {
continue; continue;
} }
}, }
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h))), machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
&TermRef::Var(Level::Root, ..) => }
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h))), &TermRef::Var(Level::Root, ..) => {
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
}
&TermRef::AnonVar(_) => { &TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = queue.pop_front() { if let Some((arity, site_h)) = queue.pop_front() {
if arity > 1 { if arity > 1 {
@@ -247,7 +254,7 @@ fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteRe
} }
continue; continue;
}, }
&TermRef::Var(_, _, ref var) => { &TermRef::Var(_, _, ref var) => {
if let Some((arity, site_h)) = queue.pop_front() { if let Some((arity, site_h)) = queue.pop_front() {
if let Some(addr) = var_dict.get(var).cloned() { if let Some(addr) = var_dict.get(var).cloned() {
@@ -262,7 +269,7 @@ fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteRe
} }
continue; continue;
}, }
_ => {} _ => {}
}; };

View File

@@ -43,8 +43,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
FactInstruction::GetConstant(lvl, constant, reg) FactInstruction::GetConstant(lvl, constant, reg)
} }
fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self {
{
FactInstruction::GetStructure(ct, arity, reg) FactInstruction::GetStructure(ct, arity, reg)
} }
@@ -59,7 +58,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
fn is_void_instr(&self) -> bool { fn is_void_instr(&self) -> bool {
match self { match self {
&FactInstruction::UnifyVoid(_) => true, &FactInstruction::UnifyVoid(_) => true,
_ => false _ => false,
} }
} }
@@ -125,7 +124,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
fn is_void_instr(&self) -> bool { fn is_void_instr(&self) -> bool {
match self { match self {
&QueryInstruction::SetVoid(_) => true, &QueryInstruction::SetVoid(_) => true,
_ => false _ => false,
} }
} }

View File

@@ -4,25 +4,24 @@ use prolog::instructions::*;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*; use prolog::machine::machine_indices::*;
use termion::input::TermRead;
use termion::event::Key; use termion::event::Key;
use termion::input::TermRead;
use std::io::stdin;
use std::fmt; use std::fmt;
use std::io::stdin;
impl fmt::Display for LocalCodePtr { impl fmt::Display for LocalCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
write!(f, "LocalCodePtr::DirEntry({})", p), LocalCodePtr::InSituDirEntry(p) => write!(f, "LocalCodePtr::InSituDirEntry({})", p),
LocalCodePtr::InSituDirEntry(p) => LocalCodePtr::TopLevel(cn, p) => write!(f, "LocalCodePtr::TopLevel({}, {})", cn, p),
write!(f, "LocalCodePtr::InSituDirEntry({})", p), LocalCodePtr::UserGoalExpansion(p) => {
LocalCodePtr::TopLevel(cn, p) => write!(f, "LocalCodePtr::UserGoalExpansion({})", p)
write!(f, "LocalCodePtr::TopLevel({}, {})", cn, p), }
LocalCodePtr::UserGoalExpansion(p) => LocalCodePtr::UserTermExpansion(p) => {
write!(f, "LocalCodePtr::UserGoalExpansion({})", p), write!(f, "LocalCodePtr::UserTermExpansion({})", p)
LocalCodePtr::UserTermExpansion(p) => }
write!(f, "LocalCodePtr::UserTermExpansion({})", p),
} }
} }
} }
@@ -30,21 +29,19 @@ impl fmt::Display for LocalCodePtr {
impl fmt::Display for REPLCodePtr { impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
REPLCodePtr::CompileBatch => REPLCodePtr::CompileBatch => write!(f, "REPLCodePtr::CompileBatch"),
write!(f, "REPLCodePtr::CompileBatch"), REPLCodePtr::SubmitQueryAndPrintResults => {
REPLCodePtr::SubmitQueryAndPrintResults =>
write!(f, "REPLCodePtr::SubmitQueryAndPrintResults") write!(f, "REPLCodePtr::SubmitQueryAndPrintResults")
} }
} }
} }
}
impl fmt::Display for IndexPtr { impl fmt::Display for IndexPtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&IndexPtr::Undefined => &IndexPtr::Undefined => write!(f, "undefined"),
write!(f, "undefined"), &IndexPtr::Index(i) => write!(f, "{}", i),
&IndexPtr::Index(i) =>
write!(f, "{}", i)
} }
} }
} }
@@ -52,26 +49,24 @@ impl fmt::Display for IndexPtr {
impl fmt::Display for FactInstruction { impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&FactInstruction::GetConstant(lvl, ref constant, ref r) => &FactInstruction::GetConstant(lvl, ref constant, ref r) => {
write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num()), write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num())
&FactInstruction::GetList(lvl, ref r) => }
write!(f, "get_list {}{}", 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) => &FactInstruction::GetStructure(ref ct, ref arity, ref r) => {
write!(f, "get_structure {}/{}, {}", ct.name(), arity, r), write!(f, "get_structure {}/{}, {}", ct.name(), arity, r)
&FactInstruction::GetValue(ref x, ref a) => }
write!(f, "get_value {}, A{}", x, a), &FactInstruction::GetValue(ref x, ref a) => write!(f, "get_value {}, A{}", x, a),
&FactInstruction::GetVariable(ref x, ref a) => &FactInstruction::GetVariable(ref x, ref a) => {
write!(f, "fact:get_variable {}, A{}", x, a), write!(f, "fact:get_variable {}, A{}", x, a)
&FactInstruction::UnifyConstant(ref constant) => }
write!(f, "unify_constant {}", constant), &FactInstruction::UnifyConstant(ref constant) => {
&FactInstruction::UnifyVariable(ref r) => write!(f, "unify_constant {}", constant)
write!(f, "unify_variable {}", r), }
&FactInstruction::UnifyLocalValue(ref r) => &FactInstruction::UnifyVariable(ref r) => write!(f, "unify_variable {}", r),
write!(f, "unify_local_value {}", r), &FactInstruction::UnifyLocalValue(ref r) => write!(f, "unify_local_value {}", r),
&FactInstruction::UnifyValue(ref r) => &FactInstruction::UnifyValue(ref r) => write!(f, "unify_value {}", r),
write!(f, "unify_value {}", r), &FactInstruction::UnifyVoid(n) => write!(f, "unify_void {}", n),
&FactInstruction::UnifyVoid(n) =>
write!(f, "unify_void {}", n)
} }
} }
} }
@@ -79,30 +74,24 @@ impl fmt::Display for FactInstruction {
impl fmt::Display for QueryInstruction { impl fmt::Display for QueryInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&QueryInstruction::GetVariable(ref x, ref a) => &QueryInstruction::GetVariable(ref x, ref a) => {
write!(f, "query:get_variable {}, A{}", x, a), write!(f, "query:get_variable {}, A{}", x, a)
&QueryInstruction::PutConstant(lvl, ref constant, ref r) => }
write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num()), &QueryInstruction::PutConstant(lvl, ref constant, ref r) => {
&QueryInstruction::PutList(lvl, ref r) => write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num())
write!(f, "put_list {}{}", lvl, r.reg_num()), }
&QueryInstruction::PutStructure(ref ct, ref arity, ref r) => &QueryInstruction::PutList(lvl, ref r) => write!(f, "put_list {}{}", lvl, r.reg_num()),
write!(f, "put_structure {}/{}, {}", ct.name(), arity, r), &QueryInstruction::PutStructure(ref ct, ref arity, ref r) => {
&QueryInstruction::PutUnsafeValue(y, a) => write!(f, "put_structure {}/{}, {}", ct.name(), arity, r)
write!(f, "put_unsafe_value Y{}, A{}", y, a), }
&QueryInstruction::PutValue(ref x, ref a) => &QueryInstruction::PutUnsafeValue(y, a) => write!(f, "put_unsafe_value Y{}, A{}", y, a),
write!(f, "put_value {}, A{}", x, a), &QueryInstruction::PutValue(ref x, ref a) => write!(f, "put_value {}, A{}", x, a),
&QueryInstruction::PutVariable(ref x, ref a) => &QueryInstruction::PutVariable(ref x, ref a) => write!(f, "put_variable {}, A{}", x, a),
write!(f, "put_variable {}, A{}", x, a), &QueryInstruction::SetConstant(ref constant) => write!(f, "set_constant {}", constant),
&QueryInstruction::SetConstant(ref constant) => &QueryInstruction::SetLocalValue(ref r) => write!(f, "set_local_value {}", r),
write!(f, "set_constant {}", constant), &QueryInstruction::SetVariable(ref r) => write!(f, "set_variable {}", r),
&QueryInstruction::SetLocalValue(ref r) => &QueryInstruction::SetValue(ref r) => write!(f, "set_value {}", r),
write!(f, "set_local_value {}", r), &QueryInstruction::SetVoid(n) => write!(f, "set_void {}", n),
&QueryInstruction::SetVariable(ref r) =>
write!(f, "set_variable {}", r),
&QueryInstruction::SetValue(ref r) =>
write!(f, "set_value {}", r),
&QueryInstruction::SetVoid(n) =>
write!(f, "set_void {}", n)
} }
} }
} }
@@ -134,15 +123,12 @@ impl fmt::Display for CompareTermQT {
impl fmt::Display for ClauseType { impl fmt::Display for ClauseType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&ClauseType::System(SystemClauseType::SetCutPoint(r)) => &ClauseType::System(SystemClauseType::SetCutPoint(r)) => write!(f, "$set_cp({})", r),
write!(f, "$set_cp({})", r), &ClauseType::Named(ref name, _, ref idx) | &ClauseType::Op(ref name, _, ref idx) => {
&ClauseType::Named(ref name, _, ref idx)
| &ClauseType::Op(ref name, _, ref idx) =>
{
let idx = idx.0.borrow(); let idx = idx.0.borrow();
write!(f, "{}:{}/{}", idx.1, name, idx.0) write!(f, "{}:{}/{}", idx.1, name, idx.0)
}, }
ref ct => write!(f, "{}", ct.name()) ref ct => write!(f, "{}", ct.name()),
} }
} }
} }
@@ -150,23 +136,29 @@ impl fmt::Display for ClauseType {
impl fmt::Display for HeapCellValue { impl fmt::Display for HeapCellValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&HeapCellValue::Addr(ref addr) => &HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
write!(f, "{}", addr), &HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => f,
write!(f, "{}/{} (op, priority: {}, spec: {})", name.as_str(), arity, "{}/{} (op, priority: {}, spec: {})",
cell.prec(), cell.assoc()), name.as_str(),
&HeapCellValue::NamedStr(arity, ref name, None) => arity,
cell.prec(),
cell.assoc()
),
&HeapCellValue::NamedStr(arity, ref name, None) => {
write!(f, "{}/{}", name.as_str(), arity) write!(f, "{}/{}", name.as_str(), arity)
} }
} }
} }
}
impl fmt::Display for DBRef { impl fmt::Display for DBRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity), &DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity),
&DBRef::Op(priority, spec, ref name, ..) => write!(f, "db_ref:op({}, {}, {})", priority, &DBRef::Op(priority, spec, ref name, ..) => {
spec, name) write!(f, "db_ref:op({}, {}, {})", priority, spec, name)
}
} }
} }
} }
@@ -180,7 +172,7 @@ impl fmt::Display for Addr {
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h), &Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h), &Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc), &Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
&Addr::Str(s) => write!(f, "Addr::Str({})", s) &Addr::Str(s) => write!(f, "Addr::Str({})", s),
} }
} }
} }
@@ -188,24 +180,27 @@ impl fmt::Display for Addr {
impl fmt::Display for ControlInstruction { impl fmt::Display for ControlInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&ControlInstruction::Allocate(num_cells) => &ControlInstruction::Allocate(num_cells) => write!(f, "allocate {}", num_cells),
write!(f, "allocate {}", num_cells), &ControlInstruction::CallClause(ref ct, arity, pvs, true, true) => {
&ControlInstruction::CallClause(ref ct, arity, pvs, true, true) => write!(f, "call_with_default_policy {}/{}, {}", ct, arity, pvs)
write!(f, "call_with_default_policy {}/{}, {}", ct, arity, pvs), }
&ControlInstruction::CallClause(ref ct, arity, pvs, false, true) => &ControlInstruction::CallClause(ref ct, arity, pvs, false, true) => {
write!(f, "execute_with_default_policy {}/{}, {}", ct, arity, pvs), write!(f, "execute_with_default_policy {}/{}, {}", ct, arity, pvs)
&ControlInstruction::CallClause(ref ct, arity, pvs, true, false) => }
write!(f, "execute {}/{}, {}", ct, arity, pvs), &ControlInstruction::CallClause(ref ct, arity, pvs, true, false) => {
&ControlInstruction::CallClause(ref ct, arity, pvs, false, false) => write!(f, "execute {}/{}, {}", ct, arity, pvs)
write!(f, "call {}/{}, {}", ct, arity, pvs), }
&ControlInstruction::Deallocate => &ControlInstruction::CallClause(ref ct, arity, pvs, false, false) => {
write!(f, "deallocate"), write!(f, "call {}/{}, {}", ct, arity, pvs)
&ControlInstruction::JmpBy(arity, offset, pvs, false) => }
write!(f, "jmp_by_call {}/{}, {}", offset, arity, pvs), &ControlInstruction::Deallocate => write!(f, "deallocate"),
&ControlInstruction::JmpBy(arity, offset, pvs, true) => &ControlInstruction::JmpBy(arity, offset, pvs, false) => {
write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs), write!(f, "jmp_by_call {}/{}, {}", offset, arity, pvs)
&ControlInstruction::Proceed => }
write!(f, "proceed"), &ControlInstruction::JmpBy(arity, offset, pvs, true) => {
write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs)
}
&ControlInstruction::Proceed => write!(f, "proceed"),
} }
} }
} }
@@ -213,12 +208,9 @@ impl fmt::Display for ControlInstruction {
impl fmt::Display for IndexedChoiceInstruction { impl fmt::Display for IndexedChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&IndexedChoiceInstruction::Try(offset) => &IndexedChoiceInstruction::Try(offset) => write!(f, "try {}", offset),
write!(f, "try {}", offset), &IndexedChoiceInstruction::Retry(offset) => write!(f, "retry {}", offset),
&IndexedChoiceInstruction::Retry(offset) => &IndexedChoiceInstruction::Trust(offset) => write!(f, "trust {}", offset),
write!(f, "retry {}", offset),
&IndexedChoiceInstruction::Trust(offset) =>
write!(f, "trust {}", offset)
} }
} }
} }
@@ -226,16 +218,13 @@ impl fmt::Display for IndexedChoiceInstruction {
impl fmt::Display for ChoiceInstruction { impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&ChoiceInstruction::TryMeElse(offset) => &ChoiceInstruction::TryMeElse(offset) => write!(f, "try_me_else {}", offset),
write!(f, "try_me_else {}", offset), &ChoiceInstruction::DefaultRetryMeElse(offset) => {
&ChoiceInstruction::DefaultRetryMeElse(offset) => write!(f, "retry_me_else_by_default {}", offset)
write!(f, "retry_me_else_by_default {}", offset), }
&ChoiceInstruction::RetryMeElse(offset) => &ChoiceInstruction::RetryMeElse(offset) => write!(f, "retry_me_else {}", offset),
write!(f, "retry_me_else {}", offset), &ChoiceInstruction::DefaultTrustMe => write!(f, "trust_me_by_default"),
&ChoiceInstruction::DefaultTrustMe => &ChoiceInstruction::TrustMe => write!(f, "trust_me"),
write!(f, "trust_me_by_default"),
&ChoiceInstruction::TrustMe =>
write!(f, "trust_me")
} }
} }
} }
@@ -243,38 +232,44 @@ impl fmt::Display for ChoiceInstruction {
impl fmt::Display for IndexingInstruction { impl fmt::Display for IndexingInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => &IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s), write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s)
&IndexingInstruction::SwitchOnConstant(num_cs, _) => }
write!(f, "switch_on_constant {}", num_cs), &IndexingInstruction::SwitchOnConstant(num_cs, _) => {
&IndexingInstruction::SwitchOnStructure(num_ss, _) => write!(f, "switch_on_constant {}", num_cs)
}
&IndexingInstruction::SwitchOnStructure(num_ss, _) => {
write!(f, "switch_on_structure {}", num_ss) write!(f, "switch_on_structure {}", num_ss)
} }
} }
} }
}
impl fmt::Display for SessionError { impl fmt::Display for SessionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&SessionError::CannotOverwriteBuiltIn(ref msg) => &SessionError::CannotOverwriteBuiltIn(ref msg) => write!(f, "cannot overwrite {}", msg),
write!(f, "cannot overwrite {}", msg), &SessionError::CannotOverwriteImport(ref msg) => {
&SessionError::CannotOverwriteImport(ref msg) => write!(f, "cannot overwrite import {}", msg)
write!(f, "cannot overwrite import {}", msg), }
&SessionError::InvalidFileName(ref filename) => &SessionError::InvalidFileName(ref filename) => {
write!(f, "filename {} is invalid", filename), write!(f, "filename {} is invalid", filename)
}
&SessionError::ModuleNotFound => write!(f, "module not found."), &SessionError::ModuleNotFound => write!(f, "module not found."),
&SessionError::ModuleDoesNotContainExport => &SessionError::ModuleDoesNotContainExport => {
write!(f, "module does not contain claimed export."), write!(f, "module does not contain claimed export.")
&SessionError::NoModuleDeclaration(ref name) => }
write!(f, "file {}.pl lacks an expected module declaration.", name), &SessionError::NoModuleDeclaration(ref name) => {
&SessionError::OpIsInfixAndPostFix(_) => write!(f, "file {}.pl lacks an expected module declaration.", name)
write!(f, "cannot define an op to be both postfix and infix."), }
&SessionError::NamelessEntry => &SessionError::OpIsInfixAndPostFix(_) => {
write!(f, "the predicate head is not an atom or clause."), write!(f, "cannot define an op to be both postfix and infix.")
&SessionError::ParserError(ref e) => }
write!(f, "syntax_error({})", e.as_str()), &SessionError::NamelessEntry => {
&SessionError::UserPrompt => write!(f, "the predicate head is not an atom or clause.")
write!(f, "enter predicate at [user] prompt") }
&SessionError::ParserError(ref e) => write!(f, "syntax_error({})", e.as_str()),
&SessionError::UserPrompt => write!(f, "enter predicate at [user] prompt"),
} }
} }
} }
@@ -284,7 +279,7 @@ impl fmt::Display for Number {
match self { match self {
&Number::Float(fl) => write!(f, "{}", fl), &Number::Float(fl) => write!(f, "{}", fl),
&Number::Integer(ref bi) => write!(f, "{}", bi), &Number::Integer(ref bi) => write!(f, "{}", bi),
&Number::Rational(ref r) => write!(f, "{}", r) &Number::Rational(ref r) => write!(f, "{}", r),
} }
} }
} }
@@ -302,80 +297,83 @@ impl fmt::Display for ArithmeticTerm {
impl fmt::Display for ArithmeticInstruction { impl fmt::Display for ArithmeticInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&ArithmeticInstruction::Abs(ref a1, ref t) => &ArithmeticInstruction::Abs(ref a1, ref t) => write!(f, "abs {}, @{}", a1, t),
write!(f, "abs {}, @{}", a1, t), &ArithmeticInstruction::Add(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Add(ref a1, ref a2, ref t) => write!(f, "add {}, {}, @{}", a1, a2, t)
write!(f, "add {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::Sub(ref a1, ref a2, ref t) => &ArithmeticInstruction::Sub(ref a1, ref a2, ref t) => {
write!(f, "sub {}, {}, @{}", a1, a2, t), write!(f, "sub {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Mul(ref a1, ref a2, ref t) => }
write!(f, "mul {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::Mul(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Pow(ref a1, ref a2, ref t) => write!(f, "mul {}, {}, @{}", a1, a2, t)
write!(f, "** {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::IntPow(ref a1, ref a2, ref t) => &ArithmeticInstruction::Pow(ref a1, ref a2, ref t) => {
write!(f, "^ {}, {}, @{}", a1, a2, t), write!(f, "** {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Div(ref a1, ref a2, ref t) => }
write!(f, "div {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::IntPow(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::IDiv(ref a1, ref a2, ref t) => write!(f, "^ {}, {}, @{}", a1, a2, t)
write!(f, "idiv {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::Max(ref a1, ref a2, ref t) => &ArithmeticInstruction::Div(ref a1, ref a2, ref t) => {
write!(f, "max {}, {}, @{}", a1, a2, t), write!(f, "div {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Min(ref a1, ref a2, ref t) => }
write!(f, "min {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::IDiv(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::IntFloorDiv(ref a1, ref a2, ref t) => write!(f, "idiv {}, {}, @{}", a1, a2, t)
write!(f, "int_floor_div {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::RDiv(ref a1, ref a2, ref t) => &ArithmeticInstruction::Max(ref a1, ref a2, ref t) => {
write!(f, "rdiv {}, {}, @{}", a1, a2, t), write!(f, "max {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Shl(ref a1, ref a2, ref t) => }
write!(f, "shl {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::Min(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Shr(ref a1, ref a2, ref t) => write!(f, "min {}, {}, @{}", a1, a2, t)
write!(f, "shr {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::Xor(ref a1, ref a2, ref t) => &ArithmeticInstruction::IntFloorDiv(ref a1, ref a2, ref t) => {
write!(f, "xor {}, {}, @{}", a1, a2, t), write!(f, "int_floor_div {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::And(ref a1, ref a2, ref t) => }
write!(f, "and {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::RDiv(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Or(ref a1, ref a2, ref t) => write!(f, "rdiv {}, {}, @{}", a1, a2, t)
write!(f, "or {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::Mod(ref a1, ref a2, ref t) => &ArithmeticInstruction::Shl(ref a1, ref a2, ref t) => {
write!(f, "mod {}, {}, @{}", a1, a2, t), write!(f, "shl {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Rem(ref a1, ref a2, ref t) => }
write!(f, "rem {}, {}, @{}", a1, a2, t), &ArithmeticInstruction::Shr(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::ATan2(ref a1, ref a2, ref t) => write!(f, "shr {}, {}, @{}", a1, a2, t)
write!(f, "atan2 {}, {}, @{}", a1, a2, t), }
&ArithmeticInstruction::Plus(ref a, ref t) => &ArithmeticInstruction::Xor(ref a1, ref a2, ref t) => {
write!(f, "plus {}, @{}", a, t), write!(f, "xor {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Neg(ref a, ref t) => }
write!(f, "neg {}, @{}", a, t), &ArithmeticInstruction::And(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Cos(ref a, ref t) => write!(f, "and {}, {}, @{}", a1, a2, t)
write!(f, "cos {}, @{}", a, t), }
&ArithmeticInstruction::Sin(ref a, ref t) => &ArithmeticInstruction::Or(ref a1, ref a2, ref t) => {
write!(f, "sin {}, @{}", a, t), write!(f, "or {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::Tan(ref a, ref t) => }
write!(f, "tan {}, @{}", a, t), &ArithmeticInstruction::Mod(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::ATan(ref a, ref t) => write!(f, "mod {}, {}, @{}", a1, a2, t)
write!(f, "atan {}, @{}", a, t), }
&ArithmeticInstruction::ASin(ref a, ref t) => &ArithmeticInstruction::Rem(ref a1, ref a2, ref t) => {
write!(f, "asin {}, @{}", a, t), write!(f, "rem {}, {}, @{}", a1, a2, t)
&ArithmeticInstruction::ACos(ref a, ref t) => }
write!(f, "acos {}, @{}", a, t), &ArithmeticInstruction::ATan2(ref a1, ref a2, ref t) => {
&ArithmeticInstruction::Log(ref a, ref t) => write!(f, "atan2 {}, {}, @{}", a1, a2, t)
write!(f, "log {}, @{}", a, t), }
&ArithmeticInstruction::Exp(ref a, ref t) => &ArithmeticInstruction::Plus(ref a, ref t) => write!(f, "plus {}, @{}", a, t),
write!(f, "exp {}, @{}", a, t), &ArithmeticInstruction::Neg(ref a, ref t) => write!(f, "neg {}, @{}", a, t),
&ArithmeticInstruction::Sqrt(ref a, ref t) => &ArithmeticInstruction::Cos(ref a, ref t) => write!(f, "cos {}, @{}", a, t),
write!(f, "sqrt {}, @{}", a, t), &ArithmeticInstruction::Sin(ref a, ref t) => write!(f, "sin {}, @{}", a, t),
&ArithmeticInstruction::BitwiseComplement(ref a, ref t) => &ArithmeticInstruction::Tan(ref a, ref t) => write!(f, "tan {}, @{}", a, t),
write!(f, "bitwise_complement {}, @{}", a, t), &ArithmeticInstruction::ATan(ref a, ref t) => write!(f, "atan {}, @{}", a, t),
&ArithmeticInstruction::Truncate(ref a, ref t) => &ArithmeticInstruction::ASin(ref a, ref t) => write!(f, "asin {}, @{}", a, t),
write!(f, "truncate {}, @{}", a, t), &ArithmeticInstruction::ACos(ref a, ref t) => write!(f, "acos {}, @{}", a, t),
&ArithmeticInstruction::Round(ref a, ref t) => &ArithmeticInstruction::Log(ref a, ref t) => write!(f, "log {}, @{}", a, t),
write!(f, "round {}, @{}", a, t), &ArithmeticInstruction::Exp(ref a, ref t) => write!(f, "exp {}, @{}", a, t),
&ArithmeticInstruction::Ceiling(ref a, ref t) => &ArithmeticInstruction::Sqrt(ref a, ref t) => write!(f, "sqrt {}, @{}", a, t),
write!(f, "ceiling {}, @{}", a, t), &ArithmeticInstruction::BitwiseComplement(ref a, ref t) => {
&ArithmeticInstruction::Floor(ref a, ref t) => write!(f, "bitwise_complement {}, @{}", a, t)
write!(f, "floor {}, @{}", a, t), }
&ArithmeticInstruction::Float(ref a, ref t) => &ArithmeticInstruction::Truncate(ref a, ref t) => write!(f, "truncate {}, @{}", a, t),
write!(f, "float {}, @{}", a, t), &ArithmeticInstruction::Round(ref a, ref t) => write!(f, "round {}, @{}", a, t),
&ArithmeticInstruction::Ceiling(ref a, ref t) => write!(f, "ceiling {}, @{}", a, t),
&ArithmeticInstruction::Floor(ref a, ref t) => write!(f, "floor {}, @{}", a, t),
&ArithmeticInstruction::Float(ref a, ref t) => write!(f, "float {}, @{}", a, t),
} }
} }
} }
@@ -383,14 +381,10 @@ impl fmt::Display for ArithmeticInstruction {
impl fmt::Display for CutInstruction { impl fmt::Display for CutInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&CutInstruction::Cut(r) => &CutInstruction::Cut(r) => write!(f, "cut {}", r),
write!(f, "cut {}", r), &CutInstruction::NeckCut => write!(f, "neck_cut"),
&CutInstruction::NeckCut => &CutInstruction::GetLevel(r) => write!(f, "get_level {}", r),
write!(f, "neck_cut"), &CutInstruction::GetLevelAndUnify(r) => write!(f, "get_level_and_unify {}", r),
&CutInstruction::GetLevel(r) =>
write!(f, "get_level {}", r),
&CutInstruction::GetLevelAndUnify(r) =>
write!(f, "get_level_and_unify {}", r)
} }
} }
} }
@@ -399,27 +393,23 @@ impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
&Level::Root | &Level::Shallow => write!(f, "A"), &Level::Root | &Level::Shallow => write!(f, "A"),
&Level::Deep => write!(f, "X") &Level::Deep => write!(f, "X"),
} }
} }
} }
pub enum ContinueResult { pub enum ContinueResult {
ContinueQuery, ContinueQuery,
Conclude Conclude,
} }
pub pub fn next_keypress() -> ContinueResult {
fn next_keypress() -> ContinueResult
{
let stdin = stdin(); let stdin = stdin();
for c in stdin.keys() { for c in stdin.keys() {
match c.unwrap() { match c.unwrap() {
Key::Char(' ') | Key::Char(';') => Key::Char(' ') | Key::Char(';') => return ContinueResult::ContinueQuery,
return ContinueResult::ContinueQuery, Key::Char('.') => return ContinueResult::Conclude,
Key::Char('.') =>
return ContinueResult::Conclude,
_ => {} _ => {}
} }
} }

File diff suppressed because it is too large Load Diff