USING-COMPUTED-HINTS-4

So far we have used computed hints only to compute when a fixed set
of keys and values are to be used as a hint. But computed hints
can, of course, compute the set of keys and values. You might, for
example, write a hint that recognizes when a clause ``ought'' to be
provable by a :BDD hint and generate the appropriate hint. You
might build in a set of useful lemmas and check to see if the clause
is proveable :BY one of them. You can keep all function symbols
disabled and use computed hints to compute which ones you want to
:EXPAND. In general, you can write a theorem prover for use in
your hints, provided you can get it do its job by directing our
theorem prover.

Suppose for example we wish to find every occurrence of an instance
of (SWAP x) and provide the corresponding instance of
ALL-SWAPS-HAVE-THE-PROPERTY. Obviously, we must explore the
clause looking for instances of (SWAP x) and build the
appropriate instances of the lemma. We could do this in many
different ways, but below we show a general purpose set of utilities
for doing it. The functions are not defined in ACL2 but could be
defined as shown.

Our plan is: (1) Find all instances of a given pattern (term) in a
clause, obtaining a set of substitutions. (2) Build a set of
:instance expressions for a given lemma name and set of
substitutions. (3) Generate a :use hint for those instances when
instances are found.

The pair of functions below find all instances of a given pattern
term in either a term or a list of terms. The functions each return
a list of substitutions, each substitution accounting for one of the
matches of pat to a subterm. At this level in ACL2 substitutions
are lists of pairs of the form (var . term). All terms mentioned
here are presumed to be in translated form.

The functions take as their third argument a list of substitutions
accumulated to date and add to it the substitutions produced by
matching pat to the subterms of the term. We intend this
accumulator to be nil initially. If the returned value is nil, then
no instances of pat occurred.

We now turn our attention to converting a list of substitutions into
a list of lemma instances, each of the form

(:INSTANCE name (var1 term1) ... (vark termk))

as written in :use hints. In the code shown above, substitutions
are lists of pairs of the form (var . term), but in lemma
instances we must write ``doublets.'' So here we show how to
convert from one to the other:

Finally, we can package it all together into a hint function. The
function takes a pattern, pat, which must be a translated term,
the name of a lemma, name, and a clause. If some instances of
pat occur in clause, then the corresponding instances of
name are :USEd in the computed hint. Otherwise, the hint does
not apply.

The design of this particular hint function makes it important that
the variables of the pattern be the variables of the named lemma and
that all of the variables we wish to instantiate occur in the
pattern. We could, of course, redesign it to allow ``free
variables'' or some sort of renaming.

The effect of the hint above is that any time a clause arises in
which any instance of (SWAP x) appears, we add the corresponding
instance of ALL-SWAPS-HAVE-THE-PROPERTY. So for example, if
Subgoal *1/3.5 contains the subterm (SWAP (SWAP A)) then this
hint fires and makes the system behave as though the hint: