Format code using 'cargo fmt'
This commit is contained in:
12
src/main.rs
12
src/main.rs
@@ -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")] {
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,11 +110,11 @@ 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> {
|
||||||
type Iter : Iterator<Item=Result<ArithTermRef<'a>, ArithmeticError>>;
|
type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;
|
||||||
|
|
||||||
fn iter(self) -> Result<Self::Iter, ArithmeticError>;
|
fn iter(self) -> Result<Self::Iter, ArithmeticError>;
|
||||||
}
|
}
|
||||||
@@ -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,34 +160,43 @@ 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)),
|
||||||
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
"/" => Ok(ArithmeticInstruction::Div(a1, a2, t)),
|
||||||
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
"//" => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
|
||||||
"max" => Ok(ArithmeticInstruction::Max(a1, a2, t)),
|
"max" => Ok(ArithmeticInstruction::Max(a1, a2, t)),
|
||||||
"min" => Ok(ArithmeticInstruction::Min(a1, a2, t)),
|
"min" => Ok(ArithmeticInstruction::Min(a1, a2, t)),
|
||||||
"div" => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
|
"div" => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
|
||||||
"rdiv" => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
|
"rdiv" => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
|
||||||
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
"*" => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
|
||||||
"**" => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
|
"**" => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
|
||||||
"^" => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
|
"^" => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
|
||||||
">>" => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
|
">>" => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
|
||||||
"<<" => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
|
"<<" => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
|
||||||
"/\\" => Ok(ArithmeticInstruction::And(a1, a2, t)),
|
"/\\" => Ok(ArithmeticInstruction::And(a1, a2, t)),
|
||||||
"\\/" => Ok(ArithmeticInstruction::Or(a1, a2, t)),
|
"\\/" => Ok(ArithmeticInstruction::Or(a1, a2, t)),
|
||||||
"xor" => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
|
"xor" => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
|
||||||
"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 {
|
||||||
|
|||||||
@@ -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! {
|
||||||
@@ -137,10 +137,10 @@ impl InlinedClauseType {
|
|||||||
&InlinedClauseType::IsAtom(..) => "atom",
|
&InlinedClauseType::IsAtom(..) => "atom",
|
||||||
&InlinedClauseType::IsAtomic(..) => "atomic",
|
&InlinedClauseType::IsAtomic(..) => "atomic",
|
||||||
&InlinedClauseType::IsCompound(..) => "compound",
|
&InlinedClauseType::IsCompound(..) => "compound",
|
||||||
&InlinedClauseType::IsInteger (..) => "integer",
|
&InlinedClauseType::IsInteger(..) => "integer",
|
||||||
&InlinedClauseType::IsRational(..) => "rational",
|
&InlinedClauseType::IsRational(..) => "rational",
|
||||||
&InlinedClauseType::IsString(..) => "string",
|
&InlinedClauseType::IsString(..) => "string",
|
||||||
&InlinedClauseType::IsFloat (..) => "float",
|
&InlinedClauseType::IsFloat(..) => "float",
|
||||||
&InlinedClauseType::IsNonVar(..) => "nonvar",
|
&InlinedClauseType::IsNonVar(..) => "nonvar",
|
||||||
&InlinedClauseType::IsPartialString(..) => "is_partial_string",
|
&InlinedClauseType::IsPartialString(..) => "is_partial_string",
|
||||||
&InlinedClauseType::IsVar(..) => "var",
|
&InlinedClauseType::IsVar(..) => "var",
|
||||||
@@ -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"),
|
||||||
@@ -331,8 +348,8 @@ impl SystemClauseType {
|
|||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
||||||
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
("$atom_chars", 2) => Some(SystemClauseType::AtomChars),
|
||||||
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
("$atom_codes", 2) => Some(SystemClauseType::AtomCodes),
|
||||||
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
("$atom_length", 2) => Some(SystemClauseType::AtomLength),
|
||||||
("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
|
("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
|
||||||
("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
|
("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
|
||||||
@@ -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 {
|
||||||
@@ -462,8 +484,8 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
|
&BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
|
||||||
&BuiltInClauseType::Eq => clause_name!("=="),
|
&BuiltInClauseType::Eq => clause_name!("=="),
|
||||||
&BuiltInClauseType::Functor => clause_name!("functor"),
|
&BuiltInClauseType::Functor => clause_name!("functor"),
|
||||||
&BuiltInClauseType::Ground => clause_name!("ground"),
|
&BuiltInClauseType::Ground => clause_name!("ground"),
|
||||||
&BuiltInClauseType::Is(..) => clause_name!("is"),
|
&BuiltInClauseType::Is(..) => clause_name!("is"),
|
||||||
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
||||||
&BuiltInClauseType::Nl => clause_name!("nl"),
|
&BuiltInClauseType::Nl => clause_name!("nl"),
|
||||||
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
||||||
@@ -483,7 +505,7 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::CopyTerm => 2,
|
&BuiltInClauseType::CopyTerm => 2,
|
||||||
&BuiltInClauseType::Eq => 2,
|
&BuiltInClauseType::Eq => 2,
|
||||||
&BuiltInClauseType::Functor => 3,
|
&BuiltInClauseType::Functor => 3,
|
||||||
&BuiltInClauseType::Ground => 1,
|
&BuiltInClauseType::Ground => 1,
|
||||||
&BuiltInClauseType::Is(..) => 2,
|
&BuiltInClauseType::Is(..) => 2,
|
||||||
&BuiltInClauseType::KeySort => 2,
|
&BuiltInClauseType::KeySort => 2,
|
||||||
&BuiltInClauseType::NotEq => 2,
|
&BuiltInClauseType::NotEq => 2,
|
||||||
@@ -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())
|
||||||
}))
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +85,7 @@ impl<'a> ConjunctInfo<'a>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for index in index .. right_index + 1 {
|
for index in index..right_index + 1 {
|
||||||
if let &mut Line::Query(ref mut query_instr) = &mut code[index] {
|
if let &mut Line::Query(ref mut query_instr) = &mut code[index] {
|
||||||
unsafe_var_marker.mark_unsafe_vars(query_instr);
|
unsafe_var_marker.mark_unsafe_vars(query_instr);
|
||||||
}
|
}
|
||||||
@@ -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 {
|
||||||
var_count: IndexMap::new(),
|
marker: Allocator::new(),
|
||||||
non_counted_bt,
|
var_count: IndexMap::new(),
|
||||||
flags }
|
non_counted_bt,
|
||||||
|
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>(
|
||||||
subterm: &'a Term,
|
&mut self,
|
||||||
term_loc: GenContext,
|
subterm: &'a Term,
|
||||||
is_exposed: bool,
|
term_loc: GenContext,
|
||||||
target: &mut Vec<Target>)
|
is_exposed: bool,
|
||||||
where Target: CompilationTarget<'a>
|
target: &mut Vec<Target>,
|
||||||
|
) 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,18 +267,19 @@ 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(_) => {
|
||||||
GenContext::Mid(chunk_num)
|
if i < chunked_terms.len() - 1 {
|
||||||
} else {
|
GenContext::Mid(chunk_num)
|
||||||
GenContext::Last(chunk_num)
|
} else {
|
||||||
|
GenContext::Last(chunk_num)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -254,7 +289,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
|||||||
}
|
}
|
||||||
|
|
||||||
let num_of_chunks = iter.chunk_num;
|
let num_of_chunks = iter.chunk_num;
|
||||||
let has_deep_cut = iter.encountered_deep_cut();
|
let has_deep_cut = iter.encountered_deep_cut();
|
||||||
|
|
||||||
vs.populate_restricting_sets();
|
vs.populate_restricting_sets();
|
||||||
vs.set_perm_vals(has_deep_cut);
|
vs.set_perm_vals(has_deep_cut);
|
||||||
@@ -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(_))) => dealloc_index += 1,
|
||||||
Some(&mut Line::Cut(CutInstruction::Cut(_))) =>
|
|
||||||
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,153 +354,151 @@ 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!(
|
||||||
at_1.unwrap_or(interm!(1)),
|
cmp,
|
||||||
at_2.unwrap_or(interm!(2))));
|
at_1.unwrap_or(interm!(1)),
|
||||||
},
|
at_2.unwrap_or(interm!(2))
|
||||||
&InlinedClauseType::IsAtom(..) =>
|
));
|
||||||
match terms[0].as_ref() {
|
}
|
||||||
&Term::Constant(_, Constant::Char(_))
|
&InlinedClauseType::IsAtom(..) => match terms[0].as_ref() {
|
||||||
| &Term::Constant(_, Constant::EmptyList)
|
&Term::Constant(_, Constant::Char(_))
|
||||||
| &Term::Constant(_, Constant::Atom(..)) => {
|
| &Term::Constant(_, Constant::EmptyList)
|
||||||
code.push(succeed!());
|
| &Term::Constant(_, Constant::Atom(..)) => {
|
||||||
},
|
code.push(succeed!());
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_atom!(r));
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsAtomic(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
|
|
||||||
code.push(fail!());
|
|
||||||
},
|
|
||||||
&Term::Constant(..) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_atomic!(r));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsCompound(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Clause(..) | &Term::Cons(..) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_compound!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsRational(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::Rational(_)) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_rational!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsFloat(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::Float(_)) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_float!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsString(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::String(_)) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_string!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsNonVar(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::AnonVar => {
|
|
||||||
code.push(fail!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_nonvar!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(succeed!());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsInteger(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(_, Constant::CharCode(_))
|
|
||||||
| &Term::Constant(_, Constant::Integer(_)) => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_integer!(r));
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
code.push(fail!());
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsVar(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
|
|
||||||
code.push(fail!());
|
|
||||||
},
|
|
||||||
&Term::AnonVar => {
|
|
||||||
code.push(succeed!());
|
|
||||||
},
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_var!(r));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
&InlinedClauseType::IsPartialString(..) =>
|
|
||||||
match terms[0].as_ref() {
|
|
||||||
&Term::Var(ref vr, ref name) => {
|
|
||||||
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
|
||||||
code.push(is_partial_string!(r));
|
|
||||||
},
|
|
||||||
_ => code.push(fail!())
|
|
||||||
}
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_atom!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsAtomic(..) => match terms[0].as_ref() {
|
||||||
|
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
&Term::Constant(..) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_atomic!(r));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsCompound(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Clause(..) | &Term::Cons(..) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_compound!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsRational(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Constant(_, Constant::Rational(_)) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_rational!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsFloat(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Constant(_, Constant::Float(_)) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_float!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsString(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Constant(_, Constant::String(_)) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_string!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsNonVar(..) => match terms[0].as_ref() {
|
||||||
|
&Term::AnonVar => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_nonvar!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsInteger(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Constant(_, Constant::CharCode(_))
|
||||||
|
| &Term::Constant(_, Constant::Integer(_)) => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_integer!(r));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsVar(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
|
||||||
|
code.push(fail!());
|
||||||
|
}
|
||||||
|
&Term::AnonVar => {
|
||||||
|
code.push(succeed!());
|
||||||
|
}
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_var!(r));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
&InlinedClauseType::IsPartialString(..) => match terms[0].as_ref() {
|
||||||
|
&Term::Var(ref vr, ref name) => {
|
||||||
|
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
|
||||||
|
code.push(is_partial_string!(r));
|
||||||
|
}
|
||||||
|
_ => 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(
|
||||||
&QueryTerm::Clause(_, ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
|
_,
|
||||||
ref terms, use_default_call_policy)
|
ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
|
||||||
=> self.compile_is_call(terms, code, term_loc, use_default_call_policy)?,
|
ref terms,
|
||||||
&QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _)
|
use_default_call_policy,
|
||||||
=> self.compile_inlined(ct, terms, term_loc, code)?,
|
) => 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(®) {
|
if let Some(found) = unsafe_vars.get_mut(®) {
|
||||||
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(®) {
|
if let Some(found) = unsafe_vars.get_mut(®) {
|
||||||
*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,12 +770,17 @@ 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);
|
||||||
let query = self.compile_target(iter, term_loc, is_exposed);
|
let query = self.compile_target(iter, term_loc, is_exposed);
|
||||||
|
|
||||||
if !query.is_empty() {
|
if !query.is_empty() {
|
||||||
@@ -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,29 +854,28 @@ 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);
|
||||||
|
|
||||||
let num_clauses = clauses.len();
|
let num_clauses = clauses.len();
|
||||||
|
|
||||||
for (i, clause) in clauses.iter().enumerate() {
|
for (i, clause) in clauses.iter().enumerate() {
|
||||||
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,21 +895,22 @@ 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>,
|
||||||
let mut code = Vec::new();
|
) -> Result<Code, ParserError> {
|
||||||
|
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;
|
||||||
|
|
||||||
for (l, r) in split_pred {
|
for (l, r) in split_pred {
|
||||||
let mut code_segment = try!(self.compile_pred_subseq(&clauses[l .. r]));
|
let mut code_segment = try!(self.compile_pred_subseq(&clauses[l..r]));
|
||||||
|
|
||||||
if multi_seq {
|
if multi_seq {
|
||||||
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));
|
||||||
|
|||||||
@@ -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::*;
|
||||||
|
|
||||||
@@ -14,27 +14,25 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
pub struct DebrayAllocator {
|
pub struct DebrayAllocator {
|
||||||
bindings: IndexMap<Rc<Var>, VarData>,
|
bindings: IndexMap<Rc<Var>, VarData>,
|
||||||
arg_c: usize,
|
arg_c: usize,
|
||||||
temp_lb: usize,
|
temp_lb: usize,
|
||||||
arity: usize, // 0 if not at head.
|
arity: usize, // 0 if not at head.
|
||||||
contents: IndexMap<usize, Rc<Var>>,
|
contents: IndexMap<usize, Rc<Var>>,
|
||||||
in_use: BTreeSet<usize>,
|
in_use: BTreeSet<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebrayAllocator {
|
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() {
|
||||||
@@ -56,7 +53,7 @@ impl DebrayAllocator {
|
|||||||
|
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
|
|
||||||
for reg in self.temp_lb .. {
|
for reg in self.temp_lb.. {
|
||||||
if !self.is_in_use(reg) {
|
if !self.is_in_use(reg) {
|
||||||
if !tvd.no_use_set.contains(®) {
|
if !tvd.no_use_set.contains(®) {
|
||||||
result = reg;
|
result = reg;
|
||||||
@@ -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() {
|
||||||
@@ -83,7 +79,7 @@ impl DebrayAllocator {
|
|||||||
|
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
|
|
||||||
for reg in self.temp_lb .. {
|
for reg in self.temp_lb.. {
|
||||||
if !self.is_in_use(reg) {
|
if !self.is_in_use(reg) {
|
||||||
if !tvd.no_use_set.contains(®) {
|
if !tvd.no_use_set.contains(®) {
|
||||||
if !tvd.conflict_set.contains(®) {
|
if !tvd.conflict_set.contains(®) {
|
||||||
@@ -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,42 +140,47 @@ 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)
|
||||||
} else {
|
} else {
|
||||||
self.alloc_with_ca(var)
|
self.alloc_with_ca(var)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.. {
|
||||||
if !self.in_use.contains(&index) {
|
if !self.in_use.contains(&index) {
|
||||||
final_index = index;
|
final_index = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -190,33 +191,32 @@ 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,
|
||||||
arg_c: 1,
|
arg_c: 1,
|
||||||
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());
|
||||||
|
|
||||||
@@ -230,15 +230,20 @@ impl<'a> Allocator<'a> for DebrayAllocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.arg_c += 1;
|
self.arg_c += 1;
|
||||||
|
|
||||||
target.push(Target::argument_to_variable(r, k));
|
target.push(Target::argument_to_variable(r, k));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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,34 +268,47 @@ 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) => {
|
||||||
// here, r is temporary *and* unassigned.
|
// here, r is temporary *and* unassigned.
|
||||||
let o = self.alloc_reg_to_var(&var, lvl, term_loc, target);
|
let o = self.alloc_reg_to_var(&var, lvl, term_loc, target);
|
||||||
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() {
|
||||||
@@ -380,8 +398,8 @@ impl<'a> Allocator<'a> for DebrayAllocator
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reset_arg(&mut self, arity: usize) {
|
fn reset_arg(&mut self, arity: usize) {
|
||||||
self.arity = 0;
|
self.arity = 0;
|
||||||
self.arg_c = 1;
|
self.arg_c = 1;
|
||||||
self.temp_lb = arity + 1;
|
self.temp_lb = arity + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ impl TempVarData {
|
|||||||
pub fn populate_conflict_set(&mut self) {
|
pub fn populate_conflict_set(&mut self) {
|
||||||
if self.last_term_arity > 0 {
|
if self.last_term_arity > 0 {
|
||||||
let arity = self.last_term_arity;
|
let arity = self.last_term_arity;
|
||||||
let mut conflict_set : BTreeSet<usize> = (1..arity).collect();
|
let mut conflict_set: BTreeSet<usize> = (1..arity).collect();
|
||||||
|
|
||||||
for &(_, reg) in self.use_set.iter() {
|
for &(_, reg) in self.use_set.iter() {
|
||||||
conflict_set.remove(®);
|
conflict_set.remove(®);
|
||||||
@@ -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(®) {
|
if let Some(found) = self.unsafe_vars.get_mut(®) {
|
||||||
*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(®) {
|
if let Some(found) = self.unsafe_vars.get_mut(®) {
|
||||||
if !*found {
|
if !*found {
|
||||||
*found = true;
|
*found = true;
|
||||||
*query_instr = QueryInstruction::SetLocalValue(reg);
|
*query_instr = QueryInstruction::SetLocalValue(reg);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,43 +264,49 @@ 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 => {
|
|
||||||
if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
|
|
||||||
if spec.prec() > 0 {
|
|
||||||
return Some(spec.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
1 => {
|
||||||
|
if let Some(OpDirValue(spec, _)) = op_dir.get(&(name.clone(), Fixity::Pre)) {
|
||||||
|
if spec.prec() > 0 {
|
||||||
|
return Some(spec.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
op_dir.get(&(name.clone(), Fixity::Post))
|
op_dir
|
||||||
.and_then(|OpDirValue(spec, _)|
|
.get(&(name.clone(), Fixity::Post))
|
||||||
if spec.prec() > 0 {
|
.and_then(|OpDirValue(spec, _)| {
|
||||||
Some(spec.clone())
|
if spec.prec() > 0 {
|
||||||
} else {
|
Some(spec.clone())
|
||||||
None
|
} else {
|
||||||
})
|
None
|
||||||
},
|
}
|
||||||
_ => None
|
})
|
||||||
}
|
}
|
||||||
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +315,7 @@ 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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,59 +26,59 @@ 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() {
|
||||||
self.state_stack.push(Addr::HeapCell(h + idx));
|
self.state_stack.push(Addr::HeapCell(h + idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
@@ -117,16 +117,16 @@ impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item=HeapCellValue>> HCPostOrderIterator<HCIter> {
|
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![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HCIter: Iterator<Item=HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
|
impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
|
||||||
type Item = HeapCellValue;
|
type Item = HeapCellValue;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,23 +20,23 @@ 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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
_ => return false,
|
||||||
},
|
},
|
||||||
Addr::Con(Constant::Integer(n)) =>
|
Addr::Con(Constant::Integer(n)) => return property_check(Constant::Integer(n)),
|
||||||
return property_check(Constant::Integer(n)),
|
Addr::Con(Constant::Float(n)) => return property_check(Constant::Float(n)),
|
||||||
Addr::Con(Constant::Float(n)) =>
|
Addr::Con(Constant::Rational(n)) => return property_check(Constant::Rational(n)),
|
||||||
return property_check(Constant::Float(n)),
|
_ => return false,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,8 +147,8 @@ fn char_to_string(c: char) -> String {
|
|||||||
'\u{0c}' => "\\f".to_string(), // UTF-8 form feed
|
'\u{0c}' => "\\f".to_string(), // UTF-8 form feed
|
||||||
'\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,17 +252,15 @@ 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,26 +268,26 @@ 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;
|
||||||
let j = n.div_rem_floor(Integer::from(26));
|
let j = n.div_rem_floor(Integer::from(26));
|
||||||
let j = <(Integer, Integer)>::from(j).1;
|
let j = <(Integer, Integer)>::from(j).1;
|
||||||
|
|
||||||
Some(if j == 0 {
|
Some(if j == 0 {
|
||||||
CHAR_CODES[i].to_string()
|
CHAR_CODES[i].to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{}{}", CHAR_CODES[i], j)
|
format!("{}{}", CHAR_CODES[i], j)
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,80 +306,94 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
cyclic_terms: IndexMap<Addr, usize>,
|
cyclic_terms: IndexMap<Addr, usize>,
|
||||||
pub(crate) var_names: IndexMap<Addr, String>,
|
pub(crate) var_names: IndexMap<Addr, String>,
|
||||||
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
|
||||||
if ac == '0' {
|
.chars()
|
||||||
oc == 'b' || oc == 'x' || oc == 'o' || oc == '\''
|
.next()
|
||||||
} else if alpha_numeric_char!(ac) {
|
.map(|oc| {
|
||||||
oc == '(' || alpha_numeric_char!(oc)
|
if ac == '0' {
|
||||||
} else if graphic_token_char!(ac) {
|
oc == 'b' || oc == 'x' || oc == 'o' || oc == '\''
|
||||||
graphic_token_char!(oc)
|
} else if alpha_numeric_char!(ac) {
|
||||||
} else if variable_indicator_char!(ac) {
|
oc == '(' || alpha_numeric_char!(oc)
|
||||||
alpha_numeric_char!(oc)
|
} else if graphic_token_char!(ac) {
|
||||||
} else if capital_letter_char!(ac) {
|
graphic_token_char!(oc)
|
||||||
alpha_numeric_char!(oc)
|
} else if variable_indicator_char!(ac) {
|
||||||
} else if sign_char!(ac) {
|
alpha_numeric_char!(oc)
|
||||||
sign_char!(oc) || decimal_digit_char!(oc)
|
} else if capital_letter_char!(ac) {
|
||||||
} else if single_quote_char!(ac) {
|
alpha_numeric_char!(oc)
|
||||||
single_quote_char!(oc)
|
} else if sign_char!(ac) {
|
||||||
} else {
|
sign_char!(oc) || decimal_digit_char!(oc)
|
||||||
false
|
} else if single_quote_char!(ac) {
|
||||||
}
|
single_quote_char!(oc)
|
||||||
}).unwrap_or(false),
|
} else {
|
||||||
_ => 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 {
|
||||||
if c == '/' {
|
if c == '/' {
|
||||||
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) => {
|
||||||
iter.all(|c| graphic_token_char!(c))
|
if graphic_token_char!(c) {
|
||||||
} else {
|
iter.all(|c| graphic_token_char!(c))
|
||||||
false
|
} else {
|
||||||
|
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) => {
|
||||||
iter.all(|c| graphic_token_char!(c))
|
if graphic_token_char!(c) {
|
||||||
} else {
|
iter.all(|c| graphic_token_char!(c))
|
||||||
false
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
iter.all(|c| graphic_token_char!(c))
|
iter.all(|c| graphic_token_char!(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn non_quoted_token<Iter: Iterator<Item=char>>(mut iter: Iter) -> bool {
|
fn non_quoted_token<Iter: Iterator<Item = char>>(mut iter: Iter) -> bool {
|
||||||
if let Some(c) = iter.next() {
|
if let Some(c) = iter.next() {
|
||||||
if small_letter_char!(c) {
|
if small_letter_char!(c) {
|
||||||
iter.all(|c| alpha_numeric_char!(c))
|
iter.all(|c| alpha_numeric_char!(c))
|
||||||
@@ -406,32 +417,37 @@ 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![],
|
heap_locs: ReverseHeapVarDict::new(),
|
||||||
heap_locs: ReverseHeapVarDict::new(),
|
toplevel_spec: None,
|
||||||
toplevel_spec: None,
|
printed_vars: IndexSet::new(),
|
||||||
printed_vars: IndexSet::new(),
|
last_item_idx: 0,
|
||||||
last_item_idx: 0,
|
numbervars: false,
|
||||||
numbervars: false,
|
numbervars_offset: Integer::from(0),
|
||||||
numbervars_offset: Integer::from(0),
|
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,9 +465,8 @@ 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,31 +488,34 @@ 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 {
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
||||||
self.state_stack.push(TokenOrRedirect::Comma);
|
self.state_stack.push(TokenOrRedirect::Comma);
|
||||||
}
|
}
|
||||||
@@ -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,55 +614,56 @@ 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) => {
|
||||||
self.printed_vars.insert(addr);
|
if !self.printed_vars.contains(&addr) {
|
||||||
return iter.next();
|
self.printed_vars.insert(addr);
|
||||||
} else {
|
return iter.next();
|
||||||
iter.stack().pop();
|
} else {
|
||||||
push_space_if_amb!(self, &var, {
|
iter.stack().pop();
|
||||||
self.append_str(&var);
|
push_space_if_amb!(self, &var, {
|
||||||
});
|
self.append_str(&var);
|
||||||
|
});
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
},
|
}
|
||||||
None => if self.machine_st.is_cyclic_term(addr.clone()) {
|
}
|
||||||
match self.cyclic_terms.get(&addr).cloned() {
|
None => {
|
||||||
Some(reps) =>
|
if self.machine_st.is_cyclic_term(addr.clone()) {
|
||||||
if reps > 0 {
|
match self.cyclic_terms.get(&addr).cloned() {
|
||||||
self.cyclic_terms.insert(addr, reps - 1);
|
Some(reps) => {
|
||||||
iter.next()
|
if reps > 0 {
|
||||||
} else {
|
self.cyclic_terms.insert(addr, reps - 1);
|
||||||
push_space_if_amb!(self, "...", {
|
iter.next()
|
||||||
self.append_str("...");
|
} else {
|
||||||
});
|
push_space_if_amb!(self, "...", {
|
||||||
|
self.append_str("...");
|
||||||
iter.stack().pop();
|
});
|
||||||
self.cyclic_terms.remove(&addr);
|
|
||||||
None
|
iter.stack().pop();
|
||||||
},
|
self.cyclic_terms.remove(&addr);
|
||||||
None => {
|
None
|
||||||
self.cyclic_terms.insert(addr, 2);
|
}
|
||||||
iter.next()
|
}
|
||||||
}
|
None => {
|
||||||
|
self.cyclic_terms.insert(addr, 2);
|
||||||
|
iter.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iter.next()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
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,12 +829,13 @@ 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();
|
||||||
|
|
||||||
for c in borrowed_str[s.cursor() ..].chars() {
|
for c in borrowed_str[s.cursor()..].chars() {
|
||||||
atom += &char_to_string(c);
|
atom += &char_to_string(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,27 +859,32 @@ 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 self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
|| if let Some(ref op) = op {
|
||||||
!iter.immediate_leaf_has_property(|c| {
|
if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
||||||
match c {
|
!iter.immediate_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,
|
||||||
}
|
}) && needs_bracketing(&spec, op)
|
||||||
}) && needs_bracketing(&spec, op)
|
} else {
|
||||||
|
needs_bracketing(&spec, op)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
needs_bracketing(&spec, op)
|
is_functor_redirect && spec.prec() >= 1000
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
is_functor_redirect && spec.prec() >= 1000
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@@ -888,46 +907,58 @@ 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());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
.or_insert(Vec::new());
|
.structures
|
||||||
|
.entry((name.clone(), terms.len()))
|
||||||
|
.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() =>
|
||||||
let is_initial_index = self.lists.is_empty();
|
{
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
// strings are lists in this case.
|
||||||
},
|
let is_initial_index = self.lists.is_empty();
|
||||||
|
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();
|
{
|
||||||
self.lists.push(Self::add_index(is_initial_index, index));
|
let is_initial_index = self.lists.is_empty();
|
||||||
},
|
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
|
||||||
.map(|index| Self::adjust_internal_index(*index))
|
.values()
|
||||||
.unwrap_or(IntIndex::Fail)
|
.next()
|
||||||
|
.map(|index| Self::adjust_internal_index(*index))
|
||||||
|
.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
|
||||||
.map(|index| Self::adjust_internal_index(*index))
|
.values()
|
||||||
.unwrap_or(IntIndex::Fail)
|
.next()
|
||||||
|
.map(|index| Self::adjust_internal_index(*index))
|
||||||
|
.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
|
||||||
.map(|i| IntIndex::External(i.offset()))
|
.first()
|
||||||
.unwrap_or(IntIndex::Fail)
|
.map(|i| IntIndex::External(i.offset()))
|
||||||
|
.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;
|
||||||
@@ -244,10 +259,11 @@ impl CodeOffsets {
|
|||||||
|
|
||||||
for (index, line) in prelude.iter_mut().enumerate() {
|
for (index, line) in prelude.iter_mut().enumerate() {
|
||||||
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));
|
||||||
|
|
||||||
|
|||||||
@@ -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,18 +115,21 @@ 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))])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
heap_cell!(h + 4 + at_1_stub.len()),
|
3,
|
||||||
heap_integer!(Integer::from(t))]);
|
[
|
||||||
|
heap_cell!(h + 4),
|
||||||
|
heap_cell!(h + 4 + at_1_stub.len()),
|
||||||
|
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,34 +354,44 @@ 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 {
|
||||||
pub fn is_jump_instr(&self) -> bool {
|
pub fn is_jump_instr(&self) -> bool {
|
||||||
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(constants)),
|
[
|
||||||
heap_integer!(Integer::from(lists)),
|
heap_integer!(Integer::from(vars)),
|
||||||
heap_integer!(Integer::from(structures))]),
|
heap_integer!(Integer::from(constants)),
|
||||||
&IndexingInstruction::SwitchOnConstant(constants, _) =>
|
heap_integer!(Integer::from(lists)),
|
||||||
functor!("switch_on_constant", 1,
|
heap_integer!(Integer::from(structures))
|
||||||
[heap_integer!(Integer::from(constants))]),
|
]
|
||||||
&IndexingInstruction::SwitchOnStructure(structures, _) =>
|
),
|
||||||
functor!("switch_on_structure", 1,
|
&IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
|
||||||
[heap_integer!(Integer::from(structures))])
|
"switch_on_constant",
|
||||||
|
1,
|
||||||
|
[heap_integer!(Integer::from(constants))]
|
||||||
|
),
|
||||||
|
&IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
|
||||||
|
"switch_on_structure",
|
||||||
|
1,
|
||||||
|
[heap_integer!(Integer::from(structures))]
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,79 +446,93 @@ 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",
|
||||||
heap_con!(constant.clone()),
|
3,
|
||||||
heap_str!(h + 6)]);
|
[
|
||||||
|
heap_str!(h + 4),
|
||||||
|
heap_con!(constant.clone()),
|
||||||
|
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",
|
||||||
heap_integer!(Integer::from(arity)),
|
3,
|
||||||
heap_str!(h + 4)]);
|
[
|
||||||
|
heap_con!(Constant::Atom(ct.name(), None)),
|
||||||
|
heap_integer!(Integer::from(arity)),
|
||||||
|
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))])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -493,92 +550,112 @@ 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",
|
||||||
heap_con!(constant.clone()),
|
3,
|
||||||
heap_str!(h + 6)]);
|
[
|
||||||
|
heap_str!(h + 4),
|
||||||
|
heap_con!(constant.clone()),
|
||||||
|
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",
|
||||||
heap_integer!(Integer::from(arity)),
|
3,
|
||||||
heap_str!(h + 4)]);
|
[
|
||||||
|
heap_con!(Constant::Atom(ct.name(), None)),
|
||||||
|
heap_integer!(Integer::from(arity)),
|
||||||
|
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))])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ 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> {
|
||||||
pub fn level(self) -> Level {
|
pub fn level(self) -> Level {
|
||||||
match self {
|
match self {
|
||||||
TermRef::AnonVar(lvl)
|
TermRef::AnonVar(lvl)
|
||||||
| 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,
|
}
|
||||||
ClauseType::from(name.clone(), terms.len(), fixity.clone()),
|
}
|
||||||
terms),
|
&Term::Clause(ref r, ref name, ref terms, ref fixity) => TermIterState::Clause(
|
||||||
&Term::Cons(..) =>
|
Level::Root,
|
||||||
return QueryIterator { state_stack: vec![] },
|
0,
|
||||||
&Term::Constant(_, _) =>
|
r,
|
||||||
return QueryIterator { state_stack: vec![] },
|
ClauseType::from(name.clone(), terms.len(), fixity.clone()),
|
||||||
&Term::Var(ref cell, ref var) =>
|
terms,
|
||||||
TermIterState::Var(Level::Root, cell, (*var).clone())
|
),
|
||||||
|
&Term::Cons(..) => {
|
||||||
|
return QueryIterator {
|
||||||
|
state_stack: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&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 =>
|
&QueryTerm::BlockedCut => QueryIterator {
|
||||||
QueryIterator { state_stack: vec![] },
|
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,15 +321,13 @@ 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_cut_var<'a, Iter: Iterator<Item=&'a Term>>(terms: Iter) -> bool {
|
fn contains_cut_var<'a, Iter: Iterator<Item = &'a Term>>(terms: Iter) -> bool {
|
||||||
for term in terms {
|
for term in terms {
|
||||||
if let &Term::Var(_, ref var) = term {
|
if let &Term::Var(_, ref var) = term {
|
||||||
if var.as_str() == "!" {
|
if var.as_str() == "!" {
|
||||||
@@ -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()
|
||||||
ChunkedTerm::BodyTerm(qt) => Some(qt),
|
.filter_map(|ct| match ct {
|
||||||
_ => None
|
ChunkedTerm::BodyTerm(qt) => Some(qt),
|
||||||
}
|
_ => 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,10 +411,9 @@ 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();
|
||||||
|
|
||||||
while let Some(term) = item {
|
while let Some(term) = item {
|
||||||
@@ -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>;
|
||||||
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ impl AndStack {
|
|||||||
pub(crate) fn take(&mut self) -> Self {
|
pub(crate) fn take(&mut self) -> Self {
|
||||||
AndStack(mem::replace(&mut self.0, vec![]))
|
AndStack(mem::replace(&mut self.0, vec![]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, global_index: usize, e: usize, cp: LocalCodePtr, n: usize) {
|
pub fn push(&mut self, global_index: usize, e: usize, cp: LocalCodePtr, n: usize) {
|
||||||
let len = self.0.len();
|
let len = self.0.len();
|
||||||
self.0.push(Frame::new(global_index, len, e, cp, n));
|
self.0.push(Frame::new(global_index, len, e, cp, n));
|
||||||
@@ -61,7 +61,7 @@ impl AndStack {
|
|||||||
if len < n {
|
if len < n {
|
||||||
self[fr].perms.reserve(n - len);
|
self[fr].perms.reserve(n - len);
|
||||||
|
|
||||||
for i in len .. n {
|
for i in len..n {
|
||||||
self[fr].perms.push(Addr::StackCell(fr, i));
|
self[fr].perms.push(Addr::StackCell(fr, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use indexmap::IndexSet;
|
|||||||
|
|
||||||
use std::vec::IntoIter;
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||||
pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
|
pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
|
||||||
|
|
||||||
pub(super) type Bindings = Vec<(usize, Addr)>;
|
pub(super) type Bindings = Vec<(usize, Addr)>;
|
||||||
@@ -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..]
|
||||||
{
|
.iter()
|
||||||
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b ..]
|
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
|
||||||
.iter().filter_map(|h|
|
Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
|
||||||
match self.store(self.deref(Addr::HeapCell(*h))) {
|
_ => None,
|
||||||
Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
|
})
|
||||||
_ => 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,23 +102,22 @@ 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));
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let query_var_list = Addr::HeapCell(self.heap.to_list(query_vars.into_iter()));
|
let query_var_list = Addr::HeapCell(self.heap.to_list(query_vars.into_iter()));
|
||||||
let attr_var_list = Addr::HeapCell(self.heap.to_list(attr_vars));
|
let attr_var_list = Addr::HeapCell(self.heap.to_list(attr_vars));
|
||||||
|
|
||||||
(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
|
||||||
@@ -127,7 +130,7 @@ impl MachineState {
|
|||||||
let e = self.e;
|
let e = self.e;
|
||||||
self.and_stack[e].interrupt_cp = self.attr_var_init.cp;
|
self.and_stack[e].interrupt_cp = self.attr_var_init.cp;
|
||||||
|
|
||||||
for i in 1 .. rs + 1 {
|
for i in 1..rs + 1 {
|
||||||
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
|
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]
|
|
||||||
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
|
||||||
self.term_dir.get(&key)
|
|
||||||
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
|
||||||
.unwrap_or((0,0))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize)
|
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
||||||
-> (Predicate, VecDeque<TopLevel>)
|
self.term_dir
|
||||||
{
|
.get(&key)
|
||||||
self.term_dir.get_mut(&key)
|
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
||||||
.map(|entry| (Predicate((entry.0).0.drain(len ..).collect()),
|
.unwrap_or((0, 0))
|
||||||
entry.1.drain(queue_len ..).collect()))
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn truncate_terms(
|
||||||
|
&mut self,
|
||||||
|
key: PredicateKey,
|
||||||
|
len: usize,
|
||||||
|
queue_len: usize,
|
||||||
|
) -> (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
|
||||||
let arity = cl.arity();
|
.0
|
||||||
cl.name().map(|name| (name, arity))
|
.first()
|
||||||
}).ok_or(SessionError::NamelessEntry)?;
|
.and_then(|cl| {
|
||||||
|
let arity = cl.arity();
|
||||||
|
cl.name().map(|name| (name, arity))
|
||||||
|
})
|
||||||
|
.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!(
|
||||||
built_in.arity(),
|
ClauseType::BuiltIn(built_in.clone()),
|
||||||
0, last_call);
|
built_in.arity(),
|
||||||
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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,16 +22,16 @@ 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> {
|
||||||
fn new(target: T) -> Self {
|
fn new(target: T) -> Self {
|
||||||
CopyTermState {
|
CopyTermState {
|
||||||
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 @ Addr::AttrVar(_)
|
||||||
Addr::Lis(addr) =>
|
| addr @ Addr::HeapCell(_)
|
||||||
self.copy_list(addr),
|
| addr @ Addr::StackCell(..) => self.copy_var(addr),
|
||||||
addr @ Addr::AttrVar(_)
|
Addr::Str(addr) => self.copy_structure(addr),
|
||||||
| addr @ Addr::HeapCell(_)
|
Addr::Con(_) | Addr::DBRef(_) => self.scan += 1,
|
||||||
| addr @ Addr::StackCell(..) =>
|
},
|
||||||
self.copy_var(addr),
|
|
||||||
Addr::Str(addr) =>
|
|
||||||
self.copy_structure(addr),
|
|
||||||
Addr::Con(_) | Addr::DBRef(_) =>
|
|
||||||
self.scan += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,12 +197,10 @@ 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,30 +111,38 @@ 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);
|
||||||
self.machine_st = machine_st;
|
self.machine_st = machine_st;
|
||||||
|
|
||||||
if let EvalSession::Error(err) = result {
|
if let EvalSession::Error(err) = result {
|
||||||
let h = self.machine_st.heap.h;
|
let h = self.machine_st.heap.h;
|
||||||
let stub = MachineError::functor_stub(src, 1);
|
let stub = MachineError::functor_stub(src, 1);
|
||||||
let err = MachineError::session_error(h, err);
|
let err = MachineError::session_error(h, err);
|
||||||
let err = self.machine_st.error_form(err, stub);
|
let err = self.machine_st.error_form(err, stub);
|
||||||
|
|
||||||
self.machine_st.throw_exception(err);
|
self.machine_st.throw_exception(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,13 +63,13 @@ impl Heap {
|
|||||||
self.h = 0;
|
self.h = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_list<Iter: Iterator<Item=Addr>>(&mut self, values: Iter) -> usize {
|
pub fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
|
||||||
let head_addr = self.h;
|
let head_addr = self.h;
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
let h = self.h;
|
let h = self.h;
|
||||||
|
|
||||||
self.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
self.push(HeapCellValue::Addr(value));
|
self.push(HeapCellValue::Addr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ impl Heap {
|
|||||||
head_addr
|
head_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend<Iter: Iterator<Item=HeapCellValue>>(&mut self, iter: Iter) {
|
pub fn extend<Iter: Iterator<Item = HeapCellValue>>(&mut self, iter: Iter) {
|
||||||
for hcv in iter {
|
for hcv in iter {
|
||||||
self.push(hcv);
|
self.push(hcv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
}
|
||||||
"private_procedure",
|
SessionError::ModuleDoesNotContainExport => Self::permission_error(
|
||||||
clause_name!("module_does_not_contain_claimed_export")),
|
PermissionError::Access,
|
||||||
SessionError::ModuleNotFound =>
|
"private_procedure",
|
||||||
Self::permission_error(PermissionError::Access,
|
clause_name!("module_does_not_contain_claimed_export"),
|
||||||
"private_procedure",
|
),
|
||||||
clause_name!("module_does_not_exist")),
|
SessionError::ModuleNotFound => Self::permission_error(
|
||||||
SessionError::NoModuleDeclaration(name) =>
|
PermissionError::Access,
|
||||||
Self::existence_error(h, ExistenceError::Module(name)),
|
"private_procedure",
|
||||||
SessionError::OpIsInfixAndPostFix(op) =>
|
clause_name!("module_does_not_exist"),
|
||||||
Self::permission_error(PermissionError::Create,
|
),
|
||||||
"operator",
|
SessionError::NoModuleDeclaration(name) => {
|
||||||
op),
|
Self::existence_error(h, ExistenceError::Module(name))
|
||||||
_ => unreachable!()
|
}
|
||||||
|
SessionError::OpIsInfixAndPostFix(op) => {
|
||||||
|
Self::permission_error(PermissionError::Create, "operator", op)
|
||||||
|
}
|
||||||
|
_ => 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",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,21 +289,21 @@ impl PermissionError {
|
|||||||
pub enum ValidType {
|
pub enum ValidType {
|
||||||
Atom,
|
Atom,
|
||||||
Atomic,
|
Atomic,
|
||||||
// Boolean,
|
// Boolean,
|
||||||
// Byte,
|
// Byte,
|
||||||
Callable,
|
Callable,
|
||||||
Character,
|
Character,
|
||||||
Compound,
|
Compound,
|
||||||
Evaluable,
|
Evaluable,
|
||||||
Float,
|
Float,
|
||||||
// InByte,
|
// InByte,
|
||||||
// InCharacter,
|
// InCharacter,
|
||||||
Integer,
|
Integer,
|
||||||
List,
|
List,
|
||||||
// Number,
|
// Number,
|
||||||
Pair,
|
Pair,
|
||||||
// PredicateIndicator,
|
// PredicateIndicator,
|
||||||
// Variable
|
// Variable
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidType {
|
impl ValidType {
|
||||||
@@ -225,34 +311,34 @@ impl ValidType {
|
|||||||
match self {
|
match self {
|
||||||
ValidType::Atom => "atom",
|
ValidType::Atom => "atom",
|
||||||
ValidType::Atomic => "atomic",
|
ValidType::Atomic => "atomic",
|
||||||
// ValidType::Boolean => "boolean",
|
// ValidType::Boolean => "boolean",
|
||||||
// ValidType::Byte => "byte",
|
// ValidType::Byte => "byte",
|
||||||
ValidType::Callable => "callable",
|
ValidType::Callable => "callable",
|
||||||
ValidType::Character => "character",
|
ValidType::Character => "character",
|
||||||
ValidType::Compound => "compound",
|
ValidType::Compound => "compound",
|
||||||
ValidType::Evaluable => "evaluable",
|
ValidType::Evaluable => "evaluable",
|
||||||
ValidType::Float => "float",
|
ValidType::Float => "float",
|
||||||
// ValidType::InByte => "in_byte",
|
// ValidType::InByte => "in_byte",
|
||||||
// ValidType::InCharacter => "in_character",
|
// ValidType::InCharacter => "in_character",
|
||||||
ValidType::Integer => "integer",
|
ValidType::Integer => "integer",
|
||||||
ValidType::List => "list",
|
ValidType::List => "list",
|
||||||
// ValidType::Number => "number",
|
// ValidType::Number => "number",
|
||||||
ValidType::Pair => "pair",
|
ValidType::Pair => "pair",
|
||||||
// ValidType::PredicateIndicator => "predicate_indicator",
|
// ValidType::PredicateIndicator => "predicate_indicator",
|
||||||
// ValidType::Variable => "variable"
|
// ValidType::Variable => "variable"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,10 +348,10 @@ impl DomainError {
|
|||||||
pub enum RepFlag {
|
pub enum RepFlag {
|
||||||
Character,
|
Character,
|
||||||
CharacterCode,
|
CharacterCode,
|
||||||
// InCharacterCode,
|
// InCharacterCode,
|
||||||
MaxArity,
|
MaxArity,
|
||||||
// MaxInteger,
|
// MaxInteger,
|
||||||
// MinInteger
|
// MinInteger
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepFlag {
|
impl RepFlag {
|
||||||
@@ -273,10 +359,10 @@ impl RepFlag {
|
|||||||
match self {
|
match self {
|
||||||
RepFlag::Character => "character",
|
RepFlag::Character => "character",
|
||||||
RepFlag::CharacterCode => "character_code",
|
RepFlag::CharacterCode => "character_code",
|
||||||
// RepFlag::InCharacterCode => "in_character_code",
|
// RepFlag::InCharacterCode => "in_character_code",
|
||||||
RepFlag::MaxArity => "max_arity",
|
RepFlag::MaxArity => "max_arity",
|
||||||
// RepFlag::MaxInteger => "max_integer",
|
// RepFlag::MaxInteger => "max_integer",
|
||||||
// RepFlag::MinInteger => "min_integer"
|
// RepFlag::MinInteger => "min_integer"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +372,7 @@ impl RepFlag {
|
|||||||
pub enum EvalError {
|
pub enum EvalError {
|
||||||
FloatOverflow,
|
FloatOverflow,
|
||||||
Undefined,
|
Undefined,
|
||||||
// Underflow,
|
// Underflow,
|
||||||
ZeroDivisor,
|
ZeroDivisor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +381,7 @@ impl EvalError {
|
|||||||
match self {
|
match self {
|
||||||
EvalError::FloatOverflow => "float_overflow",
|
EvalError::FloatOverflow => "float_overflow",
|
||||||
EvalError::Undefined => "undefined",
|
EvalError::Undefined => "undefined",
|
||||||
// EvalError::FloatUnderflow => "underflow",
|
// EvalError::FloatUnderflow => "underflow",
|
||||||
EvalError::ZeroDivisor => "zero_divisor",
|
EvalError::ZeroDivisor => "zero_divisor",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,30 +392,33 @@ pub(super) enum CycleSearchResult {
|
|||||||
EmptyList,
|
EmptyList,
|
||||||
NotList,
|
NotList,
|
||||||
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 {
|
||||||
// see 8.4.3 of Draft Technical Corrigendum 2.
|
// see 8.4.3 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_sort_errors(&self) -> CallResult {
|
pub(super) fn check_sort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||||
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
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,
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,16 +464,18 @@ impl MachineState {
|
|||||||
|
|
||||||
// see 8.4.4 of Draft Technical Corrigendum 2.
|
// see 8.4.4 of Draft Technical Corrigendum 2.
|
||||||
pub(super) fn check_keysort_errors(&self) -> CallResult {
|
pub(super) fn check_keysort_errors(&self) -> CallResult {
|
||||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||||
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
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::Addr(Addr::HeapCell(h + 3)),
|
HeapCellValue::NamedStr(2, clause_name!("error"), None),
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len))];
|
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
|
||||||
|
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(
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
vec![
|
||||||
heap_integer!(Integer::from(line_num))].into_iter());
|
HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
|
||||||
|
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
||||||
|
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 {
|
||||||
|
|||||||
@@ -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,22 +39,22 @@ 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 {
|
||||||
pub fn as_addr(self) -> Addr {
|
pub fn as_addr(self) -> Addr {
|
||||||
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,25 +69,23 @@ 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),
|
if fr1 < fr || (fr1 == fr && sc1 < sc) {
|
||||||
Ref::StackCell(fr1, sc1) =>
|
Some(Ordering::Greater)
|
||||||
if fr1 < fr || (fr1 == fr && sc1 < sc) {
|
} else if fr1 == fr && sc1 == sc {
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Equal)
|
||||||
} else if fr1 == fr && sc1 == sc {
|
} else {
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Less)
|
||||||
} else {
|
}
|
||||||
Some(Ordering::Less)
|
}
|
||||||
}
|
},
|
||||||
},
|
&Addr::HeapCell(h) | &Addr::AttrVar(h) => match r {
|
||||||
&Addr::HeapCell(h) | &Addr::AttrVar(h) =>
|
&Ref::StackCell(..) => Some(Ordering::Less),
|
||||||
match r {
|
&Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1),
|
||||||
&Ref::StackCell(..) => Some(Ordering::Less),
|
},
|
||||||
&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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,9 +170,9 @@ impl SubAssign<usize> for Addr {
|
|||||||
impl From<Ref> for Addr {
|
impl From<Ref> for Addr {
|
||||||
fn from(r: Ref) -> Self {
|
fn from(r: Ref) -> Self {
|
||||||
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,23 +255,24 @@ 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 {
|
||||||
#[inline]
|
#[inline]
|
||||||
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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
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,34 +284,33 @@ 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)]
|
||||||
pub enum CodePtr {
|
pub enum CodePtr {
|
||||||
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
||||||
CallN(usize, LocalCodePtr), // arity, local.
|
CallN(usize, LocalCodePtr), // arity, local.
|
||||||
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 {
|
||||||
pub fn local(&self) -> LocalCodePtr {
|
pub fn local(&self) -> LocalCodePtr {
|
||||||
match self {
|
match self {
|
||||||
&CodePtr::BuiltInClause(_, ref local)
|
&CodePtr::BuiltInClause(_, ref local)
|
||||||
| &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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,14 +346,14 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
|||||||
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2))
|
(&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2))
|
||||||
| (&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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,10 +388,10 @@ impl AddAssign<usize> for LocalCodePtr {
|
|||||||
fn add_assign(&mut self, rhs: usize) {
|
fn add_assign(&mut self, rhs: usize) {
|
||||||
match self {
|
match self {
|
||||||
&mut LocalCodePtr::InSituDirEntry(ref mut p)
|
&mut LocalCodePtr::InSituDirEntry(ref mut p)
|
||||||
| &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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,10 +402,12 @@ impl Add<usize> for CodePtr {
|
|||||||
fn add(self, rhs: usize) -> Self::Output {
|
fn add(self, rhs: usize) -> Self::Output {
|
||||||
match self {
|
match self {
|
||||||
p @ CodePtr::REPL(..)
|
p @ CodePtr::REPL(..)
|
||||||
| 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,14 +415,14 @@ 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
||||||
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -423,11 +432,13 @@ 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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
||||||
// key type: module name, predicate indicator.
|
// key type: module name, predicate indicator.
|
||||||
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
||||||
|
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,7 +513,7 @@ impl IndexStore {
|
|||||||
in_situ_code_dir: InSituCodeDir::new(),
|
in_situ_code_dir: InSituCodeDir::new(),
|
||||||
op_dir: default_op_dir(),
|
op_dir: default_op_dir(),
|
||||||
modules: ModuleDir::new(),
|
modules: ModuleDir::new(),
|
||||||
// parsing_stream: readline::parsing_stream(String::new())
|
// parsing_stream: readline::parsing_stream(String::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,21 +528,30 @@ 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
||||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, _))
|
chars += name.as_str();
|
||||||
if name.as_str().len() == 1 => {
|
}
|
||||||
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) => {
|
||||||
Some(p)
|
if let &IndexPtr::Index(p) = &idx.0.borrow().0 {
|
||||||
} else {
|
Some(p)
|
||||||
None
|
} else {
|
||||||
},
|
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,21 +388,20 @@ 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();
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1..n + 1 {
|
||||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.e = machine_st.or_stack[b].e;
|
machine_st.e = machine_st.or_stack[b].e;
|
||||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||||
|
|
||||||
machine_st.or_stack[b].bp = machine_st.p.clone() + offset;
|
machine_st.or_stack[b].bp = machine_st.p.clone() + offset;
|
||||||
|
|
||||||
let old_tr = machine_st.or_stack[b].tr;
|
let old_tr = machine_st.or_stack[b].tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
@@ -407,7 +409,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
let curr_pstr_tr = machine_st.pstr_tr;
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
@@ -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,21 +431,20 @@ 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();
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1..n + 1 {
|
||||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.e = machine_st.or_stack[b].e;
|
machine_st.e = machine_st.or_stack[b].e;
|
||||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||||
|
|
||||||
machine_st.or_stack[b].bp = machine_st.p.clone() + 1;
|
machine_st.or_stack[b].bp = machine_st.p.clone() + 1;
|
||||||
|
|
||||||
let old_tr = machine_st.or_stack[b].tr;
|
let old_tr = machine_st.or_stack[b].tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
@@ -448,7 +452,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
let curr_pstr_tr = machine_st.pstr_tr;
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
@@ -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,19 +474,18 @@ 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();
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1..n + 1 {
|
||||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.e = machine_st.or_stack[b].e;
|
machine_st.e = machine_st.or_stack[b].e;
|
||||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||||
|
|
||||||
let old_tr = machine_st.or_stack[b].tr;
|
let old_tr = machine_st.or_stack[b].tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
@@ -487,7 +493,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
let curr_pstr_tr = machine_st.pstr_tr;
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
@@ -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,19 +518,18 @@ 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();
|
||||||
|
|
||||||
for i in 1 .. n + 1 {
|
for i in 1..n + 1 {
|
||||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.e = machine_st.or_stack[b].e;
|
machine_st.e = machine_st.or_stack[b].e;
|
||||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||||
|
|
||||||
let old_tr = machine_st.or_stack[b].tr;
|
let old_tr = machine_st.or_stack[b].tr;
|
||||||
let curr_tr = machine_st.tr;
|
let curr_tr = machine_st.tr;
|
||||||
|
|
||||||
machine_st.unwind_trail(old_tr, curr_tr);
|
machine_st.unwind_trail(old_tr, curr_tr);
|
||||||
@@ -529,7 +537,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
|
|
||||||
machine_st.trail.truncate(machine_st.tr);
|
machine_st.trail.truncate(machine_st.tr);
|
||||||
|
|
||||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||||
let curr_pstr_tr = machine_st.pstr_tr;
|
let curr_pstr_tr = machine_st.pstr_tr;
|
||||||
|
|
||||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||||
@@ -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,57 +652,57 @@ 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);
|
||||||
let err = MachineError::syntax_error(h, e);
|
let err = MachineError::syntax_error(h, e);
|
||||||
let err = machine_st.error_form(err, stub);
|
let err = machine_st.error_form(err, stub);
|
||||||
|
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -876,21 +919,22 @@ impl CallPolicy for DefaultCallPolicy {}
|
|||||||
|
|
||||||
pub(crate) struct CWILCallPolicy {
|
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 {
|
||||||
count: Integer::from(0),
|
prev_policy,
|
||||||
limits: vec![],
|
count: Integer::from(0),
|
||||||
inference_limit_exceeded: false };
|
limits: vec![],
|
||||||
|
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
|
||||||
@@ -986,13 +1033,17 @@ impl CutPolicy for DefaultCutPolicy {
|
|||||||
pub(crate) struct SCCCutPolicy {
|
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
@@ -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(())
|
||||||
}
|
}
|
||||||
@@ -155,9 +164,9 @@ impl SubModuleUser for IndexStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
||||||
static ERROR: &str = include_str!("../lib/error.pl");
|
static ERROR: &str = include_str!("../lib/error.pl");
|
||||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||||
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
||||||
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
||||||
|
|
||||||
impl Machine {
|
impl Machine {
|
||||||
@@ -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,15 +196,15 @@ 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");
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -328,16 +343,15 @@ impl Machine {
|
|||||||
pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
|
pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
|
||||||
let h = self.machine_st.heap.h;
|
let h = self.machine_st.heap.h;
|
||||||
|
|
||||||
let err = MachineError::session_error(h, err);
|
let err = MachineError::session_error(h, err);
|
||||||
let stub = MachineError::functor_stub(key.0, key.1);
|
let stub = MachineError::functor_stub(key.0, key.1);
|
||||||
let err = self.machine_st.error_form(err, stub);
|
let err = self.machine_st.error_form(err, stub);
|
||||||
|
|
||||||
self.machine_st.throw_exception(err);
|
self.machine_st.throw_exception(err);
|
||||||
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,117 +435,128 @@ 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()
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let attr_goals = self.attribute_goals();
|
let attr_goals = self.attribute_goals();
|
||||||
|
|
||||||
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);
|
||||||
} else {
|
} else {
|
||||||
println!("true.");
|
println!("true.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if bindings.is_empty() && attr_goals.is_empty() {
|
||||||
|
print!("true");
|
||||||
|
stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
||||||
|
|
||||||
|
if !attr_goals.is_empty() {
|
||||||
|
if bindings.is_empty() {
|
||||||
|
write!(raw_stdout, "{}", attr_goals).unwrap();
|
||||||
|
} else {
|
||||||
|
write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap();
|
||||||
|
}
|
||||||
|
} else if !bindings.is_empty() {
|
||||||
|
write!(raw_stdout, "{}", bindings).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.machine_st.b > 0 {
|
||||||
|
raw_stdout.flush().unwrap();
|
||||||
|
|
||||||
|
let result = match next_keypress() {
|
||||||
|
ContinueResult::ContinueQuery => {
|
||||||
|
write!(raw_stdout, " ;\r\n").unwrap();
|
||||||
|
self.continue_query(&alloc_locs)
|
||||||
|
}
|
||||||
|
ContinueResult::Conclude => {
|
||||||
|
write!(raw_stdout, " ...\r\n").unwrap();
|
||||||
self.machine_st.absorb_snapshot(snapshot);
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if bindings.is_empty() && attr_goals.is_empty() {
|
};
|
||||||
print!("true");
|
|
||||||
stdout().flush().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
||||||
|
|
||||||
if !attr_goals.is_empty() {
|
match result {
|
||||||
if bindings.is_empty() {
|
EvalSession::QueryFailure => {
|
||||||
write!(raw_stdout, "{}", attr_goals).unwrap();
|
if self.machine_st.ball.stub.len() > 0 {
|
||||||
} else {
|
self.propagate_exception_to_toplevel(snapshot);
|
||||||
write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap();
|
return;
|
||||||
}
|
} else {
|
||||||
} else if !bindings.is_empty() {
|
write!(raw_stdout, "false.\r\n").unwrap();
|
||||||
write!(raw_stdout, "{}", bindings).unwrap();
|
raw_stdout.flush().unwrap();
|
||||||
}
|
|
||||||
|
|
||||||
if self.machine_st.b > 0 {
|
|
||||||
raw_stdout.flush().unwrap();
|
|
||||||
|
|
||||||
let result = match next_keypress() {
|
|
||||||
ContinueResult::ContinueQuery => {
|
|
||||||
write!(raw_stdout, " ;\r\n").unwrap();
|
|
||||||
self.continue_query(&alloc_locs)
|
|
||||||
},
|
|
||||||
ContinueResult::Conclude => {
|
|
||||||
write!(raw_stdout, " ...\r\n").unwrap();
|
|
||||||
self.machine_st.absorb_snapshot(snapshot);
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
EvalSession::Error(err) => {
|
||||||
|
self.machine_st.absorb_snapshot(snapshot);
|
||||||
|
self.throw_session_error(err, (clause_name!("repl"), 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if bindings.is_empty() && attr_goals.is_empty() {
|
||||||
|
write!(raw_stdout, "true.\r\n").unwrap();
|
||||||
|
} else {
|
||||||
|
let space = if !attr_goals.is_empty() {
|
||||||
|
if requires_space(&attr_goals, ".") {
|
||||||
|
" "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if requires_space(&bindings, ".") {
|
||||||
|
" "
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
write!(raw_stdout, "{}.\r\n", space).unwrap();
|
||||||
|
|
||||||
match result {
|
|
||||||
EvalSession::QueryFailure =>
|
|
||||||
if self.machine_st.ball.stub.len() > 0 {
|
|
||||||
self.propagate_exception_to_toplevel(snapshot);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
write!(raw_stdout, "false.\r\n").unwrap();
|
|
||||||
raw_stdout.flush().unwrap();
|
|
||||||
|
|
||||||
self.machine_st.absorb_snapshot(snapshot);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
EvalSession::Error(err) => {
|
|
||||||
self.machine_st.absorb_snapshot(snapshot);
|
|
||||||
self.throw_session_error(err, (clause_name!("repl"), 0));
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if bindings.is_empty() && attr_goals.is_empty() {
|
|
||||||
write!(raw_stdout, "true.\r\n").unwrap();
|
|
||||||
} else {
|
|
||||||
let space = if !attr_goals.is_empty() {
|
|
||||||
if requires_space(&attr_goals, ".") { " " } else { "" }
|
|
||||||
} else {
|
|
||||||
if requires_space(&bindings, ".") { " " } else { "" }
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(raw_stdout, "{}.\r\n", space).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
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;
|
||||||
},
|
}
|
||||||
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,24 +765,27 @@ 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;
|
||||||
|
|
||||||
self.b0 = self.or_stack[b].b0;
|
self.b0 = self.or_stack[b].b0;
|
||||||
self.p = self.or_stack[b].bp.clone();
|
self.p = self.or_stack[b].bp.clone();
|
||||||
|
|
||||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
||||||
self.fail = p == 0;
|
self.fail = p == 0;
|
||||||
@@ -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);
|
||||||
|
|
||||||
@@ -825,7 +878,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match self.p {
|
match self.p {
|
||||||
CodePtr::VerifyAttrInterrupt(_) => {
|
CodePtr::VerifyAttrInterrupt(_) => {
|
||||||
self.p = CodePtr::Local(self.attr_var_init.cp + 1);
|
self.p = CodePtr::Local(self.attr_var_init.cp + 1);
|
||||||
|
|
||||||
if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) {
|
if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) {
|
||||||
@@ -836,11 +889,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
module_decl,
|
||||||
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
atom_tbl,
|
||||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||||
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||||
code_dir: CodeDir::new(),
|
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||||
op_dir: default_op_dir(),
|
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||||
inserted_expansions: false }
|
code_dir: CodeDir::new(),
|
||||||
|
op_dir: default_op_dir(),
|
||||||
|
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.term_dir.entry((clause_name!("term_expansion"), 2))
|
let te = code_repo
|
||||||
|
.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,18 +86,18 @@ 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();
|
||||||
|
|
||||||
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
|
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
|
||||||
Some(CodeIndex (ref code_idx)) => {
|
Some(CodeIndex(ref code_idx)) => {
|
||||||
if &code_idx.borrow().1 != &module.module_decl.name {
|
if &code_idx.borrow().1 != &module.module_decl.name {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,29 +9,29 @@ pub struct Frame {
|
|||||||
pub e: usize,
|
pub e: usize,
|
||||||
pub cp: LocalCodePtr,
|
pub cp: LocalCodePtr,
|
||||||
pub attr_var_init_b: usize,
|
pub attr_var_init_b: usize,
|
||||||
pub b: usize,
|
pub b: usize,
|
||||||
pub bp: CodePtr,
|
pub bp: CodePtr,
|
||||||
pub tr: usize,
|
pub tr: usize,
|
||||||
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(
|
||||||
e: usize,
|
global_index: usize,
|
||||||
cp: LocalCodePtr,
|
e: usize,
|
||||||
attr_var_init_b: usize,
|
cp: LocalCodePtr,
|
||||||
b: usize,
|
attr_var_init_b: usize,
|
||||||
bp: CodePtr,
|
b: usize,
|
||||||
tr: usize,
|
bp: CodePtr,
|
||||||
pstr_tr: usize,
|
tr: usize,
|
||||||
h: usize,
|
pstr_tr: usize,
|
||||||
b0: usize,
|
h: usize,
|
||||||
n: usize)
|
b0: usize,
|
||||||
-> Self
|
n: usize,
|
||||||
{
|
) -> 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,20 +59,33 @@ impl OrStack {
|
|||||||
OrStack(Vec::new())
|
OrStack(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self,
|
pub fn push(
|
||||||
global_index: usize,
|
&mut self,
|
||||||
e: usize,
|
global_index: usize,
|
||||||
cp: LocalCodePtr,
|
e: usize,
|
||||||
attr_var_init_b: usize,
|
cp: LocalCodePtr,
|
||||||
b: usize,
|
attr_var_init_b: usize,
|
||||||
bp: CodePtr,
|
b: usize,
|
||||||
tr: usize,
|
bp: CodePtr,
|
||||||
pstr_tr: usize,
|
tr: usize,
|
||||||
h: usize,
|
pstr_tr: usize,
|
||||||
b0: usize,
|
h: usize,
|
||||||
n: usize)
|
b0: 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]
|
||||||
@@ -87,7 +100,7 @@ impl OrStack {
|
|||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.0.clear()
|
self.0.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn top(&self) -> Option<&Frame> {
|
pub fn top(&self) -> Option<&Frame> {
|
||||||
self.0.last()
|
self.0.last()
|
||||||
}
|
}
|
||||||
@@ -97,7 +110,7 @@ impl OrStack {
|
|||||||
pub fn truncate(&mut self, new_b: usize) {
|
pub fn truncate(&mut self, new_b: usize) {
|
||||||
self.0.truncate(new_b);
|
self.0.truncate(new_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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,22 +38,24 @@ 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(
|
||||||
vec![Box::new(prec), Box::new(term)],
|
Cell::default(),
|
||||||
None);
|
sym.clone(),
|
||||||
|
vec![Box::new(prec), Box::new(term)],
|
||||||
|
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;
|
||||||
|
|
||||||
while let Term::Cons(_, head, next_tail) = tail {
|
while let Term::Cons(_, head, next_tail) = tail {
|
||||||
terms.push(*head);
|
terms.push(*head);
|
||||||
@@ -81,19 +81,19 @@ 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 {
|
||||||
pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||||
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
||||||
let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
|
let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
|
||||||
|
|
||||||
(tes, teqs)
|
(tes, teqs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||||
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
||||||
let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
|
let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
|
||||||
|
|
||||||
(ges, geqs)
|
(ges, geqs)
|
||||||
@@ -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
@@ -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,147 +53,158 @@ 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) => {{
|
||||||
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
|
if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if $lco {
|
if $lco {
|
||||||
$machine_st.p = CodePtr::Local($machine_st.cp);
|
$machine_st.p = CodePtr::Local($machine_st.cp);
|
||||||
} else {
|
} else {
|
||||||
@@ -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 {
|
||||||
code_dir: $code_dir,
|
atom_tbl: $atom_tbl,
|
||||||
dynamic_code_dir: DynamicCodeDir::new(),
|
code_dir: $code_dir,
|
||||||
global_variables: GlobalVarDir::new(),
|
dynamic_code_dir: DynamicCodeDir::new(),
|
||||||
in_situ_code_dir: InSituCodeDir::new(),
|
global_variables: GlobalVarDir::new(),
|
||||||
op_dir: $op_dir,
|
in_situ_code_dir: InSituCodeDir::new(),
|
||||||
modules: $modules }
|
op_dir: $op_dir,
|
||||||
)
|
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)
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ pub mod readline
|
|||||||
let output_len = self.split_pending(buf, split_idx);
|
let output_len = self.split_pending(buf, split_idx);
|
||||||
|
|
||||||
if split_idx < self.pending_input.len() {
|
if split_idx < self.pending_input.len() {
|
||||||
self.pending_input = self.pending_input[split_idx ..].to_string();
|
self.pending_input = self.pending_input[split_idx..].to_string();
|
||||||
} else {
|
} else {
|
||||||
self.pending_input.clear();
|
self.pending_input.clear();
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
@@ -211,8 +216,8 @@ fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteRe
|
|||||||
|
|
||||||
match &term {
|
match &term {
|
||||||
&TermRef::Cons(lvl, ..) => {
|
&TermRef::Cons(lvl, ..) => {
|
||||||
queue.push_back((2, h+1));
|
queue.push_back((2, h + 1));
|
||||||
machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
machine_st.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||||
|
|
||||||
push_stub_addr(machine_st);
|
push_stub_addr(machine_st);
|
||||||
push_stub_addr(machine_st);
|
push_stub_addr(machine_st);
|
||||||
@@ -220,25 +225,27 @@ 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());
|
||||||
|
|
||||||
machine_st.heap.push(named);
|
machine_st.heap.push(named);
|
||||||
|
|
||||||
for _ in 0 .. subterms.len() {
|
for _ in 0..subterms.len() {
|
||||||
push_stub_addr(machine_st);
|
push_stub_addr(machine_st);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use prolog::instructions::*;
|
|||||||
use prolog::iterators::*;
|
use prolog::iterators::*;
|
||||||
|
|
||||||
pub trait CompilationTarget<'a> {
|
pub trait CompilationTarget<'a> {
|
||||||
type Iterator : Iterator<Item=TermRef<'a>>;
|
type Iterator: Iterator<Item = TermRef<'a>>;
|
||||||
|
|
||||||
fn iter(&'a Term) -> Self::Iterator;
|
fn iter(&'a Term) -> Self::Iterator;
|
||||||
|
|
||||||
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,10 +29,10 @@ 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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,10 +40,8 @@ impl fmt::Display for REPLCodePtr {
|
|||||||
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,13 +136,18 @@ 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,9 +155,10 @@ impl fmt::Display for HeapCellValue {
|
|||||||
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,8 +171,8 @@ impl fmt::Display for Addr {
|
|||||||
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
||||||
&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,12 +232,15 @@ 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,25 +248,28 @@ impl fmt::Display for IndexingInstruction {
|
|||||||
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,
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3500
src/tests.rs
3500
src/tests.rs
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user