• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Proof-automation
    • Macro-libraries
    • ACL2
      • Theories
      • Rule-classes
      • Proof-builder
      • Recursion-and-induction
      • Hons-and-memoization
      • Events
      • Parallelism
      • History
      • Programming
        • Defun
        • Declare
        • System-utilities
        • Stobj
        • State
        • Mutual-recursion
        • Memoize
        • Mbe
        • Io
        • Defpkg
        • Apply$
          • Lambda
          • Warrant
          • Defwarrant
          • Badge
          • Lambda$
          • Tame
            • Defbadge
            • Print-cl-cache
            • Introduction-to-apply$
            • Well-formed-lambda-objectp
            • Rewriting-calls-of-apply$-ev$-and-loop$-scions
            • Mixed-mode-functions
            • Explain-giant-lambda-object
            • Gratuitous-lambda-object-restrictions
            • Scion
            • Ilk
            • Ev$
            • Translam
            • Fn-equal
            • Apply$-guard
            • L<
            • Apply$-lambda-guard
            • Apply$-userfn
            • Badge-userfn
            • Defun$
            • Apply$-lambda
          • Loop$
          • Programming-with-state
          • Arrays
          • Characters
          • Time$
          • Defmacro
          • Loop$-primer
          • Fast-alists
          • Defconst
          • Evaluation
          • Guard
          • Equality-variants
          • Compilation
          • Hons
          • ACL2-built-ins
          • Developers-guide
          • System-attachments
          • Advanced-features
          • Set-check-invariant-risk
          • Numbers
          • Efficiency
          • Irrelevant-formals
          • Introduction-to-programming-in-ACL2-for-those-who-know-lisp
          • Redefining-programs
          • Lists
          • Invariant-risk
          • Errors
          • Defabbrev
          • Conses
          • Alists
          • Set-register-invariant-risk
          • Strings
          • Program-wrapper
          • Get-internal-time
          • Basics
          • Packages
          • Oracle-eval
          • Defmacro-untouchable
          • <<
          • Primitive
          • Revert-world
          • Unmemoize
          • Set-duplicate-keys-action
          • Symbols
          • Def-list-constructor
          • Easy-simplify-term
          • Defiteration
          • Fake-oracle-eval
          • Defopen
          • Sleep
        • Operational-semantics
        • Real
        • Start-here
        • Debugging
        • Miscellaneous
        • Output-controls
        • Macros
        • Interfacing-tools
      • Interfacing-tools
      • Hardware-verification
      • Software-verification
      • Math
      • Testing-utilities
    • Apply$

    Tame

    Definitions of the various notions of tameness

    The adjective ``tame'' can be applied to four different kinds of objects, LAMBDA objects, function symbols, expressions, and lists of expressions. Formally, these notions are defined mutually recursively as the macro tamep-lambdap and the :logic mode functions named tamep-functionp, tamep, and suitably-tamep-listp, respectively. We exhibit the formal definitions at the end of this documentation.

    Definitions

    • tame LAMBDA object aka tamep-lambdap: An object is a tame LAMBDA object if is of the form (LAMBDA vars body) or (LAMBDA vars dcl body) where vars is a list of symbols and body is a tame expression. Formally, an object x is a tame LAMBDA object iff (tamep-lambdap x). Tamep-lambdap is actually a macro.
    • tame function aka tamep-functionp: An object is a tame function iff it is either (a) a badged symbol and ilks is T, or (b) a tame LAMBDA object (see above). Formally, an object x is a tame function iff (tamep-functionp x).
    • tame expression aka tamep: An object is a tame expression iff it is a symbol, a quoted constant, the call of an badged function symbol on the correct number of suitably tame expressions with respect to the ilks of the function symbol, or the call of a tame LAMBDA expression on the correct number of tame expressions. Formally, an object x is a tame expression iff (tamep x). Note that tameness implies every function symbol in the expression is badged but not necessarily warranted.
    • suitably tame with (respect to arity and ilks) aka suitably-tamep-listp: A list of objects x is suitably tame with respect to an arity n and a list of ilks iff x is a true list of length n, and when an ilk is :FN the corresponding object is a quoted tame function, when an ilk is :EXPR the object is a quoted tame expression, and when an ilk is NIL the object is a tame expression. Formally, an object x is suitably tame with respect to n and ilks iff (suitably-tamep-listp n ilks x). Note in particular our use of the word ``quoted'' above. We illustrate this in the example below.

    Note that the various notions of tameness make no mention of whether the function symbols involved are in :program or :logic mode. The function symbols must have badges but need not have warrants.

    Intuitively, a tame expression can be built out of functions that are not themselves tame, e.g., scions, by making sure that every :FN slot is occupied by a quoted tame function. Put another way, if we were to trace the calls of apply$ while evaluating a tame expression every branch eventually bottoms out on a call of a primitive. This is illustrated below.

    Examples

    We assume the following events have been processed.

    (include-book "projects/apply/top" :dir :system)
    
    (defun$ sq (x) (* x x))
    
    (defun$ foldr (lst fn init)
      (if (endp lst)
          init
          (apply$ fn
                  (list (car lst)
                        (foldr (cdr lst) fn init)))))

    Sq and foldr above are defined as :logic mode functions and are badged and warranted (note the use of defun$). But for our purposes they could have been introduced by defun in :program mode and then badged with two calls of defbadge.

    As a result, we see the following badges:

    symbol           badge 
     
    CONS    (APPLY$-BADGE 2 1 . T)  ; . T means all args ordinary 
    SQ      (APPLY$-BADGE 1 1 . T)  ; . T means all args ordinary 
    FOLDR   (APPLY$-BADGE 1 1 NIL :FN NIL) 
    

    Consider the following expression.

    (foldr lst (lambda$ (x y) (foldr y 'cons (list (sq x)))) nil)

    Forgetting about tameness for a moment, what does this term compute? Study the definition of foldr if you're not familiar with it and work it out! Answer: It collects, in reverse order, the squares of the elements of lst. E.g., if lst is (1 2 3 4) the value of the foldr expression above is (16 9 4 1).

    But we are interested in whether it is tame. Tameness is a concept applied to objects representing formal (fully translated) terms (or components of terms in the case of ``tame functions,'' ``tame lambdas,'' etc.). Saying ``x is a tame expression'' is just a colloquial way of saying ``(tamep x) = t. So we can evaluate this term in the top-level ACL2 loop,

    (tamep '(foldr lst (lambda$ (x y) (foldr y 'cons (list (sq x)))) nil))

    and the result is nil because lambda$ is not a ``badged function symbol.'' In fact, lambda$ is not a function symbol. It is a macro. We're really interested in the formal translation of the foldr expression. One way to understand the situation is that tamep does not expand macros.

    The translation of the above term is

    (FOLDR LST
           '(LAMBDA (X Y)
                    (DECLARE (IGNORABLE X Y))
                    (RETURN-LAST 'PROGN
                                 '(LAMBDA$ (X Y)
                                           (FOLDR Y 'CONS (LIST (SQ X))))
                                 (FOLDR Y 'CONS (CONS (SQ X) 'NIL))))
           'NIL)

    The RETURN-LAST subterm is a marker that records the original user-supplied lambda$ expression, which is needed during compilation and execution in raw Lisp. But the value of that RETURN-LAST is the expected FOLDR expression in its last argument. To simplify our discussion of tameness let's determine whether the following equivalent term is tame.

    (FOLDR LST
           '(LAMBDA (X Y)
              (FOLDR Y
                     'CONS
                     (CONS (SQ X) 'NIL)))
           'NIL)

    The answer is yes, it is a tame expression. In particular

    (tamep '(FOLDR LST
                   '(LAMBDA (X Y)
                      (FOLDR Y
                             'CONS
                             (CONS (SQ X) 'NIL)))
                   'NIL))
    = T

    By the way, tamep answers the same way on the quotation of the actual translation of the foldr term.

    We explain below how tamep computes this result. But before we dive into details consider what this example illustrates. FOLDR is not a tame function according to the definitions above. But it can be used in the construction of tame expressions provided, mainly, that its second argument is a quoted tame function. Indeed, the example illustrates that we can even call FOLDR within the LAMBDA expression passed to another FOLDR and still have a tame expression.

    If we were to trace$ the functions tamep, tamep-functionp, and suitably-tamep-listp, and then call tamep on the FOLDR term above we would see a tree of calls of the various tameness notions. Here are selected calls from that tree. All of the calls return T. We discuss each of these calls below.

    (tamep '(CONS (SQ X) 'NIL))                                    ; [1] 
     
    (suitably-tamep-listp 3                                        ; [2] 
                          '(NIL :FN NIL) 
                          '(Y 'CONS (CONS (SQ X) 'NIL))) 
     
    (tamep '(FOLDR Y 'CONS (CONS (SQ X) 'NIL)))                    ; [3] 
     
    (tamep-functionp '(LAMBDA (X Y)                                ; [4] 
                              (FOLDR Y 'CONS (CONS (SQ X) 'NIL)))) 
     
    (tamep '(FOLDR LST                                             ; [5] 
                   '(LAMBDA (X Y) 
                            (FOLDR Y 'CONS (CONS (SQ X) 'NIL))) 
                   'NIL)) 
    

    [1]: The object here, (CONS (SQ X) 'NIL), is tame because both CONS and SQ are tame functions and they are applied to the correct number of tame expressions.

    [2]: The list of objects here, (Y 'CONS (CONS (SQ X) 'NIL)) is a suitably tame list of length 3 with ilks NIL, :FN, and NIL because Y and 'NIL are both tame and 'CONS is a quoted tame function, CONS.

    [3]: The object here is tame because FOLDR is a badged function of arity 3 and its actuals are suitably tame with respect to its arity and ilks as shown by example [2].

    [4]: The LAMBDA object here is a tame function because it is of the form (LAMBDA vars body), where vars is the list of symbols (X Y) and body is the tame object shown in example [4].

    [5]: The object here, a call of FOLDR, is tame because there are 3 actuals, the first and third are tame expressions and the second is a quoted tame function as shown in Example [4].

    Logical Definitions

    The various notions of tameness, tamep-functionp, tamep, and suitably-tamep-listp, are defined mutually recursively as :logic mode functions. The definition employs the macro tamep-lambdap, which is used by tamep-functionp to handle the LAMBDA case.

    Function: tamep-functionp

    (defun tamep-functionp (fn)
      (declare (xargs :guard t))
      (if (symbolp fn)
          (let ((bdg (badge fn)))
            (and bdg
                 (eq (access apply$-badge bdg :ilks) t)))
        (and (consp fn) (tamep-lambdap fn))))

    Function: tamep

    (defun tamep (x)
     (declare (xargs :guard t))
     (cond
      ((atom x) (symbolp x))
      ((eq (car x) 'quote)
       (and (consp (cdr x)) (null (cddr x))))
      ((symbolp (car x))
       (let ((bdg (badge (car x))))
         (cond ((null bdg) nil)
               ((eq (access apply$-badge bdg :ilks) t)
                (suitably-tamep-listp (access apply$-badge bdg :arity)
                                      nil (cdr x)))
               (t (suitably-tamep-listp (access apply$-badge bdg :arity)
                                        (access apply$-badge bdg :ilks)
                                        (cdr x))))))
      ((consp (car x))
       (let ((fn (car x)))
         (and (tamep-lambdap fn)
              (suitably-tamep-listp (length (cadr fn))
                                    nil (cdr x)))))
      (t nil)))

    Function: suitably-tamep-listp

    (defun suitably-tamep-listp (n flags args)
      (declare (xargs :guard (and (natp n) (true-listp flags))))
      (cond ((zp n) (null args))
            ((atom args) nil)
            (t (and (let ((arg (car args)))
                      (case (car flags)
                        (:fn (and (consp arg)
                                  (eq (car arg) 'quote)
                                  (consp (cdr arg))
                                  (null (cddr arg))
                                  (tamep-functionp (cadr arg))))
                        (:expr (and (consp arg)
                                    (eq (car arg) 'quote)
                                    (consp (cdr arg))
                                    (null (cddr arg))
                                    (tamep (cadr arg))))
                        (otherwise (tamep arg))))
                    (suitably-tamep-listp (- n 1)
                                          (cdr flags)
                                          (cdr args))))))

    Macro: tamep-lambdap

    (defmacro tamep-lambdap (fn)
      (list 'let
            (list (list 'fn fn))
            '(and (lambda-object-shapep fn)
                  (symbol-listp (lambda-object-formals fn))
                  (tamep (lambda-object-body fn)))))

    At the top-level of the ACL2 loop you can determine whether an object satisfies one of these predicates by calling the appropriate formal notion on the object. But because these functions are defined in terms of badge these notions of tameness are evaluable only in the evaluation theory (where warrants are implicitly assumed). If you want to prove that an object is tame, you may need warrant hypotheses. See guarantees-of-the-top-level-loop.