initial commit for merge

This commit is contained in:
Mark Thom
2020-03-26 22:01:23 -06:00
parent 121c8d8a48
commit 194e5dc94e
25 changed files with 5077 additions and 3280 deletions

View File

@@ -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);

View File

@@ -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()))),
}
}
}

View File

@@ -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
}
}
}
}

View File

@@ -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!()
}
}
}

View File

@@ -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));
}

View File

@@ -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)])
}
}
}

View 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,
))
}
}
}
}

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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(

View File

@@ -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> {

View File

@@ -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))
}
}

View File

@@ -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)
}
}
}
}

View File

@@ -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

View File

@@ -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() {

View File

@@ -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
}
}
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -43,6 +43,7 @@
).
'$submit_query_and_print_results'(Term0, VarList) :-
write('oh brother'), nl,
( expand_goals(Term0, Term) -> true
; Term0 = Term
),

View File

@@ -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),
}
}
}