WITH-LOCAL-STATE.html -- ACL2 Version 6.3

## WITH-LOCAL-STATE

locally bind state

    Major Section:  STOBJ

This is an advanced topic, probably of interest only to system developers.

Consider the following example form:

    (with-local-state
     (mv-let (result state)
             (compute-with-state x state)
             result))

This is equivalent to the following form.

    (with-local-stobj
     state
     (mv-let (result state)
             (compute-with-state x state)
             result))

By default, this form is illegal, because ACL2 does not have a way to unwind all changes to the ACL2 state; we say more on this issue below. There may however be situations where you are willing to manage or overlook this issue. In that case you may execute the following form to enable the use of `with-local-state`, by enabling the use of `with-local-stobj` on `state`; but note that it requires an active trust tag (see defttag).

    (remove-untouchable create-state t)

Please be aware that no local state is actually created, however! In particular, users of `with-local-state` need either to ensure that channels are closed and state global variables are returned to their original values, or else be willing to live with changes made to state that are not justified by the code that has been evaluated. You are welcome to look in the the ACL2 source code at the definition of macro `channel-to-string`, which employs `with-local-state` to create a local state for the purpose of creating a string.

Here is an example use of `with-local-state`. Notice the use of `defttag` -- and indeed, please understand that we are just hacking here, and in general it takes significant effort to be sure that one is using `with-local-state` correctly!

    (defttag t)

    (remove-untouchable create-state t)

    (set-state-ok t)

    (defun foo (state)
      (declare (xargs :mode :program))
      (mv-let
       (channel state)
       (open-input-channel "my-file" :object state)
       (mv-let (eofp obj state)
               (read-object channel state)
               (declare (ignore eofp))
               (let ((state (close-input-channel channel state)))
                 (mv obj state)))))

    (defun bar ()
      (declare (xargs :mode :program))
      (with-local-state (mv-let (result state)
                                (foo state)
                                result)))

    ; Multiple-value return version:

    (defun foo2 (state)
      (declare (xargs :mode :program))
      (mv-let
       (channel state)
       (open-input-channel "my-file" :object state)
       (mv-let (eofp obj state)
               (read-object channel state)
               (let ((state (close-input-channel channel state)))
                 (mv eofp obj state)))))

    (defun bar2 ()
      (declare (xargs :mode :program))
      (with-local-state (mv-let (eofp result state)
                                (foo2 state)
                                (mv eofp result))))