initial commit for merge
This commit is contained in:
@@ -399,23 +399,27 @@ impl Add<Number> for Number {
|
||||
|
||||
fn add(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 + n2)), // add_i
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Number::Integer(Rc::new(Integer::from(&*n1) + &*n2))) // add_i
|
||||
}
|
||||
(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)?))
|
||||
}
|
||||
(Number::Integer(n1), Number::Rational(n2))
|
||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||
Ok(Number::Rational(Rational::from(n1) + n2))
|
||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||
Ok(Number::Rational(Rc::new(Rational::from(&*n1) + &*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)?))
|
||||
}
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||
Ok(Number::Float(add_f(f1, f2)?))
|
||||
}
|
||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 + r2)),
|
||||
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||
Ok(Number::Rational(Rc::new(Rational::from(&*r1) + &*r2)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,9 +429,9 @@ impl Neg for Number {
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
match self {
|
||||
Number::Integer(n) => Number::Integer(-n),
|
||||
Number::Integer(n) => Number::Integer(Rc::new(-Integer::from(&*n))),
|
||||
Number::Float(OrderedFloat(f)) => Number::Float(OrderedFloat(-f)),
|
||||
Number::Rational(r) => Number::Rational(-r),
|
||||
Number::Rational(r) => Number::Rational(Rc::new(-Rational::from(&*r))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -445,14 +449,16 @@ impl Mul<Number> for Number {
|
||||
|
||||
fn mul(self, rhs: Number) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Number::Integer(n1 * n2)), // mul_i
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Number::Integer(Rc::new(Integer::from(&*n1) * &*n2))) // mul_i
|
||||
}
|
||||
(Number::Integer(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Integer(n1)) => {
|
||||
Ok(Number::Float(mul_f(float_i_to_f(&n1)?, n2)?))
|
||||
}
|
||||
(Number::Integer(n1), Number::Rational(n2))
|
||||
| (Number::Rational(n2), Number::Integer(n1)) => {
|
||||
Ok(Number::Rational(Rational::from(n1) * n2))
|
||||
Ok(Number::Rational(Rc::new(Rational::from(&*n1) * &*n2)))
|
||||
}
|
||||
(Number::Rational(n1), Number::Float(OrderedFloat(n2)))
|
||||
| (Number::Float(OrderedFloat(n2)), Number::Rational(n1)) => {
|
||||
@@ -461,7 +467,9 @@ impl Mul<Number> for Number {
|
||||
(Number::Float(OrderedFloat(f1)), Number::Float(OrderedFloat(f2))) => {
|
||||
Ok(Number::Float(mul_f(f1, f2)?))
|
||||
}
|
||||
(Number::Rational(r1), Number::Rational(r2)) => Ok(Number::Rational(r1 * r2)),
|
||||
(Number::Rational(r1), Number::Rational(r2)) => {
|
||||
Ok(Number::Rational(Rc::new(Rational::from(&*r1) * &*r2)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -539,8 +547,8 @@ impl Ord for Number {
|
||||
}
|
||||
|
||||
// Computes n ^ power. Ignores the sign of power.
|
||||
pub fn binary_pow(mut n: Integer, power: Integer) -> Integer {
|
||||
let mut power = power.abs();
|
||||
pub fn binary_pow(mut n: Integer, power: &Integer) -> Integer {
|
||||
let mut power = Integer::from(power.abs_ref());
|
||||
|
||||
if power == 0 {
|
||||
return Integer::from(1);
|
||||
|
||||
@@ -576,8 +576,8 @@ pub struct Module {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum Number {
|
||||
Float(OrderedFloat<f64>),
|
||||
Integer(Integer),
|
||||
Rational(Rational),
|
||||
Integer(Rc<Integer>),
|
||||
Rational(Rc<Rational>),
|
||||
}
|
||||
|
||||
impl Default for Number {
|
||||
@@ -586,48 +586,51 @@ impl Default for Number {
|
||||
}
|
||||
}
|
||||
|
||||
impl Number {
|
||||
pub fn to_constant(self) -> Constant {
|
||||
impl Into<HeapCellValue> for Number {
|
||||
#[inline]
|
||||
fn into(self) -> HeapCellValue {
|
||||
match self {
|
||||
Number::Integer(n) => Constant::Integer(n),
|
||||
Number::Float(f) => Constant::Float(f),
|
||||
Number::Rational(r) => Constant::Rational(r),
|
||||
Number::Integer(n) => HeapCellValue::Integer(n),
|
||||
Number::Float(f) => HeapCellValue::Addr(Addr::Float(f)),
|
||||
Number::Rational(r) => HeapCellValue::Rational(r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Number {
|
||||
#[inline]
|
||||
pub fn is_positive(&self) -> bool {
|
||||
match self {
|
||||
&Number::Integer(ref n) => n > &0,
|
||||
&Number::Integer(ref n) => &**n > &0,
|
||||
&Number::Float(OrderedFloat(f)) => f.is_sign_positive(),
|
||||
&Number::Rational(ref r) => r > &0,
|
||||
&Number::Rational(ref r) => &**r > &0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_negative(&self) -> bool {
|
||||
match self {
|
||||
&Number::Integer(ref n) => n < &0,
|
||||
&Number::Integer(ref n) => &**n < &0,
|
||||
&Number::Float(OrderedFloat(f)) => f.is_sign_negative(),
|
||||
&Number::Rational(ref r) => r < &0,
|
||||
&Number::Rational(ref r) => &**r < &0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
&Number::Integer(ref n) => n == &0,
|
||||
&Number::Integer(ref n) => &**n == &0,
|
||||
&Number::Float(f) => f == OrderedFloat(0f64),
|
||||
&Number::Rational(ref r) => r == &0,
|
||||
&Number::Rational(ref r) => &**r == &0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn abs(self) -> Self {
|
||||
match self {
|
||||
Number::Integer(n) => Number::Integer(n.abs()),
|
||||
Number::Integer(n) => Number::Integer(Rc::new(Integer::from(n.abs_ref()))),
|
||||
Number::Float(f) => Number::Float(OrderedFloat(f.abs())),
|
||||
Number::Rational(r) => Number::Rational(r.abs()),
|
||||
Number::Rational(r) => Number::Rational(Rc::new(Rational::from(r.abs_ref()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::*;
|
||||
|
||||
@@ -22,25 +20,33 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn machine_st(&self) -> &MachineState {
|
||||
&self.machine_st
|
||||
}
|
||||
|
||||
fn follow_heap(&mut self, h: usize) -> Addr {
|
||||
match &self.machine_st.heap[h] {
|
||||
HeapCellValue::NamedStr(arity, _, _) => {
|
||||
for idx in (1..arity + 1).rev() {
|
||||
&HeapCellValue::NamedStr(arity, _, _) => {
|
||||
for idx in (1 .. arity + 1).rev() {
|
||||
self.state_stack.push(Addr::HeapCell(h + idx));
|
||||
}
|
||||
|
||||
Addr::Str(h)
|
||||
}
|
||||
HeapCellValue::Addr(ref a) => {
|
||||
self.follow(a.clone())
|
||||
&HeapCellValue::Addr(a) => {
|
||||
self.follow(a)
|
||||
}
|
||||
HeapCellValue::PartialString(_) => {
|
||||
self.follow(Addr::PStrLocation(h, 0))
|
||||
}
|
||||
HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
|
||||
| HeapCellValue::Integer(_) | HeapCellValue::Rational(_) => {
|
||||
Addr::Con(h)
|
||||
}
|
||||
HeapCellValue::Stream(_) => {
|
||||
Addr::Stream(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,30 +57,6 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
let da = self.machine_st.store(self.machine_st.deref(addr));
|
||||
|
||||
match da {
|
||||
Addr::Con(Constant::String(n, s)) => {
|
||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
||||
if s.len() > n {
|
||||
if let Some(c) = s[n ..].chars().next() {
|
||||
let o = c.len_utf8();
|
||||
|
||||
self.state_stack.push(Addr::Con(Constant::String(n+o, s.clone())));
|
||||
|
||||
if self.machine_st.machine_flags().double_quotes.is_codes() {
|
||||
self.state_stack.push(Addr::Con(Constant::CharCode(c as u32)));
|
||||
} else {
|
||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Addr::Con(Constant::EmptyList);
|
||||
}
|
||||
}
|
||||
|
||||
Addr::Con(Constant::String(n, s))
|
||||
}
|
||||
Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
|
||||
da
|
||||
}
|
||||
Addr::Lis(a) => {
|
||||
self.state_stack.push(Addr::HeapCell(a + 1));
|
||||
self.state_stack.push(Addr::HeapCell(a));
|
||||
@@ -83,16 +65,14 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
}
|
||||
Addr::PStrLocation(h, n) => {
|
||||
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||
let s = pstr.block_as_str();
|
||||
|
||||
if let Some(c) = s[n ..].chars().next() {
|
||||
if pstr.len() > n + c.len_utf8() {
|
||||
if let Some(c) = pstr.range_from(n ..).next() {
|
||||
if !pstr.at_end(n + c.len_utf8()) {
|
||||
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
|
||||
} else {
|
||||
self.state_stack.push(Addr::HeapCell(h + 1));
|
||||
}
|
||||
|
||||
self.state_stack.push(Addr::Con(Constant::Char(c)));
|
||||
self.state_stack.push(Addr::Char(c));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
@@ -102,66 +82,52 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
|
||||
Addr::PStrLocation(h, n)
|
||||
}
|
||||
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
||||
da
|
||||
}
|
||||
Addr::Str(s) => {
|
||||
self.follow_heap(s) // record terms of structure.
|
||||
}
|
||||
Addr::Con(h) => {
|
||||
if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
|
||||
self.state_stack.push(Addr::HeapCell(h + 1));
|
||||
}
|
||||
|
||||
Addr::Con(h)
|
||||
}
|
||||
da => {
|
||||
da
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HCPreOrderIterator<'a> {
|
||||
type Item = HeapCellValue;
|
||||
type Item = Addr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.state_stack.pop().map(|a| match self.follow(a) {
|
||||
Addr::HeapCell(h) => {
|
||||
HeapCellValue::Addr(self.machine_st.heap[h].as_addr(h))
|
||||
}
|
||||
Addr::Str(s) => {
|
||||
match &self.machine_st.heap[s] {
|
||||
val @ HeapCellValue::NamedStr(..) => {
|
||||
val.clone()
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::StackCell(fr, sc) => {
|
||||
HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone())
|
||||
}
|
||||
da => {
|
||||
HeapCellValue::Addr(da)
|
||||
}
|
||||
})
|
||||
self.state_stack.pop().map(|a| self.follow(a))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MutStackHCIterator
|
||||
where
|
||||
Self: Iterator<Item = HeapCellValue>,
|
||||
where Self: Iterator<Item = Addr>
|
||||
{
|
||||
fn stack(&mut self) -> &mut Vec<Addr>;
|
||||
}
|
||||
|
||||
pub struct HCPostOrderIterator<HCIter> {
|
||||
base_iter: HCIter,
|
||||
parent_stack: Vec<(usize, HeapCellValue)>, // number of children, parent node.
|
||||
pub struct HCPostOrderIterator<'a> {
|
||||
base_iter: HCPreOrderIterator<'a>,
|
||||
parent_stack: Vec<(usize, Addr)>, // number of children, parent node.
|
||||
}
|
||||
|
||||
impl<HCIter> Deref for HCPostOrderIterator<HCIter> {
|
||||
type Target = HCIter;
|
||||
impl<'a> Deref for HCPostOrderIterator<'a> {
|
||||
type Target = HCPreOrderIterator<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base_iter
|
||||
}
|
||||
}
|
||||
|
||||
impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
||||
pub fn new(base_iter: HCIter) -> Self {
|
||||
impl<'a> HCPostOrderIterator<'a> {
|
||||
pub fn new(base_iter: HCPreOrderIterator<'a>) -> Self {
|
||||
HCPostOrderIterator {
|
||||
base_iter,
|
||||
parent_stack: vec![],
|
||||
@@ -169,8 +135,8 @@ impl<HCIter: Iterator<Item = HeapCellValue>> HCPostOrderIterator<HCIter> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HCIter> {
|
||||
type Item = HeapCellValue;
|
||||
impl<'a> Iterator for HCPostOrderIterator<'a> {
|
||||
type Item = Addr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
@@ -183,15 +149,23 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
||||
}
|
||||
|
||||
if let Some(item) = self.base_iter.next() {
|
||||
match item {
|
||||
HeapCellValue::NamedStr(arity, name, fix) => self
|
||||
.parent_stack
|
||||
.push((arity, HeapCellValue::NamedStr(arity, name, fix))),
|
||||
HeapCellValue::Addr(Addr::Lis(a)) => self
|
||||
.parent_stack
|
||||
.push((2, HeapCellValue::Addr(Addr::Lis(a)))),
|
||||
child_node => {
|
||||
return Some(child_node);
|
||||
match self.base_iter.machine_st.heap.index_addr(&item).as_ref() {
|
||||
&HeapCellValue::NamedStr(arity, ..) => {
|
||||
self.parent_stack.push((arity, item));
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::Lis(a)) => {
|
||||
self.parent_stack.push((2, Addr::Lis(a)));
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||
if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||
let c = pstr.range_from(n ..).next().unwrap();
|
||||
self.parent_stack.push((2, Addr::PStrLocation(h, n + c.len_utf8())));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Some(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -201,21 +175,16 @@ impl<HCIter: Iterator<Item = HeapCellValue>> Iterator for HCPostOrderIterator<HC
|
||||
}
|
||||
}
|
||||
|
||||
pub type HCProperPostOrderIterator<'a> = HCPostOrderIterator<HCPreOrderIterator<'a>>;
|
||||
|
||||
impl MachineState {
|
||||
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
|
||||
HCPreOrderIterator::new(self, a)
|
||||
}
|
||||
|
||||
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCProperPostOrderIterator<'a> {
|
||||
pub fn post_order_iter<'a>(&'a self, a: Addr) -> HCPostOrderIterator<'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<'a> {
|
||||
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
|
||||
}
|
||||
|
||||
@@ -223,7 +192,7 @@ impl MachineState {
|
||||
&'a self,
|
||||
a1: Addr,
|
||||
a2: Addr,
|
||||
) -> HCZippedAcyclicIterator<HCPreOrderIterator<'a>> {
|
||||
) -> HCZippedAcyclicIterator<'a> {
|
||||
HCZippedAcyclicIterator::new(
|
||||
HCPreOrderIterator::new(self, a1),
|
||||
HCPreOrderIterator::new(self, a2),
|
||||
@@ -237,13 +206,13 @@ impl<'a> MutStackHCIterator for HCPreOrderIterator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HCAcyclicIterator<HCIter> {
|
||||
iter: HCIter,
|
||||
pub struct HCAcyclicIterator<'a> {
|
||||
iter: HCPreOrderIterator<'a>,
|
||||
seen: IndexSet<Addr>,
|
||||
}
|
||||
|
||||
impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
||||
pub fn new(iter: HCIter) -> Self {
|
||||
impl<'a> HCAcyclicIterator<'a> {
|
||||
pub fn new(iter: HCPreOrderIterator<'a>) -> Self {
|
||||
HCAcyclicIterator {
|
||||
iter,
|
||||
seen: IndexSet::new(),
|
||||
@@ -251,19 +220,17 @@ impl<HCIter: MutStackHCIterator> HCAcyclicIterator<HCIter> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<HCIter> Deref for HCAcyclicIterator<HCIter> {
|
||||
type Target = HCIter;
|
||||
impl<'a> Deref for HCAcyclicIterator<'a> {
|
||||
type Target = HCPreOrderIterator<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.iter
|
||||
}
|
||||
}
|
||||
|
||||
impl<HCIter> Iterator for HCAcyclicIterator<HCIter>
|
||||
where
|
||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
||||
impl<'a> Iterator for HCAcyclicIterator<'a>
|
||||
{
|
||||
type Item = HeapCellValue;
|
||||
type Item = Addr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(addr) = self.iter.stack().pop() {
|
||||
@@ -279,15 +246,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HCZippedAcyclicIterator<HCIter> {
|
||||
i1: HCIter,
|
||||
i2: HCIter,
|
||||
pub struct HCZippedAcyclicIterator<'a> {
|
||||
i1: HCPreOrderIterator<'a>,
|
||||
i2: HCPreOrderIterator<'a>,
|
||||
seen: IndexSet<(Addr, Addr)>,
|
||||
pub first_to_expire: Ordering,
|
||||
}
|
||||
|
||||
impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
||||
pub fn new(i1: HCIter, i2: HCIter) -> Self {
|
||||
impl<'a> HCZippedAcyclicIterator<'a> {
|
||||
pub fn new(i1: HCPreOrderIterator<'a>, i2: HCPreOrderIterator<'a>) -> Self {
|
||||
HCZippedAcyclicIterator {
|
||||
i1,
|
||||
i2,
|
||||
@@ -297,11 +264,9 @@ impl<HCIter: MutStackHCIterator> HCZippedAcyclicIterator<HCIter> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<HCIter> Iterator for HCZippedAcyclicIterator<HCIter>
|
||||
where
|
||||
HCIter: Iterator<Item = HeapCellValue> + MutStackHCIterator,
|
||||
impl<'a> Iterator for HCZippedAcyclicIterator<'a>
|
||||
{
|
||||
type Item = (HeapCellValue, HeapCellValue);
|
||||
type Item = (Addr, Addr);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let (Some(a1), Some(a2)) = (self.i1.stack().pop(), self.i2.stack().pop()) {
|
||||
@@ -324,7 +289,9 @@ where
|
||||
self.first_to_expire = Ordering::Less;
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use prolog_parser::ast::*;
|
||||
use crate::prolog::clause_types::*;
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::heap_iter::*;
|
||||
use crate::prolog::machine::heap::*;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::*;
|
||||
use crate::prolog::ordered_float::OrderedFloat;
|
||||
@@ -88,14 +89,17 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
*/
|
||||
fn leftmost_leaf_has_property<P>(&self, property_check: P) -> bool
|
||||
where
|
||||
P: Fn(Constant) -> bool,
|
||||
P: Fn(Addr, &Heap) -> bool,
|
||||
{
|
||||
let mut addr = match self.state_stack.last().cloned() {
|
||||
Some(addr) => addr,
|
||||
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 {
|
||||
match self.machine_st.store(self.machine_st.deref(addr)) {
|
||||
@@ -110,29 +114,28 @@ impl<'a> HCPreOrderIterator<'a> {
|
||||
parent_spec = DirectedOp::Right(name.clone(), spec.clone());
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
_ => {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
Addr::Con(Constant::Integer(n)) => return property_check(Constant::Integer(n)),
|
||||
Addr::Con(Constant::Float(n)) => return property_check(Constant::Float(n)),
|
||||
Addr::Con(Constant::Rational(n)) => return property_check(Constant::Rational(n)),
|
||||
_ => return false,
|
||||
addr => {
|
||||
return property_check(addr, &self.machine_st.heap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn immediate_leaf_has_property<P>(&self, property_check: P) -> bool
|
||||
where
|
||||
P: Fn(Constant) -> bool,
|
||||
P: Fn(Addr, &Heap) -> bool,
|
||||
{
|
||||
let addr = match self.state_stack.last().cloned() {
|
||||
Some(addr) => addr,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
match self.machine_st.store(self.machine_st.deref(addr)) {
|
||||
Addr::Con(c) => property_check(c),
|
||||
_ => false,
|
||||
}
|
||||
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||
property_check(addr, &self.machine_st.heap)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,13 +264,29 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
|
||||
#[inline]
|
||||
fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool {
|
||||
if let &Some(ref op) = op {
|
||||
op.is_negative_sign()
|
||||
&& iter.leftmost_leaf_has_property(|c| match c {
|
||||
Constant::Integer(n) => n > 0,
|
||||
Constant::Float(f) => f > OrderedFloat(0f64),
|
||||
Constant::Rational(r) => r > 0,
|
||||
_ => false,
|
||||
})
|
||||
op.is_negative_sign() && iter.leftmost_leaf_has_property(|addr, heap| {
|
||||
match addr {
|
||||
Addr::Con(h) => {
|
||||
match &heap[h] {
|
||||
HeapCellValue::Integer(ref n) => {
|
||||
&**n > &0
|
||||
}
|
||||
&HeapCellValue::Rational(ref r) => {
|
||||
&**r > &0
|
||||
}
|
||||
_ => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Float(f) => {
|
||||
f > OrderedFloat(0f64)
|
||||
}
|
||||
_ => {
|
||||
false
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -293,8 +312,16 @@ fn numbervar(n: Integer) -> Var {
|
||||
impl MachineState {
|
||||
pub fn numbervar(&self, offset: &Integer, addr: Addr) -> Option<Var> {
|
||||
match self.store(self.deref(addr)) {
|
||||
Addr::Con(Constant::Integer(ref n)) if n >= &0 => {
|
||||
Some(numbervar(Integer::from(offset + n)))
|
||||
Addr::Con(h) => {
|
||||
if let &HeapCellValue::Integer(ref n) = &self.heap[h] {
|
||||
if &**n >= &0 {
|
||||
Some(numbervar(Integer::from(offset + &**n)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
@@ -823,7 +850,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
fn check_for_seen(
|
||||
&mut self,
|
||||
iter: &mut HCPreOrderIterator,
|
||||
) -> Option<HeapCellValue> {
|
||||
) -> Option<Addr> {
|
||||
iter.stack().last().cloned().and_then(|addr| {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||
|
||||
@@ -848,7 +875,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
}
|
||||
None => {
|
||||
let offset = match functor_location(&addr) {
|
||||
Some(offset) => offset,
|
||||
Some(offset) => {
|
||||
offset
|
||||
}
|
||||
None => {
|
||||
return iter.next();
|
||||
}
|
||||
@@ -969,7 +998,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
}
|
||||
|
||||
fn print_char(&mut self, is_quoted: bool, c: char)
|
||||
{
|
||||
{
|
||||
if non_quoted_token(once(c)) {
|
||||
let c = char_to_string(false, c);
|
||||
|
||||
@@ -993,178 +1022,130 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_constant(
|
||||
&mut self,
|
||||
iter: &mut HCPreOrderIterator,
|
||||
max_depth: usize,
|
||||
c: Constant,
|
||||
op: &Option<DirectedOp>,
|
||||
) {
|
||||
match c {
|
||||
Constant::Atom(atom, spec) => {
|
||||
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
|
||||
let mut result = String::new();
|
||||
|
||||
if let Some(ref op) = op {
|
||||
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
||||
result.push(' ');
|
||||
}
|
||||
|
||||
result.push('(');
|
||||
}
|
||||
|
||||
result += &self.print_op_addendum(atom.as_str());
|
||||
|
||||
if op.is_some() {
|
||||
result.push(')');
|
||||
}
|
||||
|
||||
push_space_if_amb!(self, &result, {
|
||||
self.append_str(&result);
|
||||
});
|
||||
} else {
|
||||
push_space_if_amb!(self, atom.as_str(), {
|
||||
self.print_atom(&atom);
|
||||
});
|
||||
}
|
||||
}
|
||||
Constant::CharCode(c) => {
|
||||
self.append_str(&format!("{}", c as u32));
|
||||
}
|
||||
Constant::Char(c) => {
|
||||
self.print_char(self.quoted, c);
|
||||
}
|
||||
Constant::CutPoint(b) => {
|
||||
self.append_str(&format!("{}", b));
|
||||
}
|
||||
Constant::EmptyList => {
|
||||
self.append_str("[]");
|
||||
}
|
||||
Constant::Integer(n) => {
|
||||
self.print_number(Number::Integer(n), op);
|
||||
}
|
||||
Constant::Float(n) => {
|
||||
self.print_number(Number::Float(n), op);
|
||||
}
|
||||
Constant::Rational(n) => {
|
||||
self.print_number(Number::Rational(n), op);
|
||||
}
|
||||
Constant::String(n, s) if self.print_strings_as_strs => {
|
||||
self.print_string_as_str(iter, n, s);
|
||||
}
|
||||
Constant::String(n, s) => {
|
||||
self.print_string(iter, max_depth, n, s);
|
||||
}
|
||||
Constant::Usize(i) => {
|
||||
self.append_str(&format!("u{}", i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_string_as_str(
|
||||
&mut self,
|
||||
iter: &mut HCPreOrderIterator,
|
||||
offset: usize,
|
||||
s: Rc<String>,
|
||||
mut h: usize,
|
||||
mut offset: usize,
|
||||
quoted: bool,
|
||||
) {
|
||||
let atom = String::from_iter(s[offset ..].chars().map(|c| {
|
||||
char_to_string(true, c)
|
||||
}));
|
||||
|
||||
self.push_char('"');
|
||||
self.append_str(&atom);
|
||||
self.push_char('"');
|
||||
|
||||
// eliminate lingering elements on the iterator stack (the
|
||||
// head and tail) which are there to treat the string as a
|
||||
// list.
|
||||
iter.stack().pop();
|
||||
iter.stack().pop();
|
||||
while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||
let atom = String::from_iter(pstr.range_from(offset ..).map(|c| {
|
||||
char_to_string(quoted, c)
|
||||
}));
|
||||
|
||||
self.append_str(&atom);
|
||||
|
||||
h += 2;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
self.push_char('"');
|
||||
}
|
||||
|
||||
fn print_string(
|
||||
&mut self,
|
||||
iter: &mut HCPreOrderIterator,
|
||||
mut max_depth: usize,
|
||||
offset: usize,
|
||||
s: Rc<String>)
|
||||
mut h: usize,
|
||||
mut offset: usize,
|
||||
)
|
||||
{
|
||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
||||
if self.check_max_depth(&mut max_depth) {
|
||||
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||
return;
|
||||
}
|
||||
|
||||
if s.len() <= offset && !self.at_cdr("") {
|
||||
self.append_str("[]");
|
||||
} else if self.ignore_ops {
|
||||
let mut char_count = 0;
|
||||
let mut byte_len = 0;
|
||||
|
||||
let iter: Box<dyn Iterator<Item=char>> =
|
||||
if self.max_depth == 0 {
|
||||
Box::new(s[offset ..].chars())
|
||||
|
||||
while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
|
||||
if pstr.at_end(offset) && !self.at_cdr("") {
|
||||
if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
|
||||
self.append_str("[]");
|
||||
break;
|
||||
} else {
|
||||
Box::new(s[offset ..].chars().take(max_depth))
|
||||
};
|
||||
h += 2;
|
||||
offset = 0;
|
||||
}
|
||||
} else if self.ignore_ops {
|
||||
let iter: Box<dyn Iterator<Item=char>> =
|
||||
if self.max_depth == 0 {
|
||||
Box::new(pstr.range_from(offset ..))
|
||||
} else {
|
||||
Box::new(pstr.range_from(offset ..).take(max_depth))
|
||||
};
|
||||
|
||||
for c in iter {
|
||||
self.print_char(self.quoted, '.');
|
||||
self.push_char('(');
|
||||
let mut char_count = 0;
|
||||
let mut byte_len = 0;
|
||||
|
||||
self.print_char(self.quoted, c);
|
||||
self.push_char(',');
|
||||
for c in iter {
|
||||
self.print_char(self.quoted, '.');
|
||||
self.push_char('(');
|
||||
|
||||
char_count += 1;
|
||||
byte_len += c.len_utf8();
|
||||
self.print_char(self.quoted, c);
|
||||
self.push_char(',');
|
||||
|
||||
char_count += 1;
|
||||
byte_len += c.len_utf8();
|
||||
}
|
||||
|
||||
let mut at_end = false;
|
||||
|
||||
if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
|
||||
self.append_str("...");
|
||||
at_end = true;
|
||||
} else {
|
||||
if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
|
||||
self.append_str("[]");
|
||||
at_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. char_count {
|
||||
self.push_char(')');
|
||||
}
|
||||
|
||||
if at_end {
|
||||
break;
|
||||
}
|
||||
|
||||
max_depth -= char_count;
|
||||
} else {
|
||||
self.push_char('[');
|
||||
|
||||
let iter: Box<dyn Iterator<Item=char>> =
|
||||
if self.max_depth == 0 {
|
||||
Box::new(pstr.range_from(offset ..))
|
||||
} else {
|
||||
Box::new(pstr.range_from(offset ..).take(max_depth))
|
||||
};
|
||||
|
||||
let mut byte_len = 0;
|
||||
let mut char_count = 0;
|
||||
|
||||
for c in iter {
|
||||
self.print_char(false, c);
|
||||
self.push_char(',');
|
||||
|
||||
byte_len += c.len_utf8();
|
||||
char_count += 1;
|
||||
}
|
||||
|
||||
if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
|
||||
self.append_str("...|...]");
|
||||
break;
|
||||
} else {
|
||||
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
||||
self.push_char(']');
|
||||
}
|
||||
|
||||
max_depth -= char_count;
|
||||
}
|
||||
|
||||
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
||||
self.append_str("...");
|
||||
} else {
|
||||
self.append_str("[]");
|
||||
}
|
||||
|
||||
for _ in 0 .. char_count {
|
||||
self.push_char(')');
|
||||
}
|
||||
} else {
|
||||
self.push_char('[');
|
||||
|
||||
let iter: Box<dyn Iterator<Item=char>> =
|
||||
if self.max_depth == 0 {
|
||||
Box::new(s[offset ..].chars())
|
||||
} else {
|
||||
Box::new(s[offset ..].chars().take(max_depth))
|
||||
};
|
||||
|
||||
let mut byte_len = 0;
|
||||
|
||||
for c in iter {
|
||||
self.print_char(false, c);
|
||||
self.push_char(',');
|
||||
|
||||
byte_len += c.len_utf8();
|
||||
}
|
||||
|
||||
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
||||
self.append_str("...|...]");
|
||||
} else {
|
||||
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
||||
self.push_char(']');
|
||||
}
|
||||
h += 2;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
iter.stack().pop();
|
||||
iter.stack().pop();
|
||||
} else {
|
||||
let atom = String::from_iter(s[offset ..].chars().map(|c| {
|
||||
char_to_string(self.quoted, c)
|
||||
}));
|
||||
|
||||
self.push_char('"');
|
||||
self.append_str(&atom);
|
||||
self.push_char('"');
|
||||
self.print_string_as_str(h, 0, self.quoted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1217,21 +1198,22 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
max_depth: usize,
|
||||
) {
|
||||
let add_brackets = if !self.ignore_ops {
|
||||
negated_operand
|
||||
|| if let Some(ref op) = op {
|
||||
if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
||||
!iter.immediate_leaf_has_property(|c| match c {
|
||||
Constant::Integer(n) => n >= 0,
|
||||
Constant::Float(f) => f >= OrderedFloat(0f64),
|
||||
Constant::Rational(r) => r >= 0,
|
||||
_ => false,
|
||||
}) && needs_bracketing(&spec, op)
|
||||
} else {
|
||||
needs_bracketing(&spec, op)
|
||||
}
|
||||
negated_operand || if let Some(ref op) = op {
|
||||
if self.numbervars && arity == 1 && name.as_str() == "$VAR" {
|
||||
!iter.immediate_leaf_has_property(|addr, heap| {
|
||||
match heap.index_addr(&addr).as_ref() {
|
||||
&HeapCellValue::Integer(ref n) => &**n >= &0,
|
||||
&HeapCellValue::Addr(Addr::Float(f)) => f >= OrderedFloat(0f64),
|
||||
&HeapCellValue::Rational(ref r) => &**r >= &0,
|
||||
_ => false
|
||||
}
|
||||
}) && needs_bracketing(&spec, op)
|
||||
} else {
|
||||
is_functor_redirect && spec.prec() >= 1000
|
||||
needs_bracketing(&spec, op)
|
||||
}
|
||||
} else {
|
||||
is_functor_redirect && spec.prec() >= 1000
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
@@ -1264,49 +1246,134 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
) {
|
||||
let negated_operand = negated_op_needs_bracketing(iter, &op);
|
||||
|
||||
let heap_val = match self.check_for_seen(iter) {
|
||||
Some(heap_val) => heap_val,
|
||||
let addr = match self.check_for_seen(iter) {
|
||||
Some(addr) => addr,
|
||||
None => return,
|
||||
};
|
||||
|
||||
match heap_val {
|
||||
HeapCellValue::NamedStr(arity, name, spec) => {
|
||||
|
||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
|
||||
let spec = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir);
|
||||
|
||||
if let Some(spec) = spec {
|
||||
self.handle_op_as_struct(
|
||||
name,
|
||||
name.clone(),
|
||||
arity,
|
||||
iter,
|
||||
&op,
|
||||
is_functor_redirect,
|
||||
spec,
|
||||
spec.clone(),
|
||||
negated_operand,
|
||||
max_depth,
|
||||
);
|
||||
} else {
|
||||
push_space_if_amb!(self, name.as_str(), {
|
||||
let ct = ClauseType::from(name, arity, spec);
|
||||
let ct = ClauseType::from(name.clone(), arity, spec);
|
||||
self.format_clause(iter, max_depth, arity, ct);
|
||||
});
|
||||
}
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => {
|
||||
&HeapCellValue::Atom(ref atom, ref spec) => {
|
||||
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec.clone(), self.op_dir) {
|
||||
let mut result = String::new();
|
||||
|
||||
if let Some(ref op) = op {
|
||||
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
||||
result.push(' ');
|
||||
}
|
||||
|
||||
result.push('(');
|
||||
}
|
||||
|
||||
result += &self.print_op_addendum(atom.as_str());
|
||||
|
||||
if op.is_some() {
|
||||
result.push(')');
|
||||
}
|
||||
|
||||
push_space_if_amb!(self, &result, {
|
||||
self.append_str(&result);
|
||||
});
|
||||
} else {
|
||||
push_space_if_amb!(self, atom.as_str(), {
|
||||
self.print_atom(&atom);
|
||||
});
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::CharCode(c)) => {
|
||||
self.append_str(&format!("{}", c as u32));
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::Char(c)) => {
|
||||
self.print_char(self.quoted, c);
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::CutPoint(b)) => {
|
||||
self.append_str(&format!("{}", b));
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::EmptyList) => {
|
||||
if !self.at_cdr("") {
|
||||
self.append_str("[]");
|
||||
}
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Con(c)) => {
|
||||
self.print_constant(iter, max_depth, c, &op);
|
||||
&HeapCellValue::Addr(Addr::Float(n)) => {
|
||||
self.print_number(Number::Float(n), &op);
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Lis(_)) | HeapCellValue::Addr(Addr::PStrLocation(..)) => {
|
||||
&HeapCellValue::Addr(Addr::Usize(u)) => {
|
||||
self.append_str(&format!("{}", u));
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::PStrLocation(..))
|
||||
if !self.machine_st.flags.double_quotes.is_atom() => {
|
||||
if self.ignore_ops {
|
||||
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
||||
} else {
|
||||
self.push_list(iter, max_depth);
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
|
||||
if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
|
||||
self.print_string(max_depth, h, n);
|
||||
|
||||
iter.stack().pop();
|
||||
iter.stack().pop();
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::Lis(_)) => {
|
||||
if self.ignore_ops {
|
||||
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
||||
} else {
|
||||
self.push_list(iter, max_depth);
|
||||
}
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Stream(stream)) => {
|
||||
&HeapCellValue::Addr(addr) => {
|
||||
if let Some(offset_str) = self.offset_as_string(iter, addr) {
|
||||
push_space_if_amb!(self, &offset_str, {
|
||||
self.append_str(offset_str.as_str());
|
||||
})
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
self.print_number(Number::Integer(n.clone()), &op);
|
||||
}
|
||||
&HeapCellValue::Rational(ref n) => {
|
||||
self.print_number(Number::Rational(n.clone()), &op);
|
||||
}
|
||||
&HeapCellValue::PartialString(_)
|
||||
if self.print_strings_as_strs => {
|
||||
if let Addr::Con(h) = addr {
|
||||
self.print_string_as_str(h, 0, true);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
&HeapCellValue::PartialString(_) => {
|
||||
if let Addr::Con(h) = addr {
|
||||
self.print_string(max_depth, h, 0);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Stream(ref stream) => {
|
||||
if let Some(alias) = &stream.options.alias {
|
||||
self.print_atom(alias);
|
||||
} else {
|
||||
@@ -1317,17 +1384,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapCellValue::Addr(addr) => {
|
||||
if let Some(offset_str) = self.offset_as_string(iter, addr) {
|
||||
push_space_if_amb!(self, &offset_str, {
|
||||
self.append_str(offset_str.as_str());
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// This is the partial string case. We never clone a partial string
|
||||
// for printing purposes, so.. this.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,11 @@ impl CodeOffsets {
|
||||
let is_initial_index = self.lists.is_empty();
|
||||
self.lists.push(Self::add_index(is_initial_index, index));
|
||||
}
|
||||
&Term::Constant(_, Constant::String(n, ref s)) => {
|
||||
&Term::Constant(_, Constant::String(ref s)) => {
|
||||
let is_initial_index = self.lists.is_empty();
|
||||
self.lists.push(Self::add_index(is_initial_index, index));
|
||||
|
||||
let constant = Constant::String(n, s.clone());
|
||||
let constant = Constant::String(s.clone());
|
||||
let code = self.constants.entry(constant).or_insert(Vec::new());
|
||||
|
||||
let is_initial_index = code.is_empty();
|
||||
@@ -75,9 +75,11 @@ impl CodeOffsets {
|
||||
}
|
||||
&Term::Constant(_, ref constant) => {
|
||||
if let Constant::Atom(ref name, _) = constant {
|
||||
if !name.as_str().is_empty() && name.as_str().chars().skip(1).next().is_none() {
|
||||
if name.is_char() {
|
||||
let c = name.as_str().chars().next().unwrap();
|
||||
let code = self.constants.entry(Constant::Char(c)).or_insert(vec![]);
|
||||
let code = self.constants
|
||||
.entry(Constant::Char(c))
|
||||
.or_insert(vec![]);
|
||||
|
||||
code.push(Self::add_index(code.is_empty(), index));
|
||||
}
|
||||
|
||||
@@ -2,28 +2,29 @@ use prolog_parser::ast::*;
|
||||
|
||||
use crate::prolog::clause_types::*;
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::machine::heap::*;
|
||||
use crate::prolog::machine::machine_errors::MachineStub;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
|
||||
use crate::prolog::rug::Integer;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn reg_type_into_functor(r: RegType) -> MachineStub {
|
||||
match r {
|
||||
RegType::Temp(r) => functor!("x", 1, [heap_integer!(Integer::from(r))]),
|
||||
RegType::Perm(r) => functor!("y", 1, [heap_integer!(Integer::from(r))]),
|
||||
RegType::Temp(r) => functor!("x", [integer(r)]),
|
||||
RegType::Perm(r) => functor!("y", [integer(r)]),
|
||||
}
|
||||
}
|
||||
|
||||
impl Level {
|
||||
fn into_functor(self) -> MachineStub {
|
||||
match self {
|
||||
Level::Root => functor!("level", 1, [heap_atom!("root")]),
|
||||
Level::Shallow => functor!("level", 1, [heap_atom!("shallow")]),
|
||||
Level::Deep => functor!("level", 1, [heap_atom!("deep")]),
|
||||
Level::Root => functor!("level", [atom("root")]),
|
||||
Level::Shallow => functor!("level", [atom("shallow")]),
|
||||
Level::Deep => functor!("level", [atom("deep")]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,11 +32,15 @@ impl Level {
|
||||
impl ArithmeticTerm {
|
||||
fn into_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
&ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
|
||||
&ArithmeticTerm::Interm(i) => {
|
||||
functor!("intermediate", 1, [heap_integer!(Integer::from(i))])
|
||||
&ArithmeticTerm::Reg(r) => {
|
||||
reg_type_into_functor(r)
|
||||
}
|
||||
&ArithmeticTerm::Interm(i) => {
|
||||
functor!("intermediate", [integer(i)])
|
||||
}
|
||||
&ArithmeticTerm::Number(ref n) => {
|
||||
vec![n.clone().into()]
|
||||
}
|
||||
&ArithmeticTerm::Number(ref n) => vec![heap_con!(n.clone().to_constant())],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,18 +57,20 @@ impl ChoiceInstruction {
|
||||
pub fn to_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
&ChoiceInstruction::TryMeElse(offset) => {
|
||||
functor!("try_me_else", 1, [heap_integer!(Integer::from(offset))])
|
||||
functor!("try_me_else", [integer(offset)])
|
||||
}
|
||||
&ChoiceInstruction::RetryMeElse(offset) => {
|
||||
functor!("retry_me_else", 1, [heap_integer!(Integer::from(offset))])
|
||||
functor!("retry_me_else", [integer(offset)])
|
||||
}
|
||||
&ChoiceInstruction::TrustMe => {
|
||||
functor!("trust_me")
|
||||
}
|
||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => {
|
||||
functor!("default_retry_me_else", [integer(offset)])
|
||||
}
|
||||
&ChoiceInstruction::DefaultTrustMe => {
|
||||
functor!("default_trust_me")
|
||||
}
|
||||
&ChoiceInstruction::TrustMe => vec![heap_atom!("trust_me")],
|
||||
&ChoiceInstruction::DefaultRetryMeElse(offset) => functor!(
|
||||
"default_retry_me_else",
|
||||
1,
|
||||
[heap_integer!(Integer::from(offset))]
|
||||
),
|
||||
&ChoiceInstruction::DefaultTrustMe => vec![heap_atom!("default_trust_me")],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,21 +86,20 @@ impl CutInstruction {
|
||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||
match self {
|
||||
&CutInstruction::Cut(r) => {
|
||||
let mut stub = functor!("cut", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
functor!("cut", [aux(h, 0)], [rt_stub])
|
||||
}
|
||||
&CutInstruction::GetLevel(r) => {
|
||||
let mut stub = functor!("get_level", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
functor!("get_level", [aux(h, 0)], [rt_stub])
|
||||
}
|
||||
&CutInstruction::GetLevelAndUnify(r) => {
|
||||
let mut stub = functor!("get_level_and_unify", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
functor!("get_level_and_unify", [aux(h, 0)], [rt_stub])
|
||||
}
|
||||
&CutInstruction::NeckCut => {
|
||||
functor!("neck_cut")
|
||||
}
|
||||
&CutInstruction::NeckCut => vec![heap_atom!("neck_cut")],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,13 +128,13 @@ impl IndexedChoiceInstruction {
|
||||
pub fn to_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
&IndexedChoiceInstruction::Try(offset) => {
|
||||
functor!("try", 1, [heap_integer!(Integer::from(offset))])
|
||||
functor!("try", [integer(offset)])
|
||||
}
|
||||
&IndexedChoiceInstruction::Trust(offset) => {
|
||||
functor!("trust", 1, [heap_integer!(Integer::from(offset))])
|
||||
functor!("trust", [integer(offset)])
|
||||
}
|
||||
&IndexedChoiceInstruction::Retry(offset) => {
|
||||
functor!("retry", 1, [heap_integer!(Integer::from(offset))])
|
||||
functor!("retry", [integer(offset)])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,15 +225,12 @@ fn arith_instr_unary_functor(
|
||||
t: usize,
|
||||
) -> MachineStub {
|
||||
let at_stub = at.into_functor();
|
||||
|
||||
let mut stub = functor!(
|
||||
|
||||
functor!(
|
||||
name,
|
||||
2,
|
||||
[heap_cell!(h + 4), heap_integer!(Integer::from(t))]
|
||||
);
|
||||
|
||||
stub.extend(at_stub.into_iter());
|
||||
stub
|
||||
[aux(h, 0), integer(t)],
|
||||
[at_stub]
|
||||
)
|
||||
}
|
||||
|
||||
fn arith_instr_bin_functor(
|
||||
@@ -240,20 +243,11 @@ fn arith_instr_bin_functor(
|
||||
let at_1_stub = at_1.into_functor();
|
||||
let at_2_stub = at_2.into_functor();
|
||||
|
||||
let mut stub = functor!(
|
||||
name,
|
||||
3,
|
||||
[
|
||||
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_2_stub.into_iter());
|
||||
|
||||
stub
|
||||
functor!(
|
||||
name,
|
||||
[aux(h, 0), aux(h, 1), integer(t)],
|
||||
[at_1_stub, at_2_stub]
|
||||
)
|
||||
}
|
||||
|
||||
impl ArithmeticInstruction {
|
||||
@@ -319,17 +313,39 @@ impl ArithmeticInstruction {
|
||||
&ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
|
||||
arith_instr_bin_functor(h, "gcd", at_1, at_2, t)
|
||||
}
|
||||
&ArithmeticInstruction::Sign(ref at, t) => arith_instr_unary_functor(h, "sign", at, t),
|
||||
&ArithmeticInstruction::Cos(ref at, t) => arith_instr_unary_functor(h, "cos", at, t),
|
||||
&ArithmeticInstruction::Sin(ref at, t) => arith_instr_unary_functor(h, "sin", at, t),
|
||||
&ArithmeticInstruction::Tan(ref at, t) => arith_instr_unary_functor(h, "tan", at, t),
|
||||
&ArithmeticInstruction::Log(ref at, t) => arith_instr_unary_functor(h, "log", at, t),
|
||||
&ArithmeticInstruction::Exp(ref at, t) => arith_instr_unary_functor(h, "exp", at, t),
|
||||
&ArithmeticInstruction::ACos(ref at, t) => arith_instr_unary_functor(h, "acos", at, t),
|
||||
&ArithmeticInstruction::ASin(ref at, t) => arith_instr_unary_functor(h, "asin", at, t),
|
||||
&ArithmeticInstruction::ATan(ref at, t) => arith_instr_unary_functor(h, "atan", at, t),
|
||||
&ArithmeticInstruction::Sqrt(ref at, t) => arith_instr_unary_functor(h, "sqrt", at, t),
|
||||
&ArithmeticInstruction::Abs(ref at, t) => arith_instr_unary_functor(h, "abs", at, t),
|
||||
&ArithmeticInstruction::Sign(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "sign", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Cos(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "cos", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Sin(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "sin", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Tan(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "tan", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Log(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "log", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Exp(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "exp", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::ACos(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "acos", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::ASin(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "asin", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::ATan(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "atan", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Sqrt(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "sqrt", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Abs(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "abs", at, t)
|
||||
}
|
||||
&ArithmeticInstruction::Float(ref at, t) => {
|
||||
arith_instr_unary_functor(h, "float", at, t)
|
||||
}
|
||||
@@ -345,8 +361,12 @@ impl ArithmeticInstruction {
|
||||
&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::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)
|
||||
}
|
||||
@@ -378,29 +398,23 @@ impl ControlInstruction {
|
||||
pub fn to_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
&ControlInstruction::Allocate(num_frames) => {
|
||||
functor!("allocate", 1, [heap_integer!(Integer::from(num_frames))])
|
||||
functor!("allocate", [integer(num_frames)])
|
||||
}
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
|
||||
functor!("call", [clause_name(ct.name()), integer(arity)])
|
||||
}
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
|
||||
functor!("execute", [clause_name(ct.name()), integer(arity)])
|
||||
}
|
||||
&ControlInstruction::Deallocate => {
|
||||
functor!("deallocate")
|
||||
}
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, false, _) => functor!(
|
||||
"call",
|
||||
2,
|
||||
[
|
||||
heap_con!(Constant::Atom(ct.name(), None)),
|
||||
heap_integer!(Integer::from(arity))
|
||||
]
|
||||
),
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, true, _) => functor!(
|
||||
"execute",
|
||||
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))])
|
||||
functor!("jmp_by", [integer(offset)])
|
||||
}
|
||||
&ControlInstruction::Proceed => {
|
||||
functor!("proceed")
|
||||
}
|
||||
&ControlInstruction::Proceed => vec![heap_atom!("proceed")],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,26 +434,27 @@ impl From<IndexingInstruction> for Line {
|
||||
impl IndexingInstruction {
|
||||
pub fn to_functor(&self) -> MachineStub {
|
||||
match self {
|
||||
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => functor!(
|
||||
"switch_on_term",
|
||||
4,
|
||||
[
|
||||
heap_integer!(Integer::from(vars)),
|
||||
heap_integer!(Integer::from(constants)),
|
||||
heap_integer!(Integer::from(lists)),
|
||||
heap_integer!(Integer::from(structures))
|
||||
]
|
||||
),
|
||||
&IndexingInstruction::SwitchOnConstant(constants, _) => functor!(
|
||||
"switch_on_constant",
|
||||
1,
|
||||
[heap_integer!(Integer::from(constants))]
|
||||
),
|
||||
&IndexingInstruction::SwitchOnStructure(structures, _) => functor!(
|
||||
"switch_on_structure",
|
||||
1,
|
||||
[heap_integer!(Integer::from(structures))]
|
||||
),
|
||||
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
|
||||
functor!(
|
||||
"switch_on_term",
|
||||
[integer(vars),
|
||||
integer(constants),
|
||||
integer(lists),
|
||||
integer(structures)]
|
||||
)
|
||||
}
|
||||
&IndexingInstruction::SwitchOnConstant(constants, _) => {
|
||||
functor!(
|
||||
"switch_on_constant",
|
||||
[integer(constants)]
|
||||
)
|
||||
}
|
||||
&IndexingInstruction::SwitchOnStructure(structures, _) => {
|
||||
functor!(
|
||||
"switch_on_structure",
|
||||
[integer(structures)]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -461,86 +476,85 @@ pub enum FactInstruction {
|
||||
impl FactInstruction {
|
||||
pub fn to_functor(&self, h: usize) -> MachineStub {
|
||||
match self {
|
||||
&FactInstruction::GetConstant(lvl, ref constant, r) => {
|
||||
let mut stub = functor!(
|
||||
&FactInstruction::GetConstant(lvl, ref c, r) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"get_constant",
|
||||
3,
|
||||
[
|
||||
heap_str!(h + 4),
|
||||
heap_con!(constant.clone()),
|
||||
heap_str!(h + 6)
|
||||
]
|
||||
);
|
||||
|
||||
stub.append(&mut lvl.into_functor());
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
|
||||
stub
|
||||
[aux(h, 0), constant(c), aux(h, 1)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetList(lvl, r) => {
|
||||
let mut stub = functor!("get_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
||||
stub.append(&mut lvl.into_functor());
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub
|
||||
functor!(
|
||||
"get_list",
|
||||
[aux(h, 0), aux(h, 1)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetStructure(ref ct, arity, r) => {
|
||||
let mut stub = functor!(
|
||||
"get_structure",
|
||||
3,
|
||||
[
|
||||
heap_con!(Constant::Atom(ct.name(), None)),
|
||||
heap_integer!(Integer::from(arity)),
|
||||
heap_str!(h + 4)
|
||||
]
|
||||
);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub
|
||||
functor!(
|
||||
"get_structure",
|
||||
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetValue(r, arg) => {
|
||||
let mut stub = functor!(
|
||||
"get_value",
|
||||
2,
|
||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
||||
);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub
|
||||
functor!(
|
||||
"get_value",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::GetVariable(r, arg) => {
|
||||
let mut stub = functor!(
|
||||
"get_variable",
|
||||
2,
|
||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
||||
);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub
|
||||
functor!(
|
||||
"get_variable",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::UnifyConstant(ref constant) => {
|
||||
functor!("unify_constant", 1, [heap_con!(constant.clone())])
|
||||
&FactInstruction::UnifyConstant(ref c) => {
|
||||
functor!("unify_constant", [constant(c)], [])
|
||||
}
|
||||
&FactInstruction::UnifyLocalValue(r) => {
|
||||
let mut stub = functor!("unify_local_value", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"unify_local_value",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::UnifyVariable(r) => {
|
||||
let mut stub = functor!("unify_variable", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub
|
||||
functor!(
|
||||
"unify_variable",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::UnifyValue(r) => {
|
||||
let mut stub = functor!("unify_value", 1, [heap_str!(h + 2)]);
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"unify_value",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&FactInstruction::UnifyVoid(vars) => {
|
||||
functor!("unify_void", 1, [heap_integer!(Integer::from(vars))])
|
||||
functor!("unify_void", [integer(vars)])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,103 +581,96 @@ impl QueryInstruction {
|
||||
match self {
|
||||
&QueryInstruction::PutUnsafeValue(norm, arg) => functor!(
|
||||
"put_unsafe_value",
|
||||
2,
|
||||
[
|
||||
heap_integer!(Integer::from(norm)),
|
||||
heap_integer!(Integer::from(arg))
|
||||
]
|
||||
[integer(norm), integer(arg)]
|
||||
),
|
||||
&QueryInstruction::PutConstant(lvl, ref constant, r) => {
|
||||
let mut stub = functor!(
|
||||
&QueryInstruction::PutConstant(lvl, ref c, r) => {
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"put_constant",
|
||||
3,
|
||||
[
|
||||
heap_str!(h + 4),
|
||||
heap_con!(constant.clone()),
|
||||
heap_str!(h + 6)
|
||||
]
|
||||
);
|
||||
|
||||
stub.append(&mut lvl.into_functor());
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
|
||||
stub
|
||||
[aux(h, 0), constant(c), aux(h, 1)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutList(lvl, r) => {
|
||||
let mut stub = functor!("put_list", 2, [heap_str!(h + 3), heap_str!(h + 5)]);
|
||||
|
||||
stub.append(&mut lvl.into_functor());
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
|
||||
stub
|
||||
let lvl_stub = lvl.into_functor();
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"put_list",
|
||||
[aux(h, 0), aux(h, 1)],
|
||||
[lvl_stub, rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutStructure(ref ct, arity, r) => {
|
||||
let mut stub = functor!(
|
||||
"put_structure",
|
||||
3,
|
||||
[
|
||||
heap_con!(Constant::Atom(ct.name(), None)),
|
||||
heap_integer!(Integer::from(arity)),
|
||||
heap_str!(h + 4)
|
||||
]
|
||||
);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"put_structure",
|
||||
[clause_name(ct.name()), integer(arity), aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutValue(r, arg) => {
|
||||
let mut stub = functor!(
|
||||
"put_value",
|
||||
2,
|
||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
||||
);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"put_value",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::GetVariable(r, arg) => {
|
||||
let mut stub = functor!(
|
||||
"get_variable",
|
||||
2,
|
||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
||||
);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"get_variable",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::PutVariable(r, arg) => {
|
||||
let mut stub = functor!(
|
||||
"put_variable",
|
||||
2,
|
||||
[heap_str!(h + 3), heap_integer!(Integer::from(arg))]
|
||||
);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"put_variable",
|
||||
[aux(h, 0), integer(arg)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::SetConstant(ref constant) => {
|
||||
functor!("set_constant", 1, [heap_con!(constant.clone())])
|
||||
&QueryInstruction::SetConstant(ref c) => {
|
||||
functor!("set_constant", [constant(c)], [])
|
||||
}
|
||||
&QueryInstruction::SetLocalValue(r) => {
|
||||
let mut stub = functor!("set_local_value", 1, [heap_str!(h + 2)]);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
functor!(
|
||||
"set_local_value",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::SetVariable(r) => {
|
||||
let mut stub = functor!("set_variable", 1, [heap_str!(h + 2)]);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"set_variable",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::SetValue(r) => {
|
||||
let mut stub = functor!("set_value", 1, [heap_str!(h + 2)]);
|
||||
let rt_stub = reg_type_into_functor(r);
|
||||
|
||||
stub.append(&mut reg_type_into_functor(r));
|
||||
stub
|
||||
functor!(
|
||||
"set_value",
|
||||
[aux(h, 0)],
|
||||
[rt_stub]
|
||||
)
|
||||
}
|
||||
&QueryInstruction::SetVoid(vars) => {
|
||||
functor!("set_void", 1, [heap_integer!(Integer::from(vars))])
|
||||
functor!("set_void", [integer(vars)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
786
src/prolog/machine/arithmetic_ops.rs
Normal file
786
src/prolog/machine/arithmetic_ops.rs
Normal file
@@ -0,0 +1,786 @@
|
||||
use crate::prolog_parser::ast::*;
|
||||
|
||||
use crate::prolog::arithmetic::*;
|
||||
use crate::prolog::clause_types::*;
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::machine::machine_errors::*;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::*;
|
||||
use crate::prolog::ordered_float::*;
|
||||
use crate::prolog::rug::{Integer, Rational};
|
||||
|
||||
use std::cmp;
|
||||
use std::f64;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try_numeric_result {
|
||||
($s: ident, $e: expr, $caller: expr) => (
|
||||
match $e {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Err(e) => {
|
||||
let caller_copy =
|
||||
$caller.iter().map(|v| v.context_free_clone()).collect();
|
||||
|
||||
Err($s.error_form(MachineError::evaluation_error(e), caller_copy))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(crate)
|
||||
fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
|
||||
match at {
|
||||
&ArithmeticTerm::Reg(r) => {
|
||||
self.arith_eval_by_metacall(r)
|
||||
}
|
||||
&ArithmeticTerm::Interm(i) => Ok(mem::replace(
|
||||
&mut self.interms[i - 1],
|
||||
Number::Integer(Rc::new(Integer::from(0))),
|
||||
)),
|
||||
&ArithmeticTerm::Number(ref n) => {
|
||||
Ok(n.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn rational_from_number(
|
||||
&self,
|
||||
n: Number,
|
||||
) -> Result<Rc<Rational>, MachineError> {
|
||||
match n {
|
||||
Number::Rational(r) => {
|
||||
Ok(r)
|
||||
}
|
||||
Number::Float(OrderedFloat(f)) => {
|
||||
match Rational::from_f64(f) {
|
||||
Some(r) => {
|
||||
Ok(Rc::new(r))
|
||||
}
|
||||
None => {
|
||||
Err(MachineError::instantiation_error())
|
||||
}
|
||||
}
|
||||
}
|
||||
Number::Integer(n) => {
|
||||
Ok(Rc::new(Rational::from(&*n)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn get_rational(
|
||||
&mut self,
|
||||
at: &ArithmeticTerm,
|
||||
caller: MachineStub,
|
||||
) -> Result<(Rc<Rational>, MachineStub), MachineStub> {
|
||||
let n = self.get_number(at)?;
|
||||
|
||||
match self.rational_from_number(n) {
|
||||
Ok(r) => Ok((r, caller)),
|
||||
Err(e) => Err(self.error_form(e, caller))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, MachineStub> {
|
||||
let a = self[r].clone();
|
||||
|
||||
let caller = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
let mut interms: Vec<Number> = Vec::with_capacity(64);
|
||||
|
||||
for addr in self.post_order_iter(a) {
|
||||
match self.heap.index_addr(&addr).as_ref() {
|
||||
&HeapCellValue::NamedStr(2, ref name, _) => {
|
||||
let a2 = interms.pop().unwrap();
|
||||
let a1 = interms.pop().unwrap();
|
||||
|
||||
match name.as_str() {
|
||||
"+" => interms.push(try_numeric_result!(self, a1 + a2, caller)?),
|
||||
"-" => interms.push(try_numeric_result!(self, a1 - a2, caller)?),
|
||||
"*" => interms.push(try_numeric_result!(self, a1 * a2, caller)?),
|
||||
"/" => interms.push(self.div(a1, a2)?),
|
||||
"**" => interms.push(self.pow(a1, a2, "(is)")?),
|
||||
"^" => interms.push(self.int_pow(a1, a2)?),
|
||||
"max" => interms.push(self.max(a1, a2)?),
|
||||
"min" => interms.push(self.min(a1, a2)?),
|
||||
"rdiv" => {
|
||||
let r1 = self.rational_from_number(a1);
|
||||
let r2 = r1.and_then(|r1| {
|
||||
self.rational_from_number(a2).map(|r2| (r1, r2))
|
||||
});
|
||||
|
||||
match r2 {
|
||||
Ok((r1, r2)) => {
|
||||
let result = Number::Rational(Rc::new(self.rdiv(r1, r2)?));
|
||||
interms.push(result);
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(self.error_form(e, caller));
|
||||
}
|
||||
}
|
||||
}
|
||||
"//" => interms.push(Number::Integer(Rc::new(self.idiv(a1, a2)?))),
|
||||
"div" => interms.push(Number::Integer(Rc::new(self.int_floor_div(a1, a2)?))),
|
||||
">>" => interms.push(Number::Integer(Rc::new(self.shr(a1, a2)?))),
|
||||
"<<" => interms.push(Number::Integer(Rc::new(self.shl(a1, a2)?))),
|
||||
"/\\" => interms.push(Number::Integer(Rc::new(self.and(a1, a2)?))),
|
||||
"\\/" => interms.push(Number::Integer(Rc::new(self.or(a1, a2)?))),
|
||||
"xor" => interms.push(Number::Integer(Rc::new(self.xor(a1, a2)?))),
|
||||
"mod" => interms.push(Number::Integer(Rc::new(self.modulus(a1, a2)?))),
|
||||
"rem" => interms.push(Number::Integer(Rc::new(self.remainder(a1, a2)?))),
|
||||
"atan2" => interms.push(Number::Float(OrderedFloat(self.atan2(a1, a2)?))),
|
||||
"gcd" => interms.push(Number::Integer(Rc::new(self.gcd(a1, a2)?))),
|
||||
_ => {
|
||||
return Err(self.error_form(MachineError::instantiation_error(), caller))
|
||||
}
|
||||
}
|
||||
}
|
||||
&HeapCellValue::NamedStr(1, ref name, _) => {
|
||||
let a1 = interms.pop().unwrap();
|
||||
|
||||
match name.as_str() {
|
||||
"-" => interms.push(-a1),
|
||||
"+" => interms.push(a1),
|
||||
"cos" => interms.push(Number::Float(OrderedFloat(self.cos(a1)?))),
|
||||
"sin" => interms.push(Number::Float(OrderedFloat(self.sin(a1)?))),
|
||||
"tan" => interms.push(Number::Float(OrderedFloat(self.tan(a1)?))),
|
||||
"sqrt" => interms.push(Number::Float(OrderedFloat(self.sqrt(a1)?))),
|
||||
"log" => interms.push(Number::Float(OrderedFloat(self.log(a1)?))),
|
||||
"exp" => interms.push(Number::Float(OrderedFloat(self.exp(a1)?))),
|
||||
"acos" => interms.push(Number::Float(OrderedFloat(self.acos(a1)?))),
|
||||
"asin" => interms.push(Number::Float(OrderedFloat(self.asin(a1)?))),
|
||||
"atan" => interms.push(Number::Float(OrderedFloat(self.atan(a1)?))),
|
||||
"abs" => interms.push(a1.abs()),
|
||||
"float" => interms.push(Number::Float(OrderedFloat(self.float(a1)?))),
|
||||
"truncate" => interms.push(Number::Integer(Rc::new(self.truncate(a1)))),
|
||||
"round" => interms.push(Number::Integer(Rc::new(self.round(a1)?))),
|
||||
"ceiling" => interms.push(Number::Integer(Rc::new(self.ceiling(a1)))),
|
||||
"floor" => interms.push(Number::Integer(Rc::new(self.floor(a1)))),
|
||||
"\\" => interms.push(Number::Integer(Rc::new(self.bitwise_complement(a1)?))),
|
||||
"sign" => interms.push(Number::Integer(Rc::new(self.sign(a1)))),
|
||||
_ => {
|
||||
return Err(self.error_form(MachineError::instantiation_error(), caller));
|
||||
}
|
||||
}
|
||||
}
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
interms.push(Number::Integer(n.clone()))
|
||||
}
|
||||
&HeapCellValue::Addr(Addr::Float(n)) => {
|
||||
interms.push(Number::Float(n))
|
||||
}
|
||||
&HeapCellValue::Rational(ref n) => {
|
||||
interms.push(Number::Rational(n.clone()))
|
||||
}
|
||||
&HeapCellValue::Atom(ref name, _) if name.as_str() == "pi" => {
|
||||
interms.push(Number::Float(OrderedFloat(f64::consts::PI)))
|
||||
}
|
||||
_ => {
|
||||
return Err(self.error_form(
|
||||
MachineError::instantiation_error(),
|
||||
caller,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(interms.pop().unwrap())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn rdiv(&self, r1: Rc<Rational>, r2: Rc<Rational>) -> Result<Rational, MachineStub> {
|
||||
if &*r2 == &0 {
|
||||
let stub = MachineError::functor_stub(clause_name!("(rdiv)"), 2);
|
||||
Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||
} else {
|
||||
Ok(Rational::from(&*r1 / &*r2))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn int_floor_div(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
match n1 / n2 {
|
||||
Ok(result) => Ok(rnd_i(&result).to_owned()),
|
||||
Err(e) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("(div)"), 2);
|
||||
Err(self.error_form(
|
||||
MachineError::evaluation_error(
|
||||
e
|
||||
),
|
||||
stub
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn idiv(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::evaluation_error(
|
||||
EvalError::ZeroDivisor
|
||||
),
|
||||
stub,
|
||||
))
|
||||
} else {
|
||||
Ok(<(Integer, Integer)>::from(n1.div_rem_ref(&*n2)).0)
|
||||
}
|
||||
}
|
||||
(Number::Integer(_), n2) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
(n1, _) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("(//)"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn div(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(/)"), 2);
|
||||
|
||||
if n2.is_zero() {
|
||||
Err(self.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||
} else {
|
||||
try_numeric_result!(self, n1 / n2, stub)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn atan2(&self, n1: Number, n2: Number) -> Result<f64, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
|
||||
if n1.is_zero() && n2.is_zero() {
|
||||
Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub))
|
||||
} else {
|
||||
let f1 = self.float(n1)?;
|
||||
let f2 = self.float(n2)?;
|
||||
|
||||
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.atan2(f2))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn int_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
if n1.is_zero() && n2.is_negative() {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||
}
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if &*n1 != &1 && &*n2 < &0 {
|
||||
let n = Number::Integer(n1);
|
||||
let stub = MachineError::functor_stub(clause_name!("^"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Float,
|
||||
n
|
||||
),
|
||||
stub,
|
||||
))
|
||||
} else {
|
||||
Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), n2.as_ref()))))
|
||||
}
|
||||
}
|
||||
(n1, Number::Integer(n2)) => {
|
||||
let f1 = self.float(n1)?;
|
||||
let f2 = self.float(Number::Integer(n2))?;
|
||||
|
||||
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
|
||||
.map(|f| Number::Float(OrderedFloat(f)))
|
||||
}
|
||||
(n1, n2) => {
|
||||
let f2 = self.float(n2)?;
|
||||
|
||||
if n1.is_negative() && f2 != f2.floor() {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
return Err(
|
||||
self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub)
|
||||
);
|
||||
}
|
||||
|
||||
let f1 = self.float(n1)?;
|
||||
self.unary_float_fn_template(Number::Float(OrderedFloat(f1)), |f| f.powf(f2))
|
||||
.map(|f| Number::Float(OrderedFloat(f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn gcd(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Integer::from(n1.gcd_ref(&n2)))
|
||||
}
|
||||
(Number::Float(f), _) | (_, Number::Float(f)) => {
|
||||
let n = Number::Float(f);
|
||||
let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
(Number::Rational(r), _) | (_, Number::Rational(r)) => {
|
||||
let n = Number::Rational(r);
|
||||
let stub = MachineError::functor_stub(clause_name!("gcd"), 2);
|
||||
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn float_pow(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
let f1 = result_f(&n1, rnd_f);
|
||||
let f2 = result_f(&n2, rnd_f);
|
||||
|
||||
let stub = MachineError::functor_stub(clause_name!("(**)"), 2);
|
||||
|
||||
let f1 = try_numeric_result!(self, f1, stub)?;
|
||||
let f2 = try_numeric_result!(self, f2, stub)?;
|
||||
|
||||
let result = result_f(&Number::Float(OrderedFloat(f1.powf(f2))), rnd_f);
|
||||
|
||||
Ok(Number::Float(OrderedFloat(try_numeric_result!(
|
||||
self, result, stub
|
||||
)?)))
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn pow(&self, n1: Number, n2: Number, culprit: &'static str) -> Result<Number, MachineStub> {
|
||||
if n2.is_negative() && n1.is_zero() {
|
||||
let stub = MachineError::functor_stub(clause_name!(culprit), 2);
|
||||
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||
}
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Number::Integer(Rc::new(binary_pow(n1.as_ref().clone(), &*n2))))
|
||||
}
|
||||
(n1, n2) => {
|
||||
self.float_pow(n1, n2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn unary_float_fn_template<FloatFn>(&self, n1: Number, f: FloatFn) -> Result<f64, MachineStub>
|
||||
where
|
||||
FloatFn: Fn(f64) -> f64,
|
||||
{
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
|
||||
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||
let f1 = result_f(&Number::Float(OrderedFloat(f(f1))), rnd_f);
|
||||
|
||||
try_numeric_result!(self, f1, stub)
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn sin(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.sin())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn cos(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.cos())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn tan(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.tan())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn log(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.log(f64::consts::E))
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn exp(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.exp())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn asin(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.asin())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn acos(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.acos())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn atan(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
self.unary_float_fn_template(n1, |f| f.atan())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn sqrt(&self, n1: Number) -> Result<f64, MachineStub> {
|
||||
if n1.is_negative() {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
return Err(self.error_form(MachineError::evaluation_error(EvalError::Undefined), stub));
|
||||
}
|
||||
|
||||
self.unary_float_fn_template(n1, |f| f.sqrt())
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn float(&self, n: Number) -> Result<f64, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
try_numeric_result!(self, result_f(&n, rnd_f), stub)
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn floor(&self, n1: Number) -> Integer {
|
||||
rnd_i(&n1).to_owned()
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn ceiling(&self, n1: Number) -> Integer {
|
||||
-self.floor(-n1)
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn truncate(&self, n: Number) -> Integer {
|
||||
if n.is_negative() {
|
||||
-self.floor(n.abs())
|
||||
} else {
|
||||
self.floor(n)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn round(&self, n: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(is)"), 2);
|
||||
|
||||
let result = n + Number::Float(OrderedFloat(0.5f64));
|
||||
let result = try_numeric_result!(self, result, stub)?;
|
||||
|
||||
Ok(self.floor(result))
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn shr(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(>>)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
match n2.to_u32() {
|
||||
Some(n2) => Ok(Integer::from(&*n1 >> n2)),
|
||||
_ => Ok(Integer::from(&*n1 >> u32::max_value())),
|
||||
},
|
||||
(Number::Integer(_), n2) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
(n1, _) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn shl(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(<<)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => match n2.to_u32() {
|
||||
Some(n2) => Ok(Integer::from(&*n1 << n2)),
|
||||
_ => Ok(Integer::from(&*n1 << u32::max_value())),
|
||||
},
|
||||
(Number::Integer(_), n2) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
(n1, _) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn bitwise_complement(&self, n1: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(\\)"), 2);
|
||||
|
||||
match n1 {
|
||||
Number::Integer(n1) => Ok(Integer::from(!&*n1)),
|
||||
_ => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn xor(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(xor)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Integer::from(&*n1 ^ &*n2))
|
||||
}
|
||||
(Number::Integer(_), n2) => {
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
(n1, _) => {
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn and(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(/\\)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => Ok(Integer::from(&*n1 & &*n2)),
|
||||
(Number::Integer(_), n2) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
(n1, _) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn modulus(&self, x: Number, y: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(mod)"), 2);
|
||||
|
||||
match (x, y) {
|
||||
(Number::Integer(x), Number::Integer(y)) => {
|
||||
if &*y == &0 {
|
||||
Err(self.error_form(
|
||||
MachineError::evaluation_error(EvalError::ZeroDivisor),
|
||||
stub,
|
||||
))
|
||||
} else {
|
||||
Ok(<(Integer, Integer)>::from(x.div_rem_floor_ref(&*y)).1)
|
||||
}
|
||||
}
|
||||
(Number::Integer(_), n2) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
(n1, _) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if n1 > n2 {
|
||||
Ok(Number::Integer(n1))
|
||||
} else {
|
||||
Ok(Number::Integer(n2))
|
||||
}
|
||||
}
|
||||
(n1, n2) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("max"), 2);
|
||||
|
||||
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||
let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
|
||||
|
||||
Ok(Number::Float(cmp::max(OrderedFloat(f1), OrderedFloat(f2))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn min(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if n1 < n2 {
|
||||
Ok(Number::Integer(n1))
|
||||
} else {
|
||||
Ok(Number::Integer(n2))
|
||||
}
|
||||
}
|
||||
(n1, n2) => {
|
||||
let stub = MachineError::functor_stub(clause_name!("max"), 2);
|
||||
|
||||
let f1 = try_numeric_result!(self, result_f(&n1, rnd_f), stub)?;
|
||||
let f2 = try_numeric_result!(self, result_f(&n2, rnd_f), stub)?;
|
||||
|
||||
Ok(Number::Float(cmp::min(OrderedFloat(f1), OrderedFloat(f2))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn sign(&self, n: Number) -> Integer {
|
||||
if n.is_positive() {
|
||||
Integer::from(1)
|
||||
} else if n.is_negative() {
|
||||
Integer::from(-1)
|
||||
} else {
|
||||
Integer::from(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn remainder(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if &*n2 == &0 {
|
||||
Err(self
|
||||
.error_form(MachineError::evaluation_error(EvalError::ZeroDivisor), stub))
|
||||
} else {
|
||||
Ok(Integer::from(&*n1 % &*n2))
|
||||
}
|
||||
}
|
||||
(Number::Integer(_), n2) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
(n1, _) => Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1,
|
||||
),
|
||||
stub,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn or(&self, n1: Number, n2: Number) -> Result<Integer, MachineStub> {
|
||||
let stub = MachineError::functor_stub(clause_name!("(\\/)"), 2);
|
||||
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
Ok(Integer::from(&*n1 | &*n2))
|
||||
}
|
||||
(Number::Integer(_), n2) => {
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n2,
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
(n1, _) => {
|
||||
Err(self.error_form(
|
||||
MachineError::type_error(
|
||||
self.heap.h(),
|
||||
ValidType::Integer,
|
||||
n1
|
||||
),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::prolog::machine::*;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::vec::IntoIter;
|
||||
|
||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||
@@ -66,7 +67,7 @@ impl MachineState {
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|(ref h, _)| Addr::AttrVar(*h));
|
||||
.map(|(ref h, _)| HeapCellValue::Addr(Addr::AttrVar(*h)));
|
||||
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
|
||||
@@ -74,7 +75,7 @@ impl MachineState {
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.drain(0 ..)
|
||||
.map(|(_, addr)| addr);
|
||||
.map(|(_, addr)| HeapCellValue::Addr(addr));
|
||||
|
||||
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
(var_list_addr, value_list_addr)
|
||||
@@ -100,7 +101,9 @@ impl MachineState {
|
||||
})
|
||||
.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).unwrap_or(Ordering::Less)
|
||||
});
|
||||
|
||||
self.term_dedup(&mut attr_vars);
|
||||
attr_vars.into_iter()
|
||||
@@ -117,9 +120,9 @@ impl MachineState {
|
||||
}
|
||||
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
|
||||
Addr::Con(Constant::CutPoint(self.b0));
|
||||
Addr::CutPoint(self.b0);
|
||||
self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
|
||||
Addr::Con(Constant::Usize(self.num_of_args));
|
||||
Addr::Usize(self.num_of_args);
|
||||
|
||||
self.verify_attributes();
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::stack::*;
|
||||
use crate::prolog::machine::streams::*;
|
||||
|
||||
use std::mem;
|
||||
use std::ops::IndexMut;
|
||||
|
||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
@@ -11,12 +13,13 @@ pub enum AttrVarPolicy {
|
||||
StripAttributes
|
||||
}
|
||||
|
||||
pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn threshold(&self) -> usize;
|
||||
fn push(&mut self, val: HeapCellValue);
|
||||
fn store(&self, val: Addr) -> Addr;
|
||||
pub(crate)
|
||||
trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn deref(&self, val: Addr) -> Addr;
|
||||
fn push(&mut self, val: HeapCellValue);
|
||||
fn stack(&mut self) -> &mut Stack;
|
||||
fn store(&self, val: Addr) -> Addr;
|
||||
fn threshold(&self) -> usize;
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
@@ -75,15 +78,15 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
|
||||
|
||||
let ra = self.target[addr].as_addr(threshold);
|
||||
let rd = self.target.store(self.target.deref(ra.clone()));
|
||||
let rd = self.target.store(self.target.deref(ra));
|
||||
|
||||
self.target.push(HeapCellValue::Addr(ra.clone()));
|
||||
self.target.push(HeapCellValue::Addr(ra));
|
||||
|
||||
let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
|
||||
|
||||
self.target.push(hcv);
|
||||
|
||||
match rd.clone() {
|
||||
match rd {
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h)
|
||||
if h >= self.old_h => {
|
||||
self.target[threshold] = HeapCellValue::Addr(rd)
|
||||
@@ -129,18 +132,18 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
fn copy_partial_string(&mut self, addr: usize, n: usize) {
|
||||
let threshold = self.target.threshold();
|
||||
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
||||
|
||||
let trail_item = mem::replace(
|
||||
&mut self.target[addr + 1],
|
||||
HeapCellValue::Addr(Addr::PStrLocation(threshold, 0)),
|
||||
);
|
||||
|
||||
self.trail.push((
|
||||
Ref::HeapCell(addr + 1),
|
||||
self.target[addr + 1].clone(),
|
||||
trail_item,
|
||||
));
|
||||
|
||||
let tail_addr = self.target[addr + 1].as_addr(addr + 1);
|
||||
|
||||
self.target[addr + 1] = HeapCellValue::Addr(
|
||||
Addr::PStrLocation(threshold, 0)
|
||||
);
|
||||
|
||||
let pstr =
|
||||
match &self.target[addr] {
|
||||
HeapCellValue::PartialString(ref pstr) => {
|
||||
@@ -205,7 +208,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
|
||||
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||
|
||||
let list_val = self.target[h + 1].clone();
|
||||
let list_val = self.target[h + 1].context_free_clone();
|
||||
self.target.push(list_val);
|
||||
}
|
||||
}
|
||||
@@ -214,9 +217,9 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
}
|
||||
|
||||
fn copy_var(&mut self, addr: Addr) {
|
||||
let rd = self.target.store(self.target.deref(addr.clone()));
|
||||
let rd = self.target.store(self.target.deref(addr));
|
||||
|
||||
match rd.clone() {
|
||||
match rd {
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||
self.scan += 1;
|
||||
@@ -232,7 +235,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
}
|
||||
|
||||
fn copy_structure(&mut self, addr: usize) {
|
||||
match self.target[addr].clone() {
|
||||
match self.target[addr].context_free_clone() {
|
||||
HeapCellValue::NamedStr(arity, name, fixity) => {
|
||||
let threshold = self.target.threshold();
|
||||
|
||||
@@ -247,7 +250,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||
|
||||
for i in 0..arity {
|
||||
let hcv = self.target[addr + 1 + i].clone();
|
||||
let hcv = self.target[addr + 1 + i].context_free_clone();
|
||||
self.target.push(hcv);
|
||||
}
|
||||
}
|
||||
@@ -266,13 +269,18 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
while self.scan < self.target.threshold() {
|
||||
match self.value_at_scan() {
|
||||
HeapCellValue::NamedStr(..) => {
|
||||
self.scan += 1;
|
||||
}
|
||||
HeapCellValue::Addr(ref addr) => {
|
||||
match addr.clone() {
|
||||
Addr::Lis(addr) => {
|
||||
self.copy_list(addr);
|
||||
&mut HeapCellValue::Addr(addr) => {
|
||||
match addr {
|
||||
Addr::Con(h) => {
|
||||
self.target.push(self.target[h].context_free_clone());
|
||||
self.scan += 1;
|
||||
}
|
||||
Addr::Stream(_) => {
|
||||
self.target.push(HeapCellValue::Stream(Stream::null_stream()));
|
||||
self.scan += 1;
|
||||
}
|
||||
Addr::Lis(h) => {
|
||||
self.copy_list(h);
|
||||
}
|
||||
addr @ Addr::AttrVar(_)
|
||||
| addr @ Addr::HeapCell(_)
|
||||
@@ -285,12 +293,12 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
Addr::PStrLocation(addr, n) => {
|
||||
self.copy_partial_string_from(addr, n);
|
||||
}
|
||||
Addr::Con(_) | Addr::DBRef(_) | Addr::Stream(_) => {
|
||||
_ => {
|
||||
self.scan += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapCellValue::PartialString(_) => {
|
||||
_ => {
|
||||
self.scan += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,22 @@ impl Machine {
|
||||
let arity = self.machine_st[arity].clone();
|
||||
|
||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.machine_st.heap[h] {
|
||||
name.clone()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||
Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
|
||||
arity.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -91,7 +101,7 @@ impl Machine {
|
||||
let (name, arity) = self.get_predicate_key(name, arity);
|
||||
|
||||
self.make_undefined(name.clone(), arity);
|
||||
|
||||
|
||||
self.indices.remove_code_index((name.clone(), arity));
|
||||
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
||||
}
|
||||
@@ -101,16 +111,21 @@ impl Machine {
|
||||
let module_addr = self.machine_st[module].clone();
|
||||
|
||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
|
||||
Some(ref mut module) => {
|
||||
module.code_dir.remove(&(name.clone(), arity));
|
||||
module.module_decl.name.clone()
|
||||
}
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
},
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||
match self.indices.modules.get_mut(module) {
|
||||
Some(ref mut module) => {
|
||||
module.code_dir.remove(&(name.clone(), arity));
|
||||
module.module_decl.name.clone()
|
||||
}
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -162,21 +177,34 @@ impl Machine {
|
||||
place.push_to_queue(&mut addrs, added_clause);
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
Err(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 {
|
||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
|
||||
Some(ref module) => module.atom_tbl.clone(),
|
||||
None => {
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Atom(ref module, _) = &self.machine_st.heap[h] {
|
||||
match self.indices.modules.get(module) {
|
||||
Some(ref module) => module.atom_tbl.clone(),
|
||||
None => {
|
||||
self.machine_st.fail = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.machine_st.fail = true;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -204,7 +232,12 @@ impl Machine {
|
||||
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(ref n) = &self.machine_st.heap[h] {
|
||||
n.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -224,7 +257,9 @@ impl Machine {
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
Err(err) => {
|
||||
return self.machine_st.throw_exception(err);
|
||||
}
|
||||
};
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(
|
||||
@@ -239,8 +274,15 @@ impl Machine {
|
||||
fn retract_from_dynamic_predicate(&mut self) {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
||||
_ => unreachable!(),
|
||||
Addr::Con(h) =>
|
||||
if let HeapCellValue::Integer(n) = &self.machine_st.heap[h] {
|
||||
n.to_usize().unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||
@@ -257,7 +299,9 @@ impl Machine {
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
Err(err) => {
|
||||
return self.machine_st.throw_exception(err);
|
||||
}
|
||||
};
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::prolog_parser::ast::*;
|
||||
use crate::prolog_parser::ast::Constant;
|
||||
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::partial_string::*;
|
||||
@@ -140,17 +140,175 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn push(&mut self, val: HeapCellValue) {
|
||||
unsafe {
|
||||
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
||||
ptr::write(self.buf.top as *mut _, val);
|
||||
self.buf.top = new_top;
|
||||
fn clone(&self, h: usize) -> HeapCellValue {
|
||||
match &self[h] {
|
||||
&HeapCellValue::Addr(addr) => {
|
||||
HeapCellValue::Addr(addr)
|
||||
}
|
||||
&HeapCellValue::Atom(ref name, ref op) => {
|
||||
HeapCellValue::Atom(name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::DBRef(ref db_ref) => {
|
||||
HeapCellValue::DBRef(db_ref.clone())
|
||||
}
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
HeapCellValue::Integer(n.clone())
|
||||
}
|
||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::Rational(ref r) => {
|
||||
HeapCellValue::Rational(r.clone())
|
||||
}
|
||||
&HeapCellValue::PartialString(_) => {
|
||||
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||
}
|
||||
&HeapCellValue::Stream(_) => {
|
||||
HeapCellValue::Addr(Addr::Stream(h))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn allocate_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
||||
fn put_constant(&mut self, c: Constant) -> Addr {
|
||||
match c {
|
||||
Constant::Atom(name, op) => {
|
||||
Addr::Con(self.push(HeapCellValue::Atom(name, op)))
|
||||
}
|
||||
Constant::Char(c) => {
|
||||
self.push(HeapCellValue::Addr(Addr::Char(c)));
|
||||
Addr::Char(c)
|
||||
}
|
||||
Constant::CharCode(c) => {
|
||||
self.push(HeapCellValue::Addr(Addr::CharCode(c)));
|
||||
Addr::CharCode(c)
|
||||
}
|
||||
Constant::CutPoint(cp) => {
|
||||
self.push(HeapCellValue::Addr(Addr::CutPoint(cp)));
|
||||
Addr::CutPoint(cp)
|
||||
}
|
||||
Constant::EmptyList => {
|
||||
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||
Addr::EmptyList
|
||||
}
|
||||
Constant::Integer(n) => {
|
||||
Addr::Con(self.push(HeapCellValue::Integer(n)))
|
||||
}
|
||||
Constant::Rational(r) => {
|
||||
Addr::Con(self.push(HeapCellValue::Rational(r)))
|
||||
}
|
||||
Constant::Float(f) => {
|
||||
self.push(HeapCellValue::Addr(Addr::Float(f)));
|
||||
Addr::Float(f)
|
||||
}
|
||||
Constant::String(s) => {
|
||||
let addr = self.allocate_pstr(&s);
|
||||
let h = self.h();
|
||||
|
||||
self[h - 1] = HeapCellValue::Addr(Addr::EmptyList);
|
||||
addr
|
||||
}
|
||||
Constant::Usize(n) => {
|
||||
self.push(HeapCellValue::Addr(Addr::Usize(n)));
|
||||
Addr::Usize(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn push(&mut self, val: HeapCellValue) -> usize {
|
||||
let h = self.h();
|
||||
|
||||
unsafe {
|
||||
let new_top = self.buf.new_block(mem::size_of::<HeapCellValue>());
|
||||
ptr::write(self.buf.top as *mut _, val);
|
||||
self.buf.top = new_top;
|
||||
}
|
||||
|
||||
h
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn rational_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Rational(_) = &self[h] {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn integer_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Integer(_) = &self[h] {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn atom_at(&self, h: usize) -> bool {
|
||||
if let HeapCellValue::Atom(..) = &self[h] {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
|
||||
match non_heap_value {
|
||||
HeapCellValue::Addr(addr) => {
|
||||
addr
|
||||
}
|
||||
val @ HeapCellValue::Atom(..)
|
||||
| val @ HeapCellValue::Integer(_)
|
||||
| val @ HeapCellValue::DBRef(_)
|
||||
| val @ HeapCellValue::Rational(_) => {
|
||||
Addr::Con(self.push(val))
|
||||
}
|
||||
val @ HeapCellValue::NamedStr(..) => {
|
||||
Addr::Str(self.push(val))
|
||||
}
|
||||
val @ HeapCellValue::Stream(..) => {
|
||||
Addr::Stream(self.push(val))
|
||||
}
|
||||
val @ HeapCellValue::PartialString(_) => {
|
||||
let h = self.push(val);
|
||||
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||
|
||||
Addr::Con(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn allocate_pstr(&mut self, src: &str) -> Addr {
|
||||
self.write_pstr(src)
|
||||
.unwrap_or_else(|| {
|
||||
let h = self.h();
|
||||
|
||||
self.push(HeapCellValue::PartialString(
|
||||
PartialString::empty()
|
||||
));
|
||||
|
||||
self.push(HeapCellValue::Addr(
|
||||
Addr::HeapCell(h + 1)
|
||||
));
|
||||
|
||||
Addr::PStrLocation(h, 0)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_pstr(&mut self, mut src: &str) -> Option<Addr> {
|
||||
let orig_h = self.h();
|
||||
|
||||
loop {
|
||||
@@ -245,17 +403,21 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
|
||||
fn to_list<Iter, SrcT>(&mut self, values: Iter) -> usize
|
||||
where Iter: Iterator<Item = SrcT>,
|
||||
SrcT: Into<HeapCellValue>
|
||||
{
|
||||
let head_addr = self.h();
|
||||
let mut h = head_addr;
|
||||
|
||||
for value in values {
|
||||
let h = self.h();
|
||||
|
||||
for value in values.map(|v| v.into()) {
|
||||
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||
self.push(HeapCellValue::Addr(value));
|
||||
self.push(value);
|
||||
|
||||
h += mem::size_of::<HeapCellValue>() * 2;
|
||||
}
|
||||
|
||||
self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList)));
|
||||
self.push(HeapCellValue::Addr(Addr::EmptyList));
|
||||
|
||||
head_addr
|
||||
}
|
||||
@@ -286,8 +448,8 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
pub(crate)
|
||||
fn to_local_code_ptr(&self, addr: &Addr) -> Option<LocalCodePtr> {
|
||||
let extract_integer = |s: usize| -> Option<usize> {
|
||||
match self[s].as_addr(s) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize(),
|
||||
match &self[s] {
|
||||
&HeapCellValue::Integer(ref n) => n.to_usize(),
|
||||
_ => None
|
||||
}
|
||||
};
|
||||
@@ -327,6 +489,19 @@ impl<T: RawBlockTraits> HeapTemplate<T> {
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub
|
||||
fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
|
||||
match addr {
|
||||
&Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) => {
|
||||
RefOrOwned::Borrowed(&self[h])
|
||||
}
|
||||
addr => {
|
||||
RefOrOwned::Owned(HeapCellValue::Addr(*addr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use crate::prolog::forms::PredicateKey;
|
||||
use crate::prolog::forms::{Number, PredicateKey};
|
||||
use crate::prolog::machine::heap::*;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::*;
|
||||
use crate::prolog::rug::Integer;
|
||||
@@ -21,19 +22,140 @@ pub(super) struct MachineError {
|
||||
from: ErrorProvenance,
|
||||
}
|
||||
|
||||
pub(super)
|
||||
trait TypeError {
|
||||
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError;
|
||||
}
|
||||
|
||||
impl TypeError for Addr {
|
||||
fn type_error(self, _: usize, valid_type: ValidType) -> MachineError {
|
||||
let stub = functor!(
|
||||
"type_error",
|
||||
[atom(valid_type.as_str()), addr(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeError for MachineStub {
|
||||
fn type_error(self, h: usize, valid_type: ValidType) -> MachineError {
|
||||
let stub = functor!(
|
||||
"type_error",
|
||||
[atom(valid_type.as_str()), aux(h, 0)],
|
||||
[self]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeError for Number {
|
||||
fn type_error(self, _h: usize, valid_type: ValidType) -> MachineError {
|
||||
let stub = functor!(
|
||||
"type_error",
|
||||
[atom(valid_type.as_str()), number(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
trait PermissionError {
|
||||
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError;
|
||||
}
|
||||
|
||||
impl PermissionError for Addr {
|
||||
fn permission_error(self, _: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||
let stub = functor!(
|
||||
"permission_error",
|
||||
[atom(perm.as_str()), atom(index_str), addr(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PermissionError for MachineStub {
|
||||
fn permission_error(self, h: usize, index_str: &'static str, perm: Permission) -> MachineError {
|
||||
let stub = functor!(
|
||||
"permission_error",
|
||||
[atom(perm.as_str()), atom(index_str), aux(h, 0)],
|
||||
[self]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
trait DomainError {
|
||||
fn domain_error(self, error: DomainErrorType) -> MachineError;
|
||||
}
|
||||
|
||||
impl DomainError for Addr {
|
||||
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||
let stub = functor!(
|
||||
"domain_error",
|
||||
[atom(error.as_str()), addr(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DomainError for Number {
|
||||
fn domain_error(self, error: DomainErrorType) -> MachineError {
|
||||
let stub = functor!(
|
||||
"domain_error",
|
||||
[atom(error.as_str()), number(self)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MachineError {
|
||||
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
||||
functor!(
|
||||
"/",
|
||||
2,
|
||||
[name, heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX)
|
||||
SharedOpDesc::new(400, YFX),
|
||||
[clause_name(name), integer(arity)]
|
||||
)
|
||||
}
|
||||
|
||||
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", [atom(eval_error.as_str())]);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
@@ -42,21 +164,8 @@ impl MachineError {
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
|
||||
let stub = functor!(
|
||||
"type_error",
|
||||
2,
|
||||
[
|
||||
heap_atom!(valid_type.as_str()),
|
||||
HeapCellValue::Addr(culprit)
|
||||
]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
fn type_error<T: TypeError>(h: usize, valid_type: ValidType, culprit: T) -> Self {
|
||||
culprit.type_error(h, valid_type)
|
||||
}
|
||||
|
||||
pub(super)
|
||||
@@ -66,31 +175,24 @@ impl MachineError {
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> Self {
|
||||
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_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 res_stub = functor!(
|
||||
":",
|
||||
SharedOpDesc::new(600, XFY),
|
||||
[clause_name(mod_name), clause_name(name)]
|
||||
);
|
||||
|
||||
stub.append(&mut functor!(
|
||||
let ind_stub = functor!(
|
||||
"/",
|
||||
2,
|
||||
[
|
||||
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)
|
||||
));
|
||||
SharedOpDesc::new(400, YFX),
|
||||
[aux(h + 2, 0), integer(arity)],
|
||||
[res_stub]
|
||||
);
|
||||
|
||||
let stub = functor!(
|
||||
"evaluation_error",
|
||||
[aux(h, 0)],
|
||||
[ind_stub]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -103,23 +205,29 @@ impl MachineError {
|
||||
fn existence_error(h: usize, err: ExistenceError) -> Self {
|
||||
match err {
|
||||
ExistenceError::Module(name) => {
|
||||
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",
|
||||
[atom("module"), clause_name(name)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
ExistenceError::Procedure(name, arity) => {
|
||||
let mut stub = functor!(
|
||||
"existence_error",
|
||||
2,
|
||||
[heap_atom!("procedure"), heap_str!(3 + h)]
|
||||
let culprit = functor!(
|
||||
"/",
|
||||
SharedOpDesc::new(400, YFX),
|
||||
[clause_name(name), integer(arity)]
|
||||
);
|
||||
|
||||
stub.append(&mut Self::functor_stub(name, arity));
|
||||
let stub = functor!(
|
||||
"existence_error",
|
||||
[atom("procedure"), aux(h, 0)],
|
||||
[culprit]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -127,99 +235,115 @@ impl MachineError {
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
ExistenceError::Stream(addr) => {
|
||||
let culprit = HeapCellValue::Addr(addr);
|
||||
let stub = functor!("existence_error", 2, [heap_atom!("stream"), culprit]);
|
||||
ExistenceError::Stream(culprit) => {
|
||||
let stub = functor!(
|
||||
"existence_error",
|
||||
[atom("stream"), addr(culprit)]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn permission_error<T: PermissionError>(
|
||||
h: usize,
|
||||
err: Permission,
|
||||
index_str: &'static str,
|
||||
culprit: T,
|
||||
) -> Self {
|
||||
culprit.permission_error(
|
||||
h,
|
||||
index_str,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||
match err {
|
||||
ArithmeticError::UninstantiatedVar => {
|
||||
Self::instantiation_error()
|
||||
}
|
||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
||||
let culprit = functor!(
|
||||
"/",
|
||||
SharedOpDesc::new(400, YFX),
|
||||
[constant(h, &name), integer(arity)]
|
||||
);
|
||||
|
||||
Self::type_error(h, ValidType::Evaluable, culprit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super)
|
||||
fn domain_error<T: DomainError>(error: DomainErrorType, culprit: T) -> Self {
|
||||
culprit.domain_error(error)
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn instantiation_error() -> Self {
|
||||
let stub = functor!("instantiation_error");
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn session_error(h: usize, err: SessionError) -> Self {
|
||||
match err {
|
||||
SessionError::ParserError(err) => Self::syntax_error(h, err),
|
||||
SessionError::ParserError(err) => {
|
||||
Self::syntax_error(h, err)
|
||||
}
|
||||
SessionError::CannotOverwriteBuiltIn(pred_str)
|
||||
| SessionError::CannotOverwriteImport(pred_str) => {
|
||||
Self::permission_error(
|
||||
PermissionError::Modify,
|
||||
"private_procedure",
|
||||
Addr::Con(Constant::Atom(pred_str, None)),
|
||||
h,
|
||||
Permission::Modify,
|
||||
"private_procedure",
|
||||
functor!(clause_name(pred_str)),
|
||||
)
|
||||
}
|
||||
SessionError::InvalidFileName(filename) => {
|
||||
Self::existence_error(h, ExistenceError::Module(filename))
|
||||
}
|
||||
SessionError::ModuleDoesNotContainExport(..) => Self::permission_error(
|
||||
PermissionError::Access,
|
||||
"private_procedure",
|
||||
Addr::Con(atom!("module_does_not_contain_claimed_export")),
|
||||
),
|
||||
SessionError::ModuleNotFound => Self::permission_error(
|
||||
PermissionError::Access,
|
||||
"private_procedure",
|
||||
Addr::Con(atom!("module_does_not_exist")),
|
||||
),
|
||||
SessionError::ModuleDoesNotContainExport(..) => {
|
||||
Self::permission_error(
|
||||
h,
|
||||
Permission::Access,
|
||||
"private_procedure",
|
||||
functor!("module_does_not_contain_claimed_export"),
|
||||
)
|
||||
}
|
||||
SessionError::ModuleNotFound => {
|
||||
Self::permission_error(
|
||||
h,
|
||||
Permission::Access,
|
||||
"private_procedure",
|
||||
functor!("modules_does_not_exist"),
|
||||
)
|
||||
}
|
||||
SessionError::OpIsInfixAndPostFix(op) => {
|
||||
Self::permission_error(
|
||||
PermissionError::Create,
|
||||
h,
|
||||
Permission::Create,
|
||||
"operator",
|
||||
Addr::Con(Constant::Atom(op, None)),
|
||||
functor!(clause_name(op)),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn permission_error(
|
||||
err: PermissionError,
|
||||
index_str: &'static str,
|
||||
culprit: Addr,
|
||||
) -> Self {
|
||||
let culprit = HeapCellValue::Addr(culprit);
|
||||
|
||||
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), culprit];
|
||||
let mut stub = functor!("permission_error", 3);
|
||||
|
||||
stub.extend(err.into_iter());
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
|
||||
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||
match err {
|
||||
ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
|
||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
||||
let name = HeapCellValue::Addr(Addr::Con(name));
|
||||
let culprit = functor!(
|
||||
"/",
|
||||
2,
|
||||
[name, heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX)
|
||||
);
|
||||
|
||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
|
||||
stub.extend(culprit.into_iter());
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn syntax_error(h: usize, err: ParserError) -> Self {
|
||||
if let ParserError::Arithmetic(err) = err {
|
||||
@@ -227,15 +351,13 @@ impl MachineError {
|
||||
}
|
||||
|
||||
let location = err.line_and_col_num();
|
||||
let err = vec![heap_atom!(err.as_str())];
|
||||
|
||||
let mut stub = if err.len() == 1 {
|
||||
functor!("syntax_error", 1)
|
||||
} else {
|
||||
functor!("syntax_error", 1, [heap_str!(h + 2)])
|
||||
};
|
||||
|
||||
stub.extend(err.into_iter());
|
||||
let stub = functor!(err.as_str());
|
||||
|
||||
let stub = functor!(
|
||||
"syntax_error",
|
||||
[aux(h, 0)],
|
||||
[stub]
|
||||
);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
@@ -244,33 +366,10 @@ impl MachineError {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn domain_error(error: DomainError, culprit: Addr) -> Self {
|
||||
let stub = functor!(
|
||||
"domain_error",
|
||||
2,
|
||||
[heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
|
||||
);
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn instantiation_error() -> Self {
|
||||
let stub = functor!("instantiation_error");
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn representation_error(flag: RepFlag) -> Self {
|
||||
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
|
||||
let stub = functor!("representation_error", [atom(flag.as_str())]);
|
||||
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
@@ -296,7 +395,7 @@ impl MachineError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum PermissionError {
|
||||
pub enum Permission {
|
||||
Access,
|
||||
Create,
|
||||
InputStream,
|
||||
@@ -304,14 +403,14 @@ pub enum PermissionError {
|
||||
OutputStream,
|
||||
}
|
||||
|
||||
impl PermissionError {
|
||||
impl Permission {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
PermissionError::Access => "access",
|
||||
PermissionError::Create => "create",
|
||||
PermissionError::InputStream => "input",
|
||||
PermissionError::Modify => "modify",
|
||||
PermissionError::OutputStream => "output",
|
||||
Permission::Access => "access",
|
||||
Permission::Create => "create",
|
||||
Permission::InputStream => "input",
|
||||
Permission::Modify => "modify",
|
||||
Permission::OutputStream => "output",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,18 +462,18 @@ impl ValidType {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum DomainError {
|
||||
pub enum DomainErrorType {
|
||||
NotLessThanZero,
|
||||
Stream,
|
||||
StreamOrAlias,
|
||||
}
|
||||
|
||||
impl DomainError {
|
||||
impl DomainErrorType {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
DomainError::NotLessThanZero => "not_less_than_zero",
|
||||
DomainError::Stream => "stream",
|
||||
DomainError::StreamOrAlias => "stream_or_alias",
|
||||
DomainErrorType::NotLessThanZero => "not_less_than_zero",
|
||||
DomainErrorType::Stream => "stream",
|
||||
DomainErrorType::StreamOrAlias => "stream_or_alias",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,20 +523,20 @@ impl EvalError {
|
||||
}
|
||||
|
||||
// used by '$skip_max_list'.
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum CycleSearchResult {
|
||||
EmptyList,
|
||||
NotList,
|
||||
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
||||
ProperList(usize), // the list length.
|
||||
CompleteString(usize, Rc<String>), // the string length (in bytes), the string.
|
||||
UntouchedString(usize, Rc<String>), // the cut off, past which is the untouched string.
|
||||
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
|
||||
ProperList(usize), // the list length.
|
||||
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
|
||||
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
||||
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
// 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 list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
@@ -447,14 +546,14 @@ impl MachineState {
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
CycleSearchResult::NotList => {
|
||||
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
||||
return Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match self.detect_cycles(sorted.clone()) {
|
||||
CycleSearchResult::NotList if !sorted.is_ref() => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
|
||||
Err(self.error_form(MachineError::type_error(0, ValidType::List, sorted), stub))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
@@ -465,7 +564,7 @@ impl MachineState {
|
||||
|
||||
match self.detect_cycles(list.clone()) {
|
||||
CycleSearchResult::NotList if !list.is_ref() => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
||||
Err(self.error_form(MachineError::type_error(0, ValidType::List, list), stub))
|
||||
}
|
||||
_ => {
|
||||
let mut addr = list;
|
||||
@@ -474,18 +573,23 @@ impl MachineState {
|
||||
let mut new_l = l;
|
||||
|
||||
loop {
|
||||
match self.heap[new_l].clone() {
|
||||
HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
|
||||
HeapCellValue::NamedStr(2, ref name, Some(_))
|
||||
if name.as_str() == "-" =>
|
||||
{
|
||||
break
|
||||
match self.heap.clone(new_l) {
|
||||
HeapCellValue::Addr(Addr::Str(l)) => {
|
||||
new_l = l;
|
||||
}
|
||||
HeapCellValue::NamedStr(2, ref name, Some(_))
|
||||
if name.as_str() == "-" => {
|
||||
break;
|
||||
}
|
||||
HeapCellValue::Addr(Addr::HeapCell(_)) => {
|
||||
break;
|
||||
}
|
||||
HeapCellValue::Addr(Addr::StackCell(..)) => {
|
||||
break;
|
||||
}
|
||||
HeapCellValue::Addr(Addr::HeapCell(_)) => break,
|
||||
HeapCellValue::Addr(Addr::StackCell(..)) => break,
|
||||
_ => {
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
|
||||
MachineError::type_error(0, ValidType::Pair, Addr::HeapCell(l)),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
@@ -501,9 +605,11 @@ impl MachineState {
|
||||
}
|
||||
|
||||
// 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 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()));
|
||||
|
||||
match self.detect_cycles(pairs.clone()) {
|
||||
@@ -511,7 +617,7 @@ impl MachineState {
|
||||
Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
CycleSearchResult::NotList => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
|
||||
Err(self.error_form(MachineError::type_error(0, ValidType::List, pairs), stub))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
@@ -519,7 +625,8 @@ impl MachineState {
|
||||
self.check_for_list_pairs(sorted)
|
||||
}
|
||||
|
||||
pub(super) fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
||||
pub(super)
|
||||
fn error_form(&self, err: MachineError, src: MachineStub) -> MachineStub {
|
||||
let location = err.location;
|
||||
let err_len = err.len();
|
||||
|
||||
@@ -535,21 +642,17 @@ impl MachineState {
|
||||
if let Some((line_num, _)) = location {
|
||||
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
||||
|
||||
stub.extend(
|
||||
vec![
|
||||
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.push(HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc));
|
||||
stub.push(HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)));
|
||||
stub.push(HeapCellValue::Integer(Rc::new(Integer::from(line_num))));
|
||||
}
|
||||
|
||||
stub.extend(src.into_iter());
|
||||
stub
|
||||
}
|
||||
|
||||
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
||||
pub(super)
|
||||
fn throw_exception(&mut self, err: MachineStub) {
|
||||
let h = self.heap.h();
|
||||
|
||||
self.ball.boundary = 0;
|
||||
@@ -602,4 +705,5 @@ impl From<ParserError> for EvalSession {
|
||||
fn from(err: ParserError) -> Self {
|
||||
EvalSession::from(SessionError::ParserError(err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ use crate::prolog::forms::*;
|
||||
use crate::prolog::machine::code_repo::CodeRepo;
|
||||
use crate::prolog::machine::Ball;
|
||||
use crate::prolog::machine::heap::*;
|
||||
use crate::prolog::machine::machine_state::*;
|
||||
use crate::prolog::machine::partial_string::*;
|
||||
use crate::prolog::machine::raw_block::RawBlockTraits;
|
||||
use crate::prolog::machine::streams::Stream;
|
||||
use crate::prolog::instructions::*;
|
||||
use crate::prolog::rug::Integer;
|
||||
use crate::prolog::ordered_float::OrderedFloat;
|
||||
use crate::prolog::rug::{Integer, Rational};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
@@ -39,20 +41,35 @@ pub enum DBRef {
|
||||
),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Addr {
|
||||
AttrVar(usize),
|
||||
Con(Constant),
|
||||
DBRef(DBRef),
|
||||
Lis(usize),
|
||||
HeapCell(usize),
|
||||
StackCell(usize, usize),
|
||||
Str(usize),
|
||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||
Stream(Stream),
|
||||
// 7.2
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum TermOrderCategory {
|
||||
Variable,
|
||||
FloatingPoint,
|
||||
Integer,
|
||||
Atom,
|
||||
Compound,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Addr {
|
||||
AttrVar(usize),
|
||||
Char(char),
|
||||
CharCode(u32),
|
||||
Con(usize),
|
||||
CutPoint(usize),
|
||||
EmptyList,
|
||||
Float(OrderedFloat<f64>),
|
||||
Lis(usize),
|
||||
HeapCell(usize),
|
||||
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
|
||||
StackCell(usize, usize),
|
||||
Str(usize),
|
||||
Stream(usize),
|
||||
Usize(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
|
||||
pub enum Ref {
|
||||
AttrVar(usize),
|
||||
HeapCell(usize),
|
||||
@@ -69,6 +86,28 @@ impl Ref {
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Ref {
|
||||
fn cmp(&self, other: &Ref) -> Ordering {
|
||||
match (self, other) {
|
||||
(Ref::AttrVar(h1), Ref::AttrVar(h2))
|
||||
| (Ref::HeapCell(h1), Ref::HeapCell(h2))
|
||||
| (Ref::HeapCell(h1), Ref::AttrVar(h2))
|
||||
| (Ref::AttrVar(h1), Ref::HeapCell(h2)) => {
|
||||
h1.cmp(&h2)
|
||||
}
|
||||
(Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) => {
|
||||
fr1.cmp(&fr2).then_with(|| sc1.cmp(&sc2))
|
||||
}
|
||||
(Ref::StackCell(..), _) => {
|
||||
Ordering::Greater
|
||||
}
|
||||
(_, Ref::StackCell(..)) => {
|
||||
Ordering::Less
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Ref> for Addr {
|
||||
fn eq(&self, r: &Ref) -> bool {
|
||||
self.as_var() == Some(*r)
|
||||
@@ -133,6 +172,83 @@ impl Addr {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
|
||||
match self {
|
||||
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
|
||||
Some(TermOrderCategory::Variable)
|
||||
}
|
||||
Addr::Float(_) => {
|
||||
Some(TermOrderCategory::FloatingPoint)
|
||||
}
|
||||
&Addr::Con(h) => {
|
||||
match &heap[h] {
|
||||
HeapCellValue::Atom(..) => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
HeapCellValue::Integer(_) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
HeapCellValue::Rational(_) => {
|
||||
Some(TermOrderCategory::Integer)
|
||||
}
|
||||
HeapCellValue::DBRef(_) => {
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList => {
|
||||
Some(TermOrderCategory::Atom)
|
||||
}
|
||||
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
|
||||
Some(TermOrderCategory::Compound)
|
||||
}
|
||||
Addr::CutPoint(_) | Addr::Usize(_) | Addr::Stream(_) => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
|
||||
match self {
|
||||
&Addr::Char(c) => {
|
||||
Some(Constant::Char(c))
|
||||
}
|
||||
&Addr::CharCode(c) => {
|
||||
Some(Constant::CharCode(c))
|
||||
}
|
||||
&Addr::Con(h) => {
|
||||
match &machine_st.heap[h] {
|
||||
&HeapCellValue::Atom(ref name, ref op) => {
|
||||
Some(Constant::Atom(name.clone(), op.clone()))
|
||||
}
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
Some(Constant::Integer(n.clone()))
|
||||
}
|
||||
&HeapCellValue::Rational(ref n) => {
|
||||
Some(Constant::Rational(n.clone()))
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
&Addr::Float(f) => {
|
||||
Some(Constant::Float(f))
|
||||
}
|
||||
&Addr::PStrLocation(h, n) => {
|
||||
machine_st.to_complete_string(h, n)
|
||||
.map(|s| Constant::String(Rc::new(s)))
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_protected(&self, e: usize) -> bool {
|
||||
match self {
|
||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
||||
@@ -209,27 +325,76 @@ impl From<Ref> for TrailRef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum HeapCellValue {
|
||||
Addr(Addr),
|
||||
Atom(ClauseName, Option<SharedOpDesc>),
|
||||
DBRef(DBRef),
|
||||
Integer(Rc<Integer>),
|
||||
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
|
||||
Rational(Rc<Rational>),
|
||||
PartialString(PartialString),
|
||||
Stream(Stream),
|
||||
}
|
||||
|
||||
impl HeapCellValue {
|
||||
#[inline]
|
||||
pub fn as_addr(&self, focus: usize) -> Addr {
|
||||
match self {
|
||||
HeapCellValue::Addr(ref a) => {
|
||||
a.clone()
|
||||
}
|
||||
HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
|
||||
HeapCellValue::Rational(..) => {
|
||||
Addr::Con(focus)
|
||||
}
|
||||
HeapCellValue::NamedStr(_, _, _) => {
|
||||
Addr::Str(focus)
|
||||
}
|
||||
HeapCellValue::PartialString(_) => {
|
||||
Addr::PStrLocation(focus, 0)
|
||||
}
|
||||
HeapCellValue::Stream(_) => {
|
||||
Addr::Stream(focus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn context_free_clone(&self) -> HeapCellValue {
|
||||
match self {
|
||||
&HeapCellValue::Addr(addr) => {
|
||||
HeapCellValue::Addr(addr)
|
||||
}
|
||||
&HeapCellValue::Atom(ref name, ref op) => {
|
||||
HeapCellValue::Atom(name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::DBRef(ref db_ref) => {
|
||||
HeapCellValue::DBRef(db_ref.clone())
|
||||
}
|
||||
&HeapCellValue::Integer(ref n) => {
|
||||
HeapCellValue::Integer(n.clone())
|
||||
}
|
||||
&HeapCellValue::NamedStr(arity, ref name, ref op) => {
|
||||
HeapCellValue::NamedStr(arity, name.clone(), op.clone())
|
||||
}
|
||||
&HeapCellValue::Rational(ref r) => {
|
||||
HeapCellValue::Rational(r.clone())
|
||||
}
|
||||
&HeapCellValue::PartialString(ref pstr) => {
|
||||
HeapCellValue::PartialString(pstr.clone())
|
||||
}
|
||||
&HeapCellValue::Stream(_) => {
|
||||
HeapCellValue::Stream(Stream::null_stream())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Addr> for HeapCellValue {
|
||||
#[inline]
|
||||
fn from(value: Addr) -> HeapCellValue {
|
||||
HeapCellValue::Addr(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
|
||||
@@ -407,37 +572,31 @@ impl LocalCodePtr {
|
||||
LocalCodePtr::DirEntry(p) => {
|
||||
heap.append(functor!(
|
||||
"dir_entry",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
[integer(*p)]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::InSituDirEntry(p) => {
|
||||
heap.append(functor!(
|
||||
"in_situ_dir_entry",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
[integer(*p)]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::TopLevel(chunk_num, offset) => {
|
||||
heap.append(functor!(
|
||||
"top_level",
|
||||
2,
|
||||
[heap_integer!(Integer::from(*chunk_num)),
|
||||
heap_integer!(Integer::from(*offset))]
|
||||
[integer(*chunk_num), integer(*offset)]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::UserGoalExpansion(p) => {
|
||||
heap.append(functor!(
|
||||
"user_goal_expansion",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
[integer(*p)]
|
||||
));
|
||||
}
|
||||
LocalCodePtr::UserTermExpansion(p) => {
|
||||
heap.append(functor!(
|
||||
"user_term_expansion",
|
||||
1,
|
||||
[heap_integer!(Integer::from(*p))]
|
||||
[integer(*p)]
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -449,8 +608,12 @@ impl LocalCodePtr {
|
||||
impl PartialOrd<CodePtr> for CodePtr {
|
||||
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
|
||||
_ => Some(Ordering::Greater),
|
||||
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => {
|
||||
l1.partial_cmp(l2)
|
||||
}
|
||||
_ => {
|
||||
Some(Ordering::Greater)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,8 +628,12 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
||||
p1.partial_cmp(p2)
|
||||
}
|
||||
(_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
|
||||
_ => Some(Ordering::Greater),
|
||||
(_, &LocalCodePtr::TopLevel(_, _)) => {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
_ => {
|
||||
Some(Ordering::Greater)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ use std::cmp::Ordering;
|
||||
use std::io::Write;
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Ball {
|
||||
pub(super) boundary: usize,
|
||||
@@ -58,11 +57,11 @@ impl Ball {
|
||||
|
||||
for heap_value in self.stub.iter_from(0) {
|
||||
stub.push(match heap_value {
|
||||
HeapCellValue::Addr(ref addr) => {
|
||||
HeapCellValue::Addr(addr.clone() - diff)
|
||||
&HeapCellValue::Addr(addr) => {
|
||||
HeapCellValue::Addr(addr - diff)
|
||||
}
|
||||
heap_value => {
|
||||
heap_value.clone()
|
||||
heap_value.context_free_clone()
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -185,8 +184,12 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
let index = h - self.heap_boundary;
|
||||
self.stub[index].as_addr(h)
|
||||
}
|
||||
Addr::StackCell(fr, sc) => self.stack.index_and_frame(fr)[sc].clone(),
|
||||
addr => addr,
|
||||
Addr::StackCell(fr, sc) => {
|
||||
self.stack.index_and_frame(fr)[sc].clone()
|
||||
}
|
||||
addr => {
|
||||
addr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,8 +253,6 @@ pub(super) enum HeapPtr {
|
||||
HeapCell(usize),
|
||||
PStrChar(usize, usize),
|
||||
PStrLocation(usize, usize),
|
||||
StringChar(usize, Rc<String>),
|
||||
StringLocation(usize, Rc<String>),
|
||||
}
|
||||
|
||||
impl HeapPtr {
|
||||
@@ -259,30 +260,23 @@ impl HeapPtr {
|
||||
pub(super)
|
||||
fn read(&self, heap: &Heap) -> Addr {
|
||||
match self {
|
||||
&HeapPtr::HeapCell(h) =>
|
||||
Addr::HeapCell(h),
|
||||
&HeapPtr::PStrChar(h, n) =>
|
||||
&HeapPtr::HeapCell(h) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&HeapPtr::PStrChar(h, n) => {
|
||||
if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
|
||||
let s = pstr.block_as_str();
|
||||
|
||||
if let Some(c) = s[n ..].chars().next() {
|
||||
Addr::Con(Constant::Char(c))
|
||||
if let Some(c) = pstr.range_from(n ..).next() {
|
||||
Addr::Char(c)
|
||||
} else {
|
||||
Addr::HeapCell(h + 1)
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
&HeapPtr::PStrLocation(h, n) =>
|
||||
Addr::PStrLocation(h, n),
|
||||
&HeapPtr::StringChar(n, ref s) =>
|
||||
if let Some(c) = s[n ..].chars().next() {
|
||||
Addr::Con(Constant::Char(c))
|
||||
} else {
|
||||
Addr::Con(Constant::EmptyList)
|
||||
},
|
||||
&HeapPtr::StringLocation(n, ref s) =>
|
||||
Addr::Con(Constant::String(n, s.clone())),
|
||||
}
|
||||
}
|
||||
&HeapPtr::PStrLocation(h, n) => {
|
||||
Addr::PStrLocation(h, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -330,29 +324,27 @@ impl MachineState {
|
||||
let addr = self.store(self.deref(addr.clone()));
|
||||
|
||||
match addr {
|
||||
Addr::Con(Constant::String(n, ref s))
|
||||
if self.flags.double_quotes.is_chars() => {
|
||||
if s.len() < n {
|
||||
chars += &s[n ..];
|
||||
}
|
||||
|
||||
if iter.next().is_some() {
|
||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
|
||||
}
|
||||
}
|
||||
Addr::Con(Constant::Char(c)) => {
|
||||
Addr::Char(c) => {
|
||||
chars.push(c);
|
||||
continue;
|
||||
}
|
||||
Addr::Con(Constant::Atom(ref name, _))
|
||||
if name.as_str().len() == 1 => {
|
||||
chars += name.as_str();
|
||||
Addr::Con(h) => {
|
||||
if let HeapCellValue::Atom(ref name, _) = &self.heap[h] {
|
||||
if name.is_char() {
|
||||
chars += name.as_str();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(
|
||||
MachineError::type_error(ValidType::Character, addr.clone())
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
};
|
||||
|
||||
let h = self.heap.h();
|
||||
|
||||
return Err(
|
||||
MachineError::type_error(h, ValidType::Character, addr)
|
||||
);
|
||||
}
|
||||
|
||||
Ok(chars)
|
||||
@@ -738,32 +730,36 @@ pub(crate) trait CallPolicy: Any {
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
let a3 = machine_st[temp_v!(3)].clone();
|
||||
|
||||
let c = match machine_st.compare_term_test(&a2, &a3) {
|
||||
Ordering::Greater => {
|
||||
let atom = match machine_st.compare_term_test(&a2, &a3) {
|
||||
Some(Ordering::Greater) => {
|
||||
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!(">"), spec))
|
||||
HeapCellValue::Atom(clause_name!(">"), spec)
|
||||
}
|
||||
Ordering::Equal => {
|
||||
Some(Ordering::Equal) => {
|
||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!("="), spec))
|
||||
HeapCellValue::Atom(clause_name!("="), spec)
|
||||
}
|
||||
Ordering::Less => {
|
||||
None | Some(Ordering::Less) => {
|
||||
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!("<"), spec))
|
||||
HeapCellValue::Atom(clause_name!("<"), spec)
|
||||
}
|
||||
};
|
||||
|
||||
machine_st.unify(a1, c);
|
||||
let h = machine_st.heap.h();
|
||||
|
||||
machine_st.heap.push(atom);
|
||||
machine_st.unify(a1, Addr::Con(h));
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
}
|
||||
&BuiltInClauseType::CompareTerm(qt) => {
|
||||
machine_st.compare_term(qt);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
}
|
||||
&BuiltInClauseType::Nl => {
|
||||
&BuiltInClauseType::Nl => {
|
||||
write!(current_output_stream, "\n").unwrap();
|
||||
current_output_stream.flush().unwrap();
|
||||
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
}
|
||||
&BuiltInClauseType::Read => {
|
||||
@@ -811,11 +807,12 @@ pub(crate) trait CallPolicy: Any {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
|
||||
machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
machine_st.fail =
|
||||
if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
}
|
||||
@@ -825,7 +822,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||
let mut list = machine_st.try_from_list(temp_v!(1), stub)?;
|
||||
|
||||
list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2));
|
||||
list.sort_unstable_by(|a1, a2| {
|
||||
machine_st.compare_term_test(a1, a2).unwrap_or(Ordering::Less)
|
||||
});
|
||||
|
||||
machine_st.term_dedup(&mut list);
|
||||
|
||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
|
||||
@@ -847,7 +847,9 @@ pub(crate) trait CallPolicy: Any {
|
||||
key_pairs.push((key, val.clone()));
|
||||
}
|
||||
|
||||
key_pairs.sort_by(|a1, a2| machine_st.compare_term_test(&a1.0, &a2.0));
|
||||
key_pairs.sort_by(|a1, a2| {
|
||||
machine_st.compare_term_test(&a1.0, &a2.0).unwrap_or(Ordering::Less)
|
||||
});
|
||||
|
||||
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
|
||||
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
|
||||
@@ -859,9 +861,11 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
&BuiltInClauseType::Is(r, ref at) => {
|
||||
let a1 = machine_st[r].clone();
|
||||
let a2 = machine_st.get_number(at)?;
|
||||
let n2 = machine_st.get_number(at)?;
|
||||
|
||||
let n2 = Addr::Con(machine_st.heap.push(n2.into()));
|
||||
machine_st.unify(a1, n2);
|
||||
|
||||
machine_st.unify(a1, Addr::Con(a2.to_constant()));
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
}
|
||||
}
|
||||
@@ -935,11 +939,13 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
}
|
||||
ClauseType::Hook(_) | ClauseType::System(_) => {
|
||||
let name = Addr::Con(Constant::Atom(name, None));
|
||||
let name = functor!(clause_name(name));
|
||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||
|
||||
return Err(machine_st
|
||||
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
||||
return Err(machine_st.error_form(
|
||||
MachineError::type_error(machine_st.heap.h(), ValidType::Callable, name),
|
||||
stub,
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -997,7 +1003,7 @@ impl CallPolicy for CWILCallPolicy {
|
||||
current_input_stream,
|
||||
current_output_stream
|
||||
)?;
|
||||
|
||||
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
@@ -1016,7 +1022,7 @@ impl CallPolicy for CWILCallPolicy {
|
||||
current_input_stream,
|
||||
current_output_stream,
|
||||
)?;
|
||||
|
||||
|
||||
self.increment(machine_st)
|
||||
}
|
||||
}
|
||||
@@ -1035,7 +1041,8 @@ pub(crate) struct CWILCallPolicy {
|
||||
}
|
||||
|
||||
impl CWILCallPolicy {
|
||||
pub(crate) fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
||||
pub(crate)
|
||||
fn new_in_place(policy: &mut Box<dyn CallPolicy>) {
|
||||
let mut prev_policy: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||
mem::swap(&mut prev_policy, policy);
|
||||
|
||||
@@ -1045,6 +1052,7 @@ impl CWILCallPolicy {
|
||||
limits: vec![],
|
||||
inference_limit_exceeded: false,
|
||||
};
|
||||
|
||||
*policy = Box::new(new_policy);
|
||||
}
|
||||
|
||||
@@ -1056,10 +1064,10 @@ impl CWILCallPolicy {
|
||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||
if self.count == *limit {
|
||||
self.inference_limit_exceeded = true;
|
||||
|
||||
return Err(functor!(
|
||||
"inference_limit_exceeded",
|
||||
1,
|
||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
|
||||
[addr(Addr::Usize(bp))]
|
||||
));
|
||||
} else {
|
||||
self.count += 1;
|
||||
@@ -1069,7 +1077,8 @@ impl CWILCallPolicy {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
||||
pub(crate)
|
||||
fn add_limit(&mut self, mut limit: Integer, b: usize) -> &Integer {
|
||||
limit += &self.count;
|
||||
|
||||
match self.limits.last().cloned() {
|
||||
@@ -1080,7 +1089,8 @@ impl CWILCallPolicy {
|
||||
&self.count
|
||||
}
|
||||
|
||||
pub(crate) fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||
pub(crate)
|
||||
fn remove_limit(&mut self, b: usize) -> &Integer {
|
||||
if let Some((_, bp)) = self.limits.last().cloned() {
|
||||
if bp == b {
|
||||
self.limits.pop();
|
||||
@@ -1090,11 +1100,13 @@ impl CWILCallPolicy {
|
||||
&self.count
|
||||
}
|
||||
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
pub(crate)
|
||||
fn is_empty(&self) -> bool {
|
||||
self.limits.is_empty()
|
||||
}
|
||||
|
||||
pub(crate) fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
||||
pub(crate)
|
||||
fn into_inner(&mut self) -> Box<dyn CallPolicy> {
|
||||
let mut new_inner: Box<dyn CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||
mem::swap(&mut self.prev_policy, &mut new_inner);
|
||||
new_inner
|
||||
@@ -1108,11 +1120,11 @@ pub(crate) trait CutPolicy: Any {
|
||||
|
||||
downcast!(dyn CutPolicy);
|
||||
|
||||
fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool {
|
||||
fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool {
|
||||
let b = machine_st.b;
|
||||
|
||||
match addr {
|
||||
Addr::Con(Constant::CutPoint(b0)) | Addr::Con(Constant::Usize(b0)) => {
|
||||
&Addr::CutPoint(b0) | &Addr::Usize(b0) => {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
@@ -1131,13 +1143,13 @@ pub(crate) struct DefaultCutPolicy {}
|
||||
|
||||
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
|
||||
let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
|
||||
cut_body(machine_st, addr);
|
||||
cut_body(machine_st, &addr);
|
||||
}
|
||||
|
||||
impl CutPolicy for DefaultCutPolicy {
|
||||
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
|
||||
let addr = machine_st[r].clone();
|
||||
cut_body(machine_st, addr)
|
||||
cut_body(machine_st, &addr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1175,7 +1187,7 @@ impl SCCCutPolicy {
|
||||
let (idx, arity) = if machine_st.block < prev_block {
|
||||
(dir_entry!(self.r_c_w_h), 0)
|
||||
} else {
|
||||
machine_st[temp_v!(1)] = Addr::Con(Constant::Usize(b_cutoff));
|
||||
machine_st[temp_v!(1)] = Addr::Usize(b_cutoff);
|
||||
(dir_entry!(self.r_c_wo_h), 1)
|
||||
};
|
||||
|
||||
@@ -1198,7 +1210,7 @@ impl CutPolicy for SCCCutPolicy {
|
||||
let b = machine_st.b;
|
||||
|
||||
match machine_st[r].clone() {
|
||||
Addr::Con(Constant::Usize(b0)) | Addr::Con(Constant::CutPoint(b0)) => {
|
||||
Addr::Usize(b0) | Addr::CutPoint(b0) => {
|
||||
if b > b0 {
|
||||
machine_st.b = b0;
|
||||
machine_st.tidy_trail();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,13 +19,15 @@ pub mod machine_errors;
|
||||
pub mod machine_indices;
|
||||
pub(super) mod machine_state;
|
||||
pub mod modules;
|
||||
mod partial_string;
|
||||
pub mod partial_string;
|
||||
mod raw_block;
|
||||
mod stack;
|
||||
pub(crate) mod streams;
|
||||
pub(super) mod term_expansion;
|
||||
pub mod toplevel;
|
||||
|
||||
#[macro_use]
|
||||
mod arithmetic_ops;
|
||||
#[macro_use]
|
||||
mod machine_state_impl;
|
||||
mod system_calls;
|
||||
@@ -340,8 +342,8 @@ impl Machine {
|
||||
// the first of these is the path to the scryer-prolog executable, so skip
|
||||
// it.
|
||||
for filename in env::args().skip(1) {
|
||||
let atom = atom!(filename, self.indices.atom_tbl);
|
||||
filename_atoms.push(Addr::Con(atom));
|
||||
let atom = clause_name!(filename, self.indices.atom_tbl);
|
||||
filename_atoms.push(HeapCellValue::Atom(atom, None));
|
||||
}
|
||||
|
||||
let list_addr =
|
||||
@@ -547,14 +549,14 @@ impl Machine {
|
||||
HeapCellValue::NamedStr(arity, ref name, _)
|
||||
if *arity == 2 && name.as_str() == "/" => {
|
||||
let name = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let arity = match &self.machine_st.heap[s+2] {
|
||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
@@ -565,21 +567,21 @@ impl Machine {
|
||||
HeapCellValue::NamedStr(arity, ref name, _)
|
||||
if *arity == 3 && name.as_str() == "op" => {
|
||||
let name = match &self.machine_st.heap[s+3] {
|
||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let spec = match &self.machine_st.heap[s+2] {
|
||||
&HeapCellValue::Addr(Addr::Con(Constant::Atom(ref name, _))) =>
|
||||
&HeapCellValue::Atom(ref name, _) =>
|
||||
name.clone(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let prec = match &self.machine_st.heap[s+1] {
|
||||
&HeapCellValue::Addr(Addr::Con(Constant::Integer(ref arity))) =>
|
||||
&HeapCellValue::Integer(ref arity) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ =>
|
||||
unreachable!()
|
||||
@@ -610,9 +612,13 @@ impl Machine {
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
_ => unreachable!()
|
||||
let name = {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||
|
||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||
HeapCellValue::Atom(name, _) => name.clone(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
let load_result = match to_src(name) {
|
||||
@@ -653,9 +659,13 @@ impl Machine {
|
||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||
|
||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||
let name = match self.machine_st.store(self.machine_st.deref(module_spec)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
_ => unreachable!()
|
||||
let name = {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||
|
||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||
HeapCellValue::Atom(name, _) => name.clone(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
let exports = match self.extract_module_export_list() {
|
||||
|
||||
@@ -1,26 +1,11 @@
|
||||
use crate::prolog::machine::raw_block::*;
|
||||
|
||||
use std::alloc;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::ops::{Range, RangeFrom};
|
||||
use std::str;
|
||||
|
||||
pub(crate) struct PartialStringTraits {}
|
||||
|
||||
impl RawBlockTraits for PartialStringTraits {
|
||||
#[inline]
|
||||
fn init_size() -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn align() -> usize {
|
||||
mem::align_of::<char>()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PartialString {
|
||||
pub(super) buf: RawBlock<PartialStringTraits>,
|
||||
buf: *const u8,
|
||||
}
|
||||
|
||||
impl Clone for PartialString {
|
||||
@@ -30,17 +15,10 @@ impl Clone for PartialString {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PartialString {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self as *const _ == other as *const _
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_for_terminator(src: &str) -> usize {
|
||||
fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
|
||||
let mut terminator_idx = 0;
|
||||
|
||||
for c in src.chars() {
|
||||
for c in iter {
|
||||
if c == '\u{0}' {
|
||||
break;
|
||||
}
|
||||
@@ -51,11 +29,82 @@ fn scan_for_terminator(src: &str) -> usize {
|
||||
terminator_idx
|
||||
}
|
||||
|
||||
pub struct PStrIter {
|
||||
buf: *const u8,
|
||||
}
|
||||
|
||||
impl PStrIter {
|
||||
#[inline]
|
||||
fn from(buf: *const u8, idx: usize) -> Self {
|
||||
PStrIter {
|
||||
buf: (buf as usize + idx) as *const _
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for PStrIter {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
let b = ptr::read(self.buf);
|
||||
|
||||
if b == 0u8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let c = ptr::read(self.buf as *const char);
|
||||
self.buf = self.buf.offset(c.len_utf8() as isize);
|
||||
|
||||
Some(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PStrIterBounded {
|
||||
buf: *const u8,
|
||||
end: *const u8,
|
||||
}
|
||||
|
||||
impl PStrIterBounded {
|
||||
#[inline]
|
||||
fn from(buf: *const u8, start: usize, end: usize) -> Self {
|
||||
PStrIterBounded {
|
||||
buf: (buf as usize + start) as *const _,
|
||||
end: (buf as usize + end) as *const _,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for PStrIterBounded {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
if self.buf >= self.end {
|
||||
return None;
|
||||
}
|
||||
|
||||
let b = ptr::read(self.buf);
|
||||
|
||||
if b == 0u8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let c = ptr::read(self.buf as *const char);
|
||||
self.buf = self.buf.offset(c.len_utf8() as isize);
|
||||
|
||||
Some(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialString {
|
||||
#[inline]
|
||||
pub(super)
|
||||
fn new(src: &str) -> Option<(Self, &str)> {
|
||||
let pstr = PartialString {
|
||||
buf: RawBlock::with_capacity(src.len() + '\u{0}'.len_utf8()),
|
||||
buf: ptr::null_mut(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
@@ -63,22 +112,34 @@ impl PartialString {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super)
|
||||
fn empty() -> Self {
|
||||
PartialString {
|
||||
buf: "\u{0}".as_bytes()[0] as *const _,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
|
||||
let terminator_idx = scan_for_terminator(src);
|
||||
let terminator_idx = scan_for_terminator(src.chars());
|
||||
|
||||
if terminator_idx == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let new_top = self.buf.new_block(terminator_idx + '\u{0}'.len_utf8());
|
||||
let layout = alloc::Layout::from_size_align_unchecked(
|
||||
src.len() + '\u{0}'.len_utf8(),
|
||||
mem::align_of::<u8>(),
|
||||
);
|
||||
|
||||
self.buf = alloc::alloc(layout) as *const _;
|
||||
|
||||
ptr::copy(
|
||||
src.as_ptr(),
|
||||
self.buf.top as *mut _,
|
||||
self.buf as *mut _,
|
||||
terminator_idx,
|
||||
);
|
||||
|
||||
self.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
||||
self.write_terminator_at(terminator_idx);
|
||||
|
||||
Some(if terminator_idx != src.len() {
|
||||
@@ -88,26 +149,40 @@ impl PartialString {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn iter(&self) -> PStrIter {
|
||||
PStrIter {
|
||||
buf: self.buf,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn clone_from_offset(&self, n: usize) -> Self {
|
||||
let mut pstr = PartialString {
|
||||
buf: RawBlock::with_capacity(self.len() + '\u{0}'.len_utf8()),
|
||||
buf: ptr::null_mut(),
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let len = if self.len() > n { self.len() - n } else { 0 };
|
||||
let new_top = pstr.buf.new_block(len + '\u{0}'.len_utf8());
|
||||
let len = scan_for_terminator(self.range_from(0 ..));
|
||||
let len = if len > n { len - n } else { 0 };
|
||||
|
||||
let layout = alloc::Layout::from_size_align_unchecked(
|
||||
len + '\u{0}'.len_utf8(),
|
||||
mem::align_of::<u8>(),
|
||||
);
|
||||
|
||||
pstr.buf = alloc::alloc(layout);
|
||||
|
||||
if len > 0 {
|
||||
ptr::copy(
|
||||
(self.buf.base as usize + n) as *mut u8,
|
||||
pstr.buf.base as *mut _,
|
||||
(self.buf as usize + n) as *const u8,
|
||||
pstr.buf as *mut _,
|
||||
len,
|
||||
);
|
||||
}
|
||||
|
||||
pstr.write_terminator_at(len);
|
||||
pstr.buf.top = (new_top as usize - '\u{0}'.len_utf8()) as *const _;
|
||||
}
|
||||
|
||||
pstr
|
||||
@@ -118,23 +193,26 @@ impl PartialString {
|
||||
fn write_terminator_at(&mut self, index: usize) {
|
||||
unsafe {
|
||||
ptr::write(
|
||||
(self.buf.base as usize + index) as *mut u8,
|
||||
(self.buf as usize + index) as *mut u8,
|
||||
0u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn block_as_str(&self) -> &str {
|
||||
unsafe {
|
||||
let slice = slice::from_raw_parts(self.buf.base, self.len());
|
||||
str::from_utf8(slice).unwrap()
|
||||
}
|
||||
pub fn range(&self, index: Range<usize>) -> PStrIterBounded {
|
||||
PStrIterBounded::from(self.buf, index.start, index.end)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.buf.top as usize - self.buf.base as usize
|
||||
pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
|
||||
PStrIter::from(self.buf, index.start)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn at_end(&self, end_n: usize) -> bool {
|
||||
unsafe {
|
||||
ptr::read((self.buf as usize + end_n) as *const u8) == 0u8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ pub enum EOFAction {
|
||||
pub enum StreamInstance {
|
||||
Bytes(Cursor<Vec<u8>>),
|
||||
DynReadSource(Box<dyn Read>),
|
||||
File(File),
|
||||
File(File),
|
||||
Null,
|
||||
ReadlineStream(ReadlineStream),
|
||||
Stdin,
|
||||
Stdout,
|
||||
@@ -201,6 +202,17 @@ impl Stream {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn null_stream() -> Self {
|
||||
Stream {
|
||||
options: StreamOptions::default(), // TODO: null_options?
|
||||
stream_inst: WrappedStreamInstance::new(
|
||||
StreamInstance::Null
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate)
|
||||
fn is_stdout(&self) -> bool {
|
||||
@@ -233,7 +245,7 @@ impl Stream {
|
||||
match *self.stream_inst.0.borrow() {
|
||||
StreamInstance::Stdin
|
||||
| StreamInstance::TcpStream(_)
|
||||
| StreamInstance::Bytes(_)
|
||||
| StreamInstance::Bytes(_)
|
||||
| StreamInstance::ReadlineStream(_)
|
||||
| StreamInstance::DynReadSource(_)
|
||||
| StreamInstance::File(_) => {
|
||||
@@ -251,7 +263,7 @@ impl Stream {
|
||||
match *self.stream_inst.0.borrow() {
|
||||
StreamInstance::Stdout
|
||||
| StreamInstance::TcpStream(_)
|
||||
| StreamInstance::Bytes(_)
|
||||
| StreamInstance::Bytes(_)
|
||||
| StreamInstance::File(_) => {
|
||||
true
|
||||
}
|
||||
@@ -283,7 +295,7 @@ impl Read for Stream {
|
||||
StreamInstance::Stdin => {
|
||||
stdin().read(buf)
|
||||
}
|
||||
StreamInstance::Stdout => {
|
||||
StreamInstance::Stdout | StreamInstance::Null => {
|
||||
Err(std::io::Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
StreamError::ReadFromOutputStream,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,52 +4,178 @@ macro_rules! interm {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! heap_str {
|
||||
($s:expr) => {
|
||||
HeapCellValue::Addr(Addr::Str($s))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! heap_integer {
|
||||
($i:expr) => {
|
||||
HeapCellValue::Addr(Addr::Con(Constant::Integer($i)))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! heap_cell {
|
||||
($i:expr) => {
|
||||
HeapCellValue::Addr(Addr::HeapCell($i))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! heap_con {
|
||||
($i:expr) => {
|
||||
HeapCellValue::Addr(Addr::Con($i))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! heap_atom {
|
||||
($name:expr) => {
|
||||
HeapCellValue::Addr(Addr::Con(atom!($name)))
|
||||
};
|
||||
($name:expr, $tbl:expr) => {
|
||||
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
|
||||
};
|
||||
/* A simple macro to count the arguments in a variadic list
|
||||
* of token trees.
|
||||
*/
|
||||
macro_rules! count_tt {
|
||||
() => { 0 };
|
||||
($odd:tt $($a:tt $b:tt)*) => { (count_tt!($($a)*) << 1) | 1 };
|
||||
($($a:tt $even:tt)*) => { count_tt!($($a)*) << 1 };
|
||||
}
|
||||
|
||||
macro_rules! functor {
|
||||
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||
{
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
let mut addendum = Heap::new();
|
||||
let arity = count_tt!($($dt) +);
|
||||
let aux_lens = [$($aux.len()),*];
|
||||
|
||||
let mut result =
|
||||
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||
|
||||
$(
|
||||
result.extend($aux.into_iter());
|
||||
)*
|
||||
|
||||
result.extend(addendum.into_iter());
|
||||
result
|
||||
}
|
||||
});
|
||||
($name:expr, $fixity:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||
{
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
let mut addendum = Heap::new();
|
||||
let arity = count_tt!($($dt) +);
|
||||
|
||||
let mut result =
|
||||
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), Some($fixity)),
|
||||
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
|
||||
|
||||
result.extend(addendum.into_iter());
|
||||
result
|
||||
}
|
||||
});
|
||||
($name:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
|
||||
{
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
let mut addendum = Heap::new();
|
||||
let arity = count_tt!($($dt) +);
|
||||
let aux_lens = [$($aux.len()),*];
|
||||
|
||||
let mut result =
|
||||
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
|
||||
|
||||
$(
|
||||
result.extend($aux.into_iter());
|
||||
)*
|
||||
|
||||
result.extend(addendum.into_iter());
|
||||
result
|
||||
}
|
||||
});
|
||||
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
|
||||
{
|
||||
let arity = count_tt!($($dt) +);
|
||||
|
||||
vec![ HeapCellValue::NamedStr(arity, clause_name!($name), None),
|
||||
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ]
|
||||
}
|
||||
});
|
||||
($name:expr, $fixity:expr) => (
|
||||
vec![ HeapCellValue::Atom(clause_name!($name), Some($fixity)) ]
|
||||
);
|
||||
(clause_name($name:expr)) => (
|
||||
vec![ HeapCellValue::Atom($name, None) ]
|
||||
);
|
||||
($name:expr) => (
|
||||
vec![ heap_atom!($name) ]
|
||||
vec![ HeapCellValue::Atom(clause_name!($name), None) ]
|
||||
);
|
||||
($name:expr, $len:expr) => (
|
||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None) ]
|
||||
}
|
||||
|
||||
macro_rules! functor_term {
|
||||
(aux(0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||
HeapCellValue::Addr(Addr::HeapCell($arity + 1))
|
||||
});
|
||||
(aux($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||
HeapCellValue::Addr(Addr::HeapCell($arity + 1 + len))
|
||||
});
|
||||
(aux($h:expr, 0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1))
|
||||
});
|
||||
(aux($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||
let len: usize = $aux_lens[0 .. $e].iter().sum();
|
||||
HeapCellValue::Addr(Addr::HeapCell($arity + $h + 1 + len))
|
||||
});
|
||||
(addr($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
HeapCellValue::Addr($e)
|
||||
);
|
||||
($name:expr, $len:expr, [$($args:expr),*]) => (
|
||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
|
||||
(constant($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
from_constant!($e, $h, $arity, $aux_lens, $addendum)
|
||||
);
|
||||
(constant($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
from_constant!($e, 0, $arity, $aux_lens, $addendum)
|
||||
);
|
||||
($name:expr, $len:expr, [$($args:expr),*], $fix: expr) => (
|
||||
vec![ HeapCellValue::NamedStr($len, clause_name!($name), Some($fix)), $($args),* ]
|
||||
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
$e.into()
|
||||
);
|
||||
/*
|
||||
(string($s:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
|
||||
let len: usize = $aux_lens.iter().sum();
|
||||
let h = len + $arity + 1 + $addendum.h();
|
||||
|
||||
$addendum.allocate_pstr(&$s);
|
||||
|
||||
HeapCell::PStrLocation(h, 0)
|
||||
});
|
||||
*/
|
||||
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||
HeapCellValue::Integer(Rc::new(Integer::from($e)))
|
||||
);
|
||||
(clause_name($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||
HeapCellValue::Atom($e, None)
|
||||
);
|
||||
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
|
||||
HeapCellValue::Atom(clause_name!($e), None)
|
||||
);
|
||||
($e:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => (
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! from_constant {
|
||||
($e:expr, $over_h:expr, $arity:expr, $aux_lens:expr, $addendum:ident) => ({
|
||||
match $e {
|
||||
&Constant::Atom(ref name, ref op) => {
|
||||
HeapCellValue::Atom(name.clone(), op.clone())
|
||||
}
|
||||
&Constant::Char(c) => {
|
||||
HeapCellValue::Addr(Addr::Char(c))
|
||||
}
|
||||
&Constant::CharCode(c) => {
|
||||
HeapCellValue::Addr(Addr::CharCode(c))
|
||||
}
|
||||
&Constant::CutPoint(cp) => {
|
||||
HeapCellValue::Addr(Addr::CutPoint(cp))
|
||||
}
|
||||
&Constant::Integer(ref n) => {
|
||||
HeapCellValue::Integer(n.clone())
|
||||
}
|
||||
&Constant::Rational(ref r) => {
|
||||
HeapCellValue::Rational(r.clone())
|
||||
}
|
||||
&Constant::Float(f) => {
|
||||
HeapCellValue::Addr(Addr::Float(f))
|
||||
}
|
||||
&Constant::String(ref s) => {
|
||||
let len: usize = $aux_lens.iter().sum();
|
||||
let h = len + $arity + 1 + $addendum.h() + $over_h;
|
||||
|
||||
$addendum.put_constant(Constant::String(s.clone()));
|
||||
|
||||
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
|
||||
}
|
||||
&Constant::Usize(u) => {
|
||||
HeapCellValue::Addr(Addr::Usize(u))
|
||||
}
|
||||
&Constant::EmptyList => {
|
||||
HeapCellValue::Addr(Addr::EmptyList)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! is_atom {
|
||||
|
||||
@@ -4,6 +4,7 @@ use prolog_parser::tabled_rc::TabledData;
|
||||
|
||||
use crate::prolog::forms::*;
|
||||
use crate::prolog::iterators::*;
|
||||
use crate::prolog::machine::heap::Heap;
|
||||
use crate::prolog::machine::machine_indices::*;
|
||||
use crate::prolog::machine::machine_state::MachineState;
|
||||
use crate::prolog::machine::streams::Stream;
|
||||
@@ -13,12 +14,20 @@ use std::collections::VecDeque;
|
||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||
|
||||
impl<'a> TermRef<'a> {
|
||||
fn as_addr(&self, h: usize) -> Addr {
|
||||
fn as_addr(&self, heap: &mut Heap, h: usize) -> Addr {
|
||||
match self {
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => Addr::HeapCell(h),
|
||||
&TermRef::Cons(..) => Addr::HeapCell(h),
|
||||
&TermRef::Constant(_, _, c) => Addr::Con(c.clone()),
|
||||
&TermRef::Clause(..) => Addr::Str(h),
|
||||
&TermRef::AnonVar(_) | &TermRef::Var(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Cons(..) => {
|
||||
Addr::HeapCell(h)
|
||||
}
|
||||
&TermRef::Constant(_, _, c) => {
|
||||
heap.put_constant(c.clone())
|
||||
}
|
||||
&TermRef::Clause(..) => {
|
||||
Addr::Str(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,7 +140,7 @@ fn modify_head_of_queue(
|
||||
h: usize,
|
||||
) {
|
||||
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(&mut machine_st.heap, h));
|
||||
|
||||
if arity > 1 {
|
||||
queue.push_front((arity - 1, site_h + 1));
|
||||
@@ -180,10 +189,12 @@ pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) ->
|
||||
}
|
||||
}
|
||||
&TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
|
||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
||||
let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||
machine_st.heap.push(value);
|
||||
}
|
||||
&TermRef::Var(Level::Root, ..) => {
|
||||
machine_st.heap.push(HeapCellValue::Addr(term.as_addr(h)))
|
||||
let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
|
||||
machine_st.heap.push(value);
|
||||
}
|
||||
&TermRef::AnonVar(_) => {
|
||||
if let Some((arity, site_h)) = queue.pop_front() {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
).
|
||||
|
||||
'$submit_query_and_print_results'(Term0, VarList) :-
|
||||
write('oh brother'), nl,
|
||||
( expand_goals(Term0, Term) -> true
|
||||
; Term0 = Term
|
||||
),
|
||||
|
||||
@@ -143,6 +143,10 @@ impl fmt::Display for HeapCellValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
|
||||
&HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
|
||||
&HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
|
||||
&HeapCellValue::Integer(ref n) => write!(f, "{}", n),
|
||||
&HeapCellValue::Rational(ref n) => write!(f, "{}", n),
|
||||
&HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
|
||||
f,
|
||||
"{}/{} (op, priority: {}, spec: {})",
|
||||
@@ -155,7 +159,10 @@ impl fmt::Display for HeapCellValue {
|
||||
write!(f, "{}/{}", name.as_str(), arity)
|
||||
}
|
||||
&HeapCellValue::PartialString(ref pstr) => {
|
||||
write!(f, "pstr ( buf: {} )", pstr.block_as_str())
|
||||
write!(f, "pstr ( buf: 0x{:x} )", (pstr as *const _) as usize)
|
||||
}
|
||||
&HeapCellValue::Stream(ref stream) => {
|
||||
write!(f, "$stream({})", stream.as_ptr() as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,15 +182,20 @@ impl fmt::Display for DBRef {
|
||||
impl fmt::Display for Addr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&Addr::Char(c) => write!(f, "Addr::Char({})", c),
|
||||
&Addr::CharCode(c) => write!(f, "Addr::CharCode({})", c),
|
||||
&Addr::EmptyList => write!(f, "Addr::EmptyList"),
|
||||
&Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
|
||||
&Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
|
||||
&Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
|
||||
&Addr::DBRef(ref db_ref) => write!(f, "Addr::DBRef({})", db_ref),
|
||||
&Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
|
||||
&Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
|
||||
&Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
|
||||
&Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
|
||||
&Addr::Str(s) => write!(f, "Addr::Str({})", s),
|
||||
&Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
|
||||
&Addr::Stream(ref stream) => write!(f, "Addr::Stream({})", stream.as_ptr() as usize),
|
||||
&Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
|
||||
&Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user