Filtering...

prefix-lines

books/std/strings/prefix-lines
other
(in-package "STR")
other
(include-book "cat")
other
(local (include-book "arithmetic"))
other
(defsection prefix-lines
  :parents (lines)
  :short "Add a prefix to every line in a string."
  :long "<p>@(call prefix-lines) builds a new string by adding @('prefix') to
the start of every line in the string @('x').  The start of @('x') is regarded
as the start of a line, and also gets the prefix.  For instance,</p>

@({
 (prefix-lines "hello world
 goodbye world" "  ** ")
})

<p>Would create the following result:</p>

@({
 "  ** hello world
   ** goodbye world"
})

<p>This is sometimes useful for indenting blobs of text when you are trying to
pretty-print things.  The operation is fairly efficient: we cons everything
into a character list and then coerce it back into a string at the end.</p>"
  (defund prefix-lines-aux
    (n x xl acc prefix)
    (declare (xargs :guard (and (natp n)
          (stringp x)
          (natp xl)
          (<= n xl)
          (= xl (length x))
          (stringp prefix))
        :measure (nfix (- (nfix xl) (nfix n)))))
    (let ((n (lnfix n)) (xl (lnfix xl)))
      (if (mbe :logic (zp (- xl n))
          :exec (int= n xl))
        acc
        (let* ((char (char x n)) (acc (cons char acc))
            (acc (if (eql char #\
)
                (revappend-chars prefix acc)
                acc)))
          (prefix-lines-aux (+ 1 n)
            x
            xl
            acc
            prefix)))))
  (defund prefix-lines
    (x prefix)
    (declare (xargs :guard (and (stringp x) (stringp prefix))
        :verify-guards nil))
    (let* ((acc (revappend-chars prefix nil)) (rchars (prefix-lines-aux 0
            x
            (length x)
            acc
            prefix)))
      (rchars-to-string rchars)))
  (local (in-theory (enable prefix-lines-aux prefix-lines)))
  (defthm character-listp-of-prefix-lines-aux
    (implies (and (natp n)
        (stringp x)
        (<= n xl)
        (= xl (length x))
        (stringp rprefix)
        (character-listp acc))
      (character-listp (prefix-lines-aux n
          x
          xl
          acc
          prefix)))
    :hints (("Goal" :induct (prefix-lines-aux n
         x
         xl
         acc
         prefix))))
  (verify-guards prefix-lines)
  (defthm stringp-of-prefix-lines
    (stringp (prefix-lines x prefix))
    :rule-classes :type-prescription))