if pstr.len() > n + c.len_utf8() {
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
} else {
- self.state_stack.push(Addr::PStrTail(h, n + c.len_utf8()));
+ self.state_stack.push(Addr::HeapCell(h + 1));
}
self.state_stack.push(Addr::Con(Constant::Char(c)));
Addr::PStrLocation(h, n)
}
- Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::PStrTail(..) => {
+ Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
da
}
Addr::Str(s) => {
}
}
}
- Addr::PStrTail(h, n) => {
- match &self.machine_st.heap[h] {
- HeapCellValue::PartialString(ref pstr) => {
- if pstr.len() > n {
- HeapCellValue::Addr(Addr::PStrLocation(h, n))
- } else {
- HeapCellValue::Addr(pstr.tail_addr().clone())
- }
- }
- _ => {
- unreachable!()
- }
- }
- }
Addr::StackCell(fr, sc) => {
HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone())
}
Some(match addr {
&Addr::Lis(l) => l,
&Addr::Str(s) => s,
- &Addr::PStrLocation(h, _) | &Addr::PStrTail(h, _) => h,
+ &Addr::PStrLocation(h, _) => h,
_ => {
return None;
}
Ref::StackCell(fr, sc) => {
Some(format!("_s_{}_{}", fr, sc))
}
- Ref::HeapCell(h) | Ref::AttrVar(h) | Ref::PStrTail(h, _) => {
+ Ref::HeapCell(h) | Ref::AttrVar(h) => {
Some(format!("_{}", h))
}
}
}
}
}
- &Addr::PStrLocation(h, _) | &Addr::PStrTail(h, _) => {
- let tail = match &self.machine_st.heap[h] {
- &HeapCellValue::PartialString(ref pstr) => pstr.tail_addr().clone(),
- _ => unreachable!()
- };
-
+ &Addr::PStrLocation(h, _) => {
+ let tail = self.machine_st.heap[h + 1].as_addr(h + 1);
let tail = self.machine_st.store(self.machine_st.deref(tail));
if let Some(c) = functor_location(&tail) {
false
}
- fn copied_partial_string(&mut self, addr: usize) -> bool {
- if let HeapCellValue::PartialString(ref pstr) = &self.target[addr] {
- if let Addr::PStrLocation(h, n) = pstr.tail_addr() {
- if *h >= self.old_h {
- *self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(*h, *n));
- self.scan += 1;
- return true;
- }
- }
- }
-
- false
- }
-
fn copy_list(&mut self, addr: usize) {
if self.copied_list(addr) {
return;
self.target.push(hcv);
match rd.clone() {
- Addr::AttrVar(h) | Addr::HeapCell(h) | Addr::PStrTail(h, _)
+ Addr::AttrVar(h) | Addr::HeapCell(h)
if h >= self.old_h => {
self.target[threshold] = HeapCellValue::Addr(rd)
}
var @ Addr::AttrVar(_)
| var @ Addr::HeapCell(..)
- | var @ Addr::StackCell(..)
- | var @ Addr::PStrTail(..) => {
+ | var @ Addr::StackCell(..) => {
if ra == rd {
self.reinstantiate_var(var, threshold);
self.scan += 1;
}
+ fn copied_partial_string(&mut self, addr: usize) -> bool {
+ if let &HeapCellValue::Addr(Addr::PStrLocation(h, n)) = &self.target[addr + 1] {
+ if h >= self.old_h {
+ *self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(h, n));
+ self.scan += 1;
+ return true;
+ }
+ }
+
+ false
+ }
fn copy_partial_string(&mut self, addr: usize, n: usize) {
let threshold = self.target.threshold();
- let tail_addr =
- match &self.target[addr] {
- HeapCellValue::PartialString(ref pstr) => {
- self.trail.push((
- Ref::PStrTail(addr, 0),
- HeapCellValue::Addr(pstr.tail.clone()),
- ));
+ self.trail.push((
+ Ref::HeapCell(addr + 1),
+ self.target[addr + 1].clone(),
+ ));
- self.target.store(self.target.deref(pstr.tail.clone()))
- }
- _ => {
- unreachable!()
- }
- };
+ let tail_addr = self.target[addr + 1].as_addr(addr + 1);
- let pstr =
- match &mut self.target[addr] {
- HeapCellValue::PartialString(ref mut pstr) => {
- let mut new_pstr = pstr.clone_from_offset(n);
-
- if let Addr::PStrTail(h, n) = &tail_addr {
- new_pstr.tail = if *h == addr {
- Addr::PStrTail(threshold, *n)
- } else {
- Addr::HeapCell(threshold + 1)
- };
- } else {
- new_pstr.tail = Addr::HeapCell(threshold + 1);
- }
+ self.target[addr + 1] = HeapCellValue::Addr(
+ Addr::PStrLocation(threshold, 0)
+ );
- pstr.tail = Addr::PStrLocation(threshold, 0);
- new_pstr
+ let pstr =
+ match &self.target[addr] {
+ HeapCellValue::PartialString(ref pstr) => {
+ pstr.clone_from_offset(n)
}
_ => {
unreachable!()
}
};
- match tail_addr {
- Addr::PStrTail(h, _) if h == addr => {
- self.target.push(HeapCellValue::PartialString(pstr));
- }
- addr => {
- self.target.push(HeapCellValue::PartialString(pstr));
- self.target.push(HeapCellValue::Addr(addr));
- }
- }
+ self.target.push(HeapCellValue::PartialString(pstr));
+ self.target.push(HeapCellValue::Addr(tail_addr));
}
fn copy_partial_string_from(&mut self, addr: usize, n: usize) {
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
));
}
- Addr::PStrTail(h, n) => {
- match &mut self.target[h] {
- HeapCellValue::PartialString(ref mut pstr) => {
- pstr.tail = Addr::PStrTail(frontier, n);
- }
- _ => {
- unreachable!()
- }
- }
-
- self.target[frontier] = HeapCellValue::Addr(Addr::PStrTail(frontier, n));
- self.trail.push((
- Ref::PStrTail(h, n),
- HeapCellValue::Addr(Addr::PStrTail(h, n))
- ));
- }
Addr::AttrVar(h) => {
let threshold = if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
self.target.threshold()
}
addr @ Addr::AttrVar(_)
| addr @ Addr::HeapCell(_)
- | addr @ Addr::StackCell(..)
- | addr @ Addr::PStrTail(..) => {
+ | addr @ Addr::StackCell(..) => {
self.copy_var(addr);
}
Addr::Str(addr) => {
match r {
Ref::AttrVar(h) | Ref::HeapCell(h) =>
self.target[h] = value,
- Ref::PStrTail(h, _) =>
- if let HeapCellValue::PartialString(ref mut pstr) = &mut self.target[h] {
- pstr.tail = value.as_addr(0);
- },
Ref::StackCell(fr, sc) =>
self.target.stack().index_and_frame_mut(fr)[sc] = value.as_addr(0),
}
pub(crate)
fn allocate_pstr(&mut self, mut src: &str) -> Option<Addr> {
let orig_h = self.h();
-
+
loop {
if src == "" {
return if orig_h == self.h() {
None
} else {
- let prev_h = self.h() - 1;
-
- match &mut self[prev_h] {
- HeapCellValue::PartialString(ref mut pstr) => {
- let s = pstr.block_as_str();
- pstr.tail = Addr::PStrTail(prev_h, s.len());
- }
- _ => {
- unreachable!()
- }
- }
+ let tail_h = self.h() - 1;
+ self[tail_h] = HeapCellValue::Addr(Addr::HeapCell(tail_h));
Some(Addr::PStrLocation(orig_h, 0))
};
}
-
+
let h = self.h();
- let (mut pstr, rest_src) =
- match PartialString::new(src, h) {
+ let (pstr, rest_src) =
+ match PartialString::new(src) {
Some(tuple) => {
tuple
}
} else if orig_h == h {
return None;
} else {
- let prev_h = h - 1;
-
- match &mut self[prev_h] {
- HeapCellValue::PartialString(ref mut pstr) => {
- let s = pstr.block_as_str();
- pstr.tail = Addr::PStrTail(prev_h, s.len());
- }
- _ => {
- unreachable!()
- }
- }
-
+ self[h - 1] = HeapCellValue::Addr(Addr::HeapCell(h - 1));
return Some(Addr::PStrLocation(orig_h, 0));
}
}
};
- let new_top = unsafe {
- self.buf.new_block(mem::size_of::<HeapCellValue>())
- };
+ self.push(HeapCellValue::PartialString(pstr));
if rest_src != "" {
- pstr.tail = Addr::PStrLocation(h+1, 0);
+ self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0)));
src = rest_src;
} else {
- pstr.tail = Addr::PStrTail(h, src.len());
- }
-
- unsafe{
- ptr::write(
- self.buf.top as *mut _,
- HeapCellValue::PartialString(pstr),
- );
- }
-
- self.buf.top = new_top;
-
- if rest_src == "" {
+ self.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
return Some(Addr::PStrLocation(orig_h, 0));
- }
+ }
}
}
CompleteString(usize, Rc<String>), // the string length (in bytes), the string.
UntouchedString(usize, Rc<String>), // the cut off, past which is the untouched string.
PStrLocation(usize, usize, usize), // the list length (up to max), the heap offset, byte offset into the string.
- PStrTail(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).
}
StackCell(usize, usize),
Str(usize),
PStrLocation(usize, usize), // location of pstr in heap, offset into string in bytes.
- PStrTail(usize, usize), // location of pstr in heap, offset into string in bytes.
Stream(Stream),
}
AttrVar(usize),
HeapCell(usize),
StackCell(usize, usize),
- PStrTail(usize, usize),
}
impl Ref {
Ref::AttrVar(h) => Addr::AttrVar(h),
Ref::HeapCell(h) => Addr::HeapCell(h),
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
- Ref::PStrTail(h, n) => Addr::PStrTail(h, n),
}
}
}
match self {
&Addr::StackCell(fr, sc) => {
match *r {
- Ref::AttrVar(_) | Ref::HeapCell(_) | Ref::PStrTail(..) => {
+ Ref::AttrVar(_) | Ref::HeapCell(_) => {
Some(Ordering::Greater)
}
Ref::StackCell(fr1, sc1) => {
Ref::AttrVar(h1) | Ref::HeapCell(h1) => {
h.partial_cmp(h1)
}
- Ref::PStrTail(h1, _) => {
- h.partial_cmp(h1)
- }
- }
- }
- &Addr::PStrTail(h, n) => {
- match r {
- Ref::StackCell(..) => {
- Some(Ordering::Less)
- }
- Ref::AttrVar(h1) | Ref::HeapCell(h1) => {
- h.partial_cmp(h1)
- }
- Ref::PStrTail(h1, n1) => {
- Some(h.cmp(h1).then_with(|| n.cmp(n1)))
- }
}
}
_ => {
impl Addr {
pub fn is_ref(&self) -> bool {
match self {
- Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) | Addr::PStrTail(..) => {
+ Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => {
true
}
_ => {
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
- &Addr::PStrTail(h, n) => Some(Ref::PStrTail(h, n)),
_ => None,
}
}
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
Addr::Str(s) => Addr::Str(s + rhs),
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs, n),
- Addr::PStrTail(h, n) => Addr::PStrTail(h + rhs, n),
_ => self,
}
}
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
- Addr::PStrTail(h, n) => Addr::PStrTail(h + rhs.abs() as usize, n),
Addr::PStrLocation(h, n) => Addr::PStrLocation(h + rhs.abs() as usize, n),
_ => self,
}
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
Addr::Str(s) => Addr::Str(s - rhs),
- Addr::PStrTail(h, n) => Addr::PStrTail(h - rhs, n),
Addr::PStrLocation(h, n) => Addr::PStrLocation(h - rhs, n),
_ => self,
}
for heap_value in self.stub.iter_from(0) {
stub.push(match heap_value {
- HeapCellValue::Addr(ref addr) => HeapCellValue::Addr(addr.clone() - diff),
- HeapCellValue::PartialString(ref pstr) => {
- let mut new_pstr = pstr.clone();
- new_pstr.tail = pstr.tail.clone() - diff;
- HeapCellValue::PartialString(new_pstr)
+ HeapCellValue::Addr(ref addr) => {
+ HeapCellValue::Addr(addr.clone() - diff)
+ }
+ heap_value => {
+ heap_value.clone()
}
- heap_value => heap_value.clone(),
});
}
pub(super) enum HeapPtr {
HeapCell(usize),
PStrChar(usize, usize),
- PStrTail(usize, usize),
+ PStrLocation(usize, usize),
StringChar(usize, Rc<String>),
- StringTail(usize, Rc<String>),
+ StringLocation(usize, Rc<String>),
}
impl HeapPtr {
if let Some(c) = s[n ..].chars().next() {
Addr::Con(Constant::Char(c))
} else {
- Addr::PStrTail(h, n)
+ Addr::HeapCell(h + 1)
}
} else {
unreachable!()
},
- &HeapPtr::PStrTail(h, n) =>
- Addr::PStrTail(h, n),
+ &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::StringTail(n, ref s) =>
+ &HeapPtr::StringLocation(n, ref s) =>
Addr::Con(Constant::String(n, s.clone())),
}
}
Addr::StackCell(fr, sc) => {
self.stack.index_and_frame(fr)[sc].clone()
}
- Addr::PStrTail(h, n) => {
+ Addr::PStrLocation(h, n) => {
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
if pstr.len() > n {
Addr::PStrLocation(h, n)
} else {
- pstr.tail.clone()
+ Addr::HeapCell(h + 1)
}
} else {
unreachable!()
}
}
- fn bind_pstr_tail(&mut self, h: usize, t2: Addr) {
- let pstr_len = match &mut self.heap[h] {
- HeapCellValue::PartialString(ref mut pstr) => {
- pstr.tail = t2;
- pstr.len()
- }
- _ => {
- unreachable!()
- }
- };
-
- self.trail(TrailRef::from(Ref::PStrTail(h, pstr_len)));
- }
-
pub(super)
fn bind(&mut self, r1: Ref, a2: Addr) {
let t1 = self.store(r1.as_addr());
Ref::AttrVar(h) => {
return self.bind_attr_var(h, t2);
}
- Ref::PStrTail(h, _) => {
- return self.bind_pstr_tail(h, t2);
- }
};
self.trail(TrailRef::from(r1));
Some(Ref::AttrVar(h)) => {
self.bind_attr_var(h, t1);
}
- Some(Ref::PStrTail(h, _)) => {
- self.bind_pstr_tail(h, t1);
- }
None => {
}
}
(Addr::StackCell(fr, sc), addr) | (addr, Addr::StackCell(fr, sc)) => {
self.bind_with_occurs_check(Ref::StackCell(fr, sc), addr)
}
- (Addr::PStrTail(h, n), addr) | (addr, Addr::PStrTail(h, n)) => {
- self.bind_with_occurs_check(Ref::PStrTail(h, n), addr);
- }
(Addr::Lis(a1), Addr::Str(a2)) | (Addr::Str(a2), Addr::Lis(a1)) => {
if let &HeapCellValue::NamedStr(n2, ref f2, _) = &self.heap[a2] {
if f2.as_str() == "." && n2 == 2 {
let s = pstr.block_as_str();
if let Some(c) = s[n ..].chars().next() {
- pdl.push(Addr::PStrTail(h, n + c.len_utf8()));
+ pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
pdl.push(Addr::HeapCell(l + 1));
pdl.push(Addr::Con(Constant::Char(c)));
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
let pstr_s = pstr.block_as_str();
- if let Some(c) = pstr_s[n ..].chars().next() {
- if let Some(c1) = s[n1 ..].chars().next() {
- if c == c1 {
- pdl.push(Addr::Con(Constant::String(n1 + c.len_utf8(), s)));
- pdl.push(Addr::PStrTail(h, n + c.len_utf8()));
+ let pstr_len = pstr_s[n ..].len();
+ let s_len = s[n1 ..].len();
+ let m_len = std::cmp::min(s_len, pstr_len);
- continue;
- }
+ if pstr_s[n .. n + m_len] == s[n1 .. n1 + m_len] {
+ if s_len <= pstr_len {
+ pdl.push(Addr::Con(Constant::EmptyList));
+ pdl.push(Addr::PStrLocation(h, n + m_len));
+ } else {
+ pdl.push(Addr::Con(Constant::String(n1 + m_len, s)));
+ pdl.push(Addr::HeapCell(h + 1));
}
+
+ continue;
}
self.fail = true;
let pstr_s1 = pstr1.block_as_str();
let pstr_s2 = pstr2.block_as_str();
- if let Some(c1) = pstr_s1[n1 ..].chars().next() {
- if let Some(c2) = pstr_s2[n2 ..].chars().next() {
- if c1 == c2 {
- pdl.push(Addr::PStrTail(h1, n1 + c1.len_utf8()));
- pdl.push(Addr::PStrTail(h2, n2 + c2.len_utf8()));
+ let pstr_s1_len = pstr_s1[n1 ..].len();
+ let pstr_s2_len = pstr_s2[n2 ..].len();
+ let m_len = std::cmp::min(pstr_s1_len, pstr_s2_len);
- continue;
- }
+ if pstr_s1[n1 .. n1 + m_len] == pstr_s2[n2 .. n2 + m_len] {
+ if pstr_s1_len <= pstr_s2_len {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ } else {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ pdl.push(Addr::PStrLocation(h1, n1 + m_len));
}
+
+ continue;
}
self.fail = true;
pub(super)
fn unify(&mut self, a1: Addr, a2: Addr) {
let mut pdl = vec![a1, a2];
-
+
let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new();
self.fail = false;
(Addr::StackCell(fr, sc), addr) | (addr, Addr::StackCell(fr, sc)) => {
self.bind(Ref::StackCell(fr, sc), addr);
}
- (Addr::PStrTail(h, n), addr) | (addr, Addr::PStrTail(h, n)) => {
- self.bind(Ref::PStrTail(h, n), addr);
- }
(Addr::Lis(a1), Addr::Str(a2)) | (Addr::Str(a2), Addr::Lis(a1)) => {
if let &HeapCellValue::NamedStr(n2, ref f2, _) = &self.heap[a2] {
if f2.as_str() == "." && n2 == 2 {
let s = pstr.block_as_str();
if let Some(c) = s[n ..].chars().next() {
- pdl.push(Addr::PStrTail(h, n + c.len_utf8()));
+ pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
pdl.push(Addr::HeapCell(l + 1));
pdl.push(Addr::Con(Constant::Char(c)));
if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
let pstr_s = pstr.block_as_str();
- if let Some(c) = pstr_s[n ..].chars().next() {
- if let Some(c1) = s[n1 ..].chars().next() {
- if c == c1 {
- pdl.push(Addr::Con(Constant::String(n1 + c.len_utf8(), s)));
- pdl.push(Addr::PStrTail(h, n + c.len_utf8()));
+ let pstr_len = pstr_s[n ..].len();
+ let s_len = s[n1 ..].len();
+ let m_len = std::cmp::min(s_len, pstr_len);
- continue;
- }
+ if pstr_s[n .. n + m_len] == s[n1 .. n1 + m_len] {
+ if s_len <= pstr_len {
+ pdl.push(Addr::Con(Constant::EmptyList));
+ pdl.push(Addr::PStrLocation(h, n + m_len));
+ } else {
+ pdl.push(Addr::Con(Constant::String(n1 + m_len, s)));
+ pdl.push(Addr::HeapCell(h + 1));
}
+
+ continue;
}
self.fail = true;
let pstr_s1 = pstr1.block_as_str();
let pstr_s2 = pstr2.block_as_str();
- if let Some(c1) = pstr_s1[n1 ..].chars().next() {
- if let Some(c2) = pstr_s2[n2 ..].chars().next() {
- if c1 == c2 {
- pdl.push(Addr::PStrTail(h1, n1 + c1.len_utf8()));
- pdl.push(Addr::PStrTail(h2, n2 + c2.len_utf8()));
+ let pstr_s1_len = pstr_s1[n1 ..].len();
+ let pstr_s2_len = pstr_s2[n2 ..].len();
+ let m_len = std::cmp::min(pstr_s1_len, pstr_s2_len);
- continue;
- }
+ if pstr_s1[n1 .. n1 + m_len] == pstr_s2[n2 .. n2 + m_len] {
+ if pstr_s1_len <= pstr_s2_len {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ } else {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ pdl.push(Addr::PStrLocation(h1, n1 + m_len));
}
+
+ continue;
}
self.fail = true;
self.tr += 1;
}
}
- TrailRef::Ref(Ref::PStrTail(h, n)) => {
- if h < self.hb {
- self.trail.push(TrailRef::Ref(Ref::PStrTail(h, n)));
- self.tr += 1;
- }
- }
TrailRef::AttrVarHeapLink(h) => {
if h < self.hb {
self.trail.push(TrailRef::AttrVarHeapLink(h));
HeapPtr::HeapCell(ref mut h) => {
*h += rhs;
}
- HeapPtr::PStrChar(h, n) | HeapPtr::PStrTail(h, n) => {
+ HeapPtr::PStrChar(h, n) | HeapPtr::PStrLocation(h, n) => {
match &self.heap[*h] {
HeapCellValue::PartialString(ref pstr) => {
let s = pstr.block_as_str();
*n += c.len_utf8();
}
- self.s = HeapPtr::PStrTail(*h, *n);
+ self.s = HeapPtr::PStrLocation(*h, *n);
}
_ => {
unreachable!()
}
}
}
- HeapPtr::StringChar(n, s) | HeapPtr::StringTail(n, s) => {
+ HeapPtr::StringChar(n, s) | HeapPtr::StringLocation(n, s) => {
for c in s[*n ..].chars().take(rhs) {
*n += c.len_utf8();
}
- self.s = HeapPtr::StringTail(*n, s.clone());
+ self.s = HeapPtr::StringLocation(*n, s.clone());
}
}
}
TrailRef::Ref(Ref::StackCell(fr, sc)) => {
self.stack.index_and_frame_mut(fr)[sc] = Addr::StackCell(fr, sc)
}
- TrailRef::Ref(Ref::PStrTail(h, n)) => {
- if let HeapCellValue::PartialString(ref mut pstr) = &mut self.heap[h] {
- pstr.truncate(n);
- pstr.tail = Addr::PStrTail(h, n);
-
- self.tr += 1;
- }
- }
TrailRef::AttrVarHeapLink(h) => {
self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h));
}
match self.trail[i] {
TrailRef::Ref(Ref::AttrVar(tr_i))
| TrailRef::Ref(Ref::HeapCell(tr_i))
- | TrailRef::Ref(Ref::PStrTail(tr_i, _))
| TrailRef::AttrVarHeapLink(tr_i)
| TrailRef::AttrVarListLink(tr_i, _) => {
if tr_i >= hb {
}
addr @ Addr::AttrVar(_)
| addr @ Addr::StackCell(..)
- | addr @ Addr::HeapCell(_)
- | addr @ Addr::PStrTail(..) => {
+ | addr @ Addr::HeapCell(_) => {
let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
let offset = match addr {
Addr::HeapCell(_) | Addr::StackCell(..)
- | Addr::AttrVar(..) | Addr::PStrTail(..)
- | Addr::Stream(_) => {
+ | Addr::AttrVar(..) | Addr::Stream(_) => {
v
}
Addr::Con(Constant::String(n, ref s)) => {
}
Addr::Str(_) => {
s
- }
+ }
Addr::DBRef(_) => {
self.fail = true;
return;
let a1 = self.registers[1].clone();
let addr = self.store(self.deref(a1));
- let offset = match addr {
+ let offset = match addr {
Addr::Con(constant) => match hm.get(&constant) {
Some(offset) => *offset,
_ => 0,
if addr < Ref::HeapCell(h) {
self.heap.push(HeapCellValue::Addr(addr));
- return;
+ return;
}
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
let n = self.store(self.deref(self[temp_v!(1)].clone()));
match n {
- Addr::HeapCell(_) | Addr::StackCell(..) | Addr::PStrTail(..) =>
+ Addr::HeapCell(_) | Addr::StackCell(..) =>
// 8.5.2.3 a)
{
return Err(self.error_form(MachineError::instantiation_error(), stub))
let term = self.store(self.deref(self[temp_v!(2)].clone()));
match term {
- Addr::HeapCell(_) | Addr::StackCell(..) | Addr::PStrTail(..) =>
+ Addr::HeapCell(_) | Addr::StackCell(..) =>
// 8.5.2.3 b)
{
return Err(self.error_form(MachineError::instantiation_error(), stub))
if n == 1 {
Addr::Con(Constant::Char(c))
} else {
- Addr::PStrTail(h, offset + c.len_utf8())
+ Addr::PStrLocation(h, offset + c.len_utf8())
}
} else {
unreachable!()
_ =>
// 8.5.2.3 d)
{
- return Err(self
- .error_form(MachineError::type_error(ValidType::Compound, term), stub))
+ return Err(self.error_form(
+ MachineError::type_error(ValidType::Compound, term),
+ stub,
+ ))
}
}
}
_ =>
// 8.5.2.3 c)
{
- return Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub))
+ return Err(self.error_form(
+ MachineError::type_error(ValidType::Integer, n),
+ stub,
+ ))
}
}
| (
HeapCellValue::Addr(Addr::PStrLocation(..)),
HeapCellValue::Addr(Addr::PStrLocation(..)),
- )
- | (
- HeapCellValue::Addr(Addr::PStrTail(..)),
- HeapCellValue::Addr(Addr::PStrTail(..)),
- ) => {
- }
- (
- HeapCellValue::Addr(Addr::PStrLocation(h1, _)),
- HeapCellValue::Addr(Addr::PStrTail(h2, _)),
- ) => {
- return if h1 == h2 {
- Ordering::Less
- } else {
- h1.cmp(&h2)
- };
- }
- (
- HeapCellValue::Addr(Addr::PStrTail(h2, _)),
- HeapCellValue::Addr(Addr::PStrLocation(h1, _)),
) => {
- return if h1 == h2 {
- Ordering::Greater
- } else {
- h2.cmp(&h1)
- };
}
(
HeapCellValue::Addr(Addr::PStrLocation(..)),
return hc1.cmp(&hc2);
}
}
- (
- HeapCellValue::Addr(Addr::PStrTail(hc1, _)),
- HeapCellValue::Addr(Addr::HeapCell(hc2)),
- )
- | (
- HeapCellValue::Addr(Addr::HeapCell(hc1)),
- HeapCellValue::Addr(Addr::PStrTail(hc2, _)),
- )
- | (
- HeapCellValue::Addr(Addr::PStrTail(hc1, _)),
- HeapCellValue::Addr(Addr::AttrVar(hc2)),
- )
- | (
- HeapCellValue::Addr(Addr::AttrVar(hc1)),
- HeapCellValue::Addr(Addr::PStrTail(hc2, _)),
- ) => {
- if hc1 != hc2 {
- return hc1.cmp(&hc2);
- }
- }
(HeapCellValue::Addr(Addr::HeapCell(_)), _)
- | (HeapCellValue::Addr(Addr::AttrVar(_)), _)
- | (HeapCellValue::Addr(Addr::PStrTail(..)), _) => {
+ | (HeapCellValue::Addr(Addr::AttrVar(_)), _) => {
return Ordering::Less;
}
(
HeapCellValue::Addr(Addr::StackCell(..)),
HeapCellValue::Addr(Addr::HeapCell(_)),
)
- | (
- HeapCellValue::Addr(Addr::StackCell(..)),
- HeapCellValue::Addr(Addr::PStrTail(..)),
- )
| (
HeapCellValue::Addr(Addr::StackCell(..)),
HeapCellValue::Addr(Addr::AttrVar(_)),
| (
HeapCellValue::Addr(Addr::Con(Constant::Integer(..))),
HeapCellValue::Addr(Addr::AttrVar(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Integer(..))),
- HeapCellValue::Addr(Addr::PStrTail(..)),
- )=> {
+ ) => {
return Ordering::Greater;
}
(
return n1.cmp(&n2);
}
}
- (HeapCellValue::Addr(Addr::Con(Constant::Integer(_))), _) => return Ordering::Less,
+ (HeapCellValue::Addr(Addr::Con(Constant::Integer(_))), _) => {
+ return Ordering::Less;
+ }
(
HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
HeapCellValue::Addr(Addr::HeapCell(_)),
| (
HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
HeapCellValue::Addr(Addr::AttrVar(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Float(..))),
- HeapCellValue::Addr(Addr::PStrTail(..)),
) => {
return Ordering::Greater;
}
| (
HeapCellValue::Addr(Addr::Con(Constant::Rational(..))),
HeapCellValue::Addr(Addr::AttrVar(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::Rational(..))),
- HeapCellValue::Addr(Addr::PStrTail(..)),
) => {
return Ordering::Greater;
}
| (
HeapCellValue::Addr(Addr::Con(Constant::String(..))),
HeapCellValue::Addr(Addr::AttrVar(_)),
- )
- | (
- HeapCellValue::Addr(Addr::Con(Constant::String(..))),
- HeapCellValue::Addr(Addr::PStrTail(..)),
) => {
return Ordering::Greater;
}
HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
HeapCellValue::Addr(Addr::StackCell(..)),
) => return Ordering::Greater,
- (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
- HeapCellValue::Addr(Addr::PStrTail(..)),
- ) => return Ordering::Greater,
(
HeapCellValue::Addr(Addr::Con(Constant::Atom(..))),
HeapCellValue::Addr(Addr::Con(Constant::Float(_))),
return n.as_str().cmp(".");
}
}
- (HeapCellValue::NamedStr(..), _) => return Ordering::Greater,
- (HeapCellValue::Addr(Addr::Lis(_)), _) => return Ordering::Greater,
+ (HeapCellValue::NamedStr(..), _) => {
+ return Ordering::Greater;
+ }
+ (HeapCellValue::Addr(Addr::Lis(_)), _) => {
+ return Ordering::Greater;
+ }
_ => {}
}
}
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) | Addr::PStrTail(..) => {
+ Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
self.fail = true;
}
_ => {
let d = self.store(self.deref(self[r1].clone()));
match d {
- Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::PStrTail(..) => {
+ Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
self.p += 1;
}
_ => {
let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir);
self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc)
}
- Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) | Addr::PStrTail(..) => {
+ Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => {
let name = self.store(self.deref(self[temp_v!(2)].clone()));
let arity = self.store(self.deref(self[temp_v!(3)].clone()));
Addr::Lis(l) => {
self.try_from_inner_list(vec![], l, caller, a1)
}
- Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => {
- if s.len() > n {
- Ok(Vec::from_iter(s[n ..].chars().map(|c| Addr::Con(Constant::Char(c)))))
- } else {
- Ok(vec![])
+ Addr::Con(Constant::String(n, ref s))
+ if !self.flags.double_quotes.is_atom() => {
+ if s.len() > n {
+ Ok(Vec::from_iter(s[n ..].chars().map(|c| {
+ Addr::Con(Constant::Char(c))
+ })))
+ } else {
+ Ok(vec![])
+ }
}
- }
Addr::PStrLocation(h, n) => {
self.try_from_partial_string(vec![], h, n, caller, a1)
}
- Addr::HeapCell(_) | Addr::StackCell(..) | Addr::PStrTail(..) => {
+ Addr::HeapCell(_) | Addr::StackCell(..) => {
Err(self.error_form(MachineError::instantiation_error(), caller))
}
Addr::Con(Constant::EmptyList) => {
chars.extend(s[n ..].chars().map(|c| Addr::Con(Constant::Char(c))));
- match self.store(self.deref(pstr.tail.clone())) {
+ let tail = self.heap[h + 1].as_addr(h + 1);
+
+ match self.store(self.deref(tail)) {
Addr::Con(Constant::EmptyList) => {
return Ok(chars);
}
-use crate::prolog::machine::machine_indices::*;
use crate::prolog::machine::raw_block::*;
use std::mem;
pub struct PartialString {
pub(super) buf: RawBlock<PartialStringTraits>,
- pub(super) tail: Addr,
}
impl Clone for PartialString {
impl PartialString {
pub(super)
- fn new(src: &str, h: usize) -> Option<(Self, &str)> {
+ fn new(src: &str) -> Option<(Self, &str)> {
let pstr = PartialString {
buf: RawBlock::with_capacity(src.len() + '\u{0}'.len_utf8()),
- tail: Addr::PStrTail(h, 0),
};
unsafe {
unsafe fn append_chars(mut self, src: &str) -> Option<(Self, &str)> {
let terminator_idx = scan_for_terminator(src);
-
+
if terminator_idx == 0 {
return None;
}
-
+
let new_top = self.buf.new_block(terminator_idx + '\u{0}'.len_utf8());
ptr::copy(
})
}
- /* Ordinarily cloning of heap cell values is done in copy_term,
- * so we rely on it to set the tail correctly. here it's set to PStrTail(0, 0),
- * because we don't know its heap location. */
pub(super)
fn clone_from_offset(&self, n: usize) -> Self {
let mut pstr = PartialString {
buf: RawBlock::with_capacity(self.len() + '\u{0}'.len_utf8()),
- tail: Addr::PStrTail(0, 0),
};
unsafe {
- let len = if self.len() > n { self.len() - n } else { 0 };
+ let len = if self.len() > n { self.len() - n } else { 0 };
let new_top = pstr.buf.new_block(len + '\u{0}'.len_utf8());
if len > 0 {
(self.buf.base as usize + n) as *mut u8,
pstr.buf.base as *mut _,
len,
- );
+ );
}
pstr.write_terminator_at(len);
}
}
- #[inline]
- pub(crate)
- fn tail_addr(&self) -> &Addr {
- &self.tail
- }
-
#[inline]
pub fn len(&self) -> usize {
self.buf.top as usize - self.buf.base as usize
}
-
- #[inline]
- pub fn truncate(&mut self, len: usize) {
- if (len + self.buf.base as usize) < self.buf.top as usize {
- self.buf.top = (len + self.buf.base as usize) as *const _;
- self.write_terminator_at(len);
- }
- }
}
}
}
- fn step(&mut self, hare: Addr) -> Option<CycleSearchResult> {
- self.hare = hare;
- self.steps += 1;
-
+ #[inline]
+ fn conclude_or_move_tortoise(&mut self) -> Option<CycleSearchResult> {
if self.tortoise == self.hare {
return Some(CycleSearchResult::NotList);
} else if self.steps == self.power {
self.power <<= 1;
}
-
None
}
+ #[inline]
+ fn step(&mut self, hare: Addr) -> Option<CycleSearchResult> {
+ self.hare = hare;
+ self.steps += 1;
+
+ self.conclude_or_move_tortoise()
+ }
+
fn to_result(self) -> CycleSearchResult {
match self.hare {
addr @ Addr::HeapCell(_) | addr @ Addr::StackCell(..) | addr @ Addr::AttrVar(_) => {
Addr::PStrLocation(h, n) => {
CycleSearchResult::PStrLocation(self.steps, h, n)
}
- Addr::PStrTail(h, n) => {
- CycleSearchResult::PStrTail(self.steps, h, n)
- }
Addr::Con(Constant::EmptyList) => {
CycleSearchResult::ProperList(self.steps)
}
Some(CycleSearchResult::CompleteString(s.len(), s))
}
}
- Addr::PStrTail(h, n) => {
- Some(CycleSearchResult::PStrTail(brent_st.steps, h, n))
- }
Addr::PStrLocation(h, n) => {
match &self.heap[h] {
HeapCellValue::PartialString(ref pstr) => {
let s = pstr.block_as_str();
if let Some(c) = s[n ..].chars().next() {
- brent_st.step(Addr::PStrTail(h, n + c.len_utf8()))
+ brent_st.step(Addr::PStrLocation(h, n + c.len_utf8()))
} else {
unreachable!()
}
Addr::PStrLocation(h, _) => {
return CycleSearchResult::UntouchedList(h);
}
- Addr::PStrTail(h, n) => {
- return CycleSearchResult::PStrTail(0, h, n);
- }
Addr::Con(Constant::EmptyList) => {
return CycleSearchResult::EmptyList;
}
Addr::PStrLocation(h, n) => {
Addr::PStrLocation(h, n)
}
- Addr::PStrTail(h, n) => {
- return CycleSearchResult::PStrTail(0, h, n);
- }
Addr::Con(Constant::String(0, ref s)) if !self.flags.double_quotes.is_atom() => {
return CycleSearchResult::CompleteString(s.len(), s.clone());
}
};
match search_result {
- CycleSearchResult::PStrTail(steps, h, n) => {
- self.finalize_skip_max_list(steps, Addr::PStrTail(h, n));
- }
CycleSearchResult::PStrLocation(steps, h, n) => {
self.finalize_skip_max_list(steps, Addr::PStrLocation(h, n));
}
}
};
- let pstr_tail = match &self.heap[h] {
- HeapCellValue::PartialString(ref pstr) => {
- pstr.tail_addr().clone()
- }
- _ => {
- unreachable!()
- }
- };
-
+ let pstr_tail = self.heap[h + 1].as_addr(h + 1);
+
self.unify(self[temp_v!(2)].clone(), pstr);
if !self.fail {
match pstr {
Addr::PStrLocation(h, _) => {
- let tail = if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- pstr.tail.clone()
- } else {
- unreachable!()
- };
-
+ let tail = self.heap[h + 1].as_addr(h + 1);
let target = self[temp_v!(2)].clone();
+
self.unify(tail, target);
}
_ => {
HeapCellValue::Addr(ref mut addr) => {
*addr -= self.heap.h() + lh_offset
}
- HeapCellValue::PartialString(ref mut pstr) => {
- pstr.tail -= self.heap.h() + lh_offset;
- }
_ => {}
}
}
self.heap.push(HeapCellValue::Addr(addr.clone() + h));
}
HeapCellValue::PartialString(ref pstr) => {
- let mut new_pstr = pstr.clone();
- new_pstr.tail = pstr.tail.clone() + h;
+ let new_pstr = pstr.clone();
self.heap.push(HeapCellValue::PartialString(new_pstr));
}
value => {
self.heap.push(HeapCellValue::Addr(addr.clone() + h))
}
HeapCellValue::PartialString(ref pstr) => {
- let mut new_pstr = pstr.clone();
- new_pstr.tail = pstr.tail.clone() + h;
+ let new_pstr = pstr.clone();
self.heap.push(HeapCellValue::PartialString(new_pstr));
}
value => {
write!(f, "{}/{}", name.as_str(), arity)
}
&HeapCellValue::PartialString(ref pstr) => {
- write!(f, "pstr ( buf: {}, tail: {} )", pstr.block_as_str(), pstr.tail_addr())
+ write!(f, "pstr ( buf: {} )", pstr.block_as_str())
}
}
}
&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::PStrTail(h, n) => write!(f, "Addr::PStrTail({}, {})", h, n),
&Addr::Stream(ref stream) => write!(f, "Addr::Stream({})", stream.as_ptr() as usize),
}
}