Filtering...

istrprefixp

books/std/strings/istrprefixp
other
(in-package "STR")
other
(include-book "ieqv")
other
(include-book "iprefixp")
other
(include-book "std/basic/defs" :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 iprefixp-lemma-1
    (implies (and (natp xn)
        (natp yn)
        (< xn (len x))
        (< yn (len y))
        (not (ichareqv (nth xn x) (nth yn y))))
      (not (iprefixp (nthcdr xn x)
          (nthcdr yn y))))
    :hints (("Goal" :in-theory (enable nthcdr nth iprefixp)))))
other
(local (defthm iprefixp-lemma-2
    (implies (and (natp xn)
        (natp yn)
        (< xn (len x))
        (< yn (len y))
        (ichareqv (nth xn x) (nth yn y)))
      (equal (iprefixp (nthcdr xn x)
          (nthcdr yn y))
        (iprefixp (cdr (nthcdr xn x))
          (cdr (nthcdr yn y)))))
    :hints (("Goal" :in-theory (enable iprefixp nth nthcdr)))))
other
(defsection istrprefixp
  :parents (substrings)
  :short "Case-insensitive string prefix test."
  :long "<p>@(call istrprefixp) determines if the string @('x') is a
case-insensitive prefix of the string @('y').</p>

<p>Logically, this is identical to</p>
@({
  (iprefixp (explode x) (explode y))
})

<p>But we use a more efficient implementation which avoids coercing the strings
to lists.</p>"
  (defund istrprefixp-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))))
        :guard-hints (("Goal" :in-theory (enable ichareqv)))))
    (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)
      ((ichareqv (char x xn) (char y yn)) (istrprefixp-impl x
          y
          (+ 1 (lnfix xn))
          (+ 1 (lnfix yn))
          xl
          yl))
      (t nil)))
  (definline istrprefixp
    (x y)
    (declare (type string x)
      (type string y)
      (xargs :verify-guards nil))
    (mbe :logic (iprefixp (explode x) (explode y))
      :exec (istrprefixp-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))))))
  (defthm istrprefixp-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 (istrprefixp-impl x
          y
          xn
          yn
          xl
          yl)
        (iprefixp (nthcdr xn (coerce x 'list))
          (nthcdr yn (coerce y 'list)))))
    :hints (("Goal" :in-theory (enable istrprefixp-impl))))
  (verify-guards istrprefixp$inline)
  (defcong istreqv
    equal
    (istrprefixp x y)
    1)
  (defcong istreqv
    equal
    (istrprefixp x y)
    2))