Filtering...

uninterpreted-fn-cp

books/projects/smtlink/verified/uninterpreted-fn-cp
other
(in-package "SMT")
other
(include-book "std/util/bstar" :dir :system)
other
(include-book "xdoc/top" :dir :system)
other
(include-book "std/util/define" :dir :system)
other
(include-book "pseudo-lambda-lemmas")
other
(include-book "hint-please")
other
(include-book "hint-interface")
other
(include-book "computed-hints")
other
(defsection uninterpreted-fn-cp
  :parents (verified)
  :short "Verified clause-processor for proving return types of uninterpreted
  functions."
  (defevaluator ev-uninterpreted
    ev-lst-uninterpreted
    ((not x) (if x
        y
        z)
      (hint-please hint)))
  (def-join-thms ev-uninterpreted)
  (define lambda->actuals-fix
    ((formals symbol-listp) (actuals pseudo-term-listp))
    :returns (new-actuals pseudo-term-listp)
    (b* ((formals (symbol-list-fix formals)) (actuals (pseudo-term-list-fix actuals))
        (len-formals (len formals))
        (len-actuals (len actuals))
        ((if (equal len-formals len-actuals)) actuals))
      nil))
  (define lambda->formals-fix
    ((formals symbol-listp) (actuals pseudo-term-listp))
    :returns (new-formals symbol-listp)
    (b* ((formals (symbol-list-fix formals)) (actuals (pseudo-term-list-fix actuals))
        (len-formals (len formals))
        (len-actuals (len actuals))
        ((if (equal len-formals len-actuals)) formals))
      nil))
  (local (in-theory (enable lambda->formals-fix
        lambda->actuals-fix)))
  (defprod lambda-binding
    :parents (uninterpreted-fn-cp)
    ((formals symbol-listp
       :default nil
       :reqfix (lambda->formals-fix formals actuals)) (actuals pseudo-term-listp
        :default nil
        :reqfix (lambda->actuals-fix formals actuals)))
    :require (equal (len formals) (len actuals)))
  (deflist lambda-binding-list
    :parents (lambda-binding)
    :elt-type lambda-binding
    :pred lambda-binding-listp
    :true-listp t)
  (defprod fhg-single-args
    :parents (uninterpreted-fn-cp)
    ((fn func-p :default nil) (actuals pseudo-term-listp :default nil)
      (fn-returns-hint-acc hint-pair-listp :default nil)
      (fn-more-returns-hint-acc hint-pair-listp
        :default nil)
      (lambda-acc lambda-binding-listp :default nil)))
  (local (defthm symbol-listp-of-append-of-symbol-listp
      (implies (and (symbol-listp x) (symbol-listp y))
        (symbol-listp (append x y)))))
  (local (defthm crock0
      (implies (and (fhg-single-args-p args)
          (not (equal (func->name (fhg-single-args->fn args))
              'quote)))
        (pseudo-term-listp (list (cons (func->name (fhg-single-args->fn args))
              (fhg-single-args->actuals args)))))))
  (local (defthm crock1
      (implies (and (pseudo-term-listp x)
          (pseudo-term-listp y))
        (pseudo-term-listp (append x y)))))
  (define generate-fn-hint-pair
    ((hypo hint-pair-p) (args fhg-single-args-p)
      (flag symbolp))
    :returns (fn-hint-pair hint-pair-p)
    :guard-debug t
    (b* ((hypo (hint-pair-fix hypo)) (args (fhg-single-args-fix args))
        (flag (symbol-fix flag))
        ((hint-pair h) hypo)
        ((fhg-single-args a) args)
        ((func f) a.fn)
        (formals f.flattened-formals)
        (returns f.flattened-returns)
        ((unless (equal (len returns) 1)) (prog2$ (er hard?
              'smt-goal-generator=>generate-fn-hint-pair
              "User ~
                defined function with more than one returns is not supported ~
                currently. ~%The function ~q0 has returns ~q1."
              f.name
              returns)
            (make-hint-pair)))
        ((unless (equal (len formals) (len a.actuals))) (prog2$ (er hard?
              'smt-goal-generator=>generate-fn-hint-pair
              "Number ~
                of formals and actuals don't match. ~%Formals: ~q0, actuals: ~q1."
              formals
              a.actuals)
            (make-hint-pair)))
        ((if (equal f.name 'quote)) (prog2$ (er hard?
              'smt-goal-generator=>generate-fn-hint-pair
              "Function name can't be 'quote.")
            (make-hint-pair)))
        ((unless (or (equal flag 'more-returns)
             (and (consp h.thm) (symbolp (car h.thm))))) (prog2$ (er hard?
              'smt-goal-generator=>generate-fn-hint-pair
              "Returns should have consp h.thm.~%")
            (make-hint-pair)))
        (thm (if (equal flag 'more-returns)
            `((lambda (,@SMT::FORMALS ,@SMT::RETURNS) ,SMT::H.THM) ,@SMT::A.ACTUALS
              (,SMT::F.NAME ,@SMT::A.ACTUALS))
            `(,(CAR SMT::H.THM) (,SMT::F.NAME ,@SMT::A.ACTUALS)))))
      (change-hint-pair h :thm thm)))
  (define generate-fn-returns-hint
    ((returns decl-listp) (args fhg-single-args-p))
    :returns (fn-hint-lst hint-pair-listp)
    :measure (len returns)
    (b* ((returns (decl-list-fix returns)) (args (fhg-single-args-fix args))
        ((fhg-single-args a) args)
        ((unless (consp returns)) a.fn-returns-hint-acc)
        ((cons first rest) returns)
        ((decl d) first)
        ((hint-pair h) d.type)
        (hypo (change-hint-pair h
            :thm `(,SMT::H.THM ,SMT::D.NAME)))
        (first-hint-pair (generate-fn-hint-pair hypo
            args
            'returns)))
      (generate-fn-returns-hint rest
        (change-fhg-single-args a
          :fn-returns-hint-acc (cons first-hint-pair a.fn-returns-hint-acc)))))
  (define generate-fn-more-returns-hint
    ((more-returns hint-pair-listp) (args fhg-single-args-p))
    :returns (fn-hint-lst hint-pair-listp)
    :measure (len more-returns)
    (b* ((more-returns (hint-pair-list-fix more-returns)) (args (fhg-single-args-fix args))
        ((fhg-single-args a) args)
        ((unless (consp more-returns)) a.fn-more-returns-hint-acc)
        ((cons first rest) more-returns)
        (first-hint-pair (generate-fn-hint-pair first
            args
            'more-returns)))
      (generate-fn-more-returns-hint rest
        (change-fhg-single-args a
          :fn-more-returns-hint-acc (cons first-hint-pair a.fn-more-returns-hint-acc)))))
  (define generate-fn-hint
    ((args fhg-single-args-p))
    :returns (fn-hint-lst fhg-single-args-p)
    (b* ((args (fhg-single-args-fix args)) ((fhg-single-args a) args)
        ((func f) a.fn))
      (change-fhg-single-args a
        :fn-returns-hint-acc (generate-fn-returns-hint f.returns a)
        :fn-more-returns-hint-acc (generate-fn-more-returns-hint f.more-returns
          a))))
  (defprod fhg-args
    :parents (uninterpreted-fn-cp)
    ((term-lst pseudo-term-listp :default nil) (fn-lst func-alistp :default nil)
      (fn-returns-hint-acc hint-pair-listp :default nil)
      (fn-more-returns-hint-acc hint-pair-listp
        :default nil)
      (lambda-acc lambda-binding-listp :default nil)))
  (encapsulate nil
    (local (defthm lemma-1
        (implies (fhg-args-p x)
          (pseudo-term-listp (fhg-args->term-lst x)))))
    (local (defthm lemma-2
        (implies (and (pseudo-term-listp y) (consp y))
          (pseudo-termp (car y)))))
    (local (defthm lemma-3
        (implies (and (pseudo-termp z)
            (consp z)
            (not (equal (car z) 'quote)))
          (pseudo-term-listp (cdr z)))))
    (local (defthm not-symbolp-then-consp-of-pseudo-termp
        (implies (and (pseudo-termp x) (not (symbolp x)))
          (consp x))))
    (defthm not-symbolp-then-consp-of-car-of-fhg-args->term-lst
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (not (symbolp (car (fhg-args->term-lst args)))))
        (consp (car (fhg-args->term-lst args)))))
    (local (defthm lemma-4
        (implies (and (pseudo-term-listp y) (consp y))
          (pseudo-term-listp (cdr y)))))
    (defthm pseudo-term-listp-of-cdr-of-fhg-args->term-lst
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args)))
        (pseudo-term-listp (cdr (fhg-args->term-lst args)))))
    (defthm pseudo-term-listp-of-cdar-of-fhg-args->term-lst
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (not (symbolp (car (fhg-args->term-lst args))))
          (not (equal (car (car (fhg-args->term-lst args)))
              'quote)))
        (pseudo-term-listp (cdr (car (fhg-args->term-lst args))))))
    (local (defthm lemma-5
        (implies (and (pseudo-termp z)
            (not (symbolp z))
            (not (pseudo-lambdap (car z))))
          (symbolp (car z)))
        :hints (("Goal" :in-theory (enable pseudo-termp pseudo-lambdap)))))
    (defthm symbolp-of-caar-of-fhg-args->term-lst
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (not (symbolp (car (fhg-args->term-lst args))))
          (not (pseudo-lambdap (car (car (fhg-args->term-lst args))))))
        (symbolp (car (car (fhg-args->term-lst args))))))
    (local (defthm lemma-6
        (implies (and (pseudo-termp x)
            (pseudo-lambdap (car x)))
          (equal (len (cadar x)) (len (cdr x))))
        :hints (("Goal" :in-theory (enable pseudo-lambdap pseudo-termp)))))
    (defthm len-equal-of-formals-of-pseudo-lambdap-and-actuals
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (pseudo-lambdap (car (car (fhg-args->term-lst args)))))
        (equal (len (cadr (car (car (fhg-args->term-lst args)))))
          (len (cdr (car (fhg-args->term-lst args)))))))
    (local (defthm lemma-7
        (implies (and (func-alistp x)
            (assoc-equal key x))
          (func-p (cdr (assoc-equal key x))))))
    (defthm lemma-8
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (assoc-equal (car (car (fhg-args->term-lst args)))
            (fhg-args->fn-lst args)))
        (func-p (cdr (assoc-equal (car (car (fhg-args->term-lst args)))
              (fhg-args->fn-lst args)))))
      :hints (("Goal" :in-theory (disable lemma-7)
         :use ((:instance lemma-7
            (key (car (car (fhg-args->term-lst args))))
            (x (fhg-args->fn-lst args)))))))
    (local (defthm lemma-9
        (implies (and (func-alistp x)
            (assoc-equal key x))
          (consp (assoc-equal key x)))))
    (defthm lemma-10
      (implies (and (fhg-args-p args)
          (consp (fhg-args->term-lst args))
          (assoc-equal (car (car (fhg-args->term-lst args)))
            (fhg-args->fn-lst args)))
        (consp (assoc-equal (car (car (fhg-args->term-lst args)))
            (fhg-args->fn-lst args))))
      :hints (("Goal" :in-theory (disable lemma-9)
         :use ((:instance lemma-9
            (key (car (car (fhg-args->term-lst args))))
            (x (fhg-args->fn-lst args))))))))
  (define generate-fn-hint-lst
    ((args fhg-args-p))
    :parents (uninterpreted-fn-cp)
    :short "@(call generate-fn-hint-lst) generate auxiliary hypotheses from ~
           function expansion"
    :returns (fn-hint-lst fhg-args-p)
    :measure (acl2-count (fhg-args->term-lst args))
    :verify-guards nil
    (b* ((args (fhg-args-fix args)) ((fhg-args a) args)
        ((unless (consp a.term-lst)) a)
        ((cons term rest) a.term-lst)
        ((if (symbolp term)) (generate-fn-hint-lst (change-fhg-args a :term-lst rest)))
        ((if (equal (car term) 'quote)) (generate-fn-hint-lst (change-fhg-args a :term-lst rest)))
        ((cons fn-call fn-actuals) term)
        ((if (pseudo-lambdap fn-call)) (b* ((lambda-formals (lambda-formals fn-call)) (lambda-body (lambda-body fn-call))
              (lambda-actuals fn-actuals)
              (lambda-bd (make-lambda-binding :formals lambda-formals
                  :actuals lambda-actuals))
              ((unless (mbt (lambda-binding-p lambda-bd))) a)
              (a-1 (generate-fn-hint-lst (change-fhg-args a
                    :term-lst (list lambda-body)
                    :lambda-acc (cons lambda-bd a.lambda-acc))))
              (a-2 (generate-fn-hint-lst (change-fhg-args a-1
                    :term-lst lambda-actuals))))
            (generate-fn-hint-lst (change-fhg-args a-2 :term-lst rest))))
        ((unless (mbt (symbolp fn-call))) a)
        (fn (assoc-equal fn-call a.fn-lst))
        ((unless fn) (b* ((a-1 (generate-fn-hint-lst (change-fhg-args a :term-lst fn-actuals))))
            (generate-fn-hint-lst (change-fhg-args a-1 :term-lst rest))))
        (f (cdr fn))
        (as-1 (generate-fn-hint (make-fhg-single-args :fn f
              :actuals fn-actuals
              :fn-returns-hint-acc a.fn-returns-hint-acc
              :fn-more-returns-hint-acc a.fn-more-returns-hint-acc
              :lambda-acc a.lambda-acc)))
        ((fhg-single-args as-1) as-1)
        (a-1 (change-fhg-args a
            :fn-returns-hint-acc as-1.fn-returns-hint-acc
            :fn-more-returns-hint-acc as-1.fn-more-returns-hint-acc))
        (a-2 (generate-fn-hint-lst (change-fhg-args a-1 :term-lst fn-actuals))))
      (generate-fn-hint-lst (change-fhg-args a-2 :term-lst rest))))
  (verify-guards generate-fn-hint-lst)
  (defprod uninterpreted
    ((returns hint-pair-listp) (more-returns hint-pair-listp)))
  (define uninterpreted-fn-helper
    ((cl pseudo-term-listp) (smtlink-hint smtlink-hint-p))
    :returns (uninterpreted uninterpreted-p)
    (b* ((cl (pseudo-term-list-fix cl)) (smtlink-hint (smtlink-hint-fix smtlink-hint))
        ((smtlink-hint h) smtlink-hint)
        (fn-lst (make-alist-fn-lst h.functions))
        (g (disjoin cl))
        (args (generate-fn-hint-lst (make-fhg-args :term-lst (list g)
              :fn-lst fn-lst
              :fn-returns-hint-acc nil
              :fn-more-returns-hint-acc nil
              :lambda-acc nil)))
        ((fhg-args a) args)
        (fn-returns-hint-lst a.fn-returns-hint-acc)
        (fn-more-returns-hint-lst a.fn-more-returns-hint-acc))
      (make-uninterpreted :returns fn-returns-hint-lst
        :more-returns fn-more-returns-hint-lst)))
  (define uninterpreted-subgoals
    ((hint-pair-lst hint-pair-listp) (g pseudo-termp)
      (tag symbolp))
    :returns (mv (list-of-h-thm pseudo-term-list-listp)
      (list-of-not-hs pseudo-term-listp))
    :measure (len hint-pair-lst)
    (b* ((hint-pair-lst (hint-pair-list-fix hint-pair-lst)) (g (pseudo-term-fix g))
        ((unless (or (equal tag :return) (equal tag :more-return))) (prog2$ (er hard?
              'uninterpreted-fn-cp=>uninterpreted-subgoals
              "Tag not supported: ~q0"
              tag)
            (mv nil nil)))
        ((unless (consp hint-pair-lst)) (mv nil nil))
        ((cons first-hinted-h rest-hinted-hs) hint-pair-lst)
        (h (hint-pair->thm first-hinted-h))
        (h-hint (hint-pair->hints first-hinted-h))
        (merged-hint-please-in-theory (treat-in-theory-hint '(hint-please) h-hint))
        (merged-type-hyp-in-theory (treat-in-theory-hint '(type-hyp)
            merged-hint-please-in-theory))
        (merged-expand (treat-expand-hint '((:free (x) (hide x)))
            merged-type-hyp-in-theory))
        (first-h-thm (if (equal tag :return)
            `((hint-please ',SMT::MERGED-EXPAND) (type-hyp (hide (cons ,SMT::H 'nil)) ',SMT::TAG)
              ,SMT::G)
            `((hint-please ',SMT::MERGED-HINT-PLEASE-IN-THEORY) ,SMT::H
              ,SMT::G)))
        (first-not-h-clause (if (equal tag :return)
            `(not (type-hyp (hide (cons ,SMT::H 'nil)) ',SMT::TAG))
            `(not ,SMT::H)))
        ((mv rest-h-thms rest-not-h-clauses) (uninterpreted-subgoals rest-hinted-hs
            g
            tag)))
      (mv (cons first-h-thm rest-h-thms)
        (cons first-not-h-clause rest-not-h-clauses)))
    ///
    (defthm uninterpreted-subgoals-correctness
      (implies (and (pseudo-termp g)
          (alistp b)
          (hint-pair-listp hint-pair-lst)
          (ev-uninterpreted (disjoin (mv-nth 1
                (uninterpreted-subgoals hint-pair-lst
                  g
                  tag)))
            b)
          (ev-uninterpreted (conjoin-clauses (mv-nth 0
                (uninterpreted-subgoals hint-pair-lst
                  g
                  tag)))
            b))
        (ev-uninterpreted g b))
      :hints (("Goal" :induct (uninterpreted-subgoals hint-pair-lst
           g
           tag)))))
  (local (defthm crock3
      (implies (pseudo-term-list-listp x)
        (true-listp x))))
  (local (defthm crock4
      (implies (and (pseudo-term-list-listp x)
          (pseudo-term-list-listp y))
        (pseudo-term-list-listp (append x y)))))
  (local (defthm crock5
      (implies (and (pseudo-term-listp x)
          (pseudo-term-listp y))
        (pseudo-term-listp (append x y)))))
  (define uninterpreted-fn-cp
    ((cl pseudo-term-listp) (smtlink-hint t))
    :returns (subgoal-lst pseudo-term-list-listp)
    :guard-debug t
    (b* (((unless (pseudo-term-listp cl)) nil) ((unless (smtlink-hint-p smtlink-hint)) (list cl))
        (g (disjoin cl))
        ((smtlink-hint h) smtlink-hint)
        (uninterpreted (uninterpreted-fn-helper cl h))
        (hinted-ts-returns (uninterpreted->returns uninterpreted))
        (hinted-ts-more-returns (uninterpreted->more-returns uninterpreted))
        ((mv list-of-returns-t-thm
           list-of-returns-not-ts) (uninterpreted-subgoals hinted-ts-returns
            g
            :return))
        ((mv list-of-more-returns-t-thm
           list-of-more-returns-not-ts) (uninterpreted-subgoals hinted-ts-more-returns
            g
            :more-return))
        (list-of-t-thm (append list-of-returns-t-thm
            list-of-more-returns-t-thm))
        (list-of-not-ts (append list-of-returns-not-ts
            list-of-more-returns-not-ts))
        (next-cp (if h.custom-p
            (cdr (assoc-equal 'uninterpreted-custom
                *smt-architecture*))
            (cdr (assoc-equal 'uninterpreted
                *smt-architecture*))))
        ((if (null next-cp)) (list cl))
        (the-hint `(:clause-processor (,SMT::NEXT-CP clause ',SMT::H state)))
        (cl0 `((hint-please ',SMT::THE-HINT) ,@SMT::LIST-OF-NOT-TS
            ,SMT::G)))
      `(,SMT::CL0 ,@SMT::LIST-OF-T-THM)))
  (local (in-theory (enable uninterpreted-fn-cp)))
  (defthm correctness-of-uninterpreted-fn-cp
    (implies (and (pseudo-term-listp cl)
        (alistp b)
        (ev-uninterpreted (conjoin-clauses (uninterpreted-fn-cp cl smtlink-hint))
          b))
      (ev-uninterpreted (disjoin cl) b))
    :hints (("Goal" :in-theory (disable uninterpreted-subgoals-correctness)
       :use ((:instance uninterpreted-subgoals-correctness
          (g (disjoin cl))
          (hint-pair-lst (uninterpreted->returns (uninterpreted-fn-helper cl smtlink-hint)))
          (tag :return)
          (b b)) (:instance uninterpreted-subgoals-correctness
           (g (disjoin cl))
           (hint-pair-lst (uninterpreted->more-returns (uninterpreted-fn-helper cl smtlink-hint)))
           (tag :more-return)
           (b b)))))
    :rule-classes :clause-processor))