OVERRIDE-HINTS.html -- ACL2 Version 6.3

## OVERRIDE-HINTS

a list of hints given priority in every proof attempt

    Major Section:  MISCELLANEOUS

This is an advanced feature, originally implemented to help system designers to create ``modes'' that control the way hints are supplied to the theorem prover. Please see default-hints for the much more usual way to install hints that may be applied by default.

## Some Related Topics

- ### ADD-OVERRIDE-HINTS -- add to the override-hints

- ### ADD-OVERRIDE-HINTS! -- add non-locally to the override-hints

- ### REMOVE-OVERRIDE-HINTS -- delete from the list of override-hints

- ### REMOVE-OVERRIDE-HINTS! -- delete non-locally from the list of override-hints

- ### SET-OVERRIDE-HINTS -- set the override-hints

- ### SET-OVERRIDE-HINTS! -- set the override-hints non-locally

    Examples:
    ACL2 !>(override-hints (w state))
    ((computed-hint-1 clause keyword-alist processor)
     (computed-hint-2 clause keyword-alist stable-under-simplificationp))

`Override-hints` returns a list of computed hints (see computed-hints) which, unlike other computed hints, may mention the variable `KEYWORD-ALIST`.

Before reading further, please see hints-and-the-waterfall to review the basics of how hints are applied during a proof. In particular, we assume familiarity with the notion of selecting a hint to be applied to the current goal. If there are override-hints, that hint selection is tentative, because if it reduced to `nil` after the application of override-hints, then that hint will be skipped and the attempt will continue for selecting an applicable hint. (Craft your override-hints so that `:no-op t` is returned in such cases instead of `nil`, if you don't want the hint to be skipped.) But we must explain what is meant by ``the application of override-hints'', and we do that now.

Suppose that there are override-hints when a hint is selected for the current goal. That selected hint is a keyword-alist, which is an alternating list of hint keywords and their values, whose source is either an explicit hint `(goal-name :key1 val1 ... :keyn valn)` where the `:keyi` are allowed to be custom hint keywords (which are expanded away; see custom-keyword-hints), or else is the non-`nil` keyword-alist produced by evaluating a computed hint. Then the override-hints are applied to that keyword-alist as follows, one at a time, in order of their occurrence in the list of override-hints (as determined by the use of `set-override-hints` and `add-override-hints`). The first override-hint is evaluated, in the usual manner of evaluating computed hints but with the variable `KEYWORD-ALIST` bound to the above keyword-alist. That evaluation produces a result that should also be a keyword-alist, or else an error occurs. Any custom keyword hints are then eliminated from that keyword-alist. The resulting keyword-alist must not contain the `:ERROR` hint keyword and must not start with the `:COMPUTED-HINT-REPLACEMENT` keyword; otherwise an error occurs. With `KEYWORD-ALIST` bound to this result, the second override-hint is similarly evaluated. This process continues, and the keyword-alist returned by the final override-hint is the one used when processing the goal at hand. Except: If that keyword-alist is `nil`, then the next hint among the pending hints is tentatively selected and the process repeats, applying each override hint to that new tentative selection. Of course we might obtain `nil` again, in which case we tentatively select the next pending hint; and so on.

If finally no hint is selected for the current goal, then `KEYWORD-ALIST` is bound to `nil` and the override-hints are applied as described above. But note that this final step is skipped if hint selection is being performed because `stable-under-simplificationp` has just become true, rather than at the top of the waterfall. (Otherwise the override-hints could easily keep firing uselessly yet putting us back at the top of the waterfall, with no change to the given goal, resulting in an infinite loop.)

As mentioned above, the `:COMPUTED-HINT-REPLACEMENT` keyword is illegal for the value of an override-hint. But a selected hint may be a computed hint that evaluates to a keyword-alist beginning with prefix `:COMPUTED-HINT-REPLACEMENT val`. What value does ACL2 return for such a computed hint in the presence of override-hints? First, this prefix is stripped off before passing the resulting keyword-alist to the override-hints as described above. If the result of applying override-hints to that keyword-alist is not `nil`, then the prefix is put back on the front of that resulting keyword-alist after doing internal processing of the hint, including expansion of any custom keyword hints. Otherwise, the application of override-hints to the computed hint is `nil`, so this hint is not selected after all.

WARNING: Unlike ordinary computed hints, a value of `nil` for an override-hint is not ignored. That is: When an ordinary computed hint evaluates to `nil`, it is deemed not to apply, and the next available hint is consulted. But when an override-hint is evaluated, the result is always supplied for the next binding of the variable `KEYWORD-ALIST`, even if that result is `nil`. If you want an override-hint to be a no-op, return as the expression the variable `KEYWORD-ALIST` rather than an expression that evaluates to `nil`.

This feature can be used in order to implement a form of additive hints. Suppose for example that you want a hint that turns off generalization. A simple but inadequate solution is:

    (add-default-hints '((quote (:do-not '(generalize)))))

The problem is that if there is any explicit hint supplied for a given goal, then it will be the one selected, and the above will be ignored. But suppose that the explicit hint supplied is of the form `("Subgoal x.y" :do-not '(fertilize))`. What we would really want in this case is to generate the hint for the indicated subgoal that binds `:do-not` to a list indicating that both fertilization _and_ generalization are disabled for that goal. A solution is to merge, for example as follows. (The use of `prog2$` and `cw` is of course optional, included here to provide debug printing.)

    (add-override-hints
     '((let* ((tmp (assoc-keyword :do-not KEYWORD-ALIST))
              (new-keyword-alist
               (cond (tmp (list* :do-not
                                 `(cons 'generalize ,(cadr tmp))
                                 (remove-keyword :do-not KEYWORD-ALIST)))
                     (t (list* :do-not ''(generalize) KEYWORD-ALIST)))))
         (prog2$ (cw "New: ~x0~|" new-keyword-alist)
                 new-keyword-alist))))

REMARKS

(1) The utilities `add-override-hints`, `add-override-hints!`, `set-override-hints`, `set-override-hints!`, `remove-override-hints`, and `remove-override-hints!` are also available, in complete analogy to their default-hints versions.

(2) The community book `hints/basic-tests.lisp` illustrates the use of override-hints and illuminates a number of corner cases; search in that file for ``Test override-hints.''

(3) The community book `hints/merge-hint.lisp` provides support for merging hints that might be useful for writers of override-hint expressions (see the examples at the end of that file).

(4) Override-hints are used in the processing of `:BACKTRACK` hints (see hints).