STOBJ-EXAMPLE-1-DEFUNS.html -- ACL2 Version 6.3

## STOBJ-EXAMPLE-1-DEFUNS

the defuns created by the `counters` stobj

    Major Section:  STOBJ

Consider the event shown in stobj-example-1:

    (defstobj counters
      (NodeCnt     :type integer :initially 0)
      (TipCnt      :type integer :initially 0)
      (IntTipsSeen :type t       :initially nil))

Here is a complete list of the defuns added by the event.

The careful reader will note that the `counters` argument below is not declared with the `:stobjs` `xarg` even though we insist that the argument be a stobj in calls of these functions. This ``mystery'' is explained below.

    (defun NodeCntp (x)                 ;;; Recognizer for 1st field
      (declare (xargs :guard t :verify-guards t))
      (integerp x))

    (defun TipCntp (x)                  ;;; Recognizer for 2nd field
      (declare (xargs :guard t :verify-guards t))
      (integerp x))

    (defun IntTipsSeenp (x)             ;;; Recognizer for 3rd field
      (declare (xargs :guard t :verify-guards t) (ignore x))
      t)

    (defun countersp (counters)         ;;; Recognizer for object
      (declare (xargs :guard t :verify-guards t))
      (and (true-listp counters)
           (= (length counters) 3)
           (NodeCntp (nth 0 counters))
           (TipCntp (nth 1 counters))
           (IntTipsSeenp (nth 2 counters))
           t))

    (defun create-counters ()           ;;; Creator for object
      (declare (xargs :guard t :verify-guards t))
      (list '0 '0 'nil))

    (defun NodeCnt (counters)           ;;; Accessor for 1st field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 0 counters))

    (defun update-NodeCnt (v counters)  ;;; Updater for 1st field
      (declare (xargs :guard
                      (and (integerp v)
                           (countersp counters))
                      :verify-guards t))
      (update-nth 0 v counters))

    (defun TipCnt (counters)            ;;; Accessor for 2nd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 1 counters))

    (defun update-TipCnt (v counters)   ;;; Updater for 2nd field
      (declare (xargs :guard
                      (and (integerp v)
                           (countersp counters))
                      :verify-guards t))
      (update-nth 1 v counters))

    (defun IntTipsSeen (counters)       ;;; Accessor for 3rd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 2 counters))

    (defun update-IntTipsSeen (v counters) ;;; Updater for 3rd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (update-nth 2 v counters))

Observe that there is a recognizer for each of the three fields and then a recognizer for the `counters` object itself. Then, for each field, there is an accessor and an updater.

Observe also that the functions are guarded so that they expect a `countersp` for their `counters` argument and an appropriate value for the new field values.

You can see all of the `defuns` added by a `defstobj` event by executing the event and then using the `:pcb!` command on the stobj name. E.g.,

    ACL2 !>:pcb! counters

will print the defuns above.

We now clear up the ``mystery'' mentioned above. Note, for example in `TipCnt`, that the formal `counters` is used. From the discussion in stobj-example-1 it has been made clear that `TipCnt` can only be called on the `counters` object. And yet, in that same discussion it was said that an argument is so treated only if it it declared among the `:stobjs` in the definition of the function. So why doesn't `TipCnt` include something like `(declare (xargs :stobjs (counters)))`?

The explanation of this mystery is as follows. At the time `TipCnt` was defined, during the introduction of the `counters` stobj, the name ```counters`'' was not yet a single-threaded object. The introduction of a new single-threaded object occurs in three steps: (1) The new primitive recognizers, accessors, and updaters are introduced as ``ordinary functions,'' producing their logical axiomatizations. (2) The executable counterparts are defined in raw Lisp to support destructive updating. (3) The new name is declared a single-threaded object to ensure that all future use of these primitives respects the single-threadedness of the object. The functions defined as part of the introduction of a new single-threaded object are the only functions in the system that have undeclared stobj formals other than `state`.

You may return to stobj-example-1 here.