• Top
    • Documentation
    • Books
    • Recursion-and-induction
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
      • Theories
      • Rule-classes
      • Proof-builder
      • Hons-and-memoization
      • Events
        • Defun
        • Verify-guards
        • Table
        • Memoize
        • Make-event
        • Include-book
        • Encapsulate
        • Defun-sk
        • Defttag
        • Defpkg
        • Mutual-recursion
        • Defattach
        • Defstobj
        • Defchoose
        • Progn
        • Defabsstobj
        • Verify-termination
        • Redundant-events
        • Defmacro
        • In-theory
        • Embedded-event-form
        • Defconst
        • Skip-proofs
        • Value-triple
        • Comp
        • Local
        • Defthm
        • Progn!
        • Defevaluator
        • Theory-invariant
        • Assert-event
        • Defun-inline
        • Project-dir-alist
        • Define-trusted-clause-processor
        • Partial-encapsulate
        • Defproxy
        • Defexec
        • Defun-nx
        • Defthmg
        • Defpun
          • Defabbrev
          • Defrec
          • Add-custom-keyword-hint
          • Name
          • Regenerate-tau-database
          • Deftheory
          • Deftheory-static
          • Defcong
          • Defaxiom
          • Defund
          • Evisc-table
          • Verify-guards+
          • Logical-name
          • Profile
          • Defequiv
          • Defmacro-untouchable
          • Defthmr
          • Defstub
          • Deflabel
          • Defrefinement
          • In-arithmetic-theory
          • Defabsstobj-missing-events
          • Defthmd
          • Set-body
          • Unmemoize
          • Defun-notinline
          • Dump-events
          • Defund-nx
          • Defun$
          • Remove-custom-keyword-hint
          • Dft
          • Defthy
          • Defund-notinline
          • Defnd
          • Defn
          • Defund-inline
          • Defmacro-last
        • History
        • Parallelism
        • Programming
        • Start-here
        • Real
        • Debugging
        • Miscellaneous
        • Output-controls
        • Macros
        • Interfacing-tools
      • Interfacing-tools
      • Hardware-verification
      • Software-verification
      • Testing-utilities
      • Math
    • Events

    Defpun

    Define a tail-recursive function symbol

    Defpun is a macro developed by Pete Manolios and J Moore that allows tail-recursive definitions, as well as some other ``partial'' definitions. Related utilities are discussed at the end of this topic.

    General Form:
    
    (defpun g (v1 ... vk)
      dcl ; optional
      body
      :kwd1 val1 :kwd2 val2 ... :kwdn valn)

    where dcl is an optional declare form and the pairs :kwdi vali are optional (that is n can be 0). If the optional arguments are omitted, then ACL2 will introduce a constrained function g with this exported event:

    (DEFTHM g-DEF
      (EQUAL (g v1 ... vk)
             body)
      :RULE-CLASSES :DEFINITION)

    First suppose that dcl is not present. Then the proposed definition must have a simple tail-recursive structure (see the discussion of defp below for a workaround if this is not the case).

    If dcl is present, then the definition need not be tail-recursive, and dcl must have one of the following three forms.

    (DECLARE (XARGS :witness defpun-fn))
    (DECLARE (XARGS :domain dom-expr :measure m . rest))
    (DECLARE (XARGS :gdomain dom-expr :measure m . rest)).

    You are encouraged to experiment by using :trans1 to see the expansions of defpun forms that use these declare forms; but here is a summary of what is generated.

    The first form specifies a function, defpun-fn, and instructs ACL2 to use that function as a witness for the function g to be introduced, as follows.

    (ENCAPSULATE
      ((g (v1 ... vk) t))
      (LOCAL (DEFUN-NONEXEC g (v1 ... vk) (defpun-fn v1 ... vk)))
      (DEFTHM g-DEF
        (EQUAL (g v1 ... vk))
               body)
        :RULE-CLASSES :DEFINITION)

    The remaining two declare forms introduce a function, defined recursively, with the given measure and with a modified body:

    (THE-g v1 ... vk)
    =
    (IF dom-expr body 'UNDEF)

    The following theorem is exported.

    (defthm g-DEF
      (IMPLIES domain-expr
               (EQUAL (g v1 ... vk)
                      body))
      :RULE-CLASSES :DEFINITION)

    If :gdomain is used (as opposed to :domain), then the following events are also introduced, where body\{g:=THE-g} denotes the result of replacing each call of g in body with the corresponding call of THE-g.

    (DEFUN THE-g (v1 ... vk)
      (DECLARE (XARGS :MEASURE (IF dom-expr m 0)
                      :GUARD domain-expr
                      :VERIFY-GUARDS NIL))
      (IF dom-expr body 'UNDEF))
    
    (DEFTHM g-IS-UNIQUE
      (IMPLIES domain-expr
               (EQUAL (g v1 ... vk) (THE-g v1 ... vk))))

    The optional keyword alist :kwd1 val1 :kwd2 val2 ... :kwdn valn is attached to the end of the generated defthm event. If the :rule-classes keyword is not specified by the keyword alist, :definition is used.

    Details of defpun are provided by Manolios and Moore in the chapter ``Partial Functions in ACL2'' published with the ACL2 2000 workshop. Also see Partial Functions in ACL2.

    Variants of defpun

    A variant, defp, allows more general forms of tail recursion. If defpun doesn't work for you, try defp by first executing the following event.

    (include-book "misc/defp" :dir :system)

    Sandip Ray has contributed a variant of defpun, defpun-exec, that supports executability. See community book books/defexec/defpun-exec/defpun-exec.lisp:

    (include-book "defexec/defpun-exec/defpun-exec" :dir :system)

    He has also contributed community book books/misc/misc2/defpun-exec-domain-example.lisp, for functions that are uniquely defined in a particular domain.

    Finally, it is possible to avoid termination proofs even for functions that are not tail-recursive. See def-partial-measure.