TABLE.html -- ACL2 Version 6.3

## TABLE

user-managed tables

    Major Section:  EVENTS

##

- ###

    Examples:
    (table tests 1 '(...))                ; set contents of tests[1] to '(...)
    (table tests 25)                      ; get contents of tests[25]
    (table tests)                         ; return table tests as an alist
    (table tests nil nil :clear)          ; clear table tests
    (table tests nil '((foo . 7)) :clear) ; set table tests to ((foo . 7))
    (table tests nil nil :guard)          ; fetch the table guard
    (table tests nil nil :guard term)     ; set the table guard

    Some Related Topics

    USING-TABLES-EFFICIENTLY -- Notes on how to use tables efficiently

    General Form:
    (table table-name key-term value-term op term)

where `table-name` is a symbol that is the name of a (possibly new) table, `key-term` and `value-term`, if present, are arbitrary terms involving (at most) the single variable `world`, `op`, if present, is one of the table operations below, and `term`, if present, is a term. `Table` returns an ACL2 ``error triple'' (see error-triples). The effect of `table` on `state` depends on `op` and how many arguments are presented. Some invocations actually have no effect on the ACL2 world and hence an invocation of `table` is not always an ``event''. We explain below, after giving some background information.

Important Note: The `table` forms above are calls of a macro that expand to involve the special variable `state`. This will prevent you from accessing a table from within a hint or theory where you do not have the `state` variable. However, the form

    (table-alist 'tests world)

returns the alist representation of the table named `test` in the given world. Often you have access to `world`.

The ACL2 system provides ``tables'' by which the user can associate one object with another. Tables are in essence just conventional association lists -- lists of pairs -- but the ACL2 environment provides a means of storing these lists in the ``ACL2 world'' of the current `state`. The ACL2 user could accomplish the same ends by using ACL2 ``global variables;'' however, limitations on global variable names are imposed to ensure ACL2's soundness. By convention, no table is important to ACL2's soundness, even though some features of the system use tables, and the user is invited to make free use of tables. Because tables are stored in the ACL2 world they are restored by `include-book` and undone by `:``ubt`. Many users of Nqthm requested a facility by which user data could be saved in Nqthm ``lib files'' and tables are ACL2's answer to that request.

Abstractly, each table is an association list mapping ``keys'' to ``values.'' In addition, each table has a ```:guard`,'' which is a term that must be true of any key and value used. By setting the `:guard` on a table you may enforce an invariant on the objects in the table, e.g., that all keys are positive integers and all values are symbols. Each table has a ``name,'' which must be a symbol. Given a table name, the following operations can be performed on the table.

`:put` -- associate a value with a key (possibly changing the value currently associated with that key).

`:get` -- retrieve the value associated with a key (or nil if no value has been associated with that key).

`:alist` -- return an alist showing all keys and non-nil values in the table.

`:clear` -- clear the table (so that every value is nil), or if val is supplied then set table to that value (which must be an alist).

`:guard` -- fetch or set the :guard of the table.

When the operations above suggest that the table or its `:guard` are modified, what is actually meant is that the current state is redefined so that in it, the affected table name has the appropriate properties. in such cases, the `table` form is an event (see events). In the `:put` case, if the key is already in the table and associated with the proposed value, then the `table` event is redundant (see redundant-events).

`Table` forms are commonly typed by the user while interacting with the system. `:Put` and `:get` forms are especially common. Therefore, we have adopted a positional syntax that is intended to be convenient for most applications. Essentially, some operations admit a ``short form'' of invocation.

    (table name key-term value-term :put)   ; long form
    (table name key-term value-term)        ; short form

evaluates the key- and value-terms, obtaining two objects that we call `key` and `value`, checks that the `key` and `value` satisfy the `:guard` on the named table and then ``modifies'' the named table so that the value associated with `key` is `value`. When used like this, `table` is actually an event in the sense that it changes the ACL2 world. In general, the forms evaluated to obtain the `key` and `value` may involve the variable `world`, which is bound to the then-current world during the evaluation of the forms. However, in the special case that the table in question is named `acl2-defaults-table`, the `key` and `value` terms may not contain any variables. Essentially, the keys and values used in events setting the `acl2-defaults-table` must be explicitly given constants. See acl2-defaults-table.

    (table name key-term nil :get)          ; long form
    (table name key-term)                   ; short form

evaluates the key-term (see note below), obtaining an object, `key`, and returns the value associated with `key` in the named table (or, `nil` if there is no value associated with `key`). When used like this, `table` is not an event; the value is simply returned.

    (table name nil nil :alist)             ; long form
    (table name)                            ; short form

returns an alist representing the named table; for every key in the table with a non-`nil` associated value, the alist pairs the key and its value. The order in which the keys are presented is unspecified. When used like this, `table` is not an event; the alist is simply returned.

    (table name nil val :clear)

sets the named table to the alist `val`, making the checks that `:put` makes for each key and value of `val`. When used like this, `table` is an event because it changes the ACL2 world.

    (table name nil nil :guard)

returns the translated form of the guard of the named table.

    (table name nil nil :guard term)

Provided the named table is empty and has not yet been assigned a `:guard` and `term` (which is not evaluated) is a term that mentions at most the variables `key`, `val` and `world`, this event sets the `:guard` of the named table to `term`. Whenever a subsequent `:put` occurs, `term` will be evaluated with `key` bound to the key argument of the `:put`, `val` bound to the `val` argument of the `:put`, and `world` bound to the then current world. An error will be caused by the `:put` if the result of the evaluation is `nil`.

Note that it is not allowed to change the `:guard` on a table once it has been explicitly set. Before the `:guard` is explicitly set, it is effectively just `t`. After it is set it can be changed only by undoing the event that set it. The purpose of this restriction is to prevent the user from changing the `:guards` on tables provided by other people or the system.

The intuition behind the `:guard` mechanism on tables is to enforce invariants on the keys and values in a table, so that the values, say, can be used without run-time checking. But if the `:guard` of a table is sensitive to the ACL2 world, it may be possible to cause some value in the table to cease satisfying the `:guard` without doing any operations on the table. Consider for example the `:guard` ``no value in this table is the name of an event.'' As described, that is enforced each time a value is stored. Thus, `'bang` can be `:put` in the table provided there is no event named `bang`. But once it is in the table, there is nothing to prevent the user from defining `bang` as a function, causing the table to contain a value that could not be `:put` there anymore. Observe that not all state-sensitive `:guard`s suffer this problem. The `:guard` ``every value is an event name'' remains invariant, courtesy of the fact that undoing back through an event name in the table would necessarily undo the `:put` of the name into the table.

`Table` was designed primarily for convenient top-level use. Tables are not especially efficient. Each table is represented by an alist stored on the property list of the table name. `:Get` is just a `getprop` and `assoc-equal`. `:Put` does a `getprop` to the get the table alist, a `put-assoc-equal` to record the new association, and a `putprop` to store the new table alist -- plus the overhead associated with `:guard`s and undoable events, and checking (for redundancy) if the key is already bound to its proposed value. Note that there are never duplicate keys in the resulting `alist`; in particular, when the operation `:clear` is used to install new `alist`, duplicate keys are removed from that alist.

A table name may be any symbol whatsoever. Symbols already in use as function or theorem names, for example, may be used as table names. Symbols in use only as table names may be defined with `defun`, etc. Because there are no restrictions on the user's choice of table names, table names are not included among the logical names. Thus, `:pe name` will never display a table event (for a logical name other than `:here`). Either `:pe name` will display a ``normal'' event such as `(defun name ...)` or `(defthm name ...)` or else `:pe name` will cause an error indicating that `name` is not a logical name. This happens even if `name` is in use as a table name. Similarly, we do not permit table names to have documentation strings, since the same name might already have a documentation string. If you want to associate a documentation string with a table name that is being used no other way, define the name as a label and use the `:``doc` feature of `deflabel` (see deflabel); also see defdoc.