File: instance.lisp

package info (click to toggle)
acl2 7.2dfsg-3
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 198,968 kB
  • ctags: 182,300
  • sloc: lisp: 2,415,261; ansic: 5,675; perl: 5,577; xml: 3,576; sh: 3,255; cpp: 2,835; makefile: 2,440; ruby: 2,402; python: 778; ml: 763; yacc: 709; csh: 355; php: 171; lex: 162; tcl: 44; java: 24; asm: 23; haskell: 17
file content (664 lines) | stat: -rw-r--r-- 24,021 bytes parent folder | download | duplicates (6)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
; Fully Ordered Finite Sets
; Copyright (C) 2003-2012 Kookamara LLC
;
; Contact:
;
;   Kookamara LLC
;   11410 Windermere Meadows
;   Austin, TX 78759, USA
;   http://www.kookamara.com/
;
; License: (An MIT/X11-style license)
;
;   Permission is hereby granted, free of charge, to any person obtaining a
;   copy of this software and associated documentation files (the "Software"),
;   to deal in the Software without restriction, including without limitation
;   the rights to use, copy, modify, merge, publish, distribute, sublicense,
;   and/or sell copies of the Software, and to permit persons to whom the
;   Software is furnished to do so, subject to the following conditions:
;
;   The above copyright notice and this permission notice shall be included in
;   all copies or substantial portions of the Software.
;
;   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;   DEALINGS IN THE SOFTWARE.
;
; Original author: Jared Davis <jared@kookamara.com>


; instance.lisp
;
; This is a system for dynamically instantiating ACL2 "theories" (which are
; represented as constants) to create new, concrete "theories".

; BOZO this whole file is probably subsumed by something better, in the
; make-event era.

(in-package "INSTANCE")


; Everything in this file is in program mode.  We do not intend to reason about
; these functions -- instead, we intend to use these functions to create new
; functions, which the user will reason about.

(program)


; Introduction
;
;
; The following work has been motivated by my work with quantification over
; sets.  When I started on this file, I had roughly 2000 lines of complicted
; macros in order to be able to instantiate generic and concrete theories for
; this work, and it was just becoming unmanageable.  My hope was that rewriting
; the definitions and theorems into concrete forms would provide a more concise
; way of instantiating the theory, and make it easier to keep everything
; consistent.
;
; Originally, I wanted to extract the definitions for generic functions from
; ACL2's state (well, actually from the current world).  But, to do so becomes
; very complicated, because of the restrictions on macros that they cannot take
; state as a parameter.  So, the best that I could ever accomplish that way
; would be to display a list of events, which a user could copy into a file.
; But, that is wholly unsatisfying, because it would mean that the resulting
; theories could never be "automagically" updated when new theorems are added
; to the generic theory.
;
; So, instead of doing things that way, I now simply store events in constants.
; These constants can then be rewritten to create new but related theories.
;
; A first step towards this is to introduce a simple rewriter.  Originally I
; had based my rewriter on the built in one-way-unify function in ACL2, but it
; operates only on pseudo-terms, and pseudo-terms cannot contain atoms other
; than symbols.  This gave me serious trouble when trying to rewrite theorems
; involving constants, e.g., to say that something was an integerp and greater
; than zero.  So, instead of using one-way-unify, I introduce a simple
; unification algorithm which has been adapted from Warren Hunt's work.

; The system treats all symbols beginning with a ? as variables, and all other
; atoms as literals.

(defun instance-variablep (x)
  (and (symbolp x)
       (equal (car (explode-atom x 10)) #\?)))



; We return two values: a boolean flag which indicates if we are successful in
; finding a match, and a list of substitutions of the form (variable . value).
; This is all be fairly standard stuff.
;
; For example:
;
;    (instance-unify-term '(predicate ?x) '(predicate (car a)) nil)
;    ==>
;    (t ((?x . (car a))))

(mutual-recursion

  (defun instance-unify-term (pattern term sublist)
    (if (atom pattern)
	(if (instance-variablep pattern)
	    (let ((value (assoc pattern sublist)))
	      (if (consp value)
		  (if (equal term (cdr value))
		      (mv t sublist)
		    (mv nil nil))
		(mv t (acons pattern term sublist))))
	  (if (equal term pattern)
	      (mv t sublist)
	    (mv nil nil)))
      (if (or (atom term)
	      (not (eq (car term) (car pattern))))
	  (mv nil nil)
	(if (or (eq (car term) 'quote)
		(eq (car pattern) 'quote))
	    (if (equal term pattern)
		(mv t sublist)
	      (mv nil nil))
	  (instance-unify-list (cdr pattern) (cdr term) sublist)))))

  (defun instance-unify-list (pattern-list term-list sublist)
    (if (or (atom term-list)
	    (atom pattern-list))
	(if (and (atom term-list)
		 (atom pattern-list))
	    (mv t sublist)
	  (mv nil nil))
      (mv-let (successp new-sublist)
	      (instance-unify-term (car pattern-list)
				   (car term-list)
				   sublist)
	      (if successp
		  (instance-unify-list (cdr pattern-list)
				       (cdr term-list)
				       new-sublist)
		(mv nil nil)))))
)


; After a list of substitutions has been generated, we typically want to apply
; them to a term.  We recur over the list of substitutions, simply calling
; subst to do our work throughout a term.
;
; For example:
;
;   (instance-substitute '((?x . (car a))) '(not (predicate ?x)))
;   ==>
;   (not (predicate (car a)))

(defun instance-substitute (sublist term)
  (if (endp sublist)
      term
    (let* ((old (car (car sublist)))
           (new (cdr (car sublist)))
	   (result (subst new old term)))
      (instance-substitute (cdr sublist) result))))



; We now introduce our actual rewriter.  We take three arguments: pat is the
; pattern to look for throughout the term, e.g., (predicate ?x), repl is the
; replacement to use, e.g., (not (predicate ?x)), and term is the term to match
; the pattern against in order to get the substitutions.
;
; For Example:
;
;   (instance-rewrite1 '(predicate ?x)
;                      '(not (predicate ?x))
;                      '(if (predicate (car x)) t nil))
;   =>
;   (if (not (predicate (car x))) t nil)

(mutual-recursion

  (defun instance-rewrite1 (pat repl term)
    (mv-let (successful sublist)
            (instance-unify-term pat term nil)
	    (if successful
		(instance-substitute sublist repl)
	      (if (atom term)
		  term
		(cons (instance-rewrite1 pat repl (car term))
		      (instance-rewrite-lst1 pat repl (cdr term)))))))

  (defun instance-rewrite-lst1 (pat repl lst)
    (if (endp lst)
        nil
      (cons (instance-rewrite1 pat repl (car lst))
            (instance-rewrite-lst1 pat repl (cdr lst)))))
)



; Finally, given that we can apply a rewrite a term with a single replacement,
; we go ahead and extend this notion to multiple replacements.  In other words,
; we walk through a list of substitutions, sequentially rewriting the term
; using each substitution.

(defun instance-rewrite (term subs)
  (if (endp subs)
      term
    (let ((first-sub (car subs)))
      (instance-rewrite (instance-rewrite1 (first first-sub)
					   (second first-sub)
					   term)
			(cdr subs)))))




; Instantiating Defuns
;
;
; Theories consist mainly of definitions and theorems.  Given generic theorems,
; we will want to rewrite them so that they perform different functions.  For
; example, a generic "all" function might need to be rewritten so that its
; calls to (predicate x) are replaced with calls to (not (predicate x)) for all
; x.
;
; To begin, we instantiate the function's declarations (e.g., comment strings,
; xargs, ignores, and so forth).  We simply duplicate comment strings, but for
; declare forms we allow rewriting to occur.

(defun instance-decls (decls subs)
  (if (endp decls)
      nil
    (if (pseudo-termp (car decls))
	(cons (instance-rewrite (car decls) subs)
	      (instance-decls (cdr decls) subs))
      (cons (car decls)
	    (instance-decls (cdr decls) subs)))))


; For the defun itself, we retain the same defun symbol (e.g., defun or
; defund), but we change the name and args of the function by first creating
; the list '(oldname oldarg1 oldarg2 ...) then applying our substitutions to
; the new function.
;
; As a trivial example,
;  (instance-defun '(defun f (x) (+ x 1)) '(((f x) (g x))))
;    =>
;  (defun g (x) (+ x 1))

(defun instance-defun (defun subs)
  (let* ((defun-symbol  (first defun))
 	 (defun-name    (second defun))
	 (defun-args    (third defun))
         (defun-decls   (butlast (cdddr defun) 1))
	 (defun-body    (car (last defun)))
	 (name/args     (cons defun-name defun-args))
	 (new-body      (instance-rewrite defun-body subs))
	 (new-name/args (instance-rewrite name/args subs))
	 (new-decls     (instance-decls defun-decls subs))
	 (new-name      (car new-name/args))
	 (new-args      (cdr new-name/args)))
    `(,defun-symbol
       ,new-name ,new-args
       ,@new-decls
       ,new-body)))

; We also provide a convenience function that allows you to instance a list of
; defuns.

(defun instance-defuns (defun-list subs)
  (if (endp defun-list)
      nil
    (cons (instance-defun (car defun-list) subs)
	  (instance-defuns (cdr defun-list) subs))))



; Renaming theorems

(defun defthm-names (event-list)
  (if (endp event-list)
      nil
    (let* ((first-event (car event-list))
	   (event-type  (first first-event)))
      (cond ((or (eq event-type 'defthm)
		 (eq event-type 'defthmd))
	     (cons (second first-event)
		   (defthm-names (cdr event-list))))
	    ((eq event-type 'encapsulate)
	     (append (defthm-names (cddr first-event))
		     (defthm-names (cdr event-list))))
	    (t (defthm-names (cdr event-list)))))))

(defun create-new-names (name-list suffix)
  (if (endp name-list)
      nil
    (acons (car name-list)
	   (intern-in-package-of-symbol (string-append (symbol-name (car name-list))
						       (symbol-name suffix))
					suffix)
	   (create-new-names (cdr name-list) suffix))))

(defun rename-defthms (event-list suffix)
  (sublis (create-new-names (defthm-names event-list) suffix)
	  event-list))



; Instantiating Theorems
;
;
; To instantiate defthms, we will want to be able to provide functional
; instantiations of the generic theory.  This is much more complicated than
; instancing definitions, and involves:
;
;   a) determining what functional substitutions to make
;   b) determining the theory in which to conduct the proofs
;   c) handling rule classes and other optional components
;   d) generating the actual defthm event
;
; My idea is essentially that if a substitution list can be used for
; functionally instantiating theorems, then it can also be used for creating
; the new theorem.
;
; (a) Determining what functional substitutions to make.
;
; I pass in a list of substitutions of the following form.
;
;   (((predicate ?x)  (not (in ?x y)))
;    ((all ?x)        (all-not-in ?x y))
;    ((exists ?x)     (exists-not-in ?x y)))
;
; From this list we can generate the functional instantiation hints.  So, for
; example, we simply convert ((predicate ?x) (not (in ?x y))) into the
; substitution:
;
;   (predicate (lambda (?x) (not (in ?x y))))
;
; This is easy to do with the following functions:

(defun sub-to-lambda (sub)
  (let ((term (first sub))
	(repl (second sub)))
    (let ((function-symbol (car term))
	  (lambda-args (cdr term)))
      `(,function-symbol (lambda ,lambda-args ,repl)))))

(defun subs-to-lambdas (subs)
  (if (endp subs)
      nil
    (cons (sub-to-lambda (car subs))
	  (subs-to-lambdas (cdr subs)))))


; (b) Determining the theory in which to conduct the proofs.
;
; When we prove the functional instantiation constraints, ideally we should
; work in an environment where the only definitions that are enabled are the
; definitions used in the functional instantiation hints.
;
; Well, the definitions we need are (almost) simply all of the function symbols
; in the right-hand side of the substitution list.  In other words, for the
; above substitutions, I would want to have the definitions of not, in,
; all-not-in, and exists-not-in available.
;
; Now, the problem with this approach is, what if those symbols don't have
; definitions?  This can occur if, for example, we are using a constrained
; function in the substitution list.  This is actually useful, e.g., for
; substituting (predicate ?x) -> (not (predicate ?x)).
;
; My solution is a stupid hack.  We simply pass in the names of the generic
; functions for which we do not want to generate definitions along with the
; substitutinos.
;
; To begin, the following function will extract all function symbols that occur
; within a term.

(mutual-recursion

  (defun term-functions (term)
    (if (atom term)
        nil
      (cons (car term)
	    (term-list-functions (cdr term)))))

  (defun term-list-functions (list)
    (if (endp list)
	nil
      (append (term-functions (car list))
	      (term-list-functions (cdr list)))))
)

; Next, I wrote the following function, which walks over the substitution list
; and extracts the function symbols from each right hand side, using
; term-functions.  The net result is the list of all functions that were used
; in replacements.

(defun subs-repl-functions (subs)
  (if (endp subs)
      nil
    (let* ((sub1 (car subs))
	   (repl (second sub1)))
      (append (term-functions repl)
	      (subs-repl-functions (cdr subs))))))

; Given the above, we could then convert the list of function symbols into a
; list of (:definition f)'s with the following function.  We now use :d instead
; of :definition to better support macro aliases.

(defun function-list-to-definitions (funcs)
  (if (endp funcs)
      nil
    (cons `(:d ,(car funcs))
	  (function-list-to-definitions (cdr funcs)))))

; And finally, here is a function that does "all of the work", calling
; function-list-to-definitions for all of the functions found in the
; substitution list, minus all of the generic functions that we don't want to
; generate :definition hints for.

(defun subs-to-defs (subs generics)
  (let* ((all-fns (subs-repl-functions subs))
	 (real-fns (set-difference-eq all-fns generics)))
    (function-list-to-definitions real-fns)))


; (c) Handling rule classes and other optional components.
;
; We are interested in several parts of a defthm.  In addition to the
; conjecture itself, we need to consider the rule-classes used by the theorem,
; and the other optional attributes such as the :hints, :doc, :otf-flg, etc.
; We parse these attributes into a five-tuple of pairs of the form (present
; . value), where present is a boolean that says whether or not the flag has
; been seen, value is its value, and the order of the elements is rule-classes,
; instructions, hints, otf-flg, and finally doc.  We parse these options with
; the following code:

(defconst *default-parse-values*
  '((nil . nil) (nil . nil) (nil . nil) (nil . nil) (nil . nil)))

(defun parse-defthm-option (option return-value)
  (cond ((equal (first option) :rule-classes)
         (update-nth 0 (list t (second option)) return-value))
	((equal (first option) :instructions)
	 (update-nth 1 (list t (second option)) return-value))
	((equal (first option) :hints)
	 (update-nth 2 (list t (second option)) return-value))
	((equal (first option) :otf-flg)
	 (update-nth 3 (list t (second option)) return-value))
	((equal (first option) :doc)
	 (update-nth 4 (list t (second option)) return-value))
	(t (er hard "Unknown flag in defthm options ~x0." (first option)))))

(defun parse-defthm-options (options return-value)
  (if (endp options)
      return-value
    (parse-defthm-options (cddr options)
			  (parse-defthm-option options return-value))))


; (d) Generating the actual defthm event.
;
; When we are ready to instance a defthm event, we combine the above work with
; a few new things.  First of all, we need the original theorem event, a new
; name to use, the substitutions to use, and the list of generic function
; symbols in use so that we do not create (:definition f) entries for them.
;
; We begin by making our substitutions in the body of the theorem.  We then
; parse the optional components of the defthm, but we only are interested in
; the rule-classes.  (Hints, instructions, and otf-flg will not be needed,
; because we will be proving this via functional instantiation.  Doc we ignore
; for no good reason.)  We construct a new theorem that has our new name and
; body, replicating the rule classes if necessary.  We also provide a
; functional instantiation hint of the generic theorem's name, along with a
; list of lambda substitutions to make.

(defun instance-defthm (event new-name subs generics extra-defs)
  (let* ((defthm-symbol (first event))
	 (defthm-name   (second event))
	 (defthm-body   (third event))
	 (new-body      (instance-rewrite defthm-body subs))
	 (options       (parse-defthm-options (cdddr event)
					      *default-parse-values*))
	 (rc-opt        (first options)))
    `(,defthm-symbol ,new-name
       ,new-body
       :hints(("Goal"
	       :use (:functional-instance ,defthm-name
					  ,@(subs-to-lambdas subs))
	       :in-theory (union-theories (theory 'minimal-theory)
			   (union-theories ',extra-defs
					   ',(subs-to-defs subs generics)))))
       ,@(if (car rc-opt) `(:rule-classes ,(cdr rc-opt)) nil))))



; Instantiating Encapsulates
;
;
; There are two reasons that I typically use encapsulation.  The first is as a
; purely structural/organizational purpose, where I am trying to prove some
; theorem is true, but I need some lemmas to do so.  In this case I use an
; (encapsulate nil ...) and wrap my lemmas in local forms.  The other reason is
; to actually go ahead and introduce constrained functions.
;
; Two strategies will be necessary for handling these situations.  In
; particular, if we are in an encapsulate which has no constrained function
; symbols, we will want to skip all local events and only add the non-local
; events (using functional instantiation to create the theorems).  On the other
; hand, for the case when we are introducing constrained functions, we will
; want to introduce new constrained functions based on the encapsulate.
;
; So, encapsulates are handled separately based on whether or not any functions
; are constrained.
;
; Within an (encapsulate nil ...), local events will be skipped and defthm
; events will be proven using the functional instantiation of their generic
; counterparts.
;
; Within an (encapsulate (...) ...), local events will not be skipped but will
; instead be reintroduced with new names.  Further, defthm events will be
; copied using new names and will not be proven using functional instantiation.
;
; The only "extra" thing we really need for handling encapsulates is a system
; to make the substitutions within the signatures.  We do that here by simple
; rewriting.  Note that we do not allow the number of return values to change.
; I don't really think of this as a major limitation, since almost always my
; constrained functions return a single value.  If you have an example of where
; this would be useful, it would be interesting to see it.

(defun instance-signature (signature subs)
  (let ((name (first signature))
	(rest (rest signature)))
    (cons (instance-rewrite subs name) rest)))

(defun instance-signatures (signatures subs)
  (if (endp signatures)
      nil
    (cons (instance-signature (car signatures) subs)
	  (instance-signatures (cdr signatures) subs))))

; Because encapsulates can contain many events within them, it is natural to
; make them mutually recursive with the main event list handler, which we are
; now ready to introduce.





; Instantiating Entire Theories
;
;
; We are now ready to introduce the functions which will walk through a theory
; and call the appropriate instancing functions on each of the forms we
; encounter.  To support encapsulation, our functions here are all mutually
; recursive.
;
; The arguments that we pass around are the following:
;
;   - The event or event list to instantiate
;
;   - The global list of substitutions used to derive the instance
;
;   - A suffix which will be appended to generate new names
;
;   - A list of generic functions which have no definitions
;
;   - A mode, which is either 'constrained to indicate that the nearest
;     encapsulate event has constrained functions, or is nil to indicate that
;     the nearest encapsulate is merely a structural wrapper for local lemmas.
;
; Finally, we overload our behavior based on suffix, so that if no suffix is
; given, we simply replicate the generic theory instead of instantiating a
; concrete instance of it.


(mutual-recursion

  (defun instance-event (event subs suffix generics mode extra-defs)
    (if (null suffix)
	event
      (cond ((or (eq (car event) 'defun)
		 (eq (car event) 'defund))
	     (instance-defun event subs))
	    ((or (eq (car event) 'defthm)
		 (eq (car event) 'defthmd))
	     (let* ((name (second event))
		    (new-name (intern-in-package-of-symbol
			       (acl2::string-upcase
				(concatenate 'string
					     (symbol-name name)
					     (symbol-name suffix)))
			       suffix)))
	       (instance-defthm event new-name subs generics extra-defs)))
	    ((equal (car event) 'local)
	     (if (eq mode 'constrained)
		 (instance-event (second event) subs suffix generics mode extra-defs)
	       nil))
	    ((equal (car event) 'encapsulate)
	     (instance-encapsulate event subs suffix generics mode extra-defs))
	    (t (er hard "Don't know how to handle ~x0" (car event))))))

  (defun instance-event-list (events subs suffix generics mode extra-defs)
    (if (endp events)
	nil
      (let ((first (instance-event (car events) subs suffix generics mode extra-defs))
	    (rest  (instance-event-list (cdr events) subs suffix generics mode extra-defs)))
	(if first
	    (cons first rest)
	  rest))))

  (defun instance-encapsulate (event subs suffix generics mode extra-defs)
    (declare (ignore mode))
    (let* ((signatures (second event))
	   (new-sigs   (if signatures
			   (instance-signatures subs signatures)
			 nil))
	   (new-events (instance-event-list (cddr event) subs suffix generics
					    (if signatures
						'constrained
					      nil)
					    extra-defs)))
      `(encapsulate ,new-sigs ,@new-events)))

)


; To be able to actually introduce the events, we need to emit a macro that can
; be used to actually perform substitutions.

(defmacro instance (theory)
  (let ((macro-name (intern-in-package-of-symbol
		     (acl2::string-upcase (concatenate 'string
                                                       "instance-" (string theory)))
		     theory)))
    `(defmacro ,macro-name (&key subs suffix generics extra-defs)
       (list* 'encapsulate
	      nil
	      (instance-event-list ,theory subs suffix generics nil extra-defs)))))




; Some thoughts
;
; A fundamental issue seems to be that a function and its arguments are not
; always used in a consistent manner.  For example, say we want to rewrite (all
; ?x) to (all-foo ?x y) and we want to rewrite (predicate ?x) to (not (foo ?x
; y)).  How can we accurately say just what it is that we want to rewrite in
; each case?
;
; Right now our substitutions are based on
;  ( (predicate ?x)  (not (foo ?x y)) )
;  ( (all ?x)        (all-foo ?x y) )
;
; We can easily pick out and say "all" is replaced by "all-foo", but if we try
; to just use the car of the term as its symbol replacement, then "predicate"
; would be "not".
;
; OK, so we could do some kind of preprocessing step where we fill in argument
; guards.  The "generics" list right now is a big huge hack that allows us to
; ignore the fact that :predicate doens't have a definition.  Really the issue
; that this is trying to solve is to tell us how to build our :in-theory event.
; Right now the :in-theory event is just a hack that we don't really
; understand.