From d8e0bea11084a67bdd8f9e92d7126a377f70fd53 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 1 Mar 2020 00:00:40 -0700 Subject: [PATCH] correct handling of strings and partial strings as lists, print bar operator with surrounding spaces (#274) --- src/prolog/heap_print.rs | 13 ++++----- src/prolog/machine/machine_state.rs | 35 ++++++++++++++++++++---- src/prolog/machine/machine_state_impl.rs | 20 ++++++++------ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 407f57a3..7f8fed17 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -157,6 +157,7 @@ fn char_to_string(c: char) -> String { #[derive(Clone)] pub enum TokenOrRedirect { Atom(ClauseName), + BarAsOp, Op(ClauseName, SharedOpDesc), NumberedVar(String), CompositeRedirect(DirectedOp), @@ -531,8 +532,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn format_prefix_op_with_space(&mut self, name: ClauseName, spec: SharedOpDesc) { let op = DirectedOp::Left(name.clone(), spec); - self.state_stack - .push(TokenOrRedirect::CompositeRedirect(op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect(op)); self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Atom(name)); } @@ -541,11 +541,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let left_directed_op = DirectedOp::Left(name.clone(), spec.clone()); let right_directed_op = DirectedOp::Right(name.clone(), spec.clone()); - self.state_stack - .push(TokenOrRedirect::CompositeRedirect(left_directed_op)); - self.state_stack.push(TokenOrRedirect::HeadTailSeparator); - self.state_stack - .push(TokenOrRedirect::CompositeRedirect(right_directed_op)); + self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op)); + self.state_stack.push(TokenOrRedirect::BarAsOp); + self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op)); } fn format_curly_braces(&mut self) { @@ -994,6 +992,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if let Some(loc_data) = self.state_stack.pop() { match loc_data { TokenOrRedirect::Atom(atom) => self.print_atom(&atom), + TokenOrRedirect::BarAsOp => self.append_str(" | "), TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()), TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()), TokenOrRedirect::CompositeRedirect(op) => { diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 0cb9a42e..b2f00972 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -249,18 +249,41 @@ pub(super) enum MachineMode { #[derive(Clone)] pub(super) enum HeapPtr { HeapCell(usize), - PStrLocation(usize, usize), - String(usize, Rc), + PStrChar(usize, usize), + PStrTail(usize, usize), + StringChar(usize, Rc), + StringTail(usize, Rc), } impl HeapPtr { #[inline] pub(super) - fn as_addr(&self) -> Addr { + fn read(&self, heap: &Heap) -> Addr { match self { - &HeapPtr::HeapCell(h) => Addr::HeapCell(h), - &HeapPtr::PStrLocation(h, n) => Addr::PStrLocation(h, n), - &HeapPtr::String(n, ref s) => Addr::Con(Constant::String(n, s.clone())), + &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)) + } else { + Addr::PStrTail(h, n) + } + } else { + unreachable!() + }, + &HeapPtr::PStrTail(h, n) => + Addr::PStrTail(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) => + Addr::Con(Constant::String(n, s.clone())), } } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index fb36d8cb..9ac09ca9 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -650,7 +650,7 @@ impl MachineState { HeapPtr::HeapCell(ref mut h) => { *h += rhs; } - HeapPtr::PStrLocation(h, n) => { + HeapPtr::PStrChar(h, n) | HeapPtr::PStrTail(h, n) => { match &self.heap[*h] { HeapCellValue::PartialString(ref pstr) => { let s = pstr.block_as_str(); @@ -658,16 +658,20 @@ impl MachineState { for c in s[*n ..].chars().take(rhs) { *n += c.len_utf8(); } + + self.s = HeapPtr::PStrTail(*h, *n); } _ => { unreachable!() } } } - HeapPtr::String(ref mut n, ref s) => { + HeapPtr::StringChar(n, s) | HeapPtr::StringTail(n, s) => { for c in s[*n ..].chars().take(rhs) { *n += c.len_utf8(); } + + self.s = HeapPtr::StringTail(*n, s.clone()); } } } @@ -1606,7 +1610,7 @@ impl MachineState { match self.flags.double_quotes { DoubleQuotes::Chars | DoubleQuotes::Codes if s.len() > n => { - self.s = HeapPtr::String(n, s); + self.s = HeapPtr::StringChar(n, s); self.mode = MachineMode::Read; } _ => { @@ -1614,7 +1618,7 @@ impl MachineState { } }, Addr::PStrLocation(h, n) => { - self.s = HeapPtr::PStrLocation(h, n); + self.s = HeapPtr::PStrChar(h, n); self.mode = MachineMode::Read; } addr @ Addr::AttrVar(_) @@ -1675,7 +1679,7 @@ impl MachineState { &FactInstruction::UnifyConstant(ref c) => { match self.mode { MachineMode::Read => { - let addr = self.s.as_addr(); + let addr = self.s.read(&self.heap); self.write_constant_to_var(addr, c.clone()); } MachineMode::Write => { @@ -1687,7 +1691,7 @@ impl MachineState { } &FactInstruction::UnifyVariable(reg) => { match self.mode { - MachineMode::Read => self[reg] = self.s.as_addr(), + MachineMode::Read => self[reg] = self.s.read(&self.heap), MachineMode::Write => { let h = self.heap.h(); @@ -1702,7 +1706,7 @@ impl MachineState { match self.mode { MachineMode::Read => { let reg_addr = self[reg].clone(); - self.unify(reg_addr, self.s.as_addr()); + self.unify(reg_addr, self.s.read(&self.heap)); } MachineMode::Write => { let addr = self.deref(self[reg].clone()); @@ -1730,7 +1734,7 @@ impl MachineState { match self.mode { MachineMode::Read => { let reg_addr = self[reg].clone(); - self.unify(reg_addr, self.s.as_addr()); + self.unify(reg_addr, self.s.read(&self.heap)); } MachineMode::Write => { let heap_val = self.store(self[reg].clone()); -- 2.54.0