File: MUTUAL-RECURSION.html

package info (click to toggle)
acl2 3.1-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 36,712 kB
  • ctags: 38,396
  • sloc: lisp: 464,023; makefile: 5,470; sh: 86; csh: 47; cpp: 25; ansic: 22
file content (121 lines) | stat: -rw-r--r-- 5,654 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<html>
<head><title>MUTUAL-RECURSION.html  --  ACL2 Version 3.1</title></head>
<body text=#000000 bgcolor="#FFFFFF">
<h2>MUTUAL-RECURSION</h2>define some mutually recursive functions
<pre>Major Section:  <a href="EVENTS.html">EVENTS</a>
</pre><p>


<pre>
Example:
(mutual-recursion
 (defun evenlp (x)
   (if (consp x) (oddlp (cdr x)) t))
 (defun oddlp (x)
   (if (consp x) (evenlp (cdr x)) nil)))
<p>
General Form:
(mutual-recursion def1 ... defn)
where each defi is a <code><a href="DEFUN.html">defun</a></code> form or a <code><a href="DEFUND.html">defund</a></code> form.
</pre>

When mutually recursive functions are introduced it is necessary
to do the termination analysis on the entire clique of definitions.
Each <code><a href="DEFUN.html">defun</a></code> form specifies its own measure, either with the <code>:measure</code>
keyword <code>xarg</code> (see <a href="XARGS.html">xargs</a>) or by default to <code><a href="ACL2-COUNT.html">acl2-count</a></code>.  When a
function in the clique calls a function in the clique, the measure
of the callee's actuals must be smaller than the measure of the
caller's formals -- just as in the case of a simply recursive
function.  But with mutual recursion, the callee's actuals are
measured as specified by the callee's <code><a href="DEFUN.html">defun</a></code> while the caller's
formals are measured as specified by the caller's <code><a href="DEFUN.html">defun</a></code>.  These two
measures may be different but must be comparable in the sense that
<code><a href="O_lt_.html">o&lt;</a></code> decreases through calls.<p>

If you want to specify <code>:</code><code><a href="HINTS.html">hints</a></code> or <code>:guard-hints</code> (see <a href="XARGS.html">xargs</a>), you
can put them in the <code><a href="XARGS.html">xargs</a></code> declaration of any of the <code><a href="DEFUN.html">defun</a></code> forms,
as the <code>:</code><code><a href="HINTS.html">hints</a></code> from each form will be appended together, as will the
<code><a href="GUARD-HINTS.html">guard-hints</a></code> from each form.<p>

You may find it helpful to use a lexicographic order, the idea being to have
a measure that returns a list of two arguments, where the first takes
priority over the second.  Here is an example.

<pre>
(include-book "ordinals/lexicographic-ordering" :dir :system)<p>

(encapsulate
 ()
 (set-well-founded-relation l&lt;) ; will be treated as LOCAL<p>

 (mutual-recursion
  (defun foo (x)
    (declare (xargs :measure (list (acl2-count x) 1)))
    (bar x))
  (defun bar (y)
    (declare (xargs :measure (list (acl2-count y) 0)))
    (if (zp y) y (foo (1- y))))))
</pre>
<p>

The <code><a href="GUARD.html">guard</a></code> analysis must also be done for all of the functions at
the same time.  If any one of the <code><a href="DEFUN.html">defun</a></code>s specifies the
<code>:</code><code><a href="VERIFY-GUARDS.html">verify-guards</a></code> <code>xarg</code> to be <code>nil</code>, then <a href="GUARD.html">guard</a> verification is
omitted for all of the functions.<p>

Technical Note: Each <code>defi</code> above must be of the form <code>(defun ...)</code>.  In
particular, it is not permitted for a <code>defi</code> to be a form that will
macroexpand into a <code><a href="DEFUN.html">defun</a></code> form.  This is because <code>mutual-recursion</code> is
itself a macro, and since macroexpansion occurs from the outside in,
at the time <code>(mutual-recursion def1 ... defk)</code> is expanded the <code>defi</code>
have not yet been.  But <code>mutual-recursion</code> must decompose the <code>defi</code>.
We therefore insist that they be explicitly presented as <code><a href="DEFUN.html">defun</a></code>s or
<code><a href="DEFUND.html">defund</a></code>s (or a mixture of these).<p>

Suppose you have defined your own <code><a href="DEFUN.html">defun</a></code>-like macro and wish to use
it in a <code>mutual-recursion</code> expression.  Well, you can't.  (!)  But you
can define your own version of <code>mutual-recursion</code> that allows your
<code><a href="DEFUN.html">defun</a></code>-like form.  Here is an example.  Suppose you define

<pre>
(defmacro my-defun (&amp;rest args) (my-defun-fn args))
</pre>

where <code>my-defun-fn</code> takes the arguments of the <code>my-defun</code> form and
produces from them a <code><a href="DEFUN.html">defun</a></code> form.  As noted above, you are not
allowed to write <code>(mutual-recursion (my-defun ...) ...)</code>.  But you can
define the macro <code>my-mutual-recursion</code> so that

<pre>
(my-mutual-recursion (my-defun ...) ... (my-defun ...))
</pre>

expands into <code>(mutual-recursion (defun ...) ... (defun ...))</code> by
applying <code>my-defun-fn</code> to each of the arguments of
<code>my-mutual-recursion</code>.

<pre>
(defun my-mutual-recursion-fn (lst) 
  (declare (xargs :guard (alistp lst)))<p>

; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN).  We apply my-defun-fn to the arguments of each element and
; collect the resulting list of DEFUNs.<p>

  (cond ((atom lst) nil)
        (t (cons (my-defun-fn (cdr (car lst)))
                 (my-mutual-recursion-fn (cdr lst))))))<p>

(defmacro my-mutual-recursion (&amp;rest lst)<p>

; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN).  We obtain the DEFUN corresponding to each and list them
; all inside a MUTUAL-RECURSION form.<p>

  (declare (xargs :guard (alistp lst)))
  (cons 'mutual-recursion (my-mutual-recursion-fn lst))).
</pre>

<br><br><br><a href="acl2-doc.html"><img src="llogo.gif"></a> <a href="acl2-doc-index.html"><img src="index.gif"></a>
</body>
</html>