correct handling of strings and partial strings as lists, print bar operator with surrounding spaces (#274)

This commit is contained in:
Mark Thom
2020-03-01 00:00:40 -07:00
parent b2cf6a6ea8
commit d8e0bea110
3 changed files with 47 additions and 21 deletions

View File

@@ -157,6 +157,7 @@ fn char_to_string(c: char) -> String {
#[derive(Clone)] #[derive(Clone)]
pub enum TokenOrRedirect { pub enum TokenOrRedirect {
Atom(ClauseName), Atom(ClauseName),
BarAsOp,
Op(ClauseName, SharedOpDesc), Op(ClauseName, SharedOpDesc),
NumberedVar(String), NumberedVar(String),
CompositeRedirect(DirectedOp), 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) { fn format_prefix_op_with_space(&mut self, name: ClauseName, spec: SharedOpDesc) {
let op = DirectedOp::Left(name.clone(), spec); let op = DirectedOp::Left(name.clone(), spec);
self.state_stack self.state_stack.push(TokenOrRedirect::CompositeRedirect(op));
.push(TokenOrRedirect::CompositeRedirect(op));
self.state_stack.push(TokenOrRedirect::Space); self.state_stack.push(TokenOrRedirect::Space);
self.state_stack.push(TokenOrRedirect::Atom(name)); self.state_stack.push(TokenOrRedirect::Atom(name));
} }
@@ -541,11 +541,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let left_directed_op = DirectedOp::Left(name.clone(), spec.clone()); let left_directed_op = DirectedOp::Left(name.clone(), spec.clone());
let right_directed_op = DirectedOp::Right(name.clone(), spec.clone()); let right_directed_op = DirectedOp::Right(name.clone(), spec.clone());
self.state_stack self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
.push(TokenOrRedirect::CompositeRedirect(left_directed_op)); self.state_stack.push(TokenOrRedirect::BarAsOp);
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
self.state_stack
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
} }
fn format_curly_braces(&mut self) { fn format_curly_braces(&mut self) {
@@ -994,6 +992,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
if let Some(loc_data) = self.state_stack.pop() { if let Some(loc_data) = self.state_stack.pop() {
match loc_data { match loc_data {
TokenOrRedirect::Atom(atom) => self.print_atom(&atom), TokenOrRedirect::Atom(atom) => self.print_atom(&atom),
TokenOrRedirect::BarAsOp => self.append_str(" | "),
TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()), TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()), TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()),
TokenOrRedirect::CompositeRedirect(op) => { TokenOrRedirect::CompositeRedirect(op) => {

View File

@@ -249,18 +249,41 @@ pub(super) enum MachineMode {
#[derive(Clone)] #[derive(Clone)]
pub(super) enum HeapPtr { pub(super) enum HeapPtr {
HeapCell(usize), HeapCell(usize),
PStrLocation(usize, usize), PStrChar(usize, usize),
String(usize, Rc<String>), PStrTail(usize, usize),
StringChar(usize, Rc<String>),
StringTail(usize, Rc<String>),
} }
impl HeapPtr { impl HeapPtr {
#[inline] #[inline]
pub(super) pub(super)
fn as_addr(&self) -> Addr { fn read(&self, heap: &Heap) -> Addr {
match self { match self {
&HeapPtr::HeapCell(h) => Addr::HeapCell(h), &HeapPtr::HeapCell(h) =>
&HeapPtr::PStrLocation(h, n) => Addr::PStrLocation(h, n), Addr::HeapCell(h),
&HeapPtr::String(n, ref s) => Addr::Con(Constant::String(n, s.clone())), &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())),
} }
} }
} }

View File

@@ -650,7 +650,7 @@ impl MachineState {
HeapPtr::HeapCell(ref mut h) => { HeapPtr::HeapCell(ref mut h) => {
*h += rhs; *h += rhs;
} }
HeapPtr::PStrLocation(h, n) => { HeapPtr::PStrChar(h, n) | HeapPtr::PStrTail(h, n) => {
match &self.heap[*h] { match &self.heap[*h] {
HeapCellValue::PartialString(ref pstr) => { HeapCellValue::PartialString(ref pstr) => {
let s = pstr.block_as_str(); let s = pstr.block_as_str();
@@ -658,16 +658,20 @@ impl MachineState {
for c in s[*n ..].chars().take(rhs) { for c in s[*n ..].chars().take(rhs) {
*n += c.len_utf8(); *n += c.len_utf8();
} }
self.s = HeapPtr::PStrTail(*h, *n);
} }
_ => { _ => {
unreachable!() unreachable!()
} }
} }
} }
HeapPtr::String(ref mut n, ref s) => { HeapPtr::StringChar(n, s) | HeapPtr::StringTail(n, s) => {
for c in s[*n ..].chars().take(rhs) { for c in s[*n ..].chars().take(rhs) {
*n += c.len_utf8(); *n += c.len_utf8();
} }
self.s = HeapPtr::StringTail(*n, s.clone());
} }
} }
} }
@@ -1606,7 +1610,7 @@ impl MachineState {
match self.flags.double_quotes { match self.flags.double_quotes {
DoubleQuotes::Chars | DoubleQuotes::Codes DoubleQuotes::Chars | DoubleQuotes::Codes
if s.len() > n => { if s.len() > n => {
self.s = HeapPtr::String(n, s); self.s = HeapPtr::StringChar(n, s);
self.mode = MachineMode::Read; self.mode = MachineMode::Read;
} }
_ => { _ => {
@@ -1614,7 +1618,7 @@ impl MachineState {
} }
}, },
Addr::PStrLocation(h, n) => { Addr::PStrLocation(h, n) => {
self.s = HeapPtr::PStrLocation(h, n); self.s = HeapPtr::PStrChar(h, n);
self.mode = MachineMode::Read; self.mode = MachineMode::Read;
} }
addr @ Addr::AttrVar(_) addr @ Addr::AttrVar(_)
@@ -1675,7 +1679,7 @@ impl MachineState {
&FactInstruction::UnifyConstant(ref c) => { &FactInstruction::UnifyConstant(ref c) => {
match self.mode { match self.mode {
MachineMode::Read => { MachineMode::Read => {
let addr = self.s.as_addr(); let addr = self.s.read(&self.heap);
self.write_constant_to_var(addr, c.clone()); self.write_constant_to_var(addr, c.clone());
} }
MachineMode::Write => { MachineMode::Write => {
@@ -1687,7 +1691,7 @@ impl MachineState {
} }
&FactInstruction::UnifyVariable(reg) => { &FactInstruction::UnifyVariable(reg) => {
match self.mode { match self.mode {
MachineMode::Read => self[reg] = self.s.as_addr(), MachineMode::Read => self[reg] = self.s.read(&self.heap),
MachineMode::Write => { MachineMode::Write => {
let h = self.heap.h(); let h = self.heap.h();
@@ -1702,7 +1706,7 @@ impl MachineState {
match self.mode { match self.mode {
MachineMode::Read => { MachineMode::Read => {
let reg_addr = self[reg].clone(); 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 => { MachineMode::Write => {
let addr = self.deref(self[reg].clone()); let addr = self.deref(self[reg].clone());
@@ -1730,7 +1734,7 @@ impl MachineState {
match self.mode { match self.mode {
MachineMode::Read => { MachineMode::Read => {
let reg_addr = self[reg].clone(); 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 => { MachineMode::Write => {
let heap_val = self.store(self[reg].clone()); let heap_val = self.store(self[reg].clone());