Filtering...

strprefixp

books/std/strings/strprefixp
other
(in-package "STR")
other
(include-book "eqv")
other
(include-book "std/lists/prefixp" :dir :system)
other
(include-book "misc/definline" :dir :system)
other
(local (include-book "std/lists/nthcdr" :dir :system))
other
(local (include-book "arithmetic"))
other
(local (defthm prefixp-lemma-1
    (implies (and (natp xn)
        (natp yn)
        (< xn (len x))
        (< yn (len y))
        (not (equal (nth xn x) (nth yn y))))
      (not (prefixp (nthcdr xn x)
          (nthcdr yn y))))
    :hints (("Goal" :in-theory (enable nthcdr nth prefixp)))))
other
(local (defthm prefixp-lemma-2
    (implies (and (natp xn)
        (natp yn)
        (< xn (len x))
        (< yn (len y))
        (equal (nth xn x) (nth yn y)))
      (equal (prefixp (nthcdr xn x)
          (nthcdr yn y))
        (prefixp (cdr (nthcdr xn x))
          (cdr (nthcdr yn y)))))
    :hints (("Goal" :in-theory (enable prefixp nth nthcdr)))))
other
(defsection strprefixp-impl
  :parents (strprefixp)
  :short "Fast implementation of @(see strprefixp)."
  (defund strprefixp-impl
    (x y xn yn xl yl)
    (declare (type string x)
      (type string y)
      (type integer xn)
      (type integer yn)
      (type integer xl)
      (type integer yl)
      (xargs :guard (and (stringp x)
          (stringp y)
          (natp xn)
          (natp yn)
          (natp xl)
          (natp yl)
          (= xl (length x))
          (= yl (length y))
          (<= xn (length x))
          (<= yn (length y)))
        :measure (min (nfix (- (nfix xl) (nfix xn)))
          (nfix (- (nfix yl) (nfix yn))))))
    (cond ((mbe :logic (zp (- (nfix xl) (nfix xn)))
         :exec (int= xn xl)) t)
      ((mbe :logic (zp (- (nfix yl) (nfix yn)))
         :exec (int= yn yl)) nil)
      ((eql (the character (char x xn))
         (the character (char y yn))) (mbe :logic (strprefixp-impl x
            y
            (+ (nfix xn) 1)
            (+ (nfix yn) 1)
            xl
            yl)
          :exec (strprefixp-impl (the string x)
            (the string y)
            (the integer (+ (the integer xn) 1))
            (the integer (+ (the integer yn) 1))
            (the integer xl)
            (the integer yl))))
      (t nil)))
  (local (in-theory (enable strprefixp-impl)))
  (defthm strprefixp-impl-elim
    (implies (and (force (stringp x))
        (force (stringp y))
        (force (natp xn))
        (force (natp yn))
        (force (= xl (length x)))
        (force (= yl (length y))))
      (equal (strprefixp-impl x
          y
          xn
          yn
          xl
          yl)
        (prefixp (nthcdr xn (explode x))
          (nthcdr yn (explode y)))))))
other
(defsection strprefixp
  :parents (substrings)
  :short "Case-sensitive string prefix test."
  :long "<p>@(call strprefixp) determines if the string @('x') is a prefix of
the string @('y'), in a case-sensitive manner.</p>

<p>Logically, this is identical to</p>

@({
 (prefixp (explode x) (explode y))
})

<p>But we use a more efficient implementation which avoids coercing the strings
into character lists.</p>"
  (definline strprefixp
    (x y)
    (declare (type string x)
      (type string y))
    (mbe :logic (prefixp (explode x) (explode y))
      :exec (strprefixp-impl (the string x)
        (the string y)
        (the integer 0)
        (the integer 0)
        (the integer (length (the string x)))
        (the integer (length (the string y))))))
  (defcong streqv
    equal
    (strprefixp x y)
    1)
  (defcong streqv
    equal
    (strprefixp x y)
    2))