Mercurial > emacs
annotate lisp/calc/calc-rewr.el @ 46205:6676ac71682b
Update mouse button info.
Don't give the names of Emacs commands that the characters run.
Clarify what SPC and DEL do.
Clarify the description of the minibuffer.
Wording change for completion.
Explain Mouse-2 better.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sun, 07 Jul 2002 11:31:31 +0000 |
parents | 593f7009284d |
children | f4d68f97221e |
rev | line source |
---|---|
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
1 ;;; calc-rewr.el --- rewriting functions for Calc |
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
2 |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc. |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
4 |
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
5 ;; Author: David Gillespie <daveg@synaptics.com> |
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
6 ;; Maintainer: Colin Walters <walters@debian.org> |
40785 | 7 |
8 ;; This file is part of GNU Emacs. | |
9 | |
10 ;; GNU Emacs is distributed in the hope that it will be useful, | |
11 ;; but WITHOUT ANY WARRANTY. No author or distributor | |
12 ;; accepts responsibility to anyone for the consequences of using it | |
13 ;; or for whether it serves any particular purpose or works at all, | |
14 ;; unless he says so in writing. Refer to the GNU Emacs General Public | |
15 ;; License for full details. | |
16 | |
17 ;; Everyone is granted permission to copy, modify and redistribute | |
18 ;; GNU Emacs, but only under the conditions described in the | |
19 ;; GNU Emacs General Public License. A copy of this license is | |
20 ;; supposed to have been given to you along with GNU Emacs so you | |
21 ;; can know your rights and responsibilities. It should be in a | |
22 ;; file named COPYING. Among other things, the copyright notice | |
23 ;; and this notice must be preserved on all copies. | |
24 | |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
25 ;;; Commentary: |
40785 | 26 |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
27 ;;; Code: |
40785 | 28 |
29 ;; This file is autoloaded from calc-ext.el. | |
30 (require 'calc-ext) | |
31 | |
32 (require 'calc-macs) | |
33 | |
34 (defun calc-Need-calc-rewr () nil) | |
35 | |
36 | |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
37 (defvar math-rewrite-default-iters 100) |
40785 | 38 (defun calc-rewrite-selection (rules-str &optional many prefix) |
39 (interactive "sRewrite rule(s): \np") | |
40 (calc-slow-wrapper | |
41 (calc-preserve-point) | |
42 (let* ((num (max 1 (calc-locate-cursor-element (point)))) | |
43 (reselect t) | |
44 (pop-rules nil) | |
45 (entry (calc-top num 'entry)) | |
46 (expr (car entry)) | |
47 (sel (calc-auto-selection entry)) | |
48 (math-rewrite-selections t) | |
49 (math-rewrite-default-iters 1)) | |
50 (if (or (null rules-str) (equal rules-str "") (equal rules-str "$")) | |
51 (if (= num 1) | |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
52 (error "Can't use same stack entry for formula and rules") |
40785 | 53 (setq rules (calc-top-n 1 t) |
54 pop-rules t)) | |
55 (setq rules (if (stringp rules-str) | |
56 (math-read-exprs rules-str) rules-str)) | |
57 (if (eq (car-safe rules) 'error) | |
58 (error "Bad format in expression: %s" (nth 1 rules))) | |
59 (if (= (length rules) 1) | |
60 (setq rules (car rules)) | |
61 (setq rules (cons 'vec rules))) | |
62 (or (memq (car-safe rules) '(vec var calcFunc-assign | |
63 calcFunc-condition)) | |
64 (let ((rhs (math-read-expr | |
65 (read-string (concat "Rewrite from: " rules-str | |
66 " to: "))))) | |
67 (if (eq (car-safe rhs) 'error) | |
68 (error "Bad format in expression: %s" (nth 1 rhs))) | |
69 (setq rules (list 'calcFunc-assign rules rhs)))) | |
70 (or (eq (car-safe rules) 'var) | |
71 (calc-record rules "rule"))) | |
72 (if (eq many 0) | |
73 (setq many '(var inf var-inf)) | |
74 (if many (setq many (prefix-numeric-value many)))) | |
75 (if sel | |
76 (setq expr (calc-replace-sub-formula (car entry) | |
77 sel | |
78 (list 'calcFunc-select sel))) | |
79 (setq expr (car entry) | |
80 reselect nil | |
81 math-rewrite-selections nil)) | |
82 (setq expr (calc-encase-atoms | |
83 (calc-normalize | |
84 (math-rewrite | |
85 (calc-normalize expr) | |
86 rules many))) | |
87 sel nil | |
88 expr (calc-locate-select-marker expr)) | |
89 (or (consp sel) (setq sel nil)) | |
90 (if pop-rules (calc-pop-stack 1)) | |
91 (calc-pop-push-record-list 1 (or prefix "rwrt") (list expr) | |
92 (- num (if pop-rules 1 0)) | |
93 (list (and reselect sel)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
94 (calc-handle-whys))) |
40785 | 95 |
96 (defun calc-locate-select-marker (expr) ; changes "sel" | |
97 (if (Math-primp expr) | |
98 expr | |
99 (if (and (eq (car expr) 'calcFunc-select) | |
100 (= (length expr) 2)) | |
101 (progn | |
102 (setq sel (if sel t (nth 1 expr))) | |
103 (nth 1 expr)) | |
104 (cons (car expr) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
105 (mapcar 'calc-locate-select-marker (cdr expr)))))) |
40785 | 106 |
107 | |
108 | |
109 (defun calc-rewrite (rules-str many) | |
110 (interactive "sRewrite rule(s): \nP") | |
111 (calc-slow-wrapper | |
112 (let (n rules expr) | |
113 (if (or (null rules-str) (equal rules-str "") (equal rules-str "$")) | |
114 (setq expr (calc-top-n 2) | |
115 rules (calc-top-n 1 t) | |
116 n 2) | |
117 (setq rules (if (stringp rules-str) | |
118 (math-read-exprs rules-str) rules-str)) | |
119 (if (eq (car-safe rules) 'error) | |
120 (error "Bad format in expression: %s" (nth 1 rules))) | |
121 (if (= (length rules) 1) | |
122 (setq rules (car rules)) | |
123 (setq rules (cons 'vec rules))) | |
124 (or (memq (car-safe rules) '(vec var calcFunc-assign | |
125 calcFunc-condition)) | |
126 (let ((rhs (math-read-expr | |
127 (read-string (concat "Rewrite from: " rules-str | |
128 " to: "))))) | |
129 (if (eq (car-safe rhs) 'error) | |
130 (error "Bad format in expression: %s" (nth 1 rhs))) | |
131 (setq rules (list 'calcFunc-assign rules rhs)))) | |
132 (or (eq (car-safe rules) 'var) | |
133 (calc-record rules "rule")) | |
134 (setq expr (calc-top-n 1) | |
135 n 1)) | |
136 (if (eq many 0) | |
137 (setq many '(var inf var-inf)) | |
138 (if many (setq many (prefix-numeric-value many)))) | |
139 (setq expr (calc-normalize (math-rewrite expr rules many))) | |
140 (let (sel) | |
141 (setq expr (calc-locate-select-marker expr))) | |
142 (calc-pop-push-record-list n "rwrt" (list expr))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
143 (calc-handle-whys))) |
40785 | 144 |
145 (defun calc-match (pat) | |
146 (interactive "sPattern: \n") | |
147 (calc-slow-wrapper | |
148 (let (n expr) | |
149 (if (or (null pat) (equal pat "") (equal pat "$")) | |
150 (setq expr (calc-top-n 2) | |
151 pat (calc-top-n 1) | |
152 n 2) | |
153 (if (interactive-p) (setq calc-previous-alg-entry pat)) | |
154 (setq pat (if (stringp pat) (math-read-expr pat) pat)) | |
155 (if (eq (car-safe pat) 'error) | |
156 (error "Bad format in expression: %s" (nth 1 pat))) | |
157 (if (not (eq (car-safe pat) 'var)) | |
158 (calc-record pat "pat")) | |
159 (setq expr (calc-top-n 1) | |
160 n 1)) | |
161 (or (math-vectorp expr) (error "Argument must be a vector")) | |
162 (if (calc-is-inverse) | |
163 (calc-enter-result n "mtcn" (math-match-patterns pat expr t)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
164 (calc-enter-result n "mtch" (math-match-patterns pat expr nil)))))) |
40785 | 165 |
166 | |
167 | |
168 (defun math-rewrite (whole-expr rules &optional mmt-many) | |
169 (let ((crules (math-compile-rewrites rules)) | |
170 (heads (math-rewrite-heads whole-expr)) | |
171 (trace-buffer (get-buffer "*Trace*")) | |
172 (calc-display-just 'center) | |
173 (calc-display-origin 39) | |
174 (calc-line-breaking 78) | |
175 (calc-line-numbering nil) | |
176 (calc-show-selections t) | |
177 (calc-why nil) | |
178 (mmt-func (function | |
179 (lambda (x) | |
180 (let ((result (math-apply-rewrites x (cdr crules) | |
181 heads crules))) | |
182 (if result | |
183 (progn | |
184 (if trace-buffer | |
185 (let ((fmt (math-format-stack-value | |
186 (list result nil nil)))) | |
187 (save-excursion | |
188 (set-buffer trace-buffer) | |
189 (insert "\nrewrite to\n" fmt "\n")))) | |
190 (setq heads (math-rewrite-heads result heads t)))) | |
191 result))))) | |
192 (if trace-buffer | |
193 (let ((fmt (math-format-stack-value (list whole-expr nil nil)))) | |
194 (save-excursion | |
195 (set-buffer trace-buffer) | |
196 (setq truncate-lines t) | |
197 (goto-char (point-max)) | |
198 (insert "\n\nBegin rewriting\n" fmt "\n")))) | |
199 (or mmt-many (setq mmt-many (or (nth 1 (car crules)) | |
200 math-rewrite-default-iters))) | |
201 (if (equal mmt-many '(var inf var-inf)) (setq mmt-many 1000000)) | |
202 (if (equal mmt-many '(neg (var inf var-inf))) (setq mmt-many -1000000)) | |
203 (math-rewrite-phase (nth 3 (car crules))) | |
204 (if trace-buffer | |
205 (let ((fmt (math-format-stack-value (list whole-expr nil nil)))) | |
206 (save-excursion | |
207 (set-buffer trace-buffer) | |
208 (insert "\nDone rewriting" | |
209 (if (= mmt-many 0) " (reached iteration limit)" "") | |
210 ":\n" fmt "\n")))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
211 whole-expr)) |
40785 | 212 |
213 (defun math-rewrite-phase (sched) | |
214 (while (and sched (/= mmt-many 0)) | |
215 (if (listp (car sched)) | |
216 (while (let ((save-expr whole-expr)) | |
217 (math-rewrite-phase (car sched)) | |
218 (not (equal whole-expr save-expr)))) | |
219 (if (symbolp (car sched)) | |
220 (progn | |
221 (setq whole-expr (math-normalize (list (car sched) whole-expr))) | |
222 (if trace-buffer | |
223 (let ((fmt (math-format-stack-value | |
224 (list whole-expr nil nil)))) | |
225 (save-excursion | |
226 (set-buffer trace-buffer) | |
227 (insert "\ncall " | |
228 (substring (symbol-name (car sched)) 9) | |
229 ":\n" fmt "\n"))))) | |
230 (let ((math-rewrite-phase (car sched))) | |
231 (if trace-buffer | |
232 (save-excursion | |
233 (set-buffer trace-buffer) | |
234 (insert (format "\n(Phase %d)\n" math-rewrite-phase)))) | |
235 (while (let ((save-expr whole-expr)) | |
236 (setq whole-expr (math-normalize | |
237 (math-map-tree-rec whole-expr))) | |
238 (not (equal whole-expr save-expr))))))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
239 (setq sched (cdr sched)))) |
40785 | 240 |
241 (defun calcFunc-rewrite (expr rules &optional many) | |
242 (or (null many) (integerp many) | |
243 (equal many '(var inf var-inf)) (equal many '(neg (var inf var-inf))) | |
244 (math-reject-arg many 'fixnump)) | |
245 (condition-case err | |
246 (math-rewrite expr rules (or many 1)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
247 (error (math-reject-arg rules (nth 1 err))))) |
40785 | 248 |
249 (defun calcFunc-match (pat vec) | |
250 (or (math-vectorp vec) (math-reject-arg vec 'vectorp)) | |
251 (condition-case err | |
252 (math-match-patterns pat vec nil) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
253 (error (math-reject-arg pat (nth 1 err))))) |
40785 | 254 |
255 (defun calcFunc-matchnot (pat vec) | |
256 (or (math-vectorp vec) (math-reject-arg vec 'vectorp)) | |
257 (condition-case err | |
258 (math-match-patterns pat vec t) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
259 (error (math-reject-arg pat (nth 1 err))))) |
40785 | 260 |
261 (defun math-match-patterns (pat vec &optional not-flag) | |
262 (let ((newvec nil) | |
263 (crules (math-compile-patterns pat))) | |
264 (while (setq vec (cdr vec)) | |
265 (if (eq (not (math-apply-rewrites (car vec) crules)) | |
266 not-flag) | |
267 (setq newvec (cons (car vec) newvec)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
268 (cons 'vec (nreverse newvec)))) |
40785 | 269 |
270 (defun calcFunc-matches (expr pat) | |
271 (condition-case err | |
272 (if (math-apply-rewrites expr (math-compile-patterns pat)) | |
273 1 | |
274 0) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
275 (error (math-reject-arg pat (nth 1 err))))) |
40785 | 276 |
277 (defun calcFunc-vmatches (expr pat) | |
278 (condition-case err | |
279 (or (math-apply-rewrites expr (math-compile-patterns pat)) | |
280 0) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
281 (error (math-reject-arg pat (nth 1 err))))) |
40785 | 282 |
283 | |
284 | |
285 ;;; A compiled rule set is an a-list of entries whose cars are functors, | |
286 ;;; and whose cdrs are lists of rules. If there are rules with no | |
287 ;;; well-defined head functor, they are included on all lists and also | |
288 ;;; on an extra list whose car is nil. | |
289 ;;; | |
290 ;;; The first entry in the a-list is of the form (schedule A B C ...). | |
291 ;;; | |
292 ;;; Rule list entries take the form (regs prog head phases), where: | |
293 ;;; | |
294 ;;; regs is a vector of match registers. | |
295 ;;; | |
296 ;;; prog is a match program (see below). | |
297 ;;; | |
298 ;;; head is a rare function name appearing in the rule body (but not the | |
299 ;;; head of the whole rule), or nil if none. | |
300 ;;; | |
301 ;;; phases is a list of phase numbers for which the rule is enabled. | |
302 ;;; | |
303 ;;; A match program is a list of match instructions. | |
304 ;;; | |
305 ;;; In the following, "part" is a register number that contains the | |
306 ;;; subexpression to be operated on. | |
307 ;;; | |
308 ;;; Register 0 is the whole expression being matched. The others are | |
309 ;;; meta-variables in the pattern, temporaries used for matching and | |
310 ;;; backtracking, and constant expressions. | |
311 ;;; | |
312 ;;; (same part reg) | |
313 ;;; The selected part must be math-equal to the contents of "reg". | |
314 ;;; | |
315 ;;; (same-neg part reg) | |
316 ;;; The selected part must be math-equal to the negative of "reg". | |
317 ;;; | |
318 ;;; (copy part reg) | |
319 ;;; The selected part is copied into "reg". (Rarely used.) | |
320 ;;; | |
321 ;;; (copy-neg part reg) | |
322 ;;; The negative of the selected part is copied into "reg". | |
323 ;;; | |
324 ;;; (integer part) | |
325 ;;; The selected part must be an integer. | |
326 ;;; | |
327 ;;; (real part) | |
328 ;;; The selected part must be a real. | |
329 ;;; | |
330 ;;; (constant part) | |
331 ;;; The selected part must be a constant. | |
332 ;;; | |
333 ;;; (negative part) | |
334 ;;; The selected part must "look" negative. | |
335 ;;; | |
336 ;;; (rel part op reg) | |
337 ;;; The selected part must satisfy "part op reg", where "op" | |
338 ;;; is one of the 6 relational ops, and "reg" is a register. | |
339 ;;; | |
340 ;;; (mod part modulo value) | |
341 ;;; The selected part must satisfy "part % modulo = value", where | |
342 ;;; "modulo" and "value" are constants. | |
343 ;;; | |
344 ;;; (func part head reg1 reg2 ... regn) | |
345 ;;; The selected part must be an n-ary call to function "head". | |
346 ;;; The arguments are stored in "reg1" through "regn". | |
347 ;;; | |
348 ;;; (func-def part head defs reg1 reg2 ... regn) | |
349 ;;; The selected part must be an n-ary call to function "head". | |
350 ;;; "Defs" is a list of value/register number pairs for default args. | |
351 ;;; If a match, assign default values to registers and then skip | |
352 ;;; immediately over any following "func-def" instructions and | |
353 ;;; the following "func" instruction. If wrong number of arguments, | |
354 ;;; proceed to the following "func-def" or "func" instruction. | |
355 ;;; | |
356 ;;; (func-opt part head defs reg1) | |
357 ;;; Like func-def with "n=1", except that if the selected part is | |
358 ;;; not a call to "head", then the part itself successfully matches | |
359 ;;; "reg1" (and the defaults are assigned). | |
360 ;;; | |
361 ;;; (try part heads mark reg1 [def]) | |
362 ;;; The selected part must be a function of the correct type which is | |
363 ;;; associative and/or commutative. "Heads" is a list of acceptable | |
364 ;;; types. An initial assignment of arguments to "reg1" is tried. | |
365 ;;; If the program later fails, it backtracks to this instruction | |
366 ;;; and tries other assignments of arguments to "reg1". | |
367 ;;; If "def" exists and normal matching fails, backtrack and assign | |
368 ;;; "part" to "reg1", and "def" to "reg2" in the following "try2". | |
369 ;;; The "mark" is a vector of size 5; only "mark[3-4]" are initialized. | |
370 ;;; "mark[0]" points to the argument list; "mark[1]" points to the | |
371 ;;; current argument; "mark[2]" is 0 if there are two arguments, | |
372 ;;; 1 if reg1 is matching single arguments, 2 if reg2 is matching | |
373 ;;; single arguments (a+b+c+d is never split as (a+b)+(c+d)), or | |
374 ;;; 3 if reg2 is matching "def"; "mark[3]" is 0 if the function must | |
375 ;;; have two arguments, 1 if phase-2 can be skipped, 2 if full | |
376 ;;; backtracking is necessary; "mark[4]" is t if the arguments have | |
377 ;;; been switched from the order given in the original pattern. | |
378 ;;; | |
379 ;;; (try2 try reg2) | |
380 ;;; Every "try" will be followed by a "try2" whose "try" field is | |
381 ;;; a pointer to the corresponding "try". The arguments which were | |
382 ;;; not stored in "reg1" by that "try" are now stored in "reg2". | |
383 ;;; | |
384 ;;; (alt instr nil mark) | |
385 ;;; Basic backtracking. Execute the instruction sequence "instr". | |
386 ;;; If this fails, back up and execute following the "alt" instruction. | |
387 ;;; The "mark" must be the vector "[nil nil 4]". The "instr" sequence | |
388 ;;; should execute "end-alt" at the end. | |
389 ;;; | |
390 ;;; (end-alt ptr) | |
391 ;;; Register success of the first alternative of a previous "alt". | |
392 ;;; "Ptr" is a pointer to the next instruction following that "alt". | |
393 ;;; | |
394 ;;; (apply part reg1 reg2) | |
395 ;;; The selected part must be a function call. The functor | |
396 ;;; (as a variable name) is stored in "reg1"; the arguments | |
397 ;;; (as a vector) are stored in "reg2". | |
398 ;;; | |
399 ;;; (cons part reg1 reg2) | |
400 ;;; The selected part must be a nonempty vector. The first element | |
401 ;;; of the vector is stored in "reg1"; the rest of the vector | |
402 ;;; (as another vector) is stored in "reg2". | |
403 ;;; | |
404 ;;; (rcons part reg1 reg2) | |
405 ;;; The selected part must be a nonempty vector. The last element | |
406 ;;; of the vector is stored in "reg2"; the rest of the vector | |
407 ;;; (as another vector) is stored in "reg1". | |
408 ;;; | |
409 ;;; (select part reg) | |
410 ;;; If the selected part is a unary call to function "select", its | |
411 ;;; argument is stored in "reg"; otherwise (provided this is an `a r' | |
412 ;;; and not a `g r' command) the selected part is stored in "reg". | |
413 ;;; | |
414 ;;; (cond expr) | |
415 ;;; The "expr", with registers substituted, must simplify to | |
416 ;;; a non-zero value. | |
417 ;;; | |
418 ;;; (let reg expr) | |
419 ;;; Evaluate "expr" and store the result in "reg". Always succeeds. | |
420 ;;; | |
421 ;;; (done rhs remember) | |
422 ;;; Rewrite the expression to "rhs", with register substituted. | |
423 ;;; Normalize; if the result is different from the original | |
424 ;;; expression, the match has succeeded. This is the last | |
425 ;;; instruction of every program. If "remember" is non-nil, | |
426 ;;; record the result of the match as a new literal rule. | |
427 | |
428 | |
429 ;;; Pseudo-functions related to rewrites: | |
430 ;;; | |
431 ;;; In patterns: quote, plain, condition, opt, apply, cons, select | |
432 ;;; | |
433 ;;; In righthand sides: quote, plain, eval, evalsimp, evalextsimp, | |
434 ;;; apply, cons, select | |
435 ;;; | |
436 ;;; In conditions: let + same as for righthand sides | |
437 | |
438 ;;; Some optimizations that would be nice to have: | |
439 ;;; | |
440 ;;; * Merge registers with disjoint lifetimes. | |
441 ;;; * Merge constant registers with equivalent values. | |
442 ;;; | |
443 ;;; * If an argument of a commutative op math-depends neither on the | |
444 ;;; rest of the pattern nor on any of the conditions, then no backtracking | |
445 ;;; should be done for that argument. (This won't apply to very many | |
446 ;;; cases.) | |
447 ;;; | |
448 ;;; * If top functor is "select", and its argument is a unique function, | |
449 ;;; add the rule to the lists for both "select" and that function. | |
450 ;;; (Currently rules like this go on the "nil" list.) | |
451 ;;; Same for "func-opt" functions. (Though not urgent for these.) | |
452 ;;; | |
453 ;;; * Shouldn't evaluate a "let" condition until the end, or until it | |
454 ;;; would enable another condition to be evaluated. | |
455 ;;; | |
456 | |
457 ;;; Some additional features to add / things to think about: | |
458 ;;; | |
459 ;;; * Figure out what happens to "a +/- b" and "a +/- opt(b)". | |
460 ;;; | |
461 ;;; * Same for interval forms. | |
462 ;;; | |
463 ;;; * Have a name(v,pat) pattern which matches pat, and gives the | |
464 ;;; whole match the name v. Beware of circular structures! | |
465 ;;; | |
466 | |
467 (defun math-compile-patterns (pats) | |
468 (if (and (eq (car-safe pats) 'var) | |
469 (calc-var-value (nth 2 pats))) | |
470 (let ((prop (get (nth 2 pats) 'math-pattern-cache))) | |
471 (or prop | |
472 (put (nth 2 pats) 'math-pattern-cache (setq prop (list nil)))) | |
473 (or (eq (car prop) (symbol-value (nth 2 pats))) | |
474 (progn | |
475 (setcdr prop (math-compile-patterns | |
476 (symbol-value (nth 2 pats)))) | |
477 (setcar prop (symbol-value (nth 2 pats))))) | |
478 (cdr prop)) | |
479 (let ((math-rewrite-whole t)) | |
480 (cdr (math-compile-rewrites (cons | |
481 'vec | |
482 (mapcar (function (lambda (x) | |
483 (list 'vec x t))) | |
484 (if (eq (car-safe pats) 'vec) | |
485 (cdr pats) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
486 (list pats))))))))) |
40785 | 487 |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
488 (defvar math-rewrite-whole nil) |
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
489 (defvar math-make-import-list nil) |
40785 | 490 (defun math-compile-rewrites (rules &optional name) |
491 (if (eq (car-safe rules) 'var) | |
492 (let ((prop (get (nth 2 rules) 'math-rewrite-cache)) | |
493 (math-import-list nil) | |
494 (math-make-import-list t) | |
495 p) | |
496 (or (calc-var-value (nth 2 rules)) | |
497 (error "Rules variable %s has no stored value" (nth 1 rules))) | |
498 (or prop | |
499 (put (nth 2 rules) 'math-rewrite-cache | |
500 (setq prop (list (list (cons (nth 2 rules) nil)))))) | |
501 (setq p (car prop)) | |
502 (while (and p (eq (symbol-value (car (car p))) (cdr (car p)))) | |
503 (setq p (cdr p))) | |
504 (or (null p) | |
505 (progn | |
506 (message "Compiling rule set %s..." (nth 1 rules)) | |
507 (setcdr prop (math-compile-rewrites | |
508 (symbol-value (nth 2 rules)) | |
509 (nth 2 rules))) | |
510 (message "Compiling rule set %s...done" (nth 1 rules)) | |
511 (setcar prop (cons (cons (nth 2 rules) | |
512 (symbol-value (nth 2 rules))) | |
513 math-import-list)))) | |
514 (cdr prop)) | |
515 (if (or (not (eq (car-safe rules) 'vec)) | |
516 (and (memq (length rules) '(3 4)) | |
517 (let ((p rules)) | |
518 (while (and (setq p (cdr p)) | |
519 (memq (car-safe (car p)) | |
520 '(vec | |
521 calcFunc-assign | |
522 calcFunc-condition | |
523 calcFunc-import | |
524 calcFunc-phase | |
525 calcFunc-schedule | |
526 calcFunc-iterations)))) | |
527 p))) | |
528 (setq rules (list rules)) | |
529 (setq rules (cdr rules))) | |
530 (if (assq 'calcFunc-import rules) | |
531 (let ((pp (setq rules (copy-sequence rules))) | |
532 p part) | |
533 (while (setq p (car (cdr pp))) | |
534 (if (eq (car-safe p) 'calcFunc-import) | |
535 (progn | |
536 (setcdr pp (cdr (cdr pp))) | |
537 (or (and (eq (car-safe (nth 1 p)) 'var) | |
538 (setq part (calc-var-value (nth 2 (nth 1 p)))) | |
539 (memq (car-safe part) '(vec | |
540 calcFunc-assign | |
541 calcFunc-condition))) | |
542 (error "Argument of import() must be a rules variable")) | |
543 (if math-make-import-list | |
544 (setq math-import-list | |
545 (cons (cons (nth 2 (nth 1 p)) | |
546 (symbol-value (nth 2 (nth 1 p)))) | |
547 math-import-list))) | |
548 (while (setq p (cdr (cdr p))) | |
549 (or (cdr p) | |
550 (error "import() must have odd number of arguments")) | |
551 (setq part (math-rwcomp-substitute part | |
552 (car p) (nth 1 p)))) | |
553 (if (eq (car-safe part) 'vec) | |
554 (setq part (cdr part)) | |
555 (setq part (list part))) | |
556 (setcdr pp (append part (cdr pp)))) | |
557 (setq pp (cdr pp)))))) | |
558 (let ((rule-set nil) | |
559 (all-heads nil) | |
560 (nil-rules nil) | |
561 (rule-count 0) | |
562 (math-schedule nil) | |
563 (math-iterations nil) | |
564 (math-phases nil) | |
565 (math-all-phases nil) | |
566 (math-remembering nil) | |
567 math-pattern math-rhs math-conds) | |
568 (while rules | |
569 (cond | |
570 ((and (eq (car-safe (car rules)) 'calcFunc-iterations) | |
571 (= (length (car rules)) 2)) | |
572 (or (integerp (nth 1 (car rules))) | |
573 (equal (nth 1 (car rules)) '(var inf var-inf)) | |
574 (equal (nth 1 (car rules)) '(neg (var inf var-inf))) | |
575 (error "Invalid argument for iterations(n)")) | |
576 (or math-iterations | |
577 (setq math-iterations (nth 1 (car rules))))) | |
578 ((eq (car-safe (car rules)) 'calcFunc-schedule) | |
579 (or math-schedule | |
580 (setq math-schedule (math-parse-schedule (cdr (car rules)))))) | |
581 ((eq (car-safe (car rules)) 'calcFunc-phase) | |
582 (setq math-phases (cdr (car rules))) | |
583 (if (equal math-phases '((var all var-all))) | |
584 (setq math-phases nil)) | |
585 (let ((p math-phases)) | |
586 (while p | |
587 (or (integerp (car p)) | |
588 (error "Phase numbers must be small integers")) | |
589 (or (memq (car p) math-all-phases) | |
590 (setq math-all-phases (cons (car p) math-all-phases))) | |
591 (setq p (cdr p))))) | |
592 ((or (and (eq (car-safe (car rules)) 'vec) | |
593 (cdr (cdr (car rules))) | |
594 (not (nthcdr 4 (car rules))) | |
595 (setq math-conds (nth 3 (car rules)) | |
596 math-rhs (nth 2 (car rules)) | |
597 math-pattern (nth 1 (car rules)))) | |
598 (progn | |
599 (setq math-conds nil | |
600 math-pattern (car rules)) | |
601 (while (and (eq (car-safe math-pattern) 'calcFunc-condition) | |
602 (= (length math-pattern) 3)) | |
603 (let ((cond (nth 2 math-pattern))) | |
604 (setq math-conds (if math-conds | |
605 (list 'calcFunc-land math-conds cond) | |
606 cond) | |
607 math-pattern (nth 1 math-pattern)))) | |
608 (and (eq (car-safe math-pattern) 'calcFunc-assign) | |
609 (= (length math-pattern) 3) | |
610 (setq math-rhs (nth 2 math-pattern) | |
611 math-pattern (nth 1 math-pattern))))) | |
612 (let* ((math-prog (list nil)) | |
613 (math-prog-last math-prog) | |
614 (math-num-regs 1) | |
615 (math-regs (list (list nil 0 nil nil))) | |
616 (math-bound-vars nil) | |
617 (math-aliased-vars nil) | |
618 (math-copy-neg nil)) | |
619 (setq math-conds (and math-conds (math-flatten-lands math-conds))) | |
620 (math-rwcomp-pattern math-pattern 0) | |
621 (while math-conds | |
622 (let ((expr (car math-conds))) | |
623 (setq math-conds (cdr math-conds)) | |
624 (math-rwcomp-cond-instr expr))) | |
625 (math-rwcomp-instr 'done | |
626 (if (eq math-rhs t) | |
627 (cons 'vec | |
628 (delq | |
629 nil | |
630 (nreverse | |
631 (mapcar | |
632 (function | |
633 (lambda (v) | |
634 (and (car v) | |
635 (list | |
636 'calcFunc-assign | |
637 (math-build-var-name | |
638 (car v)) | |
639 (math-rwcomp-register-expr | |
640 (nth 1 v)))))) | |
641 math-regs)))) | |
642 (math-rwcomp-match-vars math-rhs)) | |
643 math-remembering) | |
644 (setq math-prog (cdr math-prog)) | |
645 (let* ((heads (math-rewrite-heads math-pattern)) | |
646 (rule (list (vconcat | |
647 (nreverse | |
648 (mapcar (function (lambda (x) (nth 3 x))) | |
649 math-regs))) | |
650 math-prog | |
651 heads | |
652 math-phases)) | |
653 (head (and (not (Math-primp math-pattern)) | |
654 (not (and (eq (car (car math-prog)) 'try) | |
655 (nth 5 (car math-prog)))) | |
656 (not (memq (car (car math-prog)) '(func-opt | |
657 apply | |
658 select | |
659 alt))) | |
660 (if (memq (car (car math-prog)) '(func | |
661 func-def)) | |
662 (nth 2 (car math-prog)) | |
663 (if (eq (car math-pattern) 'calcFunc-quote) | |
664 (car-safe (nth 1 math-pattern)) | |
665 (car math-pattern)))))) | |
666 (let (found) | |
667 (while heads | |
668 (if (setq found (assq (car heads) all-heads)) | |
669 (setcdr found (1+ (cdr found))) | |
670 (setq all-heads (cons (cons (car heads) 1) all-heads))) | |
671 (setq heads (cdr heads)))) | |
672 (if (eq head '-) (setq head '+)) | |
673 (if (memq head '(calcFunc-cons calcFunc-rcons)) (setq head 'vec)) | |
674 (if head | |
675 (progn | |
676 (nconc (or (assq head rule-set) | |
677 (car (setq rule-set (cons (cons head | |
678 (copy-sequence | |
679 nil-rules)) | |
680 rule-set)))) | |
681 (list rule)) | |
682 (if (eq head '*) | |
683 (nconc (or (assq '/ rule-set) | |
684 (car (setq rule-set (cons (cons | |
685 '/ | |
686 (copy-sequence | |
687 nil-rules)) | |
688 rule-set)))) | |
689 (list rule)))) | |
690 (setq nil-rules (nconc nil-rules (list rule))) | |
691 (let ((ptr rule-set)) | |
692 (while ptr | |
693 (nconc (car ptr) (list rule)) | |
694 (setq ptr (cdr ptr)))))))) | |
695 (t | |
696 (error "Rewrite rule set must be a vector of A := B rules"))) | |
697 (setq rules (cdr rules))) | |
698 (if nil-rules | |
699 (setq rule-set (cons (cons nil nil-rules) rule-set))) | |
700 (setq all-heads (mapcar 'car | |
701 (sort all-heads (function | |
702 (lambda (x y) | |
703 (< (cdr x) (cdr y))))))) | |
704 (let ((set rule-set) | |
705 rule heads ptr) | |
706 (while set | |
707 (setq rule (cdr (car set))) | |
708 (while rule | |
709 (if (consp (setq heads (nth 2 (car rule)))) | |
710 (progn | |
711 (setq heads (delq (car (car set)) heads) | |
712 ptr all-heads) | |
713 (while (and ptr (not (memq (car ptr) heads))) | |
714 (setq ptr (cdr ptr))) | |
715 (setcar (nthcdr 2 (car rule)) (car ptr)))) | |
716 (setq rule (cdr rule))) | |
717 (setq set (cdr set)))) | |
718 (let ((plus (assq '+ rule-set))) | |
719 (if plus | |
720 (setq rule-set (cons (cons '- (cdr plus)) rule-set)))) | |
721 (cons (list 'schedule math-iterations name | |
722 (or math-schedule | |
723 (sort math-all-phases '<) | |
724 (list 1))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
725 rule-set)))) |
40785 | 726 |
727 (defun math-flatten-lands (expr) | |
728 (if (eq (car-safe expr) 'calcFunc-land) | |
729 (append (math-flatten-lands (nth 1 expr)) | |
730 (math-flatten-lands (nth 2 expr))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
731 (list expr))) |
40785 | 732 |
733 (defun math-rewrite-heads (expr &optional more all) | |
734 (let ((heads more) | |
735 (skips (and (not all) | |
736 '(calcFunc-apply calcFunc-condition calcFunc-opt | |
737 calcFunc-por calcFunc-pnot))) | |
738 (blanks (and (not all) | |
739 '(calcFunc-quote calcFunc-plain calcFunc-select | |
740 calcFunc-cons calcFunc-rcons | |
741 calcFunc-pand)))) | |
742 (or (Math-primp expr) | |
743 (math-rewrite-heads-rec expr)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
744 heads)) |
40785 | 745 |
746 (defun math-rewrite-heads-rec (expr) | |
747 (or (memq (car expr) skips) | |
748 (progn | |
749 (or (memq (car expr) heads) | |
750 (memq (car expr) blanks) | |
751 (memq 'algebraic (get (car expr) 'math-rewrite-props)) | |
752 (setq heads (cons (car expr) heads))) | |
753 (while (setq expr (cdr expr)) | |
754 (or (Math-primp (car expr)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
755 (math-rewrite-heads-rec (car expr))))))) |
40785 | 756 |
757 (defun math-parse-schedule (sched) | |
758 (mapcar (function | |
759 (lambda (s) | |
760 (if (integerp s) | |
761 s | |
762 (if (math-vectorp s) | |
763 (math-parse-schedule (cdr s)) | |
764 (if (eq (car-safe s) 'var) | |
765 (math-var-to-calcFunc s) | |
766 (error "Improper component in rewrite schedule")))))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
767 sched)) |
40785 | 768 |
769 (defun math-rwcomp-match-vars (expr) | |
770 (if (Math-primp expr) | |
771 (if (eq (car-safe expr) 'var) | |
772 (let ((entry (assq (nth 2 expr) math-regs))) | |
773 (if entry | |
774 (math-rwcomp-register-expr (nth 1 entry)) | |
775 expr)) | |
776 expr) | |
777 (if (and (eq (car expr) 'calcFunc-quote) | |
778 (= (length expr) 2)) | |
779 (math-rwcomp-match-vars (nth 1 expr)) | |
780 (if (and (eq (car expr) 'calcFunc-plain) | |
781 (= (length expr) 2) | |
782 (not (Math-primp (nth 1 expr)))) | |
783 (list (car expr) | |
784 (cons (car (nth 1 expr)) | |
785 (mapcar 'math-rwcomp-match-vars (cdr (nth 1 expr))))) | |
786 (cons (car expr) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
787 (mapcar 'math-rwcomp-match-vars (cdr expr))))))) |
40785 | 788 |
789 (defun math-rwcomp-register-expr (num) | |
790 (let ((entry (nth (1- (- math-num-regs num)) math-regs))) | |
791 (if (nth 2 entry) | |
792 (list 'neg (list 'calcFunc-register (nth 1 entry))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
793 (list 'calcFunc-register (nth 1 entry))))) |
40785 | 794 |
795 (defun math-rwcomp-substitute (expr old new) | |
796 (if (and (eq (car-safe old) 'var) | |
797 (memq (car-safe new) '(var calcFunc-lambda))) | |
798 (let ((old-func (math-var-to-calcFunc old)) | |
799 (new-func (math-var-to-calcFunc new))) | |
800 (math-rwcomp-subst-rec expr)) | |
801 (let ((old-func nil)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
802 (math-rwcomp-subst-rec expr)))) |
40785 | 803 |
804 (defun math-rwcomp-subst-rec (expr) | |
805 (cond ((equal expr old) new) | |
806 ((Math-primp expr) expr) | |
807 (t (if (eq (car expr) old-func) | |
808 (math-build-call new-func (mapcar 'math-rwcomp-subst-rec | |
809 (cdr expr))) | |
810 (cons (car expr) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
811 (mapcar 'math-rwcomp-subst-rec (cdr expr))))))) |
40785 | 812 |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
813 (defvar math-rwcomp-tracing nil) |
40785 | 814 |
815 (defun math-rwcomp-trace (instr) | |
41271
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
816 (when math-rwcomp-tracing |
fcd507927105
Change all toplevel `setq' forms to `defvar' forms, and move them
Colin Walters <walters@gnu.org>
parents:
41047
diff
changeset
|
817 (terpri) (princ instr)) |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
818 instr) |
40785 | 819 |
820 (defun math-rwcomp-instr (&rest instr) | |
821 (setcdr math-prog-last | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
822 (setq math-prog-last (list (math-rwcomp-trace instr))))) |
40785 | 823 |
824 (defun math-rwcomp-multi-instr (tail &rest instr) | |
825 (setcdr math-prog-last | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
826 (setq math-prog-last (list (math-rwcomp-trace (append instr tail)))))) |
40785 | 827 |
828 (defun math-rwcomp-bind-var (reg var) | |
829 (setcar (math-rwcomp-reg-entry reg) (nth 2 var)) | |
830 (setq math-bound-vars (cons (nth 2 var) math-bound-vars)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
831 (math-rwcomp-do-conditions)) |
40785 | 832 |
833 (defun math-rwcomp-unbind-vars (mark) | |
834 (while (not (eq math-bound-vars mark)) | |
835 (setcar (assq (car math-bound-vars) math-regs) nil) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
836 (setq math-bound-vars (cdr math-bound-vars)))) |
40785 | 837 |
838 (defun math-rwcomp-do-conditions () | |
839 (let ((cond math-conds)) | |
840 (while cond | |
841 (if (math-rwcomp-all-regs-done (car cond)) | |
842 (let ((expr (car cond))) | |
843 (setq math-conds (delq (car cond) math-conds)) | |
844 (setcar cond 1) | |
845 (math-rwcomp-cond-instr expr))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
846 (setq cond (cdr cond))))) |
40785 | 847 |
848 (defun math-rwcomp-cond-instr (expr) | |
849 (let (op arg) | |
850 (cond ((and (eq (car-safe expr) 'calcFunc-matches) | |
851 (= (length expr) 3) | |
852 (eq (car-safe (setq arg (math-rwcomp-match-vars (nth 1 expr)))) | |
853 'calcFunc-register)) | |
854 (math-rwcomp-pattern (nth 2 expr) (nth 1 arg))) | |
855 ((math-numberp (setq expr (math-rwcomp-match-vars expr))) | |
856 (if (Math-zerop expr) | |
857 (math-rwcomp-instr 'backtrack))) | |
858 ((and (eq (car expr) 'calcFunc-let) | |
859 (= (length expr) 3)) | |
860 (let ((reg (math-rwcomp-reg))) | |
861 (math-rwcomp-instr 'let reg (nth 2 expr)) | |
862 (math-rwcomp-pattern (nth 1 expr) reg))) | |
863 ((and (eq (car expr) 'calcFunc-let) | |
864 (= (length expr) 2) | |
865 (eq (car-safe (nth 1 expr)) 'calcFunc-assign) | |
866 (= (length (nth 1 expr)) 3)) | |
867 (let ((reg (math-rwcomp-reg))) | |
868 (math-rwcomp-instr 'let reg (nth 2 (nth 1 expr))) | |
869 (math-rwcomp-pattern (nth 1 (nth 1 expr)) reg))) | |
870 ((and (setq op (cdr (assq (car-safe expr) | |
871 '( (calcFunc-integer . integer) | |
872 (calcFunc-real . real) | |
873 (calcFunc-constant . constant) | |
874 (calcFunc-negative . negative) )))) | |
875 (= (length expr) 2) | |
876 (or (and (eq (car-safe (nth 1 expr)) 'neg) | |
877 (memq op '(integer real constant)) | |
878 (setq arg (nth 1 (nth 1 expr)))) | |
879 (setq arg (nth 1 expr))) | |
880 (eq (car-safe (setq arg (nth 1 expr))) 'calcFunc-register)) | |
881 (math-rwcomp-instr op (nth 1 arg))) | |
882 ((and (assq (car-safe expr) calc-tweak-eqn-table) | |
883 (= (length expr) 3) | |
884 (eq (car-safe (nth 1 expr)) 'calcFunc-register)) | |
885 (if (math-constp (nth 2 expr)) | |
886 (let ((reg (math-rwcomp-reg))) | |
887 (setcar (nthcdr 3 (car math-regs)) (nth 2 expr)) | |
888 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr)) | |
889 (car expr) reg)) | |
890 (if (eq (car (nth 2 expr)) 'calcFunc-register) | |
891 (math-rwcomp-instr 'rel (nth 1 (nth 1 expr)) | |
892 (car expr) (nth 1 (nth 2 expr))) | |
893 (math-rwcomp-instr 'cond expr)))) | |
894 ((and (eq (car-safe expr) 'calcFunc-eq) | |
895 (= (length expr) 3) | |
896 (eq (car-safe (nth 1 expr)) '%) | |
897 (eq (car-safe (nth 1 (nth 1 expr))) 'calcFunc-register) | |
898 (math-constp (nth 2 (nth 1 expr))) | |
899 (math-constp (nth 2 expr))) | |
900 (math-rwcomp-instr 'mod (nth 1 (nth 1 (nth 1 expr))) | |
901 (nth 2 (nth 1 expr)) (nth 2 expr))) | |
902 ((equal expr '(var remember var-remember)) | |
903 (setq math-remembering 1)) | |
904 ((and (eq (car-safe expr) 'calcFunc-remember) | |
905 (= (length expr) 2)) | |
906 (setq math-remembering (if math-remembering | |
907 (list 'calcFunc-lor | |
908 math-remembering (nth 1 expr)) | |
909 (nth 1 expr)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
910 (t (math-rwcomp-instr 'cond expr))))) |
40785 | 911 |
912 (defun math-rwcomp-same-instr (reg1 reg2 neg) | |
913 (math-rwcomp-instr (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1)) | |
914 (nth 2 (math-rwcomp-reg-entry reg2))) | |
915 neg) | |
916 'same-neg | |
917 'same) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
918 reg1 reg2)) |
40785 | 919 |
920 (defun math-rwcomp-copy-instr (reg1 reg2 neg) | |
921 (if (eq (eq (nth 2 (math-rwcomp-reg-entry reg1)) | |
922 (nth 2 (math-rwcomp-reg-entry reg2))) | |
923 neg) | |
924 (math-rwcomp-instr 'copy-neg reg1 reg2) | |
925 (or (eq reg1 reg2) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
926 (math-rwcomp-instr 'copy reg1 reg2)))) |
40785 | 927 |
928 (defun math-rwcomp-reg () | |
929 (prog1 | |
930 math-num-regs | |
931 (setq math-regs (cons (list nil math-num-regs nil 0) math-regs) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
932 math-num-regs (1+ math-num-regs)))) |
40785 | 933 |
934 (defun math-rwcomp-reg-entry (num) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
935 (nth (1- (- math-num-regs num)) math-regs)) |
40785 | 936 |
937 | |
938 (defun math-rwcomp-pattern (expr part &optional not-direct) | |
939 (cond ((or (math-rwcomp-no-vars expr) | |
940 (and (eq (car expr) 'calcFunc-quote) | |
941 (= (length expr) 2) | |
942 (setq expr (nth 1 expr)))) | |
943 (if (eq (car-safe expr) 'calcFunc-register) | |
944 (math-rwcomp-same-instr part (nth 1 expr) nil) | |
945 (let ((reg (math-rwcomp-reg))) | |
946 (setcar (nthcdr 3 (car math-regs)) expr) | |
947 (math-rwcomp-same-instr part reg nil)))) | |
948 ((eq (car expr) 'var) | |
949 (let ((entry (assq (nth 2 expr) math-regs))) | |
950 (if entry | |
951 (math-rwcomp-same-instr part (nth 1 entry) nil) | |
952 (if not-direct | |
953 (let ((reg (math-rwcomp-reg))) | |
954 (math-rwcomp-pattern expr reg) | |
955 (math-rwcomp-copy-instr part reg nil)) | |
956 (if (setq entry (assq (nth 2 expr) math-aliased-vars)) | |
957 (progn | |
958 (setcar (math-rwcomp-reg-entry (nth 1 entry)) | |
959 (nth 2 expr)) | |
960 (setcar entry nil) | |
961 (math-rwcomp-copy-instr part (nth 1 entry) nil)) | |
962 (math-rwcomp-bind-var part expr)))))) | |
963 ((and (eq (car expr) 'calcFunc-select) | |
964 (= (length expr) 2)) | |
965 (let ((reg (math-rwcomp-reg))) | |
966 (math-rwcomp-instr 'select part reg) | |
967 (math-rwcomp-pattern (nth 1 expr) reg))) | |
968 ((and (eq (car expr) 'calcFunc-opt) | |
969 (memq (length expr) '(2 3))) | |
970 (error "opt( ) occurs in context where it is not allowed")) | |
971 ((eq (car expr) 'neg) | |
972 (if (eq (car (nth 1 expr)) 'var) | |
973 (let ((entry (assq (nth 2 (nth 1 expr)) math-regs))) | |
974 (if entry | |
975 (math-rwcomp-same-instr part (nth 1 entry) t) | |
976 (if math-copy-neg | |
977 (let ((reg (math-rwcomp-best-reg (nth 1 expr)))) | |
978 (math-rwcomp-copy-instr part reg t) | |
979 (math-rwcomp-pattern (nth 1 expr) reg)) | |
980 (setcar (cdr (cdr (math-rwcomp-reg-entry part))) t) | |
981 (math-rwcomp-pattern (nth 1 expr) part)))) | |
982 (if (math-rwcomp-is-algebraic (nth 1 expr)) | |
983 (math-rwcomp-cond-instr (list 'calcFunc-eq | |
984 (math-rwcomp-register-expr part) | |
985 expr)) | |
986 (let ((reg (math-rwcomp-reg))) | |
987 (math-rwcomp-instr 'func part 'neg reg) | |
988 (math-rwcomp-pattern (nth 1 expr) reg))))) | |
989 ((and (eq (car expr) 'calcFunc-apply) | |
990 (= (length expr) 3)) | |
991 (let ((reg1 (math-rwcomp-reg)) | |
992 (reg2 (math-rwcomp-reg))) | |
993 (math-rwcomp-instr 'apply part reg1 reg2) | |
994 (math-rwcomp-pattern (nth 1 expr) reg1) | |
995 (math-rwcomp-pattern (nth 2 expr) reg2))) | |
996 ((and (eq (car expr) 'calcFunc-cons) | |
997 (= (length expr) 3)) | |
998 (let ((reg1 (math-rwcomp-reg)) | |
999 (reg2 (math-rwcomp-reg))) | |
1000 (math-rwcomp-instr 'cons part reg1 reg2) | |
1001 (math-rwcomp-pattern (nth 1 expr) reg1) | |
1002 (math-rwcomp-pattern (nth 2 expr) reg2))) | |
1003 ((and (eq (car expr) 'calcFunc-rcons) | |
1004 (= (length expr) 3)) | |
1005 (let ((reg1 (math-rwcomp-reg)) | |
1006 (reg2 (math-rwcomp-reg))) | |
1007 (math-rwcomp-instr 'rcons part reg1 reg2) | |
1008 (math-rwcomp-pattern (nth 1 expr) reg1) | |
1009 (math-rwcomp-pattern (nth 2 expr) reg2))) | |
1010 ((and (eq (car expr) 'calcFunc-condition) | |
1011 (>= (length expr) 3)) | |
1012 (math-rwcomp-pattern (nth 1 expr) part) | |
1013 (setq expr (cdr expr)) | |
1014 (while (setq expr (cdr expr)) | |
1015 (let ((cond (math-flatten-lands (car expr)))) | |
1016 (while cond | |
1017 (if (math-rwcomp-all-regs-done (car cond)) | |
1018 (math-rwcomp-cond-instr (car cond)) | |
1019 (setq math-conds (cons (car cond) math-conds))) | |
1020 (setq cond (cdr cond)))))) | |
1021 ((and (eq (car expr) 'calcFunc-pand) | |
1022 (= (length expr) 3)) | |
1023 (math-rwcomp-pattern (nth 1 expr) part) | |
1024 (math-rwcomp-pattern (nth 2 expr) part)) | |
1025 ((and (eq (car expr) 'calcFunc-por) | |
1026 (= (length expr) 3)) | |
1027 (math-rwcomp-instr 'alt nil nil [nil nil 4]) | |
1028 (let ((math-conds nil) | |
1029 (head math-prog-last) | |
1030 (mark math-bound-vars) | |
1031 (math-copy-neg t)) | |
1032 (math-rwcomp-pattern (nth 1 expr) part t) | |
1033 (let ((amark math-aliased-vars) | |
1034 (math-aliased-vars math-aliased-vars) | |
1035 (tail math-prog-last) | |
1036 (p math-bound-vars) | |
1037 entry) | |
1038 (while (not (eq p mark)) | |
1039 (setq entry (assq (car p) math-regs) | |
1040 math-aliased-vars (cons (list (car p) (nth 1 entry) nil) | |
1041 math-aliased-vars) | |
1042 p (cdr p)) | |
1043 (setcar (math-rwcomp-reg-entry (nth 1 entry)) nil)) | |
1044 (setcar (cdr (car head)) (cdr head)) | |
1045 (setcdr head nil) | |
1046 (setq math-prog-last head) | |
1047 (math-rwcomp-pattern (nth 2 expr) part) | |
1048 (math-rwcomp-instr 'same 0 0) | |
1049 (setcdr tail math-prog-last) | |
1050 (setq p math-aliased-vars) | |
1051 (while (not (eq p amark)) | |
1052 (if (car (car p)) | |
1053 (setcar (math-rwcomp-reg-entry (nth 1 (car p))) | |
1054 (car (car p)))) | |
1055 (setq p (cdr p))))) | |
1056 (math-rwcomp-do-conditions)) | |
1057 ((and (eq (car expr) 'calcFunc-pnot) | |
1058 (= (length expr) 2)) | |
1059 (math-rwcomp-instr 'alt nil nil [nil nil 4]) | |
1060 (let ((head math-prog-last) | |
1061 (mark math-bound-vars)) | |
1062 (math-rwcomp-pattern (nth 1 expr) part) | |
1063 (math-rwcomp-unbind-vars mark) | |
1064 (math-rwcomp-instr 'end-alt head) | |
1065 (math-rwcomp-instr 'backtrack) | |
1066 (setcar (cdr (car head)) (cdr head)) | |
1067 (setcdr head nil) | |
1068 (setq math-prog-last head))) | |
1069 (t (let ((props (get (car expr) 'math-rewrite-props))) | |
1070 (if (and (eq (car expr) 'calcFunc-plain) | |
1071 (= (length expr) 2) | |
1072 (not (math-primp (nth 1 expr)))) | |
1073 (setq expr (nth 1 expr))) ; but "props" is still nil | |
1074 (if (and (memq 'algebraic props) | |
1075 (math-rwcomp-is-algebraic expr)) | |
1076 (math-rwcomp-cond-instr (list 'calcFunc-eq | |
1077 (math-rwcomp-register-expr part) | |
1078 expr)) | |
1079 (if (and (memq 'commut props) | |
1080 (= (length expr) 3)) | |
1081 (let ((arg1 (nth 1 expr)) | |
1082 (arg2 (nth 2 expr)) | |
1083 try1 def code head (flip nil)) | |
1084 (if (eq (car expr) '-) | |
1085 (setq arg2 (math-rwcomp-neg arg2))) | |
1086 (setq arg1 (cons arg1 (math-rwcomp-best-reg arg1)) | |
1087 arg2 (cons arg2 (math-rwcomp-best-reg arg2))) | |
1088 (or (math-rwcomp-order arg1 arg2) | |
1089 (setq def arg1 arg1 arg2 arg2 def flip t)) | |
1090 (if (math-rwcomp-optional-arg (car expr) arg1) | |
1091 (error "Too many opt( ) arguments in this context")) | |
1092 (setq def (math-rwcomp-optional-arg (car expr) arg2) | |
1093 head (if (memq (car expr) '(+ -)) | |
1094 '(+ -) | |
1095 (if (eq (car expr) '*) | |
1096 '(* /) | |
1097 (list (car expr)))) | |
1098 code (if (math-rwcomp-is-constrained | |
1099 (car arg1) head) | |
1100 (if (math-rwcomp-is-constrained | |
1101 (car arg2) head) | |
1102 0 1) | |
1103 2)) | |
1104 (math-rwcomp-multi-instr (and def (list def)) | |
1105 'try part head | |
1106 (vector nil nil nil code flip) | |
1107 (cdr arg1)) | |
1108 (setq try1 (car math-prog-last)) | |
1109 (math-rwcomp-pattern (car arg1) (cdr arg1)) | |
1110 (math-rwcomp-instr 'try2 try1 (cdr arg2)) | |
1111 (if (and (= part 0) (not def) (not math-rewrite-whole) | |
1112 (not (eq math-rhs t)) | |
1113 (setq def (get (car expr) | |
1114 'math-rewrite-default))) | |
1115 (let ((reg1 (math-rwcomp-reg)) | |
1116 (reg2 (math-rwcomp-reg))) | |
1117 (if (= (aref (nth 3 try1) 3) 0) | |
1118 (aset (nth 3 try1) 3 1)) | |
1119 (math-rwcomp-instr 'try (cdr arg2) | |
1120 (if (equal head '(* /)) | |
1121 '(*) head) | |
1122 (vector nil nil nil | |
1123 (if (= code 0) | |
1124 1 2) | |
1125 nil) | |
1126 reg1 def) | |
1127 (setq try1 (car math-prog-last)) | |
1128 (math-rwcomp-pattern (car arg2) reg1) | |
1129 (math-rwcomp-instr 'try2 try1 reg2) | |
1130 (setq math-rhs (list (if (eq (car expr) '-) | |
1131 '+ (car expr)) | |
1132 math-rhs | |
1133 (list 'calcFunc-register | |
1134 reg2)))) | |
1135 (math-rwcomp-pattern (car arg2) (cdr arg2)))) | |
1136 (let* ((args (mapcar (function | |
1137 (lambda (x) | |
1138 (cons x (math-rwcomp-best-reg x)))) | |
1139 (cdr expr))) | |
1140 (args2 (copy-sequence args)) | |
1141 (argp (reverse args2)) | |
1142 (defs nil) | |
1143 (num 1)) | |
1144 (while argp | |
1145 (let ((def (math-rwcomp-optional-arg (car expr) | |
1146 (car argp)))) | |
1147 (if def | |
1148 (progn | |
1149 (setq args2 (delq (car argp) args2) | |
1150 defs (cons (cons def (cdr (car argp))) | |
1151 defs)) | |
1152 (math-rwcomp-multi-instr | |
1153 (mapcar 'cdr args2) | |
1154 (if (or (and (memq 'unary1 props) | |
1155 (= (length args2) 1) | |
1156 (eq (car args2) (car args))) | |
1157 (and (memq 'unary2 props) | |
1158 (= (length args) 2) | |
1159 (eq (car args2) (nth 1 args)))) | |
1160 'func-opt | |
1161 'func-def) | |
1162 part (car expr) | |
1163 defs)))) | |
1164 (setq argp (cdr argp))) | |
1165 (math-rwcomp-multi-instr (mapcar 'cdr args) | |
1166 'func part (car expr)) | |
1167 (setq args (sort args 'math-rwcomp-order)) | |
1168 (while args | |
1169 (math-rwcomp-pattern (car (car args)) (cdr (car args))) | |
1170 (setq num (1+ num) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1171 args (cdr args)))))))))) |
40785 | 1172 |
1173 (defun math-rwcomp-best-reg (x) | |
1174 (or (and (eq (car-safe x) 'var) | |
1175 (let ((entry (assq (nth 2 x) math-aliased-vars))) | |
1176 (and entry | |
1177 (not (nth 2 entry)) | |
1178 (not (nth 2 (math-rwcomp-reg-entry (nth 1 entry)))) | |
1179 (progn | |
1180 (setcar (cdr (cdr entry)) t) | |
1181 (nth 1 entry))))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1182 (math-rwcomp-reg))) |
40785 | 1183 |
1184 (defun math-rwcomp-all-regs-done (expr) | |
1185 (if (Math-primp expr) | |
1186 (or (not (eq (car-safe expr) 'var)) | |
1187 (assq (nth 2 expr) math-regs) | |
1188 (eq (nth 2 expr) 'var-remember) | |
1189 (math-const-var expr)) | |
1190 (if (and (eq (car expr) 'calcFunc-let) | |
1191 (= (length expr) 3)) | |
1192 (math-rwcomp-all-regs-done (nth 2 expr)) | |
1193 (if (and (eq (car expr) 'calcFunc-let) | |
1194 (= (length expr) 2) | |
1195 (eq (car-safe (nth 1 expr)) 'calcFunc-assign) | |
1196 (= (length (nth 1 expr)) 3)) | |
1197 (math-rwcomp-all-regs-done (nth 2 (nth 1 expr))) | |
1198 (while (and (setq expr (cdr expr)) | |
1199 (math-rwcomp-all-regs-done (car expr)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1200 (null expr))))) |
40785 | 1201 |
1202 (defun math-rwcomp-no-vars (expr) | |
1203 (if (Math-primp expr) | |
1204 (or (not (eq (car-safe expr) 'var)) | |
1205 (math-const-var expr)) | |
1206 (and (not (memq (car expr) '(calcFunc-condition | |
1207 calcFunc-select calcFunc-quote | |
1208 calcFunc-plain calcFunc-opt | |
1209 calcFunc-por calcFunc-pand | |
1210 calcFunc-pnot calcFunc-apply | |
1211 calcFunc-cons calcFunc-rcons))) | |
1212 (progn | |
1213 (while (and (setq expr (cdr expr)) | |
1214 (math-rwcomp-no-vars (car expr)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1215 (null expr))))) |
40785 | 1216 |
1217 (defun math-rwcomp-is-algebraic (expr) | |
1218 (if (Math-primp expr) | |
1219 (or (not (eq (car-safe expr) 'var)) | |
1220 (math-const-var expr) | |
1221 (assq (nth 2 expr) math-regs)) | |
1222 (and (memq 'algebraic (get (car expr) 'math-rewrite-props)) | |
1223 (progn | |
1224 (while (and (setq expr (cdr expr)) | |
1225 (math-rwcomp-is-algebraic (car expr)))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1226 (null expr))))) |
40785 | 1227 |
1228 (defun math-rwcomp-is-constrained (expr not-these) | |
1229 (if (Math-primp expr) | |
1230 (not (eq (car-safe expr) 'var)) | |
1231 (if (eq (car expr) 'calcFunc-plain) | |
1232 (math-rwcomp-is-constrained (nth 1 expr) not-these) | |
1233 (not (or (memq (car expr) '(neg calcFunc-select)) | |
1234 (memq (car expr) not-these) | |
1235 (and (memq 'commut (get (car expr) 'math-rewrite-props)) | |
1236 (or (eq (car-safe (nth 1 expr)) 'calcFunc-opt) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1237 (eq (car-safe (nth 2 expr)) 'calcFunc-opt)))))))) |
40785 | 1238 |
1239 (defun math-rwcomp-optional-arg (head argp) | |
1240 (let ((arg (car argp))) | |
1241 (if (eq (car-safe arg) 'calcFunc-opt) | |
1242 (and (memq (length arg) '(2 3)) | |
1243 (progn | |
1244 (or (eq (car-safe (nth 1 arg)) 'var) | |
1245 (error "First argument of opt( ) must be a variable")) | |
1246 (setcar argp (nth 1 arg)) | |
1247 (if (= (length arg) 2) | |
1248 (or (get head 'math-rewrite-default) | |
1249 (error "opt( ) must include a default in this context")) | |
1250 (nth 2 arg)))) | |
1251 (and (eq (car-safe arg) 'neg) | |
1252 (let* ((part (list (nth 1 arg))) | |
1253 (partp (math-rwcomp-optional-arg head part))) | |
1254 (and partp | |
1255 (setcar argp (math-rwcomp-neg (car part))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1256 (math-neg partp))))))) |
40785 | 1257 |
1258 (defun math-rwcomp-neg (expr) | |
1259 (if (memq (car-safe expr) '(* /)) | |
1260 (if (eq (car-safe (nth 1 expr)) 'var) | |
1261 (list (car expr) (list 'neg (nth 1 expr)) (nth 2 expr)) | |
1262 (if (eq (car-safe (nth 2 expr)) 'var) | |
1263 (list (car expr) (nth 1 expr) (list 'neg (nth 2 expr))) | |
1264 (math-neg expr))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1265 (math-neg expr))) |
40785 | 1266 |
1267 (defun math-rwcomp-assoc-args (expr) | |
1268 (if (and (eq (car-safe (nth 1 expr)) (car expr)) | |
1269 (= (length (nth 1 expr)) 3)) | |
1270 (math-rwcomp-assoc-args (nth 1 expr)) | |
1271 (setq math-args (cons (nth 1 expr) math-args))) | |
1272 (if (and (eq (car-safe (nth 2 expr)) (car expr)) | |
1273 (= (length (nth 2 expr)) 3)) | |
1274 (math-rwcomp-assoc-args (nth 2 expr)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1275 (setq math-args (cons (nth 2 expr) math-args)))) |
40785 | 1276 |
1277 (defun math-rwcomp-addsub-args (expr) | |
1278 (if (memq (car-safe (nth 1 expr)) '(+ -)) | |
1279 (math-rwcomp-addsub-args (nth 1 expr)) | |
1280 (setq math-args (cons (nth 1 expr) math-args))) | |
1281 (if (eq (car expr) '-) | |
1282 (setq math-args (cons (math-rwcomp-neg (nth 2 expr)) math-args)) | |
1283 (if (eq (car-safe (nth 2 expr)) '+) | |
1284 (math-rwcomp-addsub-args (nth 2 expr)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1285 (setq math-args (cons (nth 2 expr) math-args))))) |
40785 | 1286 |
1287 (defun math-rwcomp-order (a b) | |
1288 (< (math-rwcomp-priority (car a)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1289 (math-rwcomp-priority (car b)))) |
40785 | 1290 |
1291 ;;; Order of priority: 0 Constants and other exact matches (first) | |
1292 ;;; 10 Functions (except below) | |
1293 ;;; 20 Meta-variables which occur more than once | |
1294 ;;; 30 Algebraic functions | |
1295 ;;; 40 Commutative/associative functions | |
1296 ;;; 50 Meta-variables which occur only once | |
1297 ;;; +100 for every "!!!" (pnot) in the pattern | |
1298 ;;; 10000 Optional arguments (last) | |
1299 | |
1300 (defun math-rwcomp-priority (expr) | |
1301 (+ (math-rwcomp-count-pnots expr) | |
1302 (cond ((eq (car-safe expr) 'calcFunc-opt) | |
1303 10000) | |
1304 ((math-rwcomp-no-vars expr) | |
1305 0) | |
1306 ((eq (car expr) 'calcFunc-quote) | |
1307 0) | |
1308 ((eq (car expr) 'var) | |
1309 (if (assq (nth 2 expr) math-regs) | |
1310 0 | |
1311 (if (= (math-rwcomp-count-refs expr) 1) | |
1312 50 | |
1313 20))) | |
1314 (t (let ((props (get (car expr) 'math-rewrite-props))) | |
1315 (if (or (memq 'commut props) | |
1316 (memq 'assoc props)) | |
1317 40 | |
1318 (if (memq 'algebraic props) | |
1319 30 | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1320 10))))))) |
40785 | 1321 |
1322 (defun math-rwcomp-count-refs (var) | |
1323 (let ((count (or (math-expr-contains-count math-pattern var) 0)) | |
1324 (p math-conds)) | |
1325 (while p | |
1326 (if (eq (car-safe (car p)) 'calcFunc-let) | |
1327 (if (= (length (car p)) 3) | |
1328 (setq count (+ count | |
1329 (or (math-expr-contains-count (nth 2 (car p)) var) | |
1330 0))) | |
1331 (if (and (= (length (car p)) 2) | |
1332 (eq (car-safe (nth 1 (car p))) 'calcFunc-assign) | |
1333 (= (length (nth 1 (car p))) 3)) | |
1334 (setq count (+ count | |
1335 (or (math-expr-contains-count | |
1336 (nth 2 (nth 1 (car p))) var) 0)))))) | |
1337 (setq p (cdr p))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1338 count)) |
40785 | 1339 |
1340 (defun math-rwcomp-count-pnots (expr) | |
1341 (if (Math-primp expr) | |
1342 0 | |
1343 (if (eq (car expr) 'calcFunc-pnot) | |
1344 100 | |
1345 (let ((count 0)) | |
1346 (while (setq expr (cdr expr)) | |
1347 (setq count (+ count (math-rwcomp-count-pnots (car expr))))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1348 count)))) |
40785 | 1349 |
1350 ;;; In the current implementation, all associative functions must | |
1351 ;;; also be commutative. | |
1352 | |
1353 (put '+ 'math-rewrite-props '(algebraic assoc commut)) | |
1354 (put '- 'math-rewrite-props '(algebraic assoc commut)) ; see below | |
1355 (put '* 'math-rewrite-props '(algebraic assoc commut)) ; see below | |
1356 (put '/ 'math-rewrite-props '(algebraic unary1)) | |
1357 (put '^ 'math-rewrite-props '(algebraic unary1)) | |
1358 (put '% 'math-rewrite-props '(algebraic)) | |
1359 (put 'neg 'math-rewrite-props '(algebraic)) | |
1360 (put 'calcFunc-idiv 'math-rewrite-props '(algebraic)) | |
1361 (put 'calcFunc-abs 'math-rewrite-props '(algebraic)) | |
1362 (put 'calcFunc-sign 'math-rewrite-props '(algebraic)) | |
1363 (put 'calcFunc-round 'math-rewrite-props '(algebraic)) | |
1364 (put 'calcFunc-rounde 'math-rewrite-props '(algebraic)) | |
1365 (put 'calcFunc-roundu 'math-rewrite-props '(algebraic)) | |
1366 (put 'calcFunc-trunc 'math-rewrite-props '(algebraic)) | |
1367 (put 'calcFunc-floor 'math-rewrite-props '(algebraic)) | |
1368 (put 'calcFunc-ceil 'math-rewrite-props '(algebraic)) | |
1369 (put 'calcFunc-re 'math-rewrite-props '(algebraic)) | |
1370 (put 'calcFunc-im 'math-rewrite-props '(algebraic)) | |
1371 (put 'calcFunc-conj 'math-rewrite-props '(algebraic)) | |
1372 (put 'calcFunc-arg 'math-rewrite-props '(algebraic)) | |
1373 (put 'calcFunc-and 'math-rewrite-props '(assoc commut)) | |
1374 (put 'calcFunc-or 'math-rewrite-props '(assoc commut)) | |
1375 (put 'calcFunc-xor 'math-rewrite-props '(assoc commut)) | |
1376 (put 'calcFunc-eq 'math-rewrite-props '(commut)) | |
1377 (put 'calcFunc-neq 'math-rewrite-props '(commut)) | |
1378 (put 'calcFunc-land 'math-rewrite-props '(assoc commut)) | |
1379 (put 'calcFunc-lor 'math-rewrite-props '(assoc commut)) | |
1380 (put 'calcFunc-beta 'math-rewrite-props '(commut)) | |
1381 (put 'calcFunc-gcd 'math-rewrite-props '(assoc commut)) | |
1382 (put 'calcFunc-lcm 'math-rewrite-props '(assoc commut)) | |
1383 (put 'calcFunc-max 'math-rewrite-props '(algebraic assoc commut)) | |
1384 (put 'calcFunc-min 'math-rewrite-props '(algebraic assoc commut)) | |
1385 (put 'calcFunc-vunion 'math-rewrite-props '(assoc commut)) | |
1386 (put 'calcFunc-vint 'math-rewrite-props '(assoc commut)) | |
1387 (put 'calcFunc-vxor 'math-rewrite-props '(assoc commut)) | |
1388 | |
1389 ;;; Note: "*" is not commutative for matrix args, but we pretend it is. | |
1390 ;;; Also, "-" is not commutative but the code tweaks things so that it is. | |
1391 | |
1392 (put '+ 'math-rewrite-default 0) | |
1393 (put '- 'math-rewrite-default 0) | |
1394 (put '* 'math-rewrite-default 1) | |
1395 (put '/ 'math-rewrite-default 1) | |
1396 (put '^ 'math-rewrite-default 1) | |
1397 (put 'calcFunc-land 'math-rewrite-default 1) | |
1398 (put 'calcFunc-lor 'math-rewrite-default 0) | |
1399 (put 'calcFunc-vunion 'math-rewrite-default '(vec)) | |
1400 (put 'calcFunc-vint 'math-rewrite-default '(vec)) | |
1401 (put 'calcFunc-vdiff 'math-rewrite-default '(vec)) | |
1402 (put 'calcFunc-vxor 'math-rewrite-default '(vec)) | |
1403 | |
1404 (defmacro math-rwfail (&optional back) | |
1405 (list 'setq 'pc | |
1406 (list 'and | |
1407 (if back | |
1408 '(setq btrack (cdr btrack)) | |
1409 'btrack) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1410 ''((backtrack))))) |
40785 | 1411 |
1412 ;;; This monstrosity is necessary because the use of static vectors of | |
1413 ;;; registers makes rewrite rules non-reentrant. Yucko! | |
1414 (defmacro math-rweval (form) | |
1415 (list 'let '((orig (car rules))) | |
1416 '(setcar rules (quote (nil nil nil no-phase))) | |
1417 (list 'unwind-protect | |
1418 form | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1419 '(setcar rules orig)))) |
40785 | 1420 |
1421 (setq math-rewrite-phase 1) | |
1422 | |
1423 (defun math-apply-rewrites (expr rules &optional heads ruleset) | |
1424 (and | |
1425 (setq rules (cdr (or (assq (car-safe expr) rules) | |
1426 (assq nil rules)))) | |
1427 (let ((result nil) | |
1428 op regs inst part pc mark btrack | |
1429 (tracing math-rwcomp-tracing) | |
1430 (phase math-rewrite-phase)) | |
1431 (while rules | |
1432 (or | |
1433 (and (setq part (nth 2 (car rules))) | |
1434 heads | |
1435 (not (memq part heads))) | |
1436 (and (setq part (nth 3 (car rules))) | |
1437 (not (memq phase part))) | |
1438 (progn | |
1439 (setq regs (car (car rules)) | |
1440 pc (nth 1 (car rules)) | |
1441 btrack nil) | |
1442 (aset regs 0 expr) | |
1443 (while pc | |
1444 | |
1445 (and tracing | |
1446 (progn (terpri) (princ (car pc)) | |
1447 (if (and (natnump (nth 1 (car pc))) | |
1448 (< (nth 1 (car pc)) (length regs))) | |
1449 (princ (format "\n part = %s" | |
1450 (aref regs (nth 1 (car pc)))))))) | |
1451 | |
1452 (cond ((eq (setq op (car (setq inst (car pc)))) 'func) | |
1453 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1454 (eq (car part) | |
1455 (car (setq inst (cdr (cdr inst))))) | |
1456 (progn | |
1457 (while (and (setq inst (cdr inst) | |
1458 part (cdr part)) | |
1459 inst) | |
1460 (aset regs (car inst) (car part))) | |
1461 (not (or inst part)))) | |
1462 (setq pc (cdr pc)) | |
1463 (math-rwfail))) | |
1464 | |
1465 ((eq op 'same) | |
1466 (if (or (equal (setq part (aref regs (nth 1 inst))) | |
1467 (setq mark (aref regs (nth 2 inst)))) | |
1468 (Math-equal part mark)) | |
1469 (setq pc (cdr pc)) | |
1470 (math-rwfail))) | |
1471 | |
1472 ((and (eq op 'try) | |
1473 calc-matrix-mode | |
1474 (not (eq calc-matrix-mode 'scalar)) | |
1475 (eq (car (nth 2 inst)) '*) | |
1476 (consp (setq part (aref regs (car (cdr inst))))) | |
1477 (eq (car part) '*) | |
1478 (not (math-known-scalarp part))) | |
1479 (setq mark (nth 3 inst) | |
1480 pc (cdr pc)) | |
1481 (if (aref mark 4) | |
1482 (progn | |
1483 (aset regs (nth 4 inst) (nth 2 part)) | |
1484 (aset mark 1 (cdr (cdr part)))) | |
1485 (aset regs (nth 4 inst) (nth 1 part)) | |
1486 (aset mark 1 (cdr part))) | |
1487 (aset mark 0 (cdr part)) | |
1488 (aset mark 2 0)) | |
1489 | |
1490 ((eq op 'try) | |
1491 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1492 (memq (car part) (nth 2 inst)) | |
1493 (= (length part) 3) | |
1494 (or (not (eq (car part) '/)) | |
1495 (Math-objectp (nth 2 part)))) | |
1496 (progn | |
1497 (setq op nil | |
1498 mark (car (cdr (setq inst (cdr (cdr inst)))))) | |
1499 (and | |
1500 (memq 'assoc (get (car part) 'math-rewrite-props)) | |
1501 (not (= (aref mark 3) 0)) | |
1502 (while (if (and (consp (nth 1 part)) | |
1503 (memq (car (nth 1 part)) (car inst))) | |
1504 (setq op (cons (if (eq (car part) '-) | |
1505 (math-rwapply-neg | |
1506 (nth 2 part)) | |
1507 (nth 2 part)) | |
1508 op) | |
1509 part (nth 1 part)) | |
1510 (if (and (consp (nth 2 part)) | |
1511 (memq (car (nth 2 part)) | |
1512 (car inst)) | |
1513 (not (eq (car (nth 2 part)) '-))) | |
1514 (setq op (cons (nth 1 part) op) | |
1515 part (nth 2 part)))))) | |
1516 (setq op (cons (nth 1 part) | |
1517 (cons (if (eq (car part) '-) | |
1518 (math-rwapply-neg | |
1519 (nth 2 part)) | |
1520 (if (eq (car part) '/) | |
1521 (math-rwapply-inv | |
1522 (nth 2 part)) | |
1523 (nth 2 part))) | |
1524 op)) | |
1525 btrack (cons pc btrack) | |
1526 pc (cdr pc)) | |
1527 (aset regs (nth 2 inst) (car op)) | |
1528 (aset mark 0 op) | |
1529 (aset mark 1 op) | |
1530 (aset mark 2 (if (cdr (cdr op)) 1 0))) | |
1531 (if (nth 5 inst) | |
1532 (if (and (consp part) | |
1533 (eq (car part) 'neg) | |
1534 (eq (car (nth 2 inst)) '*) | |
1535 (eq (nth 5 inst) 1)) | |
1536 (progn | |
1537 (setq mark (nth 3 inst) | |
1538 pc (cdr pc)) | |
1539 (aset regs (nth 4 inst) (nth 1 part)) | |
1540 (aset mark 1 -1) | |
1541 (aset mark 2 4)) | |
1542 (setq mark (nth 3 inst) | |
1543 pc (cdr pc)) | |
1544 (aset regs (nth 4 inst) part) | |
1545 (aset mark 2 3)) | |
1546 (math-rwfail)))) | |
1547 | |
1548 ((eq op 'try2) | |
1549 (setq part (nth 1 inst) ; try instr | |
1550 mark (nth 3 part) | |
1551 op (aref mark 2) | |
1552 pc (cdr pc)) | |
1553 (aset regs (nth 2 inst) | |
1554 (cond | |
1555 ((eq op 0) | |
1556 (if (eq (aref mark 0) (aref mark 1)) | |
1557 (nth 1 (aref mark 0)) | |
1558 (car (aref mark 0)))) | |
1559 ((eq op 1) | |
1560 (setq mark (delq (car (aref mark 1)) | |
1561 (copy-sequence (aref mark 0))) | |
1562 op (car (nth 2 part))) | |
1563 (if (eq op '*) | |
1564 (progn | |
1565 (setq mark (nreverse mark) | |
1566 part (list '* (nth 1 mark) (car mark)) | |
1567 mark (cdr mark)) | |
1568 (while (setq mark (cdr mark)) | |
1569 (setq part (list '* (car mark) part)))) | |
1570 (setq part (car mark) | |
1571 mark (cdr mark) | |
1572 part (if (and (eq op '+) | |
1573 (consp (car mark)) | |
1574 (eq (car (car mark)) 'neg)) | |
1575 (list '- part | |
1576 (nth 1 (car mark))) | |
1577 (list op part (car mark)))) | |
1578 (while (setq mark (cdr mark)) | |
1579 (setq part (if (and (eq op '+) | |
1580 (consp (car mark)) | |
1581 (eq (car (car mark)) 'neg)) | |
1582 (list '- part | |
1583 (nth 1 (car mark))) | |
1584 (list op part (car mark)))))) | |
1585 part) | |
1586 ((eq op 2) | |
1587 (car (aref mark 1))) | |
1588 ((eq op 3) (nth 5 part)) | |
1589 (t (aref mark 1))))) | |
1590 | |
1591 ((eq op 'select) | |
1592 (setq pc (cdr pc)) | |
1593 (if (and (consp (setq part (aref regs (nth 1 inst)))) | |
1594 (eq (car part) 'calcFunc-select)) | |
1595 (aset regs (nth 2 inst) (nth 1 part)) | |
1596 (if math-rewrite-selections | |
1597 (math-rwfail) | |
1598 (aset regs (nth 2 inst) part)))) | |
1599 | |
1600 ((eq op 'same-neg) | |
1601 (if (or (equal (setq part (aref regs (nth 1 inst))) | |
1602 (setq mark (math-neg | |
1603 (aref regs (nth 2 inst))))) | |
1604 (Math-equal part mark)) | |
1605 (setq pc (cdr pc)) | |
1606 (math-rwfail))) | |
1607 | |
1608 ((eq op 'backtrack) | |
1609 (setq inst (car (car btrack)) ; "try" or "alt" instr | |
1610 pc (cdr (car btrack)) | |
1611 mark (or (nth 3 inst) [nil nil 4]) | |
1612 op (aref mark 2)) | |
1613 (cond ((eq op 0) | |
1614 (if (setq op (cdr (aref mark 1))) | |
1615 (aset regs (nth 4 inst) (car (aset mark 1 op))) | |
1616 (if (nth 5 inst) | |
1617 (progn | |
1618 (aset mark 2 3) | |
1619 (aset regs (nth 4 inst) | |
1620 (aref regs (nth 1 inst)))) | |
1621 (math-rwfail t)))) | |
1622 ((eq op 1) | |
1623 (if (setq op (cdr (aref mark 1))) | |
1624 (aset regs (nth 4 inst) (car (aset mark 1 op))) | |
1625 (if (= (aref mark 3) 1) | |
1626 (if (nth 5 inst) | |
1627 (progn | |
1628 (aset mark 2 3) | |
1629 (aset regs (nth 4 inst) | |
1630 (aref regs (nth 1 inst)))) | |
1631 (math-rwfail t)) | |
1632 (aset mark 2 2) | |
1633 (aset mark 1 (cons nil (aref mark 0))) | |
1634 (math-rwfail)))) | |
1635 ((eq op 2) | |
1636 (if (setq op (cdr (aref mark 1))) | |
1637 (progn | |
1638 (setq mark (delq (car (aset mark 1 op)) | |
1639 (copy-sequence | |
1640 (aref mark 0))) | |
1641 op (car (nth 2 inst))) | |
1642 (if (eq op '*) | |
1643 (progn | |
1644 (setq mark (nreverse mark) | |
1645 part (list '* (nth 1 mark) | |
1646 (car mark)) | |
1647 mark (cdr mark)) | |
1648 (while (setq mark (cdr mark)) | |
1649 (setq part (list '* (car mark) | |
1650 part)))) | |
1651 (setq part (car mark) | |
1652 mark (cdr mark) | |
1653 part (if (and (eq op '+) | |
1654 (consp (car mark)) | |
1655 (eq (car (car mark)) | |
1656 'neg)) | |
1657 (list '- part | |
1658 (nth 1 (car mark))) | |
1659 (list op part (car mark)))) | |
1660 (while (setq mark (cdr mark)) | |
1661 (setq part (if (and (eq op '+) | |
1662 (consp (car mark)) | |
1663 (eq (car (car mark)) | |
1664 'neg)) | |
1665 (list '- part | |
1666 (nth 1 (car mark))) | |
1667 (list op part (car mark)))))) | |
1668 (aset regs (nth 4 inst) part)) | |
1669 (if (nth 5 inst) | |
1670 (progn | |
1671 (aset mark 2 3) | |
1672 (aset regs (nth 4 inst) | |
1673 (aref regs (nth 1 inst)))) | |
1674 (math-rwfail t)))) | |
1675 ((eq op 4) | |
1676 (setq btrack (cdr btrack))) | |
1677 (t (math-rwfail t)))) | |
1678 | |
1679 ((eq op 'integer) | |
1680 (if (Math-integerp (setq part (aref regs (nth 1 inst)))) | |
1681 (setq pc (cdr pc)) | |
1682 (if (Math-primp part) | |
1683 (math-rwfail) | |
1684 (setq part (math-rweval (math-simplify part))) | |
1685 (if (Math-integerp part) | |
1686 (setq pc (cdr pc)) | |
1687 (math-rwfail))))) | |
1688 | |
1689 ((eq op 'real) | |
1690 (if (Math-realp (setq part (aref regs (nth 1 inst)))) | |
1691 (setq pc (cdr pc)) | |
1692 (if (Math-primp part) | |
1693 (math-rwfail) | |
1694 (setq part (math-rweval (math-simplify part))) | |
1695 (if (Math-realp part) | |
1696 (setq pc (cdr pc)) | |
1697 (math-rwfail))))) | |
1698 | |
1699 ((eq op 'constant) | |
1700 (if (math-constp (setq part (aref regs (nth 1 inst)))) | |
1701 (setq pc (cdr pc)) | |
1702 (if (Math-primp part) | |
1703 (math-rwfail) | |
1704 (setq part (math-rweval (math-simplify part))) | |
1705 (if (math-constp part) | |
1706 (setq pc (cdr pc)) | |
1707 (math-rwfail))))) | |
1708 | |
1709 ((eq op 'negative) | |
1710 (if (math-looks-negp (setq part (aref regs (nth 1 inst)))) | |
1711 (setq pc (cdr pc)) | |
1712 (if (Math-primp part) | |
1713 (math-rwfail) | |
1714 (setq part (math-rweval (math-simplify part))) | |
1715 (if (math-looks-negp part) | |
1716 (setq pc (cdr pc)) | |
1717 (math-rwfail))))) | |
1718 | |
1719 ((eq op 'rel) | |
1720 (setq part (math-compare (aref regs (nth 1 inst)) | |
1721 (aref regs (nth 3 inst))) | |
1722 op (nth 2 inst)) | |
1723 (if (= part 2) | |
1724 (setq part (math-rweval | |
1725 (math-simplify | |
1726 (calcFunc-sign | |
1727 (math-sub (aref regs (nth 1 inst)) | |
1728 (aref regs (nth 3 inst)))))))) | |
1729 (if (cond ((eq op 'calcFunc-eq) | |
1730 (eq part 0)) | |
1731 ((eq op 'calcFunc-neq) | |
1732 (memq part '(-1 1))) | |
1733 ((eq op 'calcFunc-lt) | |
1734 (eq part -1)) | |
1735 ((eq op 'calcFunc-leq) | |
1736 (memq part '(-1 0))) | |
1737 ((eq op 'calcFunc-gt) | |
1738 (eq part 1)) | |
1739 ((eq op 'calcFunc-geq) | |
1740 (memq part '(0 1)))) | |
1741 (setq pc (cdr pc)) | |
1742 (math-rwfail))) | |
1743 | |
1744 ((eq op 'func-def) | |
1745 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1746 (eq (car part) | |
1747 (car (setq inst (cdr (cdr inst)))))) | |
1748 (progn | |
1749 (setq inst (cdr inst) | |
1750 mark (car inst)) | |
1751 (while (and (setq inst (cdr inst) | |
1752 part (cdr part)) | |
1753 inst) | |
1754 (aset regs (car inst) (car part))) | |
1755 (if (or inst part) | |
1756 (setq pc (cdr pc)) | |
1757 (while (eq (car (car (setq pc (cdr pc)))) | |
1758 'func-def)) | |
1759 (setq pc (cdr pc)) ; skip over "func" | |
1760 (while mark | |
1761 (aset regs (cdr (car mark)) (car (car mark))) | |
1762 (setq mark (cdr mark))))) | |
1763 (math-rwfail))) | |
1764 | |
1765 ((eq op 'func-opt) | |
1766 (if (or (not (and (consp | |
1767 (setq part (aref regs (car (cdr inst))))) | |
1768 (eq (car part) (nth 2 inst)))) | |
1769 (and (= (length part) 2) | |
1770 (setq part (nth 1 part)))) | |
1771 (progn | |
1772 (setq mark (nth 3 inst)) | |
1773 (aset regs (nth 4 inst) part) | |
1774 (while (eq (car (car (setq pc (cdr pc)))) 'func-def)) | |
1775 (setq pc (cdr pc)) ; skip over "func" | |
1776 (while mark | |
1777 (aset regs (cdr (car mark)) (car (car mark))) | |
1778 (setq mark (cdr mark)))) | |
1779 (setq pc (cdr pc)))) | |
1780 | |
1781 ((eq op 'mod) | |
1782 (if (if (Math-zerop (setq part (aref regs (nth 1 inst)))) | |
1783 (Math-zerop (nth 3 inst)) | |
1784 (and (not (Math-zerop (nth 2 inst))) | |
1785 (progn | |
1786 (setq part (math-mod part (nth 2 inst))) | |
1787 (or (Math-numberp part) | |
1788 (setq part (math-rweval | |
1789 (math-simplify part)))) | |
1790 (Math-equal part (nth 3 inst))))) | |
1791 (setq pc (cdr pc)) | |
1792 (math-rwfail))) | |
1793 | |
1794 ((eq op 'apply) | |
1795 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1796 (not (Math-objvecp part)) | |
1797 (not (eq (car part) 'var))) | |
1798 (progn | |
1799 (aset regs (nth 2 inst) | |
1800 (math-calcFunc-to-var (car part))) | |
1801 (aset regs (nth 3 inst) | |
1802 (cons 'vec (cdr part))) | |
1803 (setq pc (cdr pc))) | |
1804 (math-rwfail))) | |
1805 | |
1806 ((eq op 'cons) | |
1807 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1808 (eq (car part) 'vec) | |
1809 (cdr part)) | |
1810 (progn | |
1811 (aset regs (nth 2 inst) (nth 1 part)) | |
1812 (aset regs (nth 3 inst) (cons 'vec (cdr (cdr part)))) | |
1813 (setq pc (cdr pc))) | |
1814 (math-rwfail))) | |
1815 | |
1816 ((eq op 'rcons) | |
1817 (if (and (consp (setq part (aref regs (car (cdr inst))))) | |
1818 (eq (car part) 'vec) | |
1819 (cdr part)) | |
1820 (progn | |
1821 (aset regs (nth 2 inst) (calcFunc-rhead part)) | |
1822 (aset regs (nth 3 inst) (calcFunc-rtail part)) | |
1823 (setq pc (cdr pc))) | |
1824 (math-rwfail))) | |
1825 | |
1826 ((eq op 'cond) | |
1827 (if (math-is-true | |
1828 (math-rweval | |
1829 (math-simplify | |
1830 (math-rwapply-replace-regs (nth 1 inst))))) | |
1831 (setq pc (cdr pc)) | |
1832 (math-rwfail))) | |
1833 | |
1834 ((eq op 'let) | |
1835 (aset regs (nth 1 inst) | |
1836 (math-rweval | |
1837 (math-normalize | |
1838 (math-rwapply-replace-regs (nth 2 inst))))) | |
1839 (setq pc (cdr pc))) | |
1840 | |
1841 ((eq op 'copy) | |
1842 (aset regs (nth 2 inst) (aref regs (nth 1 inst))) | |
1843 (setq pc (cdr pc))) | |
1844 | |
1845 ((eq op 'copy-neg) | |
1846 (aset regs (nth 2 inst) | |
1847 (math-rwapply-neg (aref regs (nth 1 inst)))) | |
1848 (setq pc (cdr pc))) | |
1849 | |
1850 ((eq op 'alt) | |
1851 (setq btrack (cons pc btrack) | |
1852 pc (nth 1 inst))) | |
1853 | |
1854 ((eq op 'end-alt) | |
1855 (while (and btrack (not (eq (car btrack) (nth 1 inst)))) | |
1856 (setq btrack (cdr btrack))) | |
1857 (setq btrack (cdr btrack) | |
1858 pc (cdr pc))) | |
1859 | |
1860 ((eq op 'done) | |
1861 (setq result (math-rwapply-replace-regs (nth 1 inst))) | |
1862 (if (or (and (eq (car-safe result) '+) | |
1863 (eq (nth 2 result) 0)) | |
1864 (and (eq (car-safe result) '*) | |
1865 (eq (nth 2 result) 1))) | |
1866 (setq result (nth 1 result))) | |
1867 (setq part (and (nth 2 inst) | |
1868 (math-is-true | |
1869 (math-rweval | |
1870 (math-simplify | |
1871 (math-rwapply-replace-regs | |
1872 (nth 2 inst))))))) | |
1873 (if (or (equal result expr) | |
1874 (equal (setq result (math-normalize result)) expr)) | |
1875 (setq result nil) | |
1876 (if part (math-rwapply-remember expr result)) | |
1877 (setq rules nil)) | |
1878 (setq pc nil)) | |
1879 | |
1880 (t (error "%s is not a valid rewrite opcode" op)))))) | |
1881 (setq rules (cdr rules))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1882 result))) |
40785 | 1883 |
1884 (defun math-rwapply-neg (expr) | |
1885 (if (and (consp expr) | |
1886 (memq (car expr) '(* /))) | |
1887 (if (Math-objectp (nth 2 expr)) | |
1888 (list (car expr) (nth 1 expr) (math-neg (nth 2 expr))) | |
1889 (list (car expr) | |
1890 (if (Math-objectp (nth 1 expr)) | |
1891 (math-neg (nth 1 expr)) | |
1892 (list '* -1 (nth 1 expr))) | |
1893 (nth 2 expr))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1894 (math-neg expr))) |
40785 | 1895 |
1896 (defun math-rwapply-inv (expr) | |
1897 (if (and (Math-integerp expr) | |
1898 calc-prefer-frac) | |
1899 (math-make-frac 1 expr) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
1900 (list '/ 1 expr))) |
40785 | 1901 |
1902 (defun math-rwapply-replace-regs (expr) | |
1903 (cond ((Math-primp expr) | |
1904 expr) | |
1905 ((eq (car expr) 'calcFunc-register) | |
1906 (setq expr (aref regs (nth 1 expr))) | |
1907 (if (eq (car-safe expr) '*) | |
1908 (if (eq (nth 1 expr) -1) | |
1909 (math-neg (nth 2 expr)) | |
1910 (if (eq (nth 1 expr) 1) | |
1911 (nth 2 expr) | |
1912 expr)) | |
1913 expr)) | |
1914 ((and (eq (car expr) 'calcFunc-eval) | |
1915 (= (length expr) 2)) | |
1916 (calc-with-default-simplification | |
1917 (math-normalize (math-rwapply-replace-regs (nth 1 expr))))) | |
1918 ((and (eq (car expr) 'calcFunc-evalsimp) | |
1919 (= (length expr) 2)) | |
1920 (math-simplify (math-rwapply-replace-regs (nth 1 expr)))) | |
1921 ((and (eq (car expr) 'calcFunc-evalextsimp) | |
1922 (= (length expr) 2)) | |
1923 (math-simplify-extended (math-rwapply-replace-regs (nth 1 expr)))) | |
1924 ((and (eq (car expr) 'calcFunc-apply) | |
1925 (= (length expr) 3)) | |
1926 (let ((func (math-rwapply-replace-regs (nth 1 expr))) | |
1927 (args (math-rwapply-replace-regs (nth 2 expr))) | |
1928 call) | |
1929 (if (and (math-vectorp args) | |
1930 (not (eq (car-safe (setq call (math-build-call | |
1931 (math-var-to-calcFunc func) | |
1932 (cdr args)))) | |
1933 'calcFunc-call))) | |
1934 call | |
1935 (list 'calcFunc-apply func args)))) | |
1936 ((and (eq (car expr) 'calcFunc-cons) | |
1937 (= (length expr) 3)) | |
1938 (let ((head (math-rwapply-replace-regs (nth 1 expr))) | |
1939 (tail (math-rwapply-replace-regs (nth 2 expr)))) | |
1940 (if (math-vectorp tail) | |
1941 (cons 'vec (cons head (cdr tail))) | |
1942 (list 'calcFunc-cons head tail)))) | |
1943 ((and (eq (car expr) 'calcFunc-rcons) | |
1944 (= (length expr) 3)) | |
1945 (let ((head (math-rwapply-replace-regs (nth 1 expr))) | |
1946 (tail (math-rwapply-replace-regs (nth 2 expr)))) | |
1947 (if (math-vectorp head) | |
1948 (append head (list tail)) | |
1949 (list 'calcFunc-rcons head tail)))) | |
1950 ((and (eq (car expr) 'neg) | |
1951 (math-rwapply-reg-looks-negp (nth 1 expr))) | |
1952 (math-rwapply-reg-neg (nth 1 expr))) | |
1953 ((and (eq (car expr) 'neg) | |
1954 (eq (car-safe (nth 1 expr)) 'calcFunc-register) | |
1955 (math-scalarp (aref regs (nth 1 (nth 1 expr))))) | |
1956 (math-neg (math-rwapply-replace-regs (nth 1 expr)))) | |
1957 ((and (eq (car expr) '+) | |
1958 (math-rwapply-reg-looks-negp (nth 1 expr))) | |
1959 (list '- (math-rwapply-replace-regs (nth 2 expr)) | |
1960 (math-rwapply-reg-neg (nth 1 expr)))) | |
1961 ((and (eq (car expr) '+) | |
1962 (math-rwapply-reg-looks-negp (nth 2 expr))) | |
1963 (list '- (math-rwapply-replace-regs (nth 1 expr)) | |
1964 (math-rwapply-reg-neg (nth 2 expr)))) | |
1965 ((and (eq (car expr) '-) | |
1966 (math-rwapply-reg-looks-negp (nth 2 expr))) | |
1967 (list '+ (math-rwapply-replace-regs (nth 1 expr)) | |
1968 (math-rwapply-reg-neg (nth 2 expr)))) | |
1969 ((eq (car expr) '*) | |
1970 (cond ((eq (nth 1 expr) -1) | |
1971 (if (math-rwapply-reg-looks-negp (nth 2 expr)) | |
1972 (math-rwapply-reg-neg (nth 2 expr)) | |
1973 (math-neg (math-rwapply-replace-regs (nth 2 expr))))) | |
1974 ((eq (nth 1 expr) 1) | |
1975 (math-rwapply-replace-regs (nth 2 expr))) | |
1976 ((eq (nth 2 expr) -1) | |
1977 (if (math-rwapply-reg-looks-negp (nth 1 expr)) | |
1978 (math-rwapply-reg-neg (nth 1 expr)) | |
1979 (math-neg (math-rwapply-replace-regs (nth 1 expr))))) | |
1980 ((eq (nth 2 expr) 1) | |
1981 (math-rwapply-replace-regs (nth 1 expr))) | |
1982 (t | |
1983 (let ((arg1 (math-rwapply-replace-regs (nth 1 expr))) | |
1984 (arg2 (math-rwapply-replace-regs (nth 2 expr)))) | |
1985 (cond ((and (eq (car-safe arg1) '/) | |
1986 (eq (nth 1 arg1) 1)) | |
1987 (list '/ arg2 (nth 2 arg1))) | |
1988 ((and (eq (car-safe arg2) '/) | |
1989 (eq (nth 1 arg2) 1)) | |
1990 (list '/ arg1 (nth 2 arg2))) | |
1991 (t (list '* arg1 arg2))))))) | |
1992 ((eq (car expr) '/) | |
1993 (let ((arg1 (math-rwapply-replace-regs (nth 1 expr))) | |
1994 (arg2 (math-rwapply-replace-regs (nth 2 expr)))) | |
1995 (if (eq (car-safe arg2) '/) | |
1996 (list '/ (list '* arg1 (nth 2 arg2)) (nth 1 arg2)) | |
1997 (list '/ arg1 arg2)))) | |
1998 ((and (eq (car expr) 'calcFunc-plain) | |
1999 (= (length expr) 2)) | |
2000 (if (Math-primp (nth 1 expr)) | |
2001 (nth 1 expr) | |
2002 (if (eq (car (nth 1 expr)) 'calcFunc-register) | |
2003 (aref regs (nth 1 (nth 1 expr))) | |
2004 (cons (car (nth 1 expr)) (mapcar 'math-rwapply-replace-regs | |
2005 (cdr (nth 1 expr))))))) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2006 (t (cons (car expr) (mapcar 'math-rwapply-replace-regs (cdr expr)))))) |
40785 | 2007 |
2008 (defun math-rwapply-reg-looks-negp (expr) | |
2009 (if (eq (car-safe expr) 'calcFunc-register) | |
2010 (math-looks-negp (aref regs (nth 1 expr))) | |
2011 (if (memq (car-safe expr) '(* /)) | |
2012 (or (math-rwapply-reg-looks-negp (nth 1 expr)) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2013 (math-rwapply-reg-looks-negp (nth 2 expr)))))) |
40785 | 2014 |
2015 (defun math-rwapply-reg-neg (expr) ; expr must satisfy rwapply-reg-looks-negp | |
2016 (if (eq (car expr) 'calcFunc-register) | |
2017 (math-neg (math-rwapply-replace-regs expr)) | |
2018 (if (math-rwapply-reg-looks-negp (nth 1 expr)) | |
2019 (math-rwapply-replace-regs (list (car expr) | |
2020 (math-rwapply-reg-neg (nth 1 expr)) | |
2021 (nth 2 expr))) | |
2022 (math-rwapply-replace-regs (list (car expr) | |
2023 (nth 1 expr) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2024 (math-rwapply-reg-neg (nth 2 expr))))))) |
40785 | 2025 |
2026 (defun math-rwapply-remember (old new) | |
2027 (let ((varval (symbol-value (nth 2 (car ruleset)))) | |
2028 (rules (assq (car-safe old) ruleset))) | |
2029 (if (and (eq (car-safe varval) 'vec) | |
2030 (not (memq (car-safe old) '(nil schedule + -))) | |
2031 rules) | |
2032 (progn | |
2033 (setcdr varval (cons (list 'calcFunc-assign | |
2034 (if (math-rwcomp-no-vars old) | |
2035 old | |
2036 (list 'calcFunc-quote old)) | |
2037 new) | |
2038 (cdr varval))) | |
2039 (setcdr rules (cons (list (vector nil old) | |
2040 (list (list 'same 0 1) | |
2041 (list 'done new nil)) | |
2042 nil nil) | |
41047
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2043 (cdr rules))))))) |
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2044 |
73f364fd8aaa
Style cleanup; don't put closing parens on their
Colin Walters <walters@gnu.org>
parents:
40785
diff
changeset
|
2045 ;;; calc-rewr.el ends here |