1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancments. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13 (macsyma-module matcom
)
15 ;; This is the Match Compiler.
17 (declare-top (special $rules $props boundlist reflist topreflist program
))
19 (defvar *afterflag nil
)
21 (defmvar $announce_rules_firing nil
)
23 (defmspec $matchdeclare
(form)
24 (let ((meta-prop-p nil
))
25 (proc-$matchdeclare
(cdr form
))))
27 (defun proc-$matchdeclare
(x)
29 (merror (intl:gettext
"matchdeclare: must be an even number of arguments.")))
30 (do ((x x
(cddr x
))) ((null x
))
31 (cond ((symbolp (car x
))
32 (cond ((and (not (symbolp (cadr x
)))
33 (or (numberp (cadr x
))
34 (member (caaadr x
) '(mand mor mnot mcond mprog
) :test
#'eq
)))
35 (improper-arg-err (cadr x
) '$matchdeclare
)))
36 (meta-add2lnc (car x
) '$props
)
37 (meta-mputprop (car x
) (ncons (cadr x
)) 'matchdeclare
))
38 ((not ($listp
(car x
)))
39 (improper-arg-err (car x
) '$matchdeclare
))
40 (t (do ((l (cdar x
) (cdr l
))) ((null l
))
41 (proc-$matchdeclare
(list (car l
) (cadr x
)))))))
44 (defun compileatom (e p
)
47 (return (cond ((null d
)
54 ((member p boundlist
:test
#'eq
)
56 (list (list 'not
(list 'equal e p
))
58 (t (setq boundlist
(cons p boundlist
)) (emit d
))))))
60 (defun emit (x) (setq program
(nconc program
(list x
))))
63 (cond ((or (numberp x
) (member x boundlist
:test
#'eq
)) x
)
64 ((and (symbolp x
) (get x
'operators
)) `(quote ,x
))
65 ;; ((NULL BOUNDLIST) (LIST 'SIMPLIFYA (LIST 'QUOTE X) NIL))
66 (t `(meval (quote ,x
)))))
68 (defun makepreds (l gg
)
70 (t (cons (cond ((atom (car l
))
71 (list 'lambda
(list (setq gg
(gensym)))
72 `(declare (special ,gg
))
74 (t (defmatch1 (car l
) (gensym))))
75 (makepreds (cdr l
) nil
)))))
77 (defun defmatch1 (pt e
)
78 (prog (topreflist program prog-variables
)
79 (setq topreflist
(list e
))
80 (cond ((atom (errset (compilematch e pt
)))
81 (merror (intl:gettext
"defmatch: failed to compile match for pattern ~M") pt
))
83 ;; NOTE TO TRANSLATORS: MEANING OF FOLLOWING TEXT IS UNKNOWN
84 (mtell "defmatch: ~M will be matched uniquely since sub-parts would otherwise be ambigious.~%" pt
)
87 `(declare (special ,e
))
90 (list (setq prog-variables
(cdr (reverse topreflist
))))
91 `((declare (special ,@ prog-variables
)))
93 (list (list 'return t
))))))))))
95 (defun compileplus (e p
)
96 (prog (reflist f g h flag leftover
)
99 (cond ((null leftover
)
100 (return (emit (list 'cond
101 (list (list 'not
(list 'equal e
0.
))
103 ((null (cdr leftover
)) (return (compilematch e
(car leftover
))))
104 ((setq f
(intersection leftover boundlist
:test
#'equal
))
111 (list '(mminus) (car f
)))))))
112 (setq leftover
(delete (car f
) leftover
:test
#'equal
))
115 ;; Almost nobody knows what this means. Just suppress the noise.
116 ;; (mtell "COMPILEPLUS: ~M partitions '+'
117 ;; expression.~%" (cons '(mplus) leftover))
118 (setq boundlist
(append boundlist
(remove-if-not #'atom leftover
)))
119 (return (emit (list 'cond
122 (list 'quote leftover
)
124 (makepreds leftover nil
))))
125 '(t (matcherr))))))))
126 ((fixedmatchp (car p
))
133 (list '(mminus) (car p
))))))))
135 (cond ((cdr p
) (setq leftover
(cons (car p
) leftover
)) (setq p
(cdr p
)) (go a1
))
136 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
137 (setq boundlist
(cons (car p
) boundlist
))
138 (emit (getdec (car p
) e
))
139 (cond ((null (cdr p
)) (return nil
)) (t (go a
))))
140 ((eq (caaar p
) 'mtimes
)
141 (cond ((and (not (or (numberp (cadar p
))
142 (and (not (atom (cadar p
)))
143 (eq (caar (cadar p
)) 'rat
))))
144 (fixedmatchp (cadar p
)))
146 (emit `(setq ,(genref)
148 (ratcoef ,e
,(memqargs (cadar p
))))))
149 (compiletimes (car reflist
) (cons '(mtimes) (cddar p
)))
150 (emit `(setq ,e
(meval
154 ((mtimes) -
1 ,(car reflist
)
157 (setq flag t
) (rplacd (car p
) (reverse (cdar p
))) (go a1
))
158 (t (setq leftover
(cons (car p
) leftover
)) (go a
))))
159 ((eq (caaar p
) 'mexpt
)
160 (cond ((fixedmatchp (cadar p
))
164 ((fixedmatchp (caddar p
))
168 (t (go functionmatch
)))
171 (list f e
(setq g
(memqargs g
)) ''mplus
)))
179 (cond ((eq f
'findexpon
)
186 (compilematch (car reflist
) h
))
187 ((not (fixedmatchp (caaar p
)))
189 (setq leftover
(cons (car p
) leftover
))
192 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
193 (setq boundlist
(cons (caaar p
) boundlist
))
198 (t (go functionmatch
)))
203 (list 'findfun e
(memqargs (caaar p
)) ''mplus
)))
204 (cond ((eq (caaar p
) 'mplus
)
205 (mtell (intl:gettext
"COMPILEPLUS: warning: '+' within '+' in: ~M~%") (car p
))
206 (compileplus (car reflist
) (car p
)))
207 (t (emit (list 'setq
(genref) (list 'kdr
(cadr reflist
))))
208 (compileeach (car reflist
) (cdar p
))))
213 (list '(mplus) e
(list '(mminus) (car p
)))))))
216 (defun compiletimes (e p
)
217 (prog (reflist f g h leftover
)
220 (cond ((null leftover
)
221 (return (emit (list 'cond
222 (list (list 'not
(list 'equal e
1.
))
224 ((null (cdr leftover
)) (return (compilematch e
(car leftover
))))
225 ((setq f
(intersection leftover boundlist
:test
#'equal
))
230 (list '(mquotient) e
(car f
))))))
231 (setq leftover
(delete (car f
) leftover
:test
#'equal
))
234 ;; Almost nobody knows what this means. Just suppress the noise.
235 ;; (mtell "COMPILETIMES: ~M partitions '*' expression.~%" (cons '(mtimes) leftover))
236 (setq boundlist
(append boundlist
(remove-if-not #'atom leftover
)))
237 (return (emit (list 'cond
240 (list 'quote leftover
)
242 (makepreds leftover nil
))))
243 '(t (matcherr))))))))
244 ((fixedmatchp (car p
))
248 (list 'quote
(list '(mquotient) e
(car p
)))))))
250 (cond ((cdr p
) (setq leftover
(cons (car p
) leftover
)) (setq p
(cdr p
)) (go a1
))
251 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
252 (setq boundlist
(cons (car p
) boundlist
))
253 (emit (getdec (car p
) e
))
254 (cond ((null (cdr p
)) (return nil
)) (t (go a
))))
255 ((eq (caaar p
) 'mexpt
)
256 (cond ((fixedmatchp (cadar p
))
260 ((fixedmatchp (caddar p
))
264 (t (go functionmatch
)))
267 (list f e
(setq g
(memqargs g
)) ''mtimes
)))
268 (cond ((eq f
'findbase
)
270 (list (list 'equal
(car reflist
) 0)
278 (cond ((eq f
'findexpon
)
279 (list '(mexpt) g
(car reflist
)))
283 (compilematch (car reflist
) h
))
284 ((not (fixedmatchp (caaar p
)))
286 (setq leftover
(cons (car p
) leftover
))
289 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
290 (setq boundlist
(cons (caaar p
) boundlist
))
295 (t (go functionmatch
)))
300 (list 'findfun e
(memqargs (caaar p
)) ''mtimes
)))
301 (cond ((eq (caaar p
) 'mtimes
)
302 (mtell (intl:gettext
"COMPILETIMES: warning: '*' within '*' in: ~M~%") (car p
))
303 (compiletimes (car reflist
) (car p
)))
304 (t (emit (list 'setq
(genref) (list 'kdr
(cadr reflist
))))
305 (compileeach (car reflist
) (cdar p
))))
309 (list 'quote
(list '(mquotient) e
(car p
))))))
313 (defmspec $defmatch
(form)
314 (let ((meta-prop-p nil
))
315 (proc-$defmatch
(cdr form
))))
317 (defun proc-$defmatch
(l)
318 (prog (pt pt
* args a boundlist reflist topreflist program name tem
)
320 (setq pt
(copy-tree (setq pt
* (simplify (cadr l
)))))
322 (setq pt
(copy-tree (setq pt
* (meval pt
))))
323 (mtell (intl:gettext
"defmatch: evaluation of atomic pattern yields: ~M~%") pt
)))
325 (cond ((null (allatoms args
)) (mtell (intl:gettext
"defmatch: some pattern variables are not atoms."))
327 (setq boundlist args
)
329 (cond ((atom (errset (compilematch a pt
)))
330 (merror (intl:gettext
"defmatch: failed to compile match for pattern ~M") pt
))
334 `(declare (special ,a
,@ args
))
337 (list (setq tem
(cdr (reverse topreflist
))))
338 `((declare (special ,@ tem
)))
341 (cond (boundlist (cons 'retlist
344 (meta-add2lnc name
'$rules
)
345 (meta-mputprop name
(list '(mlist) pt
* (cons '(mlist) args
)) '$rule
)
348 (defmspec $tellsimp
(form)
349 (let ((meta-prop-p nil
))
350 (proc-$tellsimp
(cdr form
))))
352 (defun $clear_rules
()
353 (mapc 'kill1
(cdr $rules
))
354 (loop for v in
'(mexpt mplus mtimes
)
355 do
(setf (mget v
'rulenum
) nil
)))
357 (defun proc-$tellsimp
(l)
358 (prog (pt rhs boundlist reflist topreflist a program name tem
359 oldstuff pgname oname rulenum
)
360 (setq pt
(copy-tree (simplifya (car l
) nil
)))
362 (setq rhs
(copy-tree (simplifya (cadr l
) nil
)))
363 (cond ((alike1 pt rhs
) (merror (intl:gettext
"tellsimp: circular rule attempted.")))
364 ((atom pt
) (merror (intl:gettext
"tellsimp: pattern must not be an atom; found: ~A") (fullstrip1 (getop name
))))
365 ((mget (setq name
(caar pt
)) 'matchdeclare
)
366 (merror (intl:gettext
"tellsimp: main operator of pattern must not be match variable; found: ~A") (fullstrip1 (getop name
))))
367 ((member name
'(mplus mtimes
) :test
#'eq
)
368 (mtell (intl:gettext
"tellsimp: warning: rule will treat '~M' as noncommutative and nonassociative.~%") name
)))
370 (cond ((atom (errset (compileeach a
(cdr pt
))))
371 (merror (intl:gettext
"tellsimp: failed to compile match for pattern ~M") (cdr pt
))))
372 (setq oldstuff
(get name
'operators
))
373 (setq rulenum
(mget name
'rulenum
))
374 (cond ((null rulenum
) (setq rulenum
1.
)))
375 (setq oname
(getop name
))
376 (setq pgname
(implode (append (%to$
(explodec oname
))
378 (mexploden rulenum
))))
379 (meta-mputprop pgname name
'ruleof
)
380 (meta-add2lnc pgname
'$rules
)
381 (meta-mputprop name
(f1+ rulenum
) 'rulenum
)
383 (list 'lambda
'(x a2 a3
)
384 `(declare (special x a2 a3
))
386 (list 'ans a
'rule-hit
)
387 `(declare (special ans
,a
))
395 (t (mapcar #'(lambda (h) (simplifya h a3
))
402 (list (setq tem
(nconc boundlist
403 (cdr (reverse topreflist
)))))
404 `((declare (special ,@ tem
)))
407 (list 'values
(memqargs rhs
) t
))))))
408 (cond ((not (member name
'(mtimes mplus
) :test
#'eq
))
411 '(rule-hit ans
) '((and (not dosimp
) (member 'simp
(cdar x
) :test
#'eq
))x
)
413 (cond (oldstuff (cons oldstuff
415 (t '(eqtest x x
)))))))
419 (list '(and (equal 1. a2
) rule-hit
) 'ans
)
420 '(rule-hit (meval '((mexpt) ans a2
)))
422 (cond (oldstuff (cons oldstuff
424 (t '(eqtest x x
)))))))
428 (list '(and (equal 1. a2
) rule-hit
) 'ans
)
429 '(rule-hit (meval '((mtimes) ans a2
)))
431 (cond (oldstuff (cons oldstuff
433 (t '(eqtest x x
)))))))))))
434 (meta-mputprop pgname
(list '(mequal) pt rhs
) '$rule
)
435 (cond ((null (mget name
'oldrules
))
437 (list (get name
'operators
))
439 (meta-putprop name pgname
'operators
)
440 (return (cons '(mlist)
442 (cons pgname
(mget name
'oldrules
))
445 (defun %to$
(l) (cond ((eq (car l
) '%
) (rplaca l
'$
)) (l)))
448 (defmspec $tellsimpafter
(form)
449 (let ((meta-prop-p nil
))
450 (proc-$tellsimpafter
(cdr form
))))
452 (defun proc-$tellsimpafter
(l)
453 (prog (pt rhs boundlist reflist topreflist a program name oldstuff plustimes pgname oname tem
455 (setq pt
(copy-tree (simplifya (car l
) nil
)))
457 (setq rhs
(copy-tree (simplifya (cadr l
) nil
)))
458 (cond ((alike1 pt rhs
) (merror (intl:gettext
"tellsimpafter: circular rule attempted.")))
459 ((atom pt
) (merror (intl:gettext
"tellsimpafter: pattern must not be an atom; found: ~A") (fullstrip1 (getop name
))))
460 ((mget (setq name
(caar pt
)) 'matchdeclare
)
461 (merror (intl:gettext
"tellsimpafter: main operator of pattern must not be match variable; found: ~A") (fullstrip1 (getop name
)))))
463 (setq plustimes
(member name
'(mplus mtimes
) :test
#'eq
))
464 (if (atom (if plustimes
(errset (compilematch a pt
))
465 (errset (compileeach a
(cdr pt
)))))
466 (merror (intl:gettext
"tellsimpafter: failed to compile match for pattern ~M") (cdr pt
)))
467 (setq oldstuff
(get name
'operators
))
468 (setq rulenum
(mget name
'rulenum
))
469 (if (null rulenum
) (setq rulenum
1))
470 (setq oname
(getop name
))
471 (setq pgname
(implode (append (%to$
(explodec oname
))
472 '(|r| |u| |l| |e|
) (mexploden rulenum
))))
473 (meta-mputprop pgname name
'ruleof
)
474 (meta-add2lnc pgname
'$rules
)
475 (meta-mputprop name
(f1+ rulenum
) 'rulenum
)
482 (list 'setq
'x
(list oldstuff
'x
'ans
'a3
))
483 (list 'setq
'x
(list 'simpargs1
'x
'ans
'a3
)))
489 (list (cons a
'(*afterflag rule-hit
)))
490 `((declare (special ,a
*afterflag
)))
491 (list '(setq *afterflag t
))
492 (cond (oldstuff (subst (list 'quote name
)
494 '((cond ((or (atom x
) (not (eq (caar x
) name
)))
498 (cond (plustimes 'x
) (t '(cdr x
)))))
499 (list (list 'multiple-value-setq
503 (list (setq tem
(nconc boundlist
504 (cdr (reverse topreflist
)))))
505 `((declare (special ,@ tem
)))
508 ($announce_rules_firing
509 (list (list 'return
(list 'values
(list 'announce-rule-firing
`',pgname
'x
(memqargs rhs
)) t
))))
511 (list (list 'return
(list 'values
(memqargs rhs
) t
)))))))))
512 (list '(return (if rule-hit ans
(eqtest x x
)))))))))
513 (meta-mputprop pgname
(list '(mequal) pt rhs
) '$rule
)
514 (cond ((null (mget name
'oldrules
))
515 (meta-mputprop name
(list (get name
'operators
)) 'oldrules
)))
516 (meta-putprop name pgname
'operators
)
517 (return (cons '(mlist)
519 (cons pgname
(mget name
'oldrules
))
522 (defun announce-rule-firing (rulename expr simplified-expr
)
523 (let (($display2d nil
) ($stringdisp nil
))
524 ($print
"By" rulename
"," expr
"-->" simplified-expr
))
527 (defmspec $defrule
(form)
528 (let ((meta-prop-p nil
))
529 (proc-$defrule
(cdr form
))))
531 ;;(defvar *match-specials* nil);;Hell lets declare them all special, its safer--wfs
532 (defun proc-$defrule
(l)
533 (prog (pt rhs boundlist reflist topreflist name a program lhs
* rhs
* tem
)
534 (if (not (= (length l
) 3)) (wna-err '$defrule
))
536 (if (or (not (symbolp name
)) (mopp name
) (member name
'($all $%
) :test
#'eq
))
537 (merror (intl:gettext
"defrule: rule name must be a symbol, and not an operator or 'all' or '%'; found: ~M") name
))
538 (setq pt
(copy-tree (setq lhs
* (simplify (cadr l
)))))
539 (setq rhs
(copy-tree (setq rhs
* (simplify (caddr l
)))))
541 (cond ((atom (errset (compilematch a pt
)))
542 (merror (intl:gettext
"defrule: failed to compile match for pattern ~M") pt
))
546 `(declare (special ,a
))
549 (list (setq tem
(nconc boundlist
550 (cdr (reverse topreflist
)))))
551 `((declare (special ,@ tem
)))
554 (list 'values
(memqargs rhs
) t
)))))))
555 (meta-add2lnc name
'$rules
)
556 (meta-mputprop name
(setq l
(list '(mequal) lhs
* rhs
*)) '$rule
)
557 (meta-mputprop name
'$defrule
'$ruletype
)
558 (return (list '(msetq) name
(cons '(marrow) (cdr l
))))))))
560 ; GETDEC constructs an expression of the form ``if <match> then <assign value> else <match failed>''.
562 ; matchdeclare (aa, true);
563 ; :lisp (symbol-plist '$aa) => (MPROPS (NIL MATCHDECLARE (T)))
564 ; tellsimpafter (fa(aa), ga(aa));
565 ; getdec => (MSETQ $AA TR-GENSYM~1)
567 ; matchdeclare (bb, integerp);
568 ; :lisp (symbol-plist '$bb) => (MPROPS (NIL MATCHDECLARE ($INTEGERP)))
569 ; tellsimpafter (fb(bb), gb(bb));
570 ; getdec => (COND ((IS '(($INTEGERP) TR-GENSYM~3)) (MSETQ $BB TR-GENSYM~3)) ((MATCHERR)))
572 ; my_p(x) := integerp(x) and x>100;
573 ; matchdeclare (cc, my_p);
574 ; :lisp (symbol-plist '$cc) => (MPROPS (NIL MATCHDECLARE ($MY_P)))
575 ; tellsimpafter (fc(cc), gc(cc));
576 ; getdec => (COND ((IS '(($MY_P) TR-GENSYM~5)) (MSETQ $CC TR-GENSYM~5)) ((MATCHERR)))
578 ; :lisp (defun $my_p2 (y x) (is `((mgeqp) ,x ,y)))
579 ; matchdeclare (dd, my_p2 (200));
580 ; :lisp (symbol-plist '$dd) => (MPROPS (NIL MATCHDECLARE ((($MY_P2) 200))))
581 ; tellsimpafter (fd(dd), gd(dd));
582 ; getdec => (COND ((IS '(($MY_P2) 200 TR-GENSYM~7)) (MSETQ $DD TR-GENSYM~7)) ((MATCHERR)))
584 ; my_p3 (y, x) := is (x > y);
585 ; matchdeclare (ee, my_p3 (300));
586 ; :lisp (symbol-plist '$ee) => (MPROPS (NIL MATCHDECLARE ((($MY_P3) 300))))
587 ; tellsimpafter (fe(ee), ge(ee));
588 ; getdec => (COND ((IS '(($MY_P3) 300 TR-GENSYM~9)) (MSETQ $EE TR-GENSYM~9)) ((MATCHERR)))
590 ; matchdeclare (ff, lambda ([x], x > 400));
591 ; :lisp (symbol-plist '$ff) => (MPROPS (NIL MATCHDECLARE (((LAMBDA) ((MLIST) $X) ((MGREATERP) $X 400)))))
592 ; tellsimpafter (fff(ff), ggg(ff));
593 ; getdec => (COND ((IS (MAPPLY1 '((LAMBDA) ((MLIST) $X) ((MGREATERP) $X 400)) (LIST TR-GENSYM~11) T NIL)) (MSETQ $FF TR-GENSYM~11)) ((MATCHERR)))
595 ; matchdeclare (gg, lambda ([y, x], x > y) (500));
596 ; :lisp (symbol-plist '$gg) => (MPROPS (NIL MATCHDECLARE (((MQAPPLY) ((LAMBDA) ((MLIST) $Y $X) ((MGREATERP) $X $Y)) 500))))
597 ; tellsimpafter (fg(gg), gg(gg));
598 ; getdec => (COND ((IS (MEVAL '((MQAPPLY) ((LAMBDA) ((MLIST) $Y $X) ((MGREATERP) $X $Y)) 500 TR-GENSYM~13))) (MSETQ $GG TR-GENSYM~13)) ((MATCHERR)))
600 ; pattern-variable is the pattern variable (as declared by matchdeclare)
601 ; match-against is the expression to match against
603 ; Return T if $MAYBE returns T, otherwise NIL.
604 ; That makes all non-T values (e.g. $UNKNOWN or noun expressions) act like NIL.
606 (defun definitely-so (e)
607 (eq (mfuncall '$maybe e
) t
))
609 (defun getdec (pattern-variable match-against
)
611 (if (setq p
(mget pattern-variable
'matchdeclare
))
612 ; P is (<foo>) where <foo> is the matchdeclare predicate
613 ; If <foo> is an atom, it is T or the name of a Lisp or Maxima function
614 ; Otherwise, <foo> is ((<op>) <args>)
616 ; If <foo> is $TRUE, T, or $ALL, generated code always assigns gensym value to pattern variable
617 (if (and (atom (car p
)) (member (car p
) '($true t $all
) :test
#'eq
))
618 `(msetq ,pattern-variable
,match-against
)
620 ; Otherwise, we have some work to do.
622 (let ((p-op (car p
)) (p-args) (test-expr))
625 ; P-OP is the name of a function. Try to generate a Lisp function call.
626 (if (and (fboundp p-op
) (not (get p-op
'translated
))) ; WHY THE TEST FOR TRANSLATED PROPERTY ??
627 `(eq t
(,p-op
,@(ncons match-against
)))
628 `(definitely-so '((,p-op
) ,@(ncons match-against
))))
630 ; Otherwise P-OP is something like ((<op>) <args>).
632 (setq p-args
(cdr p-op
))
634 ((eq (caar p-op
) 'lambda
)
635 `(definitely-so (mapply1 ',p-op
(list ,match-against
) t nil
)))
636 ((eq (caar p-op
) 'mqapply
)
637 `(definitely-so (meval ',(append p-op
(ncons match-against
)))))
638 ; Otherwise P-OP must be a function call with the last arg missing.
640 (if (and (consp (car p-op
)) (mget (caar p-op
) 'mmacro
))
641 `(definitely-so (cons ',(car p-op
) ,(append '(list) (mapcar 'memqargs p-args
) (ncons match-against
))))
642 `(definitely-so (cons ',(car p-op
) ',(append (mapcar 'memqargs p-args
) (ncons match-against
))))))))))
645 (,test-expr
(msetq ,pattern-variable
,match-against
))
648 (defun compilematch (e p
)
650 (cond ((fixedmatchp p
)
655 (list 'meval
(list 'quote
658 ((atom p
) (compileatom e p
))
659 ((eq (caar p
) 'mplus
) (compileplus e p
))
660 ((eq (caar p
) 'mtimes
) (compiletimes e p
))
661 (t (compileatom (list 'kaar e
)
666 (compileeach (car reflist
) (cdr p
))))
672 (setq topreflist
(cons a topreflist
))
673 (return (car (setq reflist
(cons a reflist
))))))
674 (defun compileeach (elist plist
)
675 (prog (reflist count
)
677 (setq reflist
(cons elist reflist
))
678 a
(setq count
(f1+ count
))
680 (return (emit (list 'cond
681 (list (list 'nthkdr elist
(f1- count
))
683 (emit (list 'setq
(genref) (list 'kar
(cadr reflist
))))
684 (compilematch (car reflist
) (car plist
))
685 (setq plist
(cdr plist
))
686 (setq reflist
(cons (list 'kdr
(cadr reflist
)) reflist
))
689 (defun fixedmatchp (x)
690 (cond ((numberp x
) t
)
692 (if (or (member x boundlist
:test
#'eq
) (null (mget x
'matchdeclare
))) t
))
693 (t (and (or (member (caar x
) boundlist
:test
#'eq
)
694 (null (mget (caar x
) 'matchdeclare
)))
698 (if (null x
) t
(and (fixedmatchp (car x
)) (fmp1 (cdr x
)))))