to attach a heuristic filter on a :rewrite or :linear rule

Consider the :REWRITE rule created from


The syntaxp hypothesis in this rule will allow the rule to be applied to (lxd (trn a b)) but will not allow it to be applied to (lxd (norm a)).

General Form:
(SYNTAXP test)
Syntaxp always returns t and so may be added as a vacuous hypothesis. However, when relieving the hypothesis, the test ``inside'' the syntaxp form is actually treated as a meta-level proposition about the proposed instantiation of the rule's variables and that proposition must evaluate to true (non-nil) to ``establish'' the syntaxp hypothesis.

Note that the test of a syntaxp hypothesis does not, in general, deal with the meaning or semantics or values of the terms, but rather with their syntactic forms. In the example above, the syntaxp hypothesis allows the rule to be applied to every target of the form (lxd u), provided u is not of the form (norm v). Observe that without this syntactic restriction the rule above could loop producing a sequence of increasingly complex targets (lxd a), (lxd (norm a)), (lxd (norm (norm a))), etc. An intuitive reading of the rule might be ``norm the argument of lxd unless it has already been normed.''

Note also that a syntaxp hypothesis deals with the syntactic form used internally by ACL2, rather than that seen by the user. In some cases these are the same, but there can be subtle differences with which the writer of a syntaxp hypothesis must be aware. You can use :trans to display this internal representation.

There are two types of syntaxp hypotheses. The simpler type of syntaxp hypothesis may be used as the nth hypothesis in a :rewrite or :linear rule whose :corollary is (implies (and hyp1 ... hypn ... hypk) (equiv lhs rhs)) provided test is a term, test contains at least one variable, and every variable occuring freely in test occurs freely in lhs or in some hypi, i<n. In addition, test must not use any stobjs. (Later below we will describe the second type, an extended syntaxp hypothesis, which may use state.)

We illustrate the use of simple syntaxp hypotheses by slightly elaborating the example given above. Consider a :rewrite rule whose :corollary is:

              (SYNTAXP (NOT (AND (CONSP X)
                                 (EQ (CAR X) 'NORM)))))
         (EQUAL (LXD X)
                (LXD (NORM X))))
How is this rule applied to (lxd (trn a b))? First, we form a substitution that instantiates the left-hand side of the conclusion of the rule so that it is identical to the target term. In the present case, the substitution replaces x with (trn a b).
(LXD X) ==> (LXD (trn a b)).
Then we backchain to establish the hypotheses, in order. Ordinarily this means that we instantiate each hypothesis with our substitution and then attempt to rewrite the resulting instance to true. Thus, in order to relieve the first hypothesis above, we rewrite
(RATIONALP (trn a b)).
If this rewrites to true, we continue.

Of course, most users are aware of some exceptions to this general description of the way we relieve hypotheses. For example, if a hypothesis contains a ``free-variable'' -- one not bound by the current substitution -- we attempt to extend the substitution by searching for an instance of the hypothesis among known truths. See free-variables. Forced hypotheses are another exception to the general rule of how hypotheses are relieved.

Hypotheses marked with syntaxp, as in (syntaxp test), are also exceptions. We instantiate such a hypothesis; but instead of rewriting the instantiated instance, we evaluate the instantiated test. More precisely, we evaluate test in an environment in which its variable symbols are bound to the quotations of the terms to which those variables are bound in the instantiating substitution. So in the case in point, we (in essence) evaluate

(NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
This clearly evaluates to t. When a syntaxp test evaluates to true, we consider the syntaxp hypothesis to have been established; this is sound because logically (syntaxp test) is t regardless of test. If the test evaluates to nil (or fails to evaluate because of guard violations) we act as though we cannot establish the hypothesis and abandon the attempt to apply the rule; it is always sound to give up.

The acute reader will have noticed something odd about the form

(NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
When relieving the first hypothesis, (RATIONALP X), we substituted (trn a b) for X; but when relieving the second hypothesis, (SYNTAXP (NOT (AND (CONSP X) (EQ (CAR X) 'NORM)))), we substituted the quotation of (trn a b) for X. Why the difference? Remember that in the first hypothesis we are talking about the value of (trn a b) -- is it rational -- while in the second one we are talking about its syntactic form. Remember also that Lisp, and hence ACL2, evaluates the arguments to a function before applying the function to the resulting values. Thus, we are asking ``Is the list (trn a b) a consp and if so, is its car the symbol NORM?'' The quotes on both (trn a b) and NORM are therefore necesary. One can verify this by defining trn to be, say cons, and then evaluating forms such as
(AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))
(AND (CONSP (trn a b)) (EQ (CAR (trn a b)) NORM))
(AND (CONSP (trn 'a 'b)) (EQ (CAR (trn 'a 'b)) NORM))
(AND (CONSP '(trn a b)) (EQ '(CAR (trn a b)) ''NORM))
at the top-level ACL2 prompt.

See syntaxp-examples for more examples of the use of syntaxp.

An extended syntaxp hypothesis is similar to the simple type described above, but it uses two additional variables, mfc and state, which must not be bound by the left hand side or an earlier hypothesis of the rule. They must be the last two variables mentioned by form; first mfc, then state. These two variables give access to the functions mfc-xxx; see extended-metafunctions. As described there, mfc is bound to the so-called metafunction-context and state to ACL2's state. See syntaxp-examples for an example of the use of these extended syntaxp hypotheses.