• Top
    • Documentation
    • Books
    • Boolean-reasoning
    • Projects
    • Debugging
    • Std
    • Community
    • 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$
          • Defconst
          • Defmacro
          • Loop$-primer
          • Fast-alists
          • Evaluation
          • Guard
          • Equality-variants
          • Compilation
          • Hons
          • ACL2-built-ins
            • Let
            • Declare
            • Mbe
            • 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
              • Fmt
              • Loop$
              • Return-last
              • Mv-let
              • Df
              • Pseudo-termp
              • Defwarrant
              • Time$
              • Mbt
              • Ec-call
              • Mv-nth
              • Sys-call
              • Msg
              • Er
              • Value-triple
              • O-p
              • Comp
              • Member
              • O<
              • Cw
              • Flet
              • Or
              • Hons
              • Cbd
              • Mv
              • Defbadge
              • Append
              • *ACL2-exports*
              • Comment
              • Eql
              • List
              • Unsigned-byte-p
              • Posp
              • Natp
              • The
              • Nth
              • And
              • Len
              • Time-tracker
              • Term-order
              • True-listp
              • Msgp
              • Booleanp
              • <
              • If
              • Pseudo-term-listp
              • +
              • Not
              • With-global-stobj
              • Bitp
              • Equal
              • Cdr
              • Car
              • String-listp
              • Nat-listp
              • Implies
              • Iff
              • Character-listp
              • Alistp
              • Cons
              • Symbol-listp
              • Macrolet
              • Quote
              • Integerp
              • Consp
              • True-list-listp
              • State-global-let*
              • Compress1
              • Symbolp
              • Stringp
              • *common-lisp-symbols-from-main-lisp-package*
              • Characterp
              • Prog2$
              • *
              • Last-prover-steps
              • Hons-acons
              • Let*
              • Eq
              • With-guard-checking
              • @
              • Length
              • With-local-stobj
              • Hard-error
              • -
              • Zp
              • Search
              • Intersection$
              • Assign
              • Aset1
              • Symbol-name
              • Union$
              • Set-gc-strategy
              • In-tau-intervalp
              • Cons-with-hint
              • Break-on-error
              • Pand
              • Case-match
              • Fast-alist-fork
              • Sys-call+
              • Signed-byte-p
              • ACL2-count
              • Remove-duplicates
              • With-serialize-character
              • Observation
              • Hons-resize
              • Make-tau-interval
              • Assoc
              • Logbitp
              • Termp
              • Position
              • *standard-co*
              • Hons-acons!
              • Update-nth
              • Aref1
              • Symbol-alistp
              • Read-run-time
              • Take
              • Symbol-package-name
              • Hons-wash
              • Keywordp
              • Expt
              • Coerce
              • Get-internal-time
              • Intern
              • Non-exec
              • Case
              • Standard-oi
              • Standard-co
              • Formula
              • Atom
              • Without-evisc
              • Good-bye
              • Ash
              • With-local-state
              • Spec-mv-let
              • Intern-in-package-of-symbol
              • Binary-+
              • <=
              • With-fast-alist
              • Set-difference$
              • Hons-clear
              • Flush-compress
              • Rationalp
              • Por
              • Rassoc
              • Remove-assoc
              • =
              • Nthcdr
              • Logand
              • Pargs
              • Nfix
              • Hons-copy
              • Alphorder
              • Subsetp
              • Floor
              • Remove1-assoc
              • No-duplicatesp
              • Mv-list
              • Canonical-pathname
              • Aset2
              • Serialize-read
              • Random$
              • Fmt-to-comment-window
              • F-put-global
              • Compress2
              • Concatenate
              • Fast-alist-clean
              • Assert$
              • Remove
              • Remove1
              • Intersectp
              • Endp
              • Put-assoc
              • Princ$
              • Primitive
              • Keyword-value-listp
              • True-list-fix
              • Swap-stobjs
              • Integer-listp
              • Illegal
              • Hons-get
              • With-output-lock
              • Setenv$
              • Open-output-channel!
              • Fast-alist-free
              • Er-progn
              • Cw-print-base-radix
              • Reverse
              • Cond
              • Complex
              • Add-to-set
              • Truncate
              • Digit-char-p
              • Code-char
              • Char-code
              • Set-print-case
              • Set-print-base
              • Read-ACL2-oracle
              • Error1
              • Print-object$
              • Plet
              • Integer-length
              • Zip
              • With-live-state
              • Hons-assoc-equal
              • Extend-pathname
              • Logior
              • In-package
              • With-guard-checking-event
              • Term-listp
              • Print-object$+
              • Fmx-cw
              • String
              • Mod
              • Unary--
              • Set-print-radix
              • Resize-list
              • Pkg-witness
              • Revappend
              • Null
              • Term-list-listp
              • Make-fast-alist
              • Header
              • Boole$
              • Subseq
              • With-guard-checking-error-triple
              • /
              • Make-list
              • Logxor
              • Char-upcase
              • Char-downcase
              • Strip-cars
              • Set-fmt-hard-right-margin
              • Make-ord
              • Ifix
              • Fast-alist-free-on-exit
              • F-get-global
              • Aref2
              • Standard-char-p
              • Lognot
              • Must-be-equal
              • Integer-range-p
              • Getenv$
              • Binary-append
              • Er-hard
              • Eqlablep
              • Cpu-core-count
              • Boolean-listp
              • Allocate-fixnum-range
              • ACL2-numberp
              • Butlast
              • Pairlis$
              • Mod-expt
              • Hons-equal
              • Gc$
              • Substitute
              • Ceiling
              • With-stolen-alist
              • Mv?-let
              • String-upcase
              • String-downcase
              • Round
              • Count
              • Char
              • Sys-call-status
              • Progn$
              • Pprogn
              • Lexorder
              • Hons-summary
              • Break$
              • Assert*
              • Alpha-char-p
              • Strip-cdrs
              • Serialize-write
              • Keyword-listp
              • Upper-case-p
              • Lower-case-p
              • Logeqv
              • List*
              • Last
              • Proofs-co
              • Maximum-length
              • Fix
              • Explode-nonnegative-integer
              • Eqlable-listp
              • Dimensions
              • Default
              • Arity
              • Sublis
              • Max
              • Evenp
              • Explode-atom
              • Change
              • Zerop
              • String<
              • String-equal
              • Abs
              • Set-print-base-radix
              • Print-base-p
              • Nonnegative-integer-quotient
              • Intern$
              • Getprop
              • Binary-*
              • Aset1-trusted
              • Symbol<
              • String-append
              • Rfix
              • Mv?
              • Logic-fns-list-listp
              • Fast-alist-fork!
              • Er-hard?
              • Char-equal
              • 1+
              • *standard-oi*
              • Sys-call*
              • Pos-listp
              • Mbt*
              • Hons-wash!
              • Hons-clear!
              • Signum
              • Rem
              • Real/rationalp
              • Rational-listp
              • O-first-coeff
              • Logic-fnsp
              • Logic-fns-listp
              • Hons-copy-persistent
              • Gc-strategy
              • Fast-alist-summary
              • String>=
              • String<=
              • Acons
              • O-first-expt
              • Fast-alist-clean!
              • >=
              • >
              • Subst
              • Logcount
              • Getpropc
              • Evens
              • Er-soft
              • Digit-to-char
              • Comp-gcl
              • Atom-listp
              • Arities-okp
              • ACL2-number-listp
              • /=
              • Cadr
              • *standard-ci*
              • Unary-/
              • The-true-list
              • Realfix
              • O-rst
              • Fast-alist-len
              • Complex/complex-rationalp
              • Array2p
              • Array1p
              • Logtest
              • Logandc1
              • Char<
              • Trace-co
              • Putprop
              • Get-real-time
              • Eqlable-alistp
              • Count-keys
              • Assoc-string-equal
              • Logorc1
              • Logandc2
              • Denominator
              • 1-
              • Packn
              • Logic-termp
              • Logic-term-list-listp
              • Fmt!
              • Fms
              • Cw!
              • Assoc-keyword
              • String>
              • Numerator
              • Logorc2
              • Char>=
              • Update-nth-array
              • The-number
              • Odds
              • Makunbound-global
              • Make-character-list
              • Make
              • List$
              • Int=
              • Get-cpu-time
              • Fmt-to-comment-window!
              • Fms!
              • F-boundp-global
              • Complex-rationalp
              • Alist-to-doublets
              • Access
              • Min
              • Lognor
              • Listp
              • Identity
              • Char>
              • Char<=
              • Zpf
              • Standard-char-listp
              • O-finp
              • Number-subtrees
              • Logic-term-listp
              • Last-cdr
              • Fmt1!
              • Fmt-to-comment-window!+
              • Character-alistp
              • Oddp
              • Minusp
              • Lognand
              • Imagpart
              • Conjugate
              • Xor
              • Unquote
              • String-alistp
              • Packn-pos
              • Maybe-flush-and-compress1
              • Kwote
              • Fmt1
              • Fmt-to-comment-window+
              • Cw-print-base-radix!
              • Alist-keys-subsetp
              • Realpart
              • Plusp
              • First
              • Symbol-name-lst
              • R-symbol-alistp
              • R-eqlable-alistp
              • Fmx
              • Cw!+
              • Cons-subtrees
              • Cons-count-bounded
              • Cddr
              • Caar
              • Proper-consp
              • Kwote-lst
              • Improper-consp
              • Cw+
              • Rest
              • Standard-char-p+
              • Mbe1
              • Caddr
              • Pairlis-x2
              • Pairlis-x1
              • O>=
              • O<=
              • O-infp
              • Merge-sort-lexorder
              • Fix-true-list
              • Cdddr
              • Set-fmt-soft-right-margin
              • Real-listp
              • O>
              • Cddar
              • Cdar
              • Cdadr
              • Cdaar
              • Cadar
              • Caadr
              • Caaar
              • Cadddr
              • Caddar
              • Third
              • Tenth
              • Sixth
              • Seventh
              • Second
              • Ninth
              • Fourth
              • Fifth
              • Eighth
              • Cddddr
              • Cdddar
              • Cddadr
              • Cddaar
              • Cdaddr
              • Cdadar
              • Cdaadr
              • Cdaaar
              • Cadadr
              • Cadaar
              • Caaddr
              • Caadar
              • Caaadr
              • Caaaar
              • Hons-shrink-alist!
              • Hons-shrink-alist
              • Flush-hons-get-hash-table-link
              • Delete-assoc
            • 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$

      Well-formed-lambda-objectp

      Predicate for recognizing well-formed LAMBDA objects

      Example:                                    value
      (well-formed-lambda-objectp                   T
       '(lambda (x) (binary-+ '1 x))
       (w state))
      
      (well-formed-lambda-objectp                   NIL
       '(lambda (x) (+ 1 x))
       (w state))
      
      (well-formed-lambda-objectp                   T
       '(lambda (x)
          (declare (type (satisfies natp) x)
                   (xargs :guard (natp x)
                          :split-types t))
          (binary-+ '1 x))
       (w state))
      
      (well-formed-lambda-objectp                   NIL
       '(lambda (x)
          (declare (type (satisfies natp) x))
          (binary-+ '1 x))
       (w state))
      
      General Form:
      (well-formed-lambda-objectp obj wrld)

      Well-formed-lambda-objectp is a :program mode function that checks the well-formedness of an arbitrary ACL2 object being used as a LAMBDA object by apply$.

      Before we tell you what ``well-formedness'' means in this context we collect some random related facts that we consider more important than its precise meaning!

      Lambda$ terms always translate to quoted well-formed LAMBDA objects unless translate signals an explanatory error. Don't try to type well-formed LAMBDA objects as explicitly quoted constants. Use lambda$!

      Only well-formed LAMBDA objects can be compiled. Use lambda$.

      But the compiled code is not necessarily always run when a well-formed LAMBDA object is apply$d! The object must additionally be guard verified and its guards must be satisfied by the arguments supplied by apply$. Well-formedness does not do guard verification.

      The definitional axiom for apply$ knows nothing about well-formedness. It checks that the purported LAMBDA object satisfies tamep-lambdap, which is a simpler :logic mode concept. If you are writing a definition or theorem about an arbitrary object to be used as a LAMBDA object by apply$, and want to restrict it to the kind of objects handled as LAMBDA objects by apply$, use the predicate tamep-lambdap to characterize the object. (Since well-formed-lambda-objectp is in :program mode and requires access to the world, using it in a :logic mode context would involve a lot of work!)

      Well-formedness implies tameness. So if you write your LAMBDA objects with lambda$ apply$ will be able to handle them. But apply$ can handle more objects than the Common Lisp compiler can. Some tame LAMBDA objects can be applied faster than others. The fast ones are recognized by well-formed-lambda-objectp -- but also have to be guard verified and guard checked. Applications of ill-formed but tame LAMBDA objects are evaluable, but the evaluation is done more slowly. See the performance comparison in print-cl-cache.

      We compare well-formedness to tameness at the end of this topic.

      You can't call this predicate on a lambda$ term, as by

      (well-formed-lambda-objectp (lambda$ (x) x) (w state))

      because lambda$ can only be called in slots of ilk :FN. Furthermore, there's no point! Lambda$ terms always translate to well-formed LAMBDA objects unless an explanatory error is signaled by translation.

      If you want to see the translation of a lambda$ term, e.g., to copy the text and modify it to produce some similar LAMBDA object, use :translam. We sometimes do this to explore by example the restrictions on well-formedness.

      If you have a LAMBDA object, e.g., one printed by print-cl-cache, that you suspect is ill-formed, this function won't tell you why it is ill-formed! It will just tell you whether it's ill-formed. If you want to know why, translate the quoted LAMBDA object with :translam, which generates sometimes verbose error messages.

      The global setting of set-ignore-ok has no effect on well-formedness of LAMBDA objects. IGNORE and IGNORABLE declarations inside the LAMBDA are effective.

      ACL2 !>(set-ignore-ok t)
      T
      ACL2 !>(well-formed-lambda-objectp
              '(LAMBDA (X Y)
                 (DECLARE (XARGS :GUARD (NATP X) :SPLIT-TYPES T))
                 (BINARY-+ '1 X))
              (w state))
      NIL
      
      ACL2 !>(well-formed-lambda-objectp
              '(LAMBDA (X Y)
                 (DECLARE (XARGS :GUARD (NATP X) :SPLIT-TYPES T)
                          (IGNORE Y))
                 (BINARY-+ '1 X))
              (w state))
      T

      There should be very few occasions on which you need to know what this predicate checks!

      That said, here are the rules enforced.

      An object is a well-formed LAMBDA object iff it has one of the following two forms:

      (LAMBDA vars tbody)          ; ``simple''  LAMBDA object 
      (LAMBDA vars tdcl tbody)     ; ``declared'' LAMBDA object 
      

      where

      • vars is a list of distinct legal variable names
      • tdcl, if present, is a DECLARE form containing, at most, TYPE, IGNORE, IGNORABLE, and XARGS keys. The user of lambda$ may provide multiple DECLARE forms but when translated they are combined into one as shown here.
      • If an XARGS key is present it has exactly this form (XARGS :GUARD tguard :SPLIT-TYPES T), where tguard is a fully translated logic mode term involving only the formal variables, vars. Note that the user of lambda$ may supply :SPLIT-TYPES NIL and may do so before or after the :GUARD, and the guard term need not be in translated form, but the resulting LAMBDA object has the form described here.
      • The :GUARD specified in XARGS must include as a conjunct every TYPE expression generated by any TYPE specs. E.g., (INTEGERP x) must be a conjunct of tguard if (TYPE INTEGER ... x ...) is declared. That is consistent with the :SPLIT-TYPES T setting and means the guard does not need to be extended any further with the TYPES. The point of this restriction is to guarantee that the guard implies the types declared to the compiler. But this is a purely syntactic check and so may at times require entering silly-looking guards. For example, (declare (type rational x) (xargs :guard (integerp x) :split-types t)) is ruled ill-formed because (rationalp x) is not a conjunct of the guard, even though it is logically implied by the guard. So you'd have to use (declare (type rational x) (xargs :guard (if (integerp x) (rationalp x) 'nil) :split-types t)). Note also that the guard is a fully translated conjunction, i.e., an IF, not an AND! Order of the conjuncts does not matter.

        Note: The guard need not be tame (or even fully badged) because guards are irrelevant to the axioms of apply$. But guards must be in :logic mode from the outset because we may have to prove guard obligations on-the-fly in evaluation (we do not want to try to convert functions used in the guard from from :program to :logic mode while doing an evaluation of an apply$).

      • tbody is a fully translated, tame term, involving no free variables and respecting the declared IGNORE and IGNORABLE declarations.

        Furthermore, in the case of a lambda object generated by lambda$, tbody is a ``tagged'' version of the translation of the body used in the lambda$ expression. Tagging involves use of a special form generated by tag-translated-lambda$-body and recognized by lambda$-bodyp. This form contains the untranslated lambda$ expression as well as the translation of its body. For example, (lambda$ (x) (+ 1 x)) translates to the tagged lambda object '(LAMBDA (X) (RETURN-LAST 'PROGN 'orig-form tbody)), where orig-form is (LAMBDA$ (X) (+ 1 X)) and tbody is (BINARY-+ '1 X).

        It may be helpful to use :translam to inspect examples of the translations of lambda$ expressions.

      The Differences Between Well-Formed and Merely Tame Lambda Objects

      Roughly put, tame LAMBDA objects have to have one of the two basic shapes described above (simple or declared), the listed formals merely have to be symbols -- not necessarily variable symbols and not necessarily distinct. The declaration, if present, is completely irrelevant and the body merely has to be a tame expression -- not necessarily closed with respect to the formals or respecting IGNORE or IGNORABLE declarations. The meaning assigned to such an object when applied to some arguments is just the result delivered by ev$ under an alist formed by pairing the formals -- including non-variables and any duplicates -- with the actuals. If a free variable is encountered, ev$ gives it the value NIL courtesy of assoc.

      This behavior is implemented by compiled Common Lisp only when well-formedness, guard verification, and guard checking approve of the object and its application.