• 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
          • World
          • Io
          • Wormhole
            • Wormhole-eval
            • Wormhole-status
              • Wormhole-programming-tips
              • Wormhole-implementation
              • Sync-ephemeral-whs-with-persistent-whs
              • Get-persistent-whs
              • Set-persistent-whs-and-ephemeral-whs
              • Make-wormhole-status
              • Set-wormhole-entry-code
              • Set-wormhole-data
              • Wormhole-data
              • Wormhole-entry-code
              • Wormhole-statusp
              • Wormhole-p
            • Programming-with-state
            • W
            • Set-state-ok
            • Random$
          • Mutual-recursion
          • Memoize
          • Mbe
          • Io
          • Defpkg
          • Apply$
          • 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
    • Wormhole

    Wormhole-status

    the two senses of a wormhole's status

    As noted in the discussion of wormholes, every wormhole has a current status, which is some ACL2 object whose shape is largely determined by the author of the wormhole. That object is not stored in the ACL2 state. When the wormhole is entered, its status is assigned to the state global variable wormhole-status, making it visible. When the wormhole is exited, the value of wormhole-status is transferred back to its ``hidden'' location outside of the state. Thus, the next time it is entered the wormhole-status is the same as it was when it was last exited.

    We call the ``hidden'' version of a wormhole's status the persistent wormhole status or persistent-whs and the version occasionally found in the state global wormhole-status as the ephemeral wormhole status or ephemeral-whs. It is helpful to think of the persistent-whs as the wormhole's status as stored in some distant location and its ephemeral-whs as an easily accessible, nearby cache. When the two locations hold the same value we say the wormhole is coherent.

    The state global variable wormhole-status is untouchable: you can read it but not directly write to it via assign or f-put-global. But you can write to the persistent-whs. That is what wormhole-eval does. So while a wormhole is coherent when you first enter it it can become incoherent if you use wormhole-eval to change its persistent-whs while inside the wormhole. And remember, the use of wormhole-eval can be disguised via a function definition.

    The following script illustrates this. First, create a wormhole named demo whose data field is empty. We'll use it to accumulate items without modifying state. We define (save x) to cons x onto the data field of the demo wormhole. So execute these five commands at the top-level of ACL2.

    (wormhole-eval 'demo '(lambda nil '(:enter . nil)) nil)
    (defun save (x)
      (wormhole-eval
       'demo
       '(lambda (whs)(set-wormhole-data whs (cons x (wormhole-data whs))))
       nil))
    (save 'a)
    (save 'b)
    (save 'c)

    Then inspect the persistent-whs of demo:

    ACL2 !>(get-persistent-whs 'demo state)
     (:ENTER C B A)

    So save works as we planned. But now let's enter the demo wormhole. Inside the wormhole we first inspect the ephemeral-whs (i.e., (@ wormhole-status), and the persistent-whs to confirm the wormhole is coherent. Then we execute (save 'd) to add D to the accumulator. Inspecting the persistent-whs shows that it worked. But the ephemeral-whs did not change! The wormhole is now incoherent, thanks to the ``disguised'' use of wormhole-eval while in the wormhole.

    ACL2 !>(wormhole 'demo '(lambda (whs) whs) nil '(quote (welcome!)))
    
    Project-dir-alist:
    ((:SYSTEM . "/Users/moore/Desktop/v85k1/books/")).
    Type :help for help.
    Type (quit) to quit completely out of ACL2.
    
    Wormhole ACL2 !>(WELCOME!)
    Wormhole ACL2 !>(@ wormhole-status)
    (:ENTER C B A)
    Wormhole ACL2 !>(get-persistent-whs 'demo state)
     (:ENTER C B A)
    Wormhole ACL2 !>(save 'd)
    NIL
    Wormhole ACL2 !>(get-persistent-whs 'demo state)
     (:ENTER D C B A)
    Wormhole ACL2 !>(@ wormhole-status)
    (:ENTER C B A)
    Wormhole ACL2 !>:q
    NIL

    The :q above exits the wormhole. Now re-enter the wormhole and inspect the ephemeral-whs and persistent-whs.

    ACL2 !>(wormhole 'demo '(lambda (whs) whs) nil '(quote (welcome back!)))
    
    Project-dir-alist:
    ((:SYSTEM . "/Users/moore/Desktop/v85k1/books/")).
    Type :help for help.
    Type (quit) to quit completely out of ACL2.
    
    Wormhole ACL2 !>(WELCOME BACK!)
    Wormhole ACL2 !>(@ wormhole-status)
    (:ENTER C B A)
    Wormhole ACL2 !>(get-persistent-whs 'demo state)
     (:ENTER C B A)
    Wormhole ACL2 !>(value :q)
    NIL

    The wormhole is coherent of course; wormholes are always coherent upon entry. But notice the value of the data field! It doesn't list D! That happened because when we exited the wormhole, the ephemeral-whs was written back to the persistent-whs, and the ephemeral-whs of the incoherent status did not contain D.

    There are ways ensure that your wormholes remain coherent and they all involve using the function sync-ephemeral-whs-with-persistent-whs, which does what its name says. For example, we could have defined save this way instead.

    (defun save (x state)
      (prog2$
        (wormhole-eval
         'demo
         '(lambda (whs)(set-wormhole-data whs (cons x (wormhole-data whs))))
         nil)
        (sync-ephemeral-whs-with-persistent-whs 'demo state)))

    But note that we must now provide state as an argument to all calls of save and save must return state because read-ACL2-oracle was used to reach out to the persistent-whs to refresh the ephemeral-whs. This means we can only call this version of save in environments in which we have state and can return state.

    Perhaps a better way preserve coherence is to keep save defined in the earlier, state-less way but to call sync-ephemeral-whs-with-persistent-whs from within the wormhole after we call (save 'd). That is easy enough to do if you are in complete control of the demo wormhole. Recall the specification of wormhole. If the entry lambda sets the wormhole-entry-code to :enter, then ld is invoked but the first form executed by the resulting read-eval-print loop is the form argument of wormhole. We used the form argument in the script above to just print a greeting but it can be an arbitrary form. If form returns (value nil) the ld is exited without ever giving the user the opportunity to type and evaluate an arbitrary form.

    But if the demo wormhole allows a user to type and evaluate arbitrary forms (including forms like wormhole-eval or the state-less save), there is no way to ensure coherency. We admit this is an unfortunate aspect of the current design.

    The simplest way to avoid such problems is to use wormhole-eval exclusively and avoid use of the interactive read-eval-print loop provided by wormhole, except loops intended for experts. This is the approach taken by such system utilities as accumulated-persistence and fc-report: wormhole-eval is used to collect data and either wormhole-eval or a non-interactive wormhole is used to display it.