Filtering...

istrpos

books/std/strings/istrpos
other
(in-package "STR")
other
(include-book "iprefixp")
other
(include-book "istrprefixp")
other
(local (include-book "arithmetic"))
other
(defsection istrpos
  :parents (substrings)
  :short "Case-insensitivly locate the first occurrence of a substring."
  :long "<p>@(call istrpos) is like @(see strpos), but the comparisons are done
in a case insensitive manner.  It returns @('nil') if @('x') never occurs in
@('y'), or returns the index of the first character of the first occurrence
otherwise.</p>

<p>The function is "efficient" in the sense that it does not coerce its
arguments into lists, but rather traverses both strings with @(see char).  On
the other hand, it is a naive string search which operates by repeatedly
calling @(see istrprefixp) rather than some better algorithm.</p>

<p>The "soundness" and "completness" of strpos are established in the
theorems @('iprefixp-of-istrpos') and @('completeness-of-istrpos').</p>"
  (defund istrpos-impl
    (x y n xl yl)
    (declare (type string x y)
      (type (integer 0 *) n xl yl)
      (xargs :guard (and (stringp x)
          (stringp y)
          (natp xl)
          (natp yl)
          (natp n)
          (<= n (length y))
          (= xl (length x))
          (= yl (length y)))
        :measure (nfix (- (nfix yl) (nfix n)))))
    (cond ((mbe :logic (iprefixp (explode x)
           (nthcdr n (explode y)))
         :exec (istrprefixp-impl (the string x)
           (the string y)
           (the (integer 0 *) 0)
           (the (integer 0 *) n)
           (the (integer 0 *) xl)
           (the (integer 0 *) yl))) (lnfix n))
      ((mbe :logic (zp (- (nfix yl) (nfix n)))
         :exec (int= n yl)) nil)
      (t (istrpos-impl (the string x)
          (the string y)
          (the (integer 0 *)
            (+ 1 (the (integer 0 *) (lnfix n))))
          (the (integer 0 *) xl)
          (the (integer 0 *) yl)))))
  (definlined istrpos
    (x y)
    (declare (type string x y))
    (let* ((xl (mbe :logic (len (explode x))
           :exec (length (the string x)))) (yl (mbe :logic (len (explode y))
            :exec (length (the string y)))))
      (declare (type (integer 0 *) xl yl))
      (istrpos-impl (the string x)
        (the string y)
        (the (integer 0 *) 0)
        xl
        yl)))
  (local (in-theory (enable istrpos istrpos-impl)))
  (defthm istrpos-type
    (or (and (integerp (istrpos x y))
        (<= 0 (istrpos x y)))
      (not (istrpos x y)))
    :rule-classes :type-prescription)
  (encapsulate nil
    (local (defthm lemma
        (implies (and (istrpos-impl x y n xl yl)
            (natp xl)
            (natp yl)
            (natp n)
            (= xl (len (explode x)))
            (= yl (len (explode y))))
          (iprefixp (explode x)
            (nthcdr (istrpos-impl x y n xl yl)
              (explode y))))
        :hints (("Goal" :induct (istrpos-impl x y n xl yl)))))
    (defthm iprefixp-of-istrpos
      (implies (istrpos x y)
        (iprefixp (explode x)
          (nthcdr (istrpos x y) (explode y))))))
  (encapsulate nil
    (local (defun my-induction
        (x y n m xl yl)
        (declare (xargs :measure (nfix (- (nfix yl) (nfix n)))))
        (cond ((iprefixp (explode x)
             (nthcdr n (explode y))) nil)
          ((zp (- (nfix yl) (nfix n))) (list x y n m xl yl))
          (t (my-induction x
              y
              (+ (nfix n) 1)
              (if (= (nfix n) (nfix m))
                (+ (nfix m) 1)
                (nfix m))
              xl
              yl)))))
    (local (defthm lemma
        (implies (and (iprefixp (explode x)
              (nthcdr m (explode y)))
            (natp xl)
            (natp yl)
            (natp n)
            (natp m)
            (<= n (nfix m))
            (= xl (len (explode x)))
            (= yl (len (explode y))))
          (and (natp (istrpos-impl x y n xl yl))
            (<= (istrpos-impl x y n xl yl)
              m)))
        :hints (("Goal" :induct (my-induction x
             y
             n
             m
             xl
             yl)
           :do-not '(generalize fertilize)))))
    (defthm completeness-of-istrpos
      (implies (and (iprefixp (explode x)
            (nthcdr m (explode y)))
          (force (natp m)))
        (and (natp (istrpos x y))
          (<= (istrpos x y) m)))))
  (defcong istreqv
    equal
    (istrpos-impl x y n xl yl)
    1)
  (defcong istreqv
    equal
    (istrpos-impl x y n xl yl)
    2)
  (local (in-theory (disable istreqv)))
  (defcong istreqv
    equal
    (istrpos x y)
    1)
  (defcong istreqv
    equal
    (istrpos x y)
    2))