1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
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 boundlist reflist topreflist program
))
19 (defmvar $announce_rules_firing nil
)
21 (defmspec $matchdeclare
(form)
22 (let ((meta-prop-p nil
))
23 (proc-$matchdeclare
(cdr form
))))
25 (defun proc-$matchdeclare
(x)
27 (merror (intl:gettext
"matchdeclare: must be an even number of arguments.")))
28 (do ((x x
(cddr x
))) ((null x
))
29 (cond ((symbolp (car x
))
30 (cond ((and (not (symbolp (cadr x
)))
31 (or (numberp (cadr x
))
32 (member (caaadr x
) '(mand mor mnot mcond mprog
) :test
#'eq
)))
33 (improper-arg-err (cadr x
) '$matchdeclare
)))
34 (meta-add2lnc (car x
) '$props
)
35 (meta-mputprop (car x
) (ncons (cadr x
)) 'matchdeclare
))
36 ((not ($listp
(car x
)))
37 (improper-arg-err (car x
) '$matchdeclare
))
38 (t (do ((l (cdar x
) (cdr l
))) ((null l
))
39 (proc-$matchdeclare
(list (car l
) (cadr x
)))))))
42 (defun compileatom (e p
)
45 (return (cond ((null d
)
52 ((member p boundlist
:test
#'eq
)
54 (list (list 'not
(list 'equal e p
))
56 (t (setq boundlist
(cons p boundlist
)) (emit d
))))))
58 (defun emit (x) (setq program
(nconc program
(list x
))))
61 (cond ((or (numberp x
) (member x boundlist
:test
#'eq
)) x
)
62 ((and (symbolp x
) (get x
'operators
)) `(quote ,x
))
63 ;; ((NULL BOUNDLIST) (LIST 'SIMPLIFYA (LIST 'QUOTE X) NIL))
64 (t `(meval (quote ,x
)))))
66 (defun makepreds (l gg
)
68 (t (cons (cond ((atom (car l
))
69 (list 'lambda
(list (setq gg
(gensym)))
70 `(declare (special ,gg
))
72 (t (defmatch1 (car l
) (gensym))))
73 (makepreds (cdr l
) nil
)))))
75 (defun defmatch1 (pt e
)
76 (prog (topreflist program prog-variables
)
77 (setq topreflist
(list e
))
78 (cond ((atom (errset (compilematch e pt
)))
79 (merror (intl:gettext
"defmatch: failed to compile match for pattern ~M") pt
))
81 ;; NOTE TO TRANSLATORS: MEANING OF FOLLOWING TEXT IS UNKNOWN
82 (mtell "defmatch: ~M will be matched uniquely since sub-parts would otherwise be ambiguous.~%" pt
)
85 `(declare (special ,e
))
88 (list (setq prog-variables
(cdr (reverse topreflist
))))
89 `((declare (special ,@ prog-variables
)))
91 (list (list 'return t
))))))))))
93 (defun compileplus (e p
)
94 (prog (reflist f g h flag leftover
)
97 (cond ((null leftover
)
98 (return (emit (list 'cond
99 (list (list 'not
(list 'equal e
0.
))
101 ((null (cdr leftover
)) (return (compilematch e
(car leftover
))))
102 ((setq f
(intersection leftover boundlist
:test
#'equal
))
109 (list '(mminus) (car f
)))))))
110 (setq leftover
(delete (car f
) leftover
:test
#'equal
))
113 ;; Almost nobody knows what this means. Just suppress the noise.
114 ;; (mtell "COMPILEPLUS: ~M partitions '+'
115 ;; expression.~%" (cons '(mplus) leftover))
116 (setq boundlist
(append boundlist
(remove-if-not #'atom leftover
)))
117 (return (emit (list 'cond
120 (list 'quote leftover
)
122 (makepreds leftover nil
))))
123 '(t (matcherr))))))))
124 ((fixedmatchp (car p
))
131 (list '(mminus) (car p
))))))))
133 (cond ((cdr p
) (setq leftover
(cons (car p
) leftover
)) (setq p
(cdr p
)) (go a1
))
134 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
135 (setq boundlist
(cons (car p
) boundlist
))
136 (emit (getdec (car p
) e
))
137 (cond ((null (cdr p
)) (return nil
)) (t (go a
))))
138 ((eq (caaar p
) 'mtimes
)
139 (cond ((and (not (or (numberp (cadar p
))
140 (and (not (atom (cadar p
)))
141 (eq (caar (cadar p
)) 'rat
))))
142 (fixedmatchp (cadar p
)))
144 (emit `(setq ,(genref)
146 (ratcoef ,e
,(memqargs (cadar p
))))))
147 (compiletimes (car reflist
) (cons '(mtimes) (cddar p
)))
148 (emit `(setq ,e
(meval
152 ((mtimes) -
1 ,(car reflist
)
155 (setq flag t
) (rplacd (car p
) (reverse (cdar p
))) (go a1
))
156 (t (setq leftover
(cons (car p
) leftover
)) (go a
))))
157 ((eq (caaar p
) 'mexpt
)
158 (cond ((fixedmatchp (cadar p
))
162 ((fixedmatchp (caddar p
))
166 (t (go functionmatch
)))
169 (list f e
(setq g
(memqargs g
)) ''mplus
)))
177 (cond ((eq f
'findexpon
)
184 (compilematch (car reflist
) h
))
185 ((not (fixedmatchp (caaar p
)))
187 (setq leftover
(cons (car p
) leftover
))
190 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
191 (setq boundlist
(cons (caaar p
) boundlist
))
196 (t (go functionmatch
)))
201 (list 'findfun e
(memqargs (caaar p
)) ''mplus
)))
202 (cond ((eq (caaar p
) 'mplus
)
203 (mtell (intl:gettext
"COMPILEPLUS: warning: '+' within '+' in: ~M~%") (car p
))
204 (compileplus (car reflist
) (car p
)))
205 (t (emit (list 'setq
(genref) (list 'kdr
(cadr reflist
))))
206 (compileeach (car reflist
) (cdar p
))))
211 (list '(mplus) e
(list '(mminus) (car p
)))))))
214 (defun compiletimes (e p
)
215 (prog (reflist f g h leftover
)
218 (cond ((null leftover
)
219 (return (emit (list 'cond
220 (list (list 'not
(list 'equal e
1.
))
222 ((null (cdr leftover
)) (return (compilematch e
(car leftover
))))
223 ((setq f
(intersection leftover boundlist
:test
#'equal
))
228 (list '(mquotient) e
(car f
))))))
229 (setq leftover
(delete (car f
) leftover
:test
#'equal
))
232 ;; Almost nobody knows what this means. Just suppress the noise.
233 ;; (mtell "COMPILETIMES: ~M partitions '*' expression.~%" (cons '(mtimes) leftover))
234 (setq boundlist
(append boundlist
(remove-if-not #'atom leftover
)))
235 (return (emit (list 'cond
238 (list 'quote leftover
)
240 (makepreds leftover nil
))))
241 '(t (matcherr))))))))
242 ((fixedmatchp (car p
))
246 (list 'quote
(list '(mquotient) e
(car p
)))))))
248 (cond ((cdr p
) (setq leftover
(cons (car p
) leftover
)) (setq p
(cdr p
)) (go a1
))
249 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
250 (setq boundlist
(cons (car p
) boundlist
))
251 (emit (getdec (car p
) e
))
252 (cond ((null (cdr p
)) (return nil
)) (t (go a
))))
253 ((eq (caaar p
) 'mexpt
)
254 (cond ((fixedmatchp (cadar p
))
258 ((fixedmatchp (caddar p
))
262 (t (go functionmatch
)))
265 (list f e
(setq g
(memqargs g
)) ''mtimes
)))
266 (cond ((eq f
'findbase
)
268 (list (list 'equal
(car reflist
) 0)
276 (cond ((eq f
'findexpon
)
277 (list '(mexpt) g
(car reflist
)))
281 (compilematch (car reflist
) h
))
282 ((not (fixedmatchp (caaar p
)))
284 (setq leftover
(cons (car p
) leftover
))
287 (leftover (setq leftover
(cons (car p
) leftover
)) (setq p nil
) (go a1
)))
288 (setq boundlist
(cons (caaar p
) boundlist
))
293 (t (go functionmatch
)))
298 (list 'findfun e
(memqargs (caaar p
)) ''mtimes
)))
299 (cond ((eq (caaar p
) 'mtimes
)
300 (mtell (intl:gettext
"COMPILETIMES: warning: '*' within '*' in: ~M~%") (car p
))
301 (compiletimes (car reflist
) (car p
)))
302 (t (emit (list 'setq
(genref) (list 'kdr
(cadr reflist
))))
303 (compileeach (car reflist
) (cdar p
))))
307 (list 'quote
(list '(mquotient) e
(car p
))))))
311 (defmspec $defmatch
(form)
312 (let ((meta-prop-p nil
))
313 (proc-$defmatch
(cdr form
))))
315 (defun proc-$defmatch
(l)
316 (prog (pt pt
* args a boundlist reflist topreflist program name tem
)
318 (setq pt
(copy-tree (setq pt
* (simplify (cadr l
)))))
320 (setq pt
(copy-tree (setq pt
* (meval pt
))))
321 (mtell (intl:gettext
"defmatch: evaluation of atomic pattern yields: ~M~%") pt
)))
323 (cond ((null (allatoms args
)) (mtell (intl:gettext
"defmatch: some pattern variables are not atoms."))
325 (setq boundlist args
)
327 (cond ((atom (errset (compilematch a pt
)))
328 (merror (intl:gettext
"defmatch: failed to compile match for pattern ~M") pt
))
332 `(declare (special ,a
,@ boundlist
))
335 (list (setq tem
(cdr (reverse topreflist
))))
336 `((declare (special ,@ tem
)))
338 (when (not (atom pt
))
339 ;; Ensure that the expression to be matched is an array expression iff the pattern is.
340 (if (member 'array
(car pt
))
341 (list `(when (not (member 'array
(kar ,a
))) (matcherr)))
342 (list `(when (member 'array
(kar ,a
)) (matcherr)))))
346 (cond (boundlist (cons 'retlist
349 (meta-add2lnc name
'$rules
)
350 (meta-mputprop name
(list '(mlist) pt
* (cons '(mlist) args
)) '$rule
)
353 (defmspec $tellsimp
(form)
354 (let ((meta-prop-p nil
))
355 (proc-$tellsimp
(cdr form
))))
357 (defmfun $clear_rules
()
358 (mapc 'kill1
(cdr $rules
))
359 (loop for v in
'(mexpt mplus mtimes
)
360 do
(setf (mget v
'rulenum
) nil
)))
362 (defun proc-$tellsimp
(l)
363 (prog (pt rhs boundlist reflist topreflist a program name tem
364 oldstuff pgname oname rulenum
)
365 (setq pt
(copy-tree (simplifya (car l
) nil
)))
367 (setq rhs
(copy-tree (simplifya (cadr l
) nil
)))
368 (cond ((alike1 pt rhs
) (merror (intl:gettext
"tellsimp: circular rule attempted.")))
369 ((atom pt
) (merror (intl:gettext
"tellsimp: pattern must not be an atom; found: ~A") (fullstrip1 (getop name
))))
370 ((mget (setq name
(caar pt
)) 'matchdeclare
)
371 (merror (intl:gettext
"tellsimp: main operator of pattern must not be match variable; found: ~A") (fullstrip1 (getop name
))))
372 ((member name
'(mplus mtimes
) :test
#'eq
)
373 (mtell (intl:gettext
"tellsimp: warning: rule will treat '~M' as noncommutative and nonassociative.~%") name
)))
375 (cond ((atom (errset (compileeach a
(cdr pt
))))
376 (merror (intl:gettext
"tellsimp: failed to compile match for pattern ~M") (cdr pt
))))
377 (setq oldstuff
(get name
'operators
))
378 (setq rulenum
(mget name
'rulenum
))
379 (cond ((null rulenum
) (setq rulenum
1.
)))
380 (setq oname
(getop name
))
381 (setq pgname
(implode (append (%to$
(explodec oname
))
383 (mexploden rulenum
))))
384 (meta-mputprop pgname name
'ruleof
)
385 (meta-add2lnc pgname
'$rules
)
386 (meta-mputprop name
(f1+ rulenum
) 'rulenum
)
388 (list 'lambda
'(x a2 a3
)
389 `(declare (special x a2 a3
))
391 (list 'ans a
'rule-hit
)
392 `(declare (special ans
,a
))
400 (t (mapcar #'(lambda (h) (simplifya h a3
))
407 (list (setq tem
(nconc boundlist
408 (cdr (reverse topreflist
)))))
409 `((declare (special ,@ tem
)))
411 ;; Ensure that the expression to be matched is an array expression iff the pattern is.
412 (if (member 'array
(car pt
))
413 (list '(when (not (member 'array
(kar x
))) (matcherr)))
414 (list '(when (member 'array
(kar x
)) (matcherr))))
418 (list 'values
(memqargs rhs
) t
))))))
419 (cond ((not (member name
'(mtimes mplus
) :test
#'eq
))
422 '(rule-hit ans
) '((and (not dosimp
) (member 'simp
(cdar x
) :test
#'eq
))x
)
424 (cond (oldstuff (cons oldstuff
426 (t '(eqtest x x
)))))))
430 (list '(and (equal 1. a2
) rule-hit
) 'ans
)
431 '(rule-hit (meval '((mexpt) ans a2
)))
433 (cond (oldstuff (cons oldstuff
435 (t '(eqtest x x
)))))))
439 (list '(and (equal 1. a2
) rule-hit
) 'ans
)
440 '(rule-hit (meval '((mtimes) ans a2
)))
442 (cond (oldstuff (cons oldstuff
444 (t '(eqtest x x
)))))))))))
445 (meta-mputprop pgname
(list '(mequal) pt rhs
) '$rule
)
446 (cond ((null (mget name
'oldrules
))
448 (list (get name
'operators
))
450 (meta-putprop name pgname
'operators
)
451 (return (cons '(mlist)
453 (cons pgname
(mget name
'oldrules
))
456 (defun %to$
(l) (cond ((eq (car l
) '%
) (rplaca l
'$
)) (l)))
459 (defmspec $tellsimpafter
(form)
460 (let ((meta-prop-p nil
))
461 (proc-$tellsimpafter
(cdr form
))))
463 (defun proc-$tellsimpafter
(l)
464 (prog (pt rhs boundlist reflist topreflist a program name oldstuff plustimes pgname oname tem
465 rulenum my
*afterflag
)
466 (setq pt
(copy-tree (simplifya (car l
) nil
)))
468 (setq rhs
(copy-tree (simplifya (cadr l
) nil
)))
469 (cond ((alike1 pt rhs
) (merror (intl:gettext
"tellsimpafter: circular rule attempted.")))
470 ((atom pt
) (merror (intl:gettext
"tellsimpafter: pattern must not be an atom; found: ~A") (fullstrip1 (getop name
))))
471 ((mget (setq name
(caar pt
)) 'matchdeclare
)
472 (merror (intl:gettext
"tellsimpafter: main operator of pattern must not be match variable; found: ~A") (fullstrip1 (getop name
)))))
474 (setq plustimes
(member name
'(mplus mtimes
) :test
#'eq
))
475 (if (atom (if plustimes
(errset (compilematch a pt
))
476 (errset (compileeach a
(cdr pt
)))))
477 (merror (intl:gettext
"tellsimpafter: failed to compile match for pattern ~M") (cdr pt
)))
478 (setq oldstuff
(get name
'operators
))
479 (setq rulenum
(mget name
'rulenum
))
480 (if (null rulenum
) (setq rulenum
1))
481 (setq oname
(getop name
))
482 (setq pgname
(implode (append (%to$
(explodec oname
))
483 '(|r| |u| |l| |e|
) (mexploden rulenum
))))
484 (setq my
*afterflag
(gensym "*AFTERFLAG-"))
485 (proclaim `(special ,my
*afterflag
))
486 (setf (symbol-value my
*afterflag
) nil
)
487 (meta-mputprop pgname name
'ruleof
)
488 (meta-add2lnc pgname
'$rules
)
489 (meta-mputprop name
(f1+ rulenum
) 'rulenum
)
496 (list 'setq
'x
(list oldstuff
'x
'ans
'a3
))
497 (list 'setq
'x
(list 'simpargs1
'x
'ans
'a3
)))
504 (list (cons a
`(,my
*afterflag rule-hit
)))
505 `((declare (special ,a
,my
*afterflag
)))
506 (list `(setq ,my
*afterflag t
))
507 (cond (oldstuff (subst (list 'quote name
)
509 '((cond ((or (atom x
) (not (eq (caar x
) name
)))
513 (cond (plustimes 'x
) (t '(cdr x
)))))
514 (list (list 'multiple-value-setq
518 (list (setq tem
(nconc boundlist
519 (cdr (reverse topreflist
)))))
520 `((declare (special ,@ tem
)))
522 ;; Ensure that the expression to be matched is an array expression iff the pattern is.
523 (if (member 'array
(car pt
))
524 (list '(when (not (member 'array
(kar x
))) (matcherr)))
525 (list '(when (member 'array
(kar x
)) (matcherr))))
529 ($announce_rules_firing
530 (list (list 'return
(list 'values
(list 'announce-rule-firing
`',pgname
'x
(memqargs rhs
)) t
))))
532 (list (list 'return
(list 'values
(memqargs rhs
) t
)))))))))
533 (list '(return (if rule-hit ans
(eqtest x x
)))))))))
534 (meta-mputprop pgname
(list '(mequal) pt rhs
) '$rule
)
535 (cond ((null (mget name
'oldrules
))
536 (meta-mputprop name
(list (get name
'operators
)) 'oldrules
)))
537 (meta-putprop name pgname
'operators
)
538 (return (cons '(mlist)
540 (cons pgname
(mget name
'oldrules
))
543 (defun announce-rule-firing (rulename expr simplified-expr
)
544 (let (($display2d nil
) ($stringdisp nil
))
545 ($print
"By" rulename
"," expr
"-->" simplified-expr
))
548 (defmspec $defrule
(form)
549 (let ((meta-prop-p nil
))
550 (proc-$defrule
(cdr form
))))
552 ;;(defvar *match-specials* nil);;Hell lets declare them all special, its safer--wfs
553 (defun proc-$defrule
(l)
554 (prog (pt rhs boundlist reflist topreflist name a program lhs
* rhs
* tem
)
555 (if (not (= (length l
) 3)) (wna-err '$defrule
))
557 (if (or (not (symbolp name
)) (mopp name
) (member name
'($all $%
) :test
#'eq
))
558 (merror (intl:gettext
"defrule: rule name must be a symbol, and not an operator or 'all' or '%'; found: ~M") name
))
559 (setq pt
(copy-tree (setq lhs
* (simplify (cadr l
)))))
560 (setq rhs
(copy-tree (setq rhs
* (simplify (caddr l
)))))
562 (cond ((atom (errset (compilematch a pt
)))
563 (merror (intl:gettext
"defrule: failed to compile match for pattern ~M") pt
))
567 `(declare (special ,a
))
570 (list (setq tem
(nconc boundlist
571 (cdr (reverse topreflist
)))))
572 `((declare (special ,@ tem
)))
574 (when (not (atom pt
))
575 ;; Ensure that the expression to be matched is an array expression iff the pattern is.
576 (if (member 'array
(car pt
))
577 (list `(when (not (member 'array
(kar ,a
))) (matcherr)))
578 (list `(when (member 'array
(kar ,a
)) (matcherr)))))
582 (list 'values
(memqargs rhs
) t
)))))))
583 (meta-add2lnc name
'$rules
)
584 (meta-mputprop name
(setq l
(list '(mequal) lhs
* rhs
*)) '$rule
)
585 (meta-mputprop name
'$defrule
'$ruletype
)
586 (return (list '(msetq) name
(cons '(marrow) (cdr l
))))))))
588 ; GETDEC constructs an expression of the form ``if <match> then <assign value> else <match failed>''.
590 ; matchdeclare (aa, true);
591 ; :lisp (symbol-plist '$aa) => (MPROPS (NIL MATCHDECLARE (T)))
592 ; tellsimpafter (fa(aa), ga(aa));
593 ; getdec => (MSETQ $AA TR-GENSYM~1)
595 ; matchdeclare (bb, integerp);
596 ; :lisp (symbol-plist '$bb) => (MPROPS (NIL MATCHDECLARE ($INTEGERP)))
597 ; tellsimpafter (fb(bb), gb(bb));
598 ; getdec => (COND ((IS '(($INTEGERP) TR-GENSYM~3)) (MSETQ $BB TR-GENSYM~3)) ((MATCHERR)))
600 ; my_p(x) := integerp(x) and x>100;
601 ; matchdeclare (cc, my_p);
602 ; :lisp (symbol-plist '$cc) => (MPROPS (NIL MATCHDECLARE ($MY_P)))
603 ; tellsimpafter (fc(cc), gc(cc));
604 ; getdec => (COND ((IS '(($MY_P) TR-GENSYM~5)) (MSETQ $CC TR-GENSYM~5)) ((MATCHERR)))
606 ; :lisp (defmfun $my_p2 (y x) (is `((mgeqp) ,x ,y)))
607 ; matchdeclare (dd, my_p2 (200));
608 ; :lisp (symbol-plist '$dd) => (MPROPS (NIL MATCHDECLARE ((($MY_P2) 200))))
609 ; tellsimpafter (fd(dd), gd(dd));
610 ; getdec => (COND ((IS '(($MY_P2) 200 TR-GENSYM~7)) (MSETQ $DD TR-GENSYM~7)) ((MATCHERR)))
612 ; my_p3 (y, x) := is (x > y);
613 ; matchdeclare (ee, my_p3 (300));
614 ; :lisp (symbol-plist '$ee) => (MPROPS (NIL MATCHDECLARE ((($MY_P3) 300))))
615 ; tellsimpafter (fe(ee), ge(ee));
616 ; getdec => (COND ((IS '(($MY_P3) 300 TR-GENSYM~9)) (MSETQ $EE TR-GENSYM~9)) ((MATCHERR)))
618 ; matchdeclare (ff, lambda ([x], x > 400));
619 ; :lisp (symbol-plist '$ff) => (MPROPS (NIL MATCHDECLARE (((LAMBDA) ((MLIST) $X) ((MGREATERP) $X 400)))))
620 ; tellsimpafter (fff(ff), ggg(ff));
621 ; getdec => (COND ((IS (MAPPLY1 '((LAMBDA) ((MLIST) $X) ((MGREATERP) $X 400)) (LIST TR-GENSYM~11) T NIL)) (MSETQ $FF TR-GENSYM~11)) ((MATCHERR)))
623 ; matchdeclare (gg, lambda ([y, x], x > y) (500));
624 ; :lisp (symbol-plist '$gg) => (MPROPS (NIL MATCHDECLARE (((MQAPPLY) ((LAMBDA) ((MLIST) $Y $X) ((MGREATERP) $X $Y)) 500))))
625 ; tellsimpafter (fg(gg), gg(gg));
626 ; getdec => (COND ((IS (MEVAL '((MQAPPLY) ((LAMBDA) ((MLIST) $Y $X) ((MGREATERP) $X $Y)) 500 TR-GENSYM~13))) (MSETQ $GG TR-GENSYM~13)) ((MATCHERR)))
628 ; pattern-variable is the pattern variable (as declared by matchdeclare)
629 ; match-against is the expression to match against
631 ; Return T if $MAYBE returns T, otherwise NIL.
632 ; That makes all non-T values (e.g. $UNKNOWN or noun expressions) act like NIL.
634 (defun definitely-so (e)
635 (eq (mfuncall '$maybe e
) t
))
637 (defun getdec (pattern-variable match-against
)
639 (if (setq p
(mget pattern-variable
'matchdeclare
))
640 ; P is (<foo>) where <foo> is the matchdeclare predicate
641 ; If <foo> is an atom, it is T or the name of a Lisp or Maxima function
642 ; Otherwise, <foo> is ((<op>) <args>)
644 ; If <foo> is $TRUE, T, or $ALL, generated code always assigns gensym value to pattern variable
645 (if (and (atom (car p
)) (member (car p
) '($true t $all
) :test
#'eq
))
646 `(msetq ,pattern-variable
,match-against
)
648 ; Otherwise, we have some work to do.
650 (let ((p-op (car p
)) (p-args) (test-expr))
653 ; P-OP is the name of a function. Try to generate a Lisp function call.
654 (if (and (fboundp p-op
) (not (get p-op
'translated
))) ; WHY THE TEST FOR TRANSLATED PROPERTY ??
655 `(eq t
(,p-op
,@(ncons match-against
)))
656 `(definitely-so '((,p-op
) ,@(ncons match-against
))))
658 ; Otherwise P-OP is something like ((<op>) <args>).
660 (setq p-args
(cdr p-op
))
662 ((eq (caar p-op
) 'lambda
)
663 `(definitely-so (mapply1 ',p-op
(list ,match-against
) t nil
)))
664 ((eq (caar p-op
) 'mqapply
)
665 `(definitely-so (meval ',(append p-op
(ncons match-against
)))))
666 ; Otherwise P-OP must be a function call with the last arg missing.
668 (if (and (consp (car p-op
)) (mget (caar p-op
) 'mmacro
))
669 `(definitely-so (cons ',(car p-op
) ,(append '(list) (mapcar 'memqargs p-args
) (ncons match-against
))))
670 `(definitely-so (cons ',(car p-op
) ',(append (mapcar 'memqargs p-args
) (ncons match-against
))))))))))
673 (,test-expr
(msetq ,pattern-variable
,match-against
))
676 (defun compilematch (e p
)
678 (cond ((fixedmatchp p
)
683 (list 'meval
(list 'quote
686 ((atom p
) (compileatom e p
))
687 ((eq (caar p
) 'mplus
) (compileplus e p
))
688 ((eq (caar p
) 'mtimes
) (compiletimes e p
))
689 (t (compileatom (list 'kaar e
)
694 (compileeach (car reflist
) (cdr p
))))
700 (setq topreflist
(cons a topreflist
))
701 (return (car (setq reflist
(cons a reflist
))))))
702 (defun compileeach (elist plist
)
703 (prog (reflist count
)
705 (setq reflist
(cons elist reflist
))
706 a
(setq count
(f1+ count
))
708 (return (emit (list 'cond
709 (list (list 'nthkdr elist
(f1- count
))
711 (emit (list 'setq
(genref) (list 'kar
(cadr reflist
))))
712 (compilematch (car reflist
) (car plist
))
713 (setq plist
(cdr plist
))
714 (setq reflist
(cons (list 'kdr
(cadr reflist
)) reflist
))
717 (defun fixedmatchp (x)
718 (cond ((numberp x
) t
)
720 (if (or (member x boundlist
:test
#'eq
) (null (mget x
'matchdeclare
))) t
))
721 (t (and (or (member (caar x
) boundlist
:test
#'eq
)
722 (null (mget (caar x
) 'matchdeclare
)))
726 (if (null x
) t
(and (fixedmatchp (car x
)) (fmp1 (cdr x
)))))