calc-prog.el 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368
  1. ;;; calc-prog.el --- user programmability functions for Calc
  2. ;; Copyright (C) 1990-1993, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: David Gillespie <daveg@synaptics.com>
  4. ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. ;; This file is autoloaded from calc-ext.el.
  19. (require 'calc-ext)
  20. (require 'calc-macs)
  21. ;; Declare functions which are defined elsewhere.
  22. (declare-function edmacro-format-keys "edmacro" (macro &optional verbose))
  23. (declare-function edmacro-parse-keys "edmacro" (string &optional need-vector))
  24. (declare-function math-read-expr-level "calc-aent" (exp-prec &optional exp-term))
  25. (defun calc-equal-to (arg)
  26. (interactive "P")
  27. (calc-wrapper
  28. (if (and (integerp arg) (> arg 2))
  29. (calc-enter-result arg "eq" (cons 'calcFunc-eq (calc-top-list-n arg)))
  30. (calc-binary-op "eq" 'calcFunc-eq arg))))
  31. (defun calc-remove-equal (arg)
  32. (interactive "P")
  33. (calc-wrapper
  34. (calc-unary-op "rmeq" 'calcFunc-rmeq arg)))
  35. (defun calc-not-equal-to (arg)
  36. (interactive "P")
  37. (calc-wrapper
  38. (if (and (integerp arg) (> arg 2))
  39. (calc-enter-result arg "neq" (cons 'calcFunc-neq (calc-top-list-n arg)))
  40. (calc-binary-op "neq" 'calcFunc-neq arg))))
  41. (defun calc-less-than (arg)
  42. (interactive "P")
  43. (calc-wrapper
  44. (calc-binary-op "lt" 'calcFunc-lt arg)))
  45. (defun calc-greater-than (arg)
  46. (interactive "P")
  47. (calc-wrapper
  48. (calc-binary-op "gt" 'calcFunc-gt arg)))
  49. (defun calc-less-equal (arg)
  50. (interactive "P")
  51. (calc-wrapper
  52. (calc-binary-op "leq" 'calcFunc-leq arg)))
  53. (defun calc-greater-equal (arg)
  54. (interactive "P")
  55. (calc-wrapper
  56. (calc-binary-op "geq" 'calcFunc-geq arg)))
  57. (defun calc-in-set (arg)
  58. (interactive "P")
  59. (calc-wrapper
  60. (calc-binary-op "in" 'calcFunc-in arg)))
  61. (defun calc-logical-and (arg)
  62. (interactive "P")
  63. (calc-wrapper
  64. (calc-binary-op "land" 'calcFunc-land arg 1)))
  65. (defun calc-logical-or (arg)
  66. (interactive "P")
  67. (calc-wrapper
  68. (calc-binary-op "lor" 'calcFunc-lor arg 0)))
  69. (defun calc-logical-not (arg)
  70. (interactive "P")
  71. (calc-wrapper
  72. (calc-unary-op "lnot" 'calcFunc-lnot arg)))
  73. (defun calc-logical-if ()
  74. (interactive)
  75. (calc-wrapper
  76. (calc-enter-result 3 "if" (cons 'calcFunc-if (calc-top-list-n 3)))))
  77. (defun calc-timing (n)
  78. (interactive "P")
  79. (calc-wrapper
  80. (calc-change-mode 'calc-timing n nil t)
  81. (message (if calc-timing
  82. "Reporting timing of slow commands in Trail"
  83. "Not reporting timing of commands"))))
  84. (defun calc-pass-errors ()
  85. (interactive)
  86. ;; The following two cases are for the new, optimizing byte compiler
  87. ;; or the standard 18.57 byte compiler, respectively.
  88. (condition-case err
  89. (let ((place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 15)))
  90. (or (memq (car-safe (car-safe place)) '(error xxxerror))
  91. (setq place (aref (nth 2 (nth 2 (symbol-function 'calc-do))) 27)))
  92. (or (memq (car (car place)) '(error xxxerror))
  93. (error "foo"))
  94. (setcar (car place) 'xxxerror))
  95. (error (error "The calc-do function has been modified; unable to patch"))))
  96. (defun calc-user-define ()
  97. (interactive)
  98. (message "Define user key: z-")
  99. (let ((key (read-char)))
  100. (if (= (calc-user-function-classify key) 0)
  101. (error "Can't redefine \"?\" key"))
  102. (let ((func (intern (completing-read (concat "Set key z "
  103. (char-to-string key)
  104. " to command: ")
  105. obarray
  106. 'commandp
  107. t
  108. "calc-"))))
  109. (let* ((kmap (calc-user-key-map))
  110. (old (assq key kmap)))
  111. (if old
  112. (setcdr old func)
  113. (setcdr kmap (cons (cons key func) (cdr kmap))))))))
  114. (defun calc-user-undefine ()
  115. (interactive)
  116. (message "Undefine user key: z-")
  117. (let ((key (read-char)))
  118. (if (= (calc-user-function-classify key) 0)
  119. (error "Can't undefine \"?\" key"))
  120. (let* ((kmap (calc-user-key-map)))
  121. (delq (or (assq key kmap)
  122. (assq (upcase key) kmap)
  123. (assq (downcase key) kmap)
  124. (error "No such user key is defined"))
  125. kmap))))
  126. ;; math-integral-cache-state is originally declared in calcalg2.el,
  127. ;; it is used in calc-user-define-variable.
  128. (defvar math-integral-cache-state)
  129. ;; calc-user-formula-alist is local to calc-user-define-formula,
  130. ;; calc-user-define-composition and calc-finish-formula-edit,
  131. ;; but is used by calc-fix-user-formula.
  132. (defvar calc-user-formula-alist)
  133. (defun calc-user-define-formula ()
  134. (interactive)
  135. (calc-wrapper
  136. (let* ((form (calc-top 1))
  137. (math-arglist nil)
  138. (is-lambda (and (eq (car-safe form) 'calcFunc-lambda)
  139. (>= (length form) 2)))
  140. odef key keyname cmd cmd-base cmd-base-default
  141. func calc-user-formula-alist is-symb)
  142. (if is-lambda
  143. (setq math-arglist (mapcar (function (lambda (x) (nth 1 x)))
  144. (nreverse (cdr (reverse (cdr form)))))
  145. form (nth (1- (length form)) form))
  146. (calc-default-formula-arglist form)
  147. (setq math-arglist (sort math-arglist 'string-lessp)))
  148. (message "Define user key: z-")
  149. (setq key (read-char))
  150. (if (= (calc-user-function-classify key) 0)
  151. (error "Can't redefine \"?\" key"))
  152. (setq key (and (not (memq key '(13 32))) key)
  153. keyname (and key
  154. (if (or (and (<= ?0 key) (<= key ?9))
  155. (and (<= ?a key) (<= key ?z))
  156. (and (<= ?A key) (<= key ?Z)))
  157. (char-to-string key)
  158. (format "%03d" key)))
  159. odef (assq key (calc-user-key-map)))
  160. (unless keyname
  161. (setq keyname (format "%05d" (abs (% (random) 10000)))))
  162. (while
  163. (progn
  164. (setq cmd-base-default (concat "User-" keyname))
  165. (setq cmd (completing-read
  166. (concat "Define M-x command name (default calc-"
  167. cmd-base-default
  168. "): ")
  169. obarray 'commandp nil
  170. (if (and odef (symbolp (cdr odef)))
  171. (symbol-name (cdr odef))
  172. "calc-")))
  173. (if (or (string-equal cmd "")
  174. (string-equal cmd "calc-"))
  175. (setq cmd (concat "calc-User-" keyname)))
  176. (setq cmd-base (and (string-match "\\`calc-\\(.+\\)\\'" cmd)
  177. (math-match-substring cmd 1)))
  178. (setq cmd (intern cmd))
  179. (and cmd
  180. (fboundp cmd)
  181. odef
  182. (not
  183. (y-or-n-p
  184. (if (get cmd 'calc-user-defn)
  185. (concat "Replace previous definition for "
  186. (symbol-name cmd) "? ")
  187. "That name conflicts with a built-in Emacs function. Replace this function? "))))))
  188. (while
  189. (progn
  190. (setq cmd-base-default
  191. (if cmd-base
  192. (if (string-match
  193. "\\`User-.+" cmd-base)
  194. (concat
  195. "User"
  196. (substring cmd-base 5))
  197. cmd-base)
  198. (concat "User" keyname)))
  199. (setq func
  200. (concat "calcFunc-"
  201. (completing-read
  202. (concat "Define algebraic function name (default "
  203. cmd-base-default "): ")
  204. (mapcar (lambda (x) (substring x 9))
  205. (all-completions "calcFunc-"
  206. obarray))
  207. (lambda (x)
  208. (fboundp
  209. (intern (concat "calcFunc-" x))))
  210. nil)))
  211. (setq func
  212. (if (string-equal func "calcFunc-")
  213. (intern (concat "calcFunc-" cmd-base-default))
  214. (intern func)))
  215. (and func
  216. (fboundp func)
  217. (not (fboundp cmd))
  218. odef
  219. (not
  220. (y-or-n-p
  221. (if (get func 'calc-user-defn)
  222. (concat "Replace previous definition for "
  223. (symbol-name func) "? ")
  224. "That name conflicts with a built-in Emacs function. Replace this function? "))))))
  225. (if (not func)
  226. (setq func (intern (concat "calcFunc-User"
  227. (or keyname
  228. (and cmd (symbol-name cmd))
  229. (format "%05d" (% (random) 10000)))))))
  230. (if is-lambda
  231. (setq calc-user-formula-alist math-arglist)
  232. (while
  233. (progn
  234. (setq calc-user-formula-alist
  235. (read-from-minibuffer "Function argument list: "
  236. (if math-arglist
  237. (prin1-to-string math-arglist)
  238. "()")
  239. minibuffer-local-map
  240. t))
  241. (and (not (calc-subsetp calc-user-formula-alist math-arglist))
  242. (not (y-or-n-p
  243. "Okay for arguments that don't appear in formula to be ignored? "))))))
  244. (setq is-symb (and calc-user-formula-alist
  245. func
  246. (y-or-n-p
  247. "Leave it symbolic for non-constant arguments? ")))
  248. (setq calc-user-formula-alist
  249. (mapcar (function (lambda (x)
  250. (or (cdr (assq x '((nil . arg-nil)
  251. (t . arg-t))))
  252. x))) calc-user-formula-alist))
  253. (if cmd
  254. (progn
  255. (require 'calc-macs)
  256. (fset cmd
  257. (list 'lambda
  258. '()
  259. '(interactive)
  260. (list 'calc-wrapper
  261. (list 'calc-enter-result
  262. (length calc-user-formula-alist)
  263. (let ((name (symbol-name (or func cmd))))
  264. (and (string-match
  265. "\\([^-][^-]?[^-]?[^-]?\\)[^-]*\\'"
  266. name)
  267. (math-match-substring name 1)))
  268. (list 'cons
  269. (list 'quote func)
  270. (list 'calc-top-list-n
  271. (length calc-user-formula-alist)))))))
  272. (put cmd 'calc-user-defn t)))
  273. (let ((body (list 'math-normalize (calc-fix-user-formula form))))
  274. (fset func
  275. (append
  276. (list 'lambda calc-user-formula-alist)
  277. (and is-symb
  278. (mapcar (function (lambda (v)
  279. (list 'math-check-const v t)))
  280. calc-user-formula-alist))
  281. (list body))))
  282. (put func 'calc-user-defn form)
  283. (setq math-integral-cache-state nil)
  284. (if key
  285. (let* ((kmap (calc-user-key-map))
  286. (old (assq key kmap)))
  287. (if old
  288. (setcdr old cmd)
  289. (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
  290. (message "")))
  291. (defvar math-arglist) ; dynamically bound in all callers
  292. (defun calc-default-formula-arglist (form)
  293. (if (consp form)
  294. (if (eq (car form) 'var)
  295. (if (or (memq (nth 1 form) math-arglist)
  296. (math-const-var form))
  297. ()
  298. (setq math-arglist (cons (nth 1 form) math-arglist)))
  299. (calc-default-formula-arglist-step (cdr form)))))
  300. (defun calc-default-formula-arglist-step (l)
  301. (and l
  302. (progn
  303. (calc-default-formula-arglist (car l))
  304. (calc-default-formula-arglist-step (cdr l)))))
  305. (defun calc-subsetp (a b)
  306. (or (null a)
  307. (and (memq (car a) b)
  308. (calc-subsetp (cdr a) b))))
  309. (defun calc-fix-user-formula (f)
  310. (if (consp f)
  311. (let (temp)
  312. (cond ((and (eq (car f) 'var)
  313. (memq (setq temp (or (cdr (assq (nth 1 f) '((nil . arg-nil)
  314. (t . arg-t))))
  315. (nth 1 f)))
  316. calc-user-formula-alist))
  317. temp)
  318. ((or (math-constp f) (eq (car f) 'var))
  319. (list 'quote f))
  320. ((and (eq (car f) 'calcFunc-eval)
  321. (= (length f) 2))
  322. (list 'let '((calc-simplify-mode nil))
  323. (list 'math-normalize (calc-fix-user-formula (nth 1 f)))))
  324. ((and (eq (car f) 'calcFunc-evalsimp)
  325. (= (length f) 2))
  326. (list 'math-simplify (calc-fix-user-formula (nth 1 f))))
  327. ((and (eq (car f) 'calcFunc-evalextsimp)
  328. (= (length f) 2))
  329. (list 'math-simplify-extended
  330. (calc-fix-user-formula (nth 1 f))))
  331. (t
  332. (cons 'list
  333. (cons (list 'quote (car f))
  334. (mapcar 'calc-fix-user-formula (cdr f)))))))
  335. f))
  336. (defun calc-user-define-composition ()
  337. (interactive)
  338. (calc-wrapper
  339. (if (eq calc-language 'unform)
  340. (error "Can't define formats for unformatted mode"))
  341. (let* ((comp (calc-top 1))
  342. (func (intern
  343. (concat "calcFunc-"
  344. (completing-read "Define format for which function: "
  345. (mapcar (lambda (x) (substring x 9))
  346. (all-completions "calcFunc-"
  347. obarray))
  348. (lambda (x)
  349. (fboundp
  350. (intern (concat "calcFunc-" x))))))))
  351. (comps (get func 'math-compose-forms))
  352. entry entry2
  353. (math-arglist nil)
  354. (calc-user-formula-alist nil))
  355. (if (math-zerop comp)
  356. (if (setq entry (assq calc-language comps))
  357. (put func 'math-compose-forms (delq entry comps)))
  358. (calc-default-formula-arglist comp)
  359. (setq math-arglist (sort math-arglist 'string-lessp))
  360. (while
  361. (progn
  362. (setq calc-user-formula-alist
  363. (read-from-minibuffer "Composition argument list: "
  364. (if math-arglist
  365. (prin1-to-string math-arglist)
  366. "()")
  367. minibuffer-local-map
  368. t))
  369. (and (not (calc-subsetp calc-user-formula-alist math-arglist))
  370. (y-or-n-p
  371. "Okay for arguments that don't appear in formula to be invisible? "))))
  372. (or (setq entry (assq calc-language comps))
  373. (put func 'math-compose-forms
  374. (cons (setq entry (list calc-language)) comps)))
  375. (or (setq entry2 (assq (length calc-user-formula-alist) (cdr entry)))
  376. (setcdr entry
  377. (cons (setq entry2
  378. (list (length calc-user-formula-alist))) (cdr entry))))
  379. (setcdr entry2
  380. (list 'lambda calc-user-formula-alist (calc-fix-user-formula comp))))
  381. (calc-pop-stack 1)
  382. (calc-do-refresh))))
  383. (defun calc-user-define-kbd-macro (arg)
  384. (interactive "P")
  385. (or last-kbd-macro
  386. (error "No keyboard macro defined"))
  387. (message "Define last kbd macro on user key: z-")
  388. (let ((key (read-char)))
  389. (if (= (calc-user-function-classify key) 0)
  390. (error "Can't redefine \"?\" key"))
  391. (let ((cmd (intern (completing-read "Full name for new command: "
  392. obarray
  393. 'commandp
  394. nil
  395. (concat "calc-User-"
  396. (if (or (and (>= key ?a)
  397. (<= key ?z))
  398. (and (>= key ?A)
  399. (<= key ?Z))
  400. (and (>= key ?0)
  401. (<= key ?9)))
  402. (char-to-string key)
  403. (format "%03d" key)))))))
  404. (and (fboundp cmd)
  405. (not (let ((f (symbol-function cmd)))
  406. (or (stringp f)
  407. (and (consp f)
  408. (eq (car-safe (nth 3 f))
  409. 'calc-execute-kbd-macro)))))
  410. (error "Function %s is already defined and not a keyboard macro"
  411. cmd))
  412. (put cmd 'calc-user-defn t)
  413. (fset cmd (if (< (prefix-numeric-value arg) 0)
  414. last-kbd-macro
  415. (list 'lambda
  416. '(arg)
  417. '(interactive "P")
  418. (list 'calc-execute-kbd-macro
  419. (vector (key-description last-kbd-macro)
  420. last-kbd-macro)
  421. 'arg
  422. (format "z%c" key)))))
  423. (let* ((kmap (calc-user-key-map))
  424. (old (assq key kmap)))
  425. (if old
  426. (setcdr old cmd)
  427. (setcdr kmap (cons (cons key cmd) (cdr kmap))))))))
  428. (defun calc-edit-user-syntax ()
  429. (interactive)
  430. (calc-wrapper
  431. (let ((lang calc-language))
  432. (calc-edit-mode (list 'calc-finish-user-syntax-edit (list 'quote lang))
  433. t
  434. (format "Editing %s-Mode Syntax Table. "
  435. (cond ((null lang) "Normal")
  436. ((eq lang 'tex) "TeX")
  437. ((eq lang 'latex) "LaTeX")
  438. (t (capitalize (symbol-name lang))))))
  439. (calc-write-parse-table (cdr (assq lang calc-user-parse-tables))
  440. lang)))
  441. (calc-show-edit-buffer))
  442. (defvar calc-original-buffer)
  443. (defun calc-finish-user-syntax-edit (lang)
  444. (let ((tab (calc-read-parse-table calc-original-buffer lang))
  445. (entry (assq lang calc-user-parse-tables)))
  446. (if tab
  447. (setcdr (or entry
  448. (car (setq calc-user-parse-tables
  449. (cons (list lang) calc-user-parse-tables))))
  450. tab)
  451. (if entry
  452. (setq calc-user-parse-tables
  453. (delq entry calc-user-parse-tables)))))
  454. (switch-to-buffer calc-original-buffer))
  455. ;; The variable calc-lang is local to calc-write-parse-table, but is
  456. ;; used by calc-write-parse-table-part which is called by
  457. ;; calc-write-parse-table. The variable is also local to
  458. ;; calc-read-parse-table, but is used by calc-fix-token-name which
  459. ;; is called (indirectly) by calc-read-parse-table.
  460. (defvar calc-lang)
  461. (defun calc-write-parse-table (tab calc-lang)
  462. (let ((p tab))
  463. (while p
  464. (calc-write-parse-table-part (car (car p)))
  465. (insert ":= "
  466. (let ((math-format-hash-args t))
  467. (math-format-flat-expr (cdr (car p)) 0))
  468. "\n")
  469. (setq p (cdr p)))))
  470. (defun calc-write-parse-table-part (p)
  471. (while p
  472. (cond ((stringp (car p))
  473. (let ((s (car p)))
  474. (if (and (string-match "\\`\\\\dots\\>" s)
  475. (not (memq calc-lang '(tex latex))))
  476. (setq s (concat ".." (substring s 5))))
  477. (if (or (and (string-match
  478. "[a-zA-Z0-9\"{}]\\|\\`:=\\'\\|\\`#\\|\\`%%" s)
  479. (string-match "[^a-zA-Z0-9\\]" s))
  480. (and (assoc s '((")") ("]") (">")))
  481. (not (cdr p))))
  482. (insert (prin1-to-string s) " ")
  483. (insert s " "))))
  484. ((integerp (car p))
  485. (insert "#")
  486. (or (= (car p) 0)
  487. (insert "/" (int-to-string (car p))))
  488. (insert " "))
  489. ((and (eq (car (car p)) '\?) (equal (car (nth 2 (car p))) "$$"))
  490. (insert (car (nth 1 (car p))) " "))
  491. (t
  492. (insert "{ ")
  493. (calc-write-parse-table-part (nth 1 (car p)))
  494. (insert "}" (symbol-name (car (car p))))
  495. (if (nth 2 (car p))
  496. (calc-write-parse-table-part (list (car (nth 2 (car p)))))
  497. (insert " "))))
  498. (setq p (cdr p))))
  499. (defun calc-read-parse-table (calc-buf calc-lang)
  500. (let ((tab nil))
  501. (while (progn
  502. (skip-chars-forward "\n\t ")
  503. (not (eobp)))
  504. (if (looking-at "%%")
  505. (end-of-line)
  506. (let ((pt (point))
  507. (p (calc-read-parse-table-part ":=[\n\t ]+" ":=")))
  508. (or (stringp (car p))
  509. (and (integerp (car p))
  510. (stringp (nth 1 p)))
  511. (progn
  512. (goto-char pt)
  513. (error "Malformed syntax rule")))
  514. (let ((pos (point)))
  515. (end-of-line)
  516. (let* ((str (buffer-substring pos (point)))
  517. (exp (with-current-buffer calc-buf
  518. (let ((calc-user-parse-tables nil)
  519. (calc-language nil)
  520. (math-expr-opers (math-standard-ops))
  521. (calc-hashes-used 0))
  522. (math-read-expr
  523. (if (string-match ",[ \t]*\\'" str)
  524. (substring str 0 (match-beginning 0))
  525. str))))))
  526. (if (eq (car-safe exp) 'error)
  527. (progn
  528. (goto-char (+ pos (nth 1 exp)))
  529. (error (nth 2 exp))))
  530. (setq tab (nconc tab (list (cons p exp)))))))))
  531. tab))
  532. (defun calc-fix-token-name (name &optional unquoted)
  533. (cond ((string-match "\\`\\.\\." name)
  534. (concat "\\dots" (substring name 2)))
  535. ((and (equal name "{") (memq calc-lang '(tex latex eqn)))
  536. "(")
  537. ((and (equal name "}") (memq calc-lang '(tex latex eqn)))
  538. ")")
  539. ((and (equal name "&") (memq calc-lang '(tex latex)))
  540. ",")
  541. ((equal name "#")
  542. (search-backward "#")
  543. (error "Token '#' is reserved"))
  544. ((and unquoted (string-match "#" name))
  545. (error "Tokens containing '#' must be quoted"))
  546. ((not (string-match "[^ ]" name))
  547. (search-backward "\"" nil t)
  548. (error "Blank tokens are not allowed"))
  549. (t name)))
  550. (defun calc-read-parse-table-part (term eterm)
  551. (let ((part nil)
  552. (quoted nil))
  553. (while (progn
  554. (skip-chars-forward "\n\t ")
  555. (if (eobp) (error "Expected '%s'" eterm))
  556. (not (looking-at term)))
  557. (cond ((looking-at "%%")
  558. (end-of-line))
  559. ((looking-at "{[\n\t ]")
  560. (forward-char 2)
  561. (let ((p (calc-read-parse-table-part "}" "}")))
  562. (or (looking-at "[+*?]")
  563. (error "Expected '+', '*', or '?'"))
  564. (let ((sym (intern (buffer-substring (point) (1+ (point))))))
  565. (forward-char 1)
  566. (looking-at "[^\n\t ]*")
  567. (let ((sep (buffer-substring (point) (match-end 0))))
  568. (goto-char (match-end 0))
  569. (and (eq sym '\?) (> (length sep) 0)
  570. (not (equal sep "$")) (not (equal sep "."))
  571. (error "Separator not allowed with { ... }?"))
  572. (if (string-match "\\`\"" sep)
  573. (setq sep (read-from-string sep)))
  574. (if (> (length sep) 0)
  575. (setq sep (calc-fix-token-name sep)))
  576. (setq part (nconc part
  577. (list (list sym p
  578. (and (> (length sep) 0)
  579. (cons sep p))))))))))
  580. ((looking-at "}")
  581. (error "Too many }'s"))
  582. ((looking-at "\"")
  583. (setq quoted (calc-fix-token-name (read (current-buffer)))
  584. part (nconc part (list quoted))))
  585. ((looking-at "#\\(\\(/[0-9]+\\)?\\)[\n\t ]")
  586. (setq part (nconc part (list (if (= (match-beginning 1)
  587. (match-end 1))
  588. 0
  589. (string-to-number
  590. (buffer-substring
  591. (1+ (match-beginning 1))
  592. (match-end 1)))))))
  593. (goto-char (match-end 0)))
  594. ((looking-at ":=[\n\t ]")
  595. (error "Misplaced ':='"))
  596. (t
  597. (looking-at "[^\n\t ]*")
  598. (let ((end (match-end 0)))
  599. (setq part (nconc part (list (calc-fix-token-name
  600. (buffer-substring
  601. (point) end) t))))
  602. (goto-char end)))))
  603. (goto-char (match-end 0))
  604. (let ((len (length part)))
  605. (while (and (> len 1)
  606. (let ((last (nthcdr (setq len (1- len)) part)))
  607. (and (assoc (car last) '((")") ("]") (">")))
  608. (not (eq (car last) quoted))
  609. (setcar last
  610. (list '\? (list (car last)) '("$$"))))))))
  611. part))
  612. (defun calc-user-define-invocation ()
  613. (interactive)
  614. (or last-kbd-macro
  615. (error "No keyboard macro defined"))
  616. (setq calc-invocation-macro last-kbd-macro)
  617. (message "Use `C-x * Z' to invoke this macro"))
  618. (defun calc-user-define-edit ()
  619. (interactive) ; but no calc-wrapper!
  620. (message "Edit definition of command: z-")
  621. (let* (cmdname
  622. (key (read-char))
  623. (def (or (assq key (calc-user-key-map))
  624. (assq (upcase key) (calc-user-key-map))
  625. (assq (downcase key) (calc-user-key-map))
  626. (error "No command defined for that key")))
  627. (cmd (cdr def)))
  628. (when (symbolp cmd)
  629. (setq cmdname (symbol-name cmd))
  630. (setq cmd (symbol-function cmd)))
  631. (cond ((or (stringp cmd)
  632. (and (consp cmd)
  633. (eq (car-safe (nth 3 cmd)) 'calc-execute-kbd-macro)))
  634. (let* ((mac (elt (nth 1 (nth 3 cmd)) 1))
  635. (str (edmacro-format-keys mac t))
  636. (kys (nth 3 (nth 3 cmd))))
  637. (calc-edit-mode
  638. (list 'calc-edit-macro-finish-edit cmdname kys)
  639. t (format (concat
  640. "Editing keyboard macro (%s, bound to %s).\n"
  641. "Original keys: %s \n")
  642. cmdname kys (elt (nth 1 (nth 3 cmd)) 0)))
  643. (insert str "\n")
  644. (calc-edit-format-macro-buffer)
  645. (calc-show-edit-buffer)))
  646. (t (let* ((func (calc-stack-command-p cmd))
  647. (defn (and func
  648. (symbolp func)
  649. (get func 'calc-user-defn)))
  650. (kys (concat "z" (char-to-string (car def))))
  651. (intcmd (symbol-name (cdr def)))
  652. (algcmd (if func (substring (symbol-name func) 9) "")))
  653. (if (and defn (calc-valid-formula-func func))
  654. (let ((niceexpr (math-format-nice-expr defn (frame-width))))
  655. (calc-wrapper
  656. (calc-edit-mode
  657. (list 'calc-finish-formula-edit (list 'quote func))
  658. nil
  659. (format (concat
  660. "Editing formula (%s, %s, bound to %s).\n"
  661. "Original formula: %s\n")
  662. intcmd algcmd kys niceexpr))
  663. (insert (math-showing-full-precision
  664. niceexpr)
  665. "\n"))
  666. (calc-show-edit-buffer))
  667. (error "That command's definition cannot be edited")))))))
  668. ;; Formatting the macro buffer
  669. (defvar calc-edit-top)
  670. (defun calc-edit-macro-repeats ()
  671. (goto-char calc-edit-top)
  672. (while
  673. (re-search-forward "^\\([0-9]+\\)\\*" nil t)
  674. (let ((num (string-to-number (match-string 1)))
  675. (line (buffer-substring (point) (line-end-position))))
  676. (goto-char (line-beginning-position))
  677. (kill-line 1)
  678. (while (> num 0)
  679. (insert line "\n")
  680. (setq num (1- num))))))
  681. (defun calc-edit-macro-adjust-buffer ()
  682. (calc-edit-macro-repeats)
  683. (goto-char calc-edit-top)
  684. (while (re-search-forward "^RET$" nil t)
  685. (delete-char 1))
  686. (goto-char calc-edit-top)
  687. (while (and (re-search-forward "^$" nil t)
  688. (not (= (point) (point-max))))
  689. (delete-char 1)))
  690. (defun calc-edit-macro-command ()
  691. "Return the command on the current line in a Calc macro editing buffer."
  692. (let ((beg (line-beginning-position))
  693. (end (save-excursion
  694. (if (search-forward ";;" (line-end-position) 1)
  695. (forward-char -2))
  696. (skip-chars-backward " \t")
  697. (point))))
  698. (buffer-substring beg end)))
  699. (defun calc-edit-macro-command-type ()
  700. "Return the type of command on the current line in a Calc macro editing buffer."
  701. (let ((beg (save-excursion
  702. (if (search-forward ";;" (line-end-position) t)
  703. (progn
  704. (skip-chars-forward " \t")
  705. (point)))))
  706. (end (save-excursion
  707. (goto-char (line-end-position))
  708. (skip-chars-backward " \t")
  709. (point))))
  710. (if beg
  711. (buffer-substring beg end)
  712. "")))
  713. (defun calc-edit-macro-combine-alg-ent ()
  714. "Put an entire algebraic entry on a single line."
  715. (let ((line (calc-edit-macro-command))
  716. (type (calc-edit-macro-command-type))
  717. curline
  718. match)
  719. (goto-char (line-beginning-position))
  720. (kill-line 1)
  721. (setq curline (calc-edit-macro-command))
  722. (while (and curline
  723. (not (string-equal "RET" curline))
  724. (not (setq match (string-match "<return>" curline))))
  725. (setq line (concat line curline))
  726. (kill-line 1)
  727. (setq curline (calc-edit-macro-command)))
  728. (when match
  729. (kill-line 1)
  730. (setq line (concat line (substring curline 0 match))))
  731. (setq line (replace-regexp-in-string "SPC" " SPC "
  732. (replace-regexp-in-string " " "" line)))
  733. (insert line "\t\t\t")
  734. (if (> (current-column) 24)
  735. (delete-char -1))
  736. (insert ";; " type "\n")
  737. (if match
  738. (insert "RET\t\t\t;; calc-enter\n"))))
  739. (defun calc-edit-macro-combine-ext-command ()
  740. "Put an entire extended command on a single line."
  741. (let ((cmdbeg (calc-edit-macro-command))
  742. (line "")
  743. (type (calc-edit-macro-command-type))
  744. curline
  745. match)
  746. (goto-char (line-beginning-position))
  747. (kill-line 1)
  748. (setq curline (calc-edit-macro-command))
  749. (while (and curline
  750. (not (string-equal "RET" curline))
  751. (not (setq match (string-match "<return>" curline))))
  752. (setq line (concat line curline))
  753. (kill-line 1)
  754. (setq curline (calc-edit-macro-command)))
  755. (when match
  756. (kill-line 1)
  757. (setq line (concat line (substring curline 0 match))))
  758. (setq line (replace-regexp-in-string " " "" line))
  759. (insert cmdbeg " " line "\t\t\t")
  760. (if (> (current-column) 24)
  761. (delete-char -1))
  762. (insert ";; " type "\n")
  763. (if match
  764. (insert "RET\t\t\t;; calc-enter\n"))))
  765. (defun calc-edit-macro-combine-var-name ()
  766. "Put an entire variable name on a single line."
  767. (let ((line (calc-edit-macro-command))
  768. curline
  769. match)
  770. (goto-char (line-beginning-position))
  771. (kill-line 1)
  772. (if (member line '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))
  773. (insert line "\t\t\t;; calc quick variable\n")
  774. (setq curline (calc-edit-macro-command))
  775. (while (and curline
  776. (not (string-equal "RET" curline))
  777. (not (setq match (string-match "<return>" curline))))
  778. (setq line (concat line curline))
  779. (kill-line 1)
  780. (setq curline (calc-edit-macro-command)))
  781. (when match
  782. (kill-line 1)
  783. (setq line (concat line (substring curline 0 match))))
  784. (setq line (replace-regexp-in-string " " "" line))
  785. (insert line "\t\t\t")
  786. (if (> (current-column) 24)
  787. (delete-char -1))
  788. (insert ";; calc variable\n")
  789. (if match
  790. (insert "RET\t\t\t;; calc-enter\n")))))
  791. (defun calc-edit-macro-combine-digits ()
  792. "Put an entire sequence of digits on a single line."
  793. (let ((line (calc-edit-macro-command))
  794. curline)
  795. (goto-char (line-beginning-position))
  796. (kill-line 1)
  797. (while (string-equal (calc-edit-macro-command-type) "calcDigit-start")
  798. (setq line (concat line (calc-edit-macro-command)))
  799. (kill-line 1))
  800. (insert line "\t\t\t")
  801. (if (> (current-column) 24)
  802. (delete-char -1))
  803. (insert ";; calc digits\n")))
  804. (defun calc-edit-format-macro-buffer ()
  805. "Rewrite the Calc macro editing buffer."
  806. (calc-edit-macro-adjust-buffer)
  807. (goto-char calc-edit-top)
  808. (let ((type (calc-edit-macro-command-type)))
  809. (while (not (string-equal type ""))
  810. (cond
  811. ((or
  812. (string-equal type "calc-algebraic-entry")
  813. (string-equal type "calc-auto-algebraic-entry"))
  814. (calc-edit-macro-combine-alg-ent))
  815. ((string-equal type "calc-execute-extended-command")
  816. (calc-edit-macro-combine-ext-command))
  817. ((string-equal type "calcDigit-start")
  818. (calc-edit-macro-combine-digits))
  819. ((or
  820. (string-equal type "calc-store")
  821. (string-equal type "calc-store-into")
  822. (string-equal type "calc-store-neg")
  823. (string-equal type "calc-store-plus")
  824. (string-equal type "calc-store-minus")
  825. (string-equal type "calc-store-div")
  826. (string-equal type "calc-store-times")
  827. (string-equal type "calc-store-power")
  828. (string-equal type "calc-store-concat")
  829. (string-equal type "calc-store-inv")
  830. (string-equal type "calc-store-dec")
  831. (string-equal type "calc-store-incr")
  832. (string-equal type "calc-store-exchange")
  833. (string-equal type "calc-unstore")
  834. (string-equal type "calc-recall")
  835. (string-equal type "calc-let")
  836. (string-equal type "calc-permanent-variable"))
  837. (forward-line 1)
  838. (calc-edit-macro-combine-var-name))
  839. ((or
  840. (string-equal type "calc-copy-variable")
  841. (string-equal type "calc-copy-special-constant")
  842. (string-equal type "calc-declare-variable"))
  843. (forward-line 1)
  844. (calc-edit-macro-combine-var-name)
  845. (calc-edit-macro-combine-var-name))
  846. (t (forward-line 1)))
  847. (setq type (calc-edit-macro-command-type))))
  848. (goto-char calc-edit-top))
  849. ;; Finish editing the macro
  850. (defun calc-edit-macro-pre-finish-edit ()
  851. (goto-char calc-edit-top)
  852. (while (re-search-forward "\\(^\\| \\)RET\\($\\|\t\\| \\)" nil t)
  853. (search-backward "RET")
  854. (delete-char 3)
  855. (insert "<return>")))
  856. (defun calc-edit-macro-finish-edit (cmdname key)
  857. "Finish editing a Calc macro.
  858. Redefine the corresponding command."
  859. (interactive)
  860. (let ((cmd (intern cmdname)))
  861. (calc-edit-macro-pre-finish-edit)
  862. (let* ((str (buffer-substring calc-edit-top (point-max)))
  863. (mac (edmacro-parse-keys str t)))
  864. (if (= (length mac) 0)
  865. (fmakunbound cmd)
  866. (fset cmd
  867. (list 'lambda '(arg)
  868. '(interactive "P")
  869. (list 'calc-execute-kbd-macro
  870. (vector (key-description mac)
  871. mac)
  872. 'arg key)))))))
  873. (defun calc-finish-formula-edit (func)
  874. (let ((buf (current-buffer))
  875. (str (buffer-substring calc-edit-top (point-max)))
  876. (start (point))
  877. (body (calc-valid-formula-func func)))
  878. (set-buffer calc-original-buffer)
  879. (let ((val (math-read-expr str)))
  880. (if (eq (car-safe val) 'error)
  881. (progn
  882. (set-buffer buf)
  883. (goto-char (+ start (nth 1 val)))
  884. (error (nth 2 val))))
  885. (setcar (cdr body)
  886. (let ((calc-user-formula-alist (nth 1 (symbol-function func))))
  887. (calc-fix-user-formula val)))
  888. (put func 'calc-user-defn val))))
  889. (defun calc-valid-formula-func (func)
  890. (let ((def (symbol-function func)))
  891. (and (consp def)
  892. (eq (car def) 'lambda)
  893. (progn
  894. (setq def (cdr (cdr def)))
  895. (while (and def
  896. (not (eq (car (car def)) 'math-normalize)))
  897. (setq def (cdr def)))
  898. (car def)))))
  899. (defun calc-get-user-defn ()
  900. (interactive)
  901. (calc-wrapper
  902. (message "Get definition of command: z-")
  903. (let* ((key (read-char))
  904. (def (or (assq key (calc-user-key-map))
  905. (assq (upcase key) (calc-user-key-map))
  906. (assq (downcase key) (calc-user-key-map))
  907. (error "No command defined for that key")))
  908. (cmd (cdr def)))
  909. (if (symbolp cmd)
  910. (setq cmd (symbol-function cmd)))
  911. (cond ((stringp cmd)
  912. (message "Keyboard macro: %s" cmd))
  913. (t (let* ((func (calc-stack-command-p cmd))
  914. (defn (and func
  915. (symbolp func)
  916. (get func 'calc-user-defn))))
  917. (if defn
  918. (progn
  919. (and (calc-valid-formula-func func)
  920. (setq defn (append '(calcFunc-lambda)
  921. (mapcar 'math-build-var-name
  922. (nth 1 (symbol-function
  923. func)))
  924. (list defn))))
  925. (calc-enter-result 0 "gdef" defn))
  926. (error "That command is not defined by a formula"))))))))
  927. (defun calc-user-define-permanent ()
  928. (interactive)
  929. (calc-wrapper
  930. (message "Record in %s the command: z-" calc-settings-file)
  931. (let* ((key (read-char))
  932. (def (or (assq key (calc-user-key-map))
  933. (assq (upcase key) (calc-user-key-map))
  934. (assq (downcase key) (calc-user-key-map))
  935. (and (eq key ?\')
  936. (cons nil
  937. (intern
  938. (concat "calcFunc-"
  939. (completing-read
  940. (format "Record in %s the algebraic function: "
  941. calc-settings-file)
  942. (mapcar (lambda (x) (substring x 9))
  943. (all-completions "calcFunc-"
  944. obarray))
  945. (lambda (x)
  946. (fboundp
  947. (intern (concat "calcFunc-" x))))
  948. t)))))
  949. (and (eq key ?\M-x)
  950. (cons nil
  951. (intern (completing-read
  952. (format "Record in %s the command: "
  953. calc-settings-file)
  954. obarray 'fboundp nil "calc-"))))
  955. (error "No command defined for that key"))))
  956. (set-buffer (find-file-noselect (substitute-in-file-name
  957. calc-settings-file)))
  958. (goto-char (point-max))
  959. (let* ((cmd (cdr def))
  960. (fcmd (and cmd (symbolp cmd) (symbol-function cmd)))
  961. (func nil)
  962. (pt (point))
  963. (fill-column 70)
  964. (fill-prefix nil)
  965. str q-ok)
  966. (insert "\n;;; Definition stored by Calc on " (current-time-string)
  967. "\n(put 'calc-define '"
  968. (if (symbolp cmd) (symbol-name cmd) (format "key%d" key))
  969. " '(progn\n")
  970. (if (and fcmd
  971. (eq (car-safe fcmd) 'lambda)
  972. (get cmd 'calc-user-defn))
  973. (let ((pt (point)))
  974. (and (eq (car-safe (nth 3 fcmd)) 'calc-execute-kbd-macro)
  975. (vectorp (nth 1 (nth 3 fcmd)))
  976. (progn (and (fboundp 'edit-kbd-macro)
  977. (edit-kbd-macro nil))
  978. (fboundp 'edmacro-parse-keys))
  979. (setq q-ok t)
  980. (aset (nth 1 (nth 3 fcmd)) 1 nil))
  981. (insert (setq str (prin1-to-string
  982. (cons 'defun (cons cmd (cdr fcmd)))))
  983. "\n")
  984. (or (and (string-match "\"" str) (not q-ok))
  985. (fill-region pt (point)))
  986. (indent-rigidly pt (point) 2)
  987. (delete-region pt (1+ pt))
  988. (insert " (put '" (symbol-name cmd)
  989. " 'calc-user-defn '"
  990. (prin1-to-string (get cmd 'calc-user-defn))
  991. ")\n")
  992. (setq func (calc-stack-command-p cmd))
  993. (let ((ffunc (and func (symbolp func) (symbol-function func)))
  994. (pt (point)))
  995. (and ffunc
  996. (eq (car-safe ffunc) 'lambda)
  997. (get func 'calc-user-defn)
  998. (progn
  999. (insert (setq str (prin1-to-string
  1000. (cons 'defun (cons func
  1001. (cdr ffunc)))))
  1002. "\n")
  1003. (or (and (string-match "\"" str) (not q-ok))
  1004. (fill-region pt (point)))
  1005. (indent-rigidly pt (point) 2)
  1006. (delete-region pt (1+ pt))
  1007. (setq pt (point))
  1008. (insert "(put '" (symbol-name func)
  1009. " 'calc-user-defn '"
  1010. (prin1-to-string (get func 'calc-user-defn))
  1011. ")\n")
  1012. (fill-region pt (point))
  1013. (indent-rigidly pt (point) 2)
  1014. (delete-region pt (1+ pt))))))
  1015. (and (stringp fcmd)
  1016. (insert " (fset '" (prin1-to-string cmd)
  1017. " " (prin1-to-string fcmd) ")\n")))
  1018. (or func (setq func (and cmd (symbolp cmd) (fboundp cmd) cmd)))
  1019. (if (get func 'math-compose-forms)
  1020. (let ((pt (point)))
  1021. (insert "(put '" (symbol-name cmd)
  1022. " 'math-compose-forms '"
  1023. (prin1-to-string (get func 'math-compose-forms))
  1024. ")\n")
  1025. (fill-region pt (point))
  1026. (indent-rigidly pt (point) 2)
  1027. (delete-region pt (1+ pt))))
  1028. (if (car def)
  1029. (insert " (define-key calc-mode-map "
  1030. (prin1-to-string (concat "z" (char-to-string key)))
  1031. " '"
  1032. (prin1-to-string cmd)
  1033. ")\n")))
  1034. (insert "))\n")
  1035. (save-buffer))))
  1036. (defun calc-stack-command-p (cmd)
  1037. (if (and cmd (symbolp cmd))
  1038. (and (fboundp cmd)
  1039. (calc-stack-command-p (symbol-function cmd)))
  1040. (and (consp cmd)
  1041. (eq (car cmd) 'lambda)
  1042. (setq cmd (or (assq 'calc-wrapper cmd)
  1043. (assq 'calc-slow-wrapper cmd)))
  1044. (setq cmd (assq 'calc-enter-result cmd))
  1045. (memq (car (nth 3 cmd)) '(cons list))
  1046. (eq (car (nth 1 (nth 3 cmd))) 'quote)
  1047. (nth 1 (nth 1 (nth 3 cmd))))))
  1048. (defun calc-call-last-kbd-macro (arg)
  1049. (interactive "P")
  1050. (and defining-kbd-macro
  1051. (error "Can't execute anonymous macro while defining one"))
  1052. (or last-kbd-macro
  1053. (error "No kbd macro has been defined"))
  1054. (calc-execute-kbd-macro last-kbd-macro arg))
  1055. (defun calc-execute-kbd-macro (mac arg &rest prefix)
  1056. (if calc-keep-args-flag
  1057. (calc-keep-args))
  1058. (if (and (vectorp mac) (> (length mac) 0) (stringp (aref mac 0)))
  1059. (setq mac (or (aref mac 1)
  1060. (aset mac 1 (progn (and (fboundp 'edit-kbd-macro)
  1061. (edit-kbd-macro nil))
  1062. (edmacro-parse-keys (aref mac 0)))))))
  1063. (if (< (prefix-numeric-value arg) 0)
  1064. (execute-kbd-macro mac (- (prefix-numeric-value arg)))
  1065. (if calc-executing-macro
  1066. (execute-kbd-macro mac arg)
  1067. (calc-slow-wrapper
  1068. (let ((old-stack-whole (copy-sequence calc-stack))
  1069. (old-stack-top calc-stack-top)
  1070. (old-buffer-size (buffer-size))
  1071. (old-refresh-count calc-refresh-count))
  1072. (unwind-protect
  1073. (let ((calc-executing-macro mac))
  1074. (execute-kbd-macro mac arg))
  1075. (calc-select-buffer)
  1076. (let ((new-stack (reverse calc-stack))
  1077. (old-stack (reverse old-stack-whole)))
  1078. (while (and new-stack old-stack
  1079. (equal (car new-stack) (car old-stack)))
  1080. (setq new-stack (cdr new-stack)
  1081. old-stack (cdr old-stack)))
  1082. (or (equal prefix '(nil))
  1083. (calc-record-list (if (> (length new-stack) 1)
  1084. (mapcar 'car new-stack)
  1085. '(""))
  1086. (or (car prefix) "kmac")))
  1087. (calc-record-undo (list 'set 'saved-stack-top old-stack-top))
  1088. (and old-stack
  1089. (calc-record-undo (list 'pop 1 (mapcar 'car old-stack))))
  1090. (let ((calc-stack old-stack-whole)
  1091. (calc-stack-top 0))
  1092. (calc-cursor-stack-index (length old-stack)))
  1093. (if (and (= old-buffer-size (buffer-size))
  1094. (= old-refresh-count calc-refresh-count))
  1095. (let ((buffer-read-only nil))
  1096. (delete-region (point) (point-max))
  1097. (while new-stack
  1098. (calc-record-undo (list 'push 1))
  1099. (insert (math-format-stack-value (car new-stack)) "\n")
  1100. (setq new-stack (cdr new-stack)))
  1101. (calc-renumber-stack))
  1102. (while new-stack
  1103. (calc-record-undo (list 'push 1))
  1104. (setq new-stack (cdr new-stack)))
  1105. (calc-refresh))
  1106. (calc-record-undo (list 'set 'saved-stack-top 0)))))))))
  1107. (defun calc-push-list-in-macro (vals m sels)
  1108. (let ((entry (list (car vals) 1 (car sels)))
  1109. (mm (+ (or m 1) calc-stack-top)))
  1110. (if (> mm 1)
  1111. (setcdr (nthcdr (- mm 2) calc-stack)
  1112. (cons entry (nthcdr (1- mm) calc-stack)))
  1113. (setq calc-stack (cons entry calc-stack)))))
  1114. (defun calc-pop-stack-in-macro (n mm)
  1115. (if (> mm 1)
  1116. (setcdr (nthcdr (- mm 2) calc-stack)
  1117. (nthcdr (+ n mm -1) calc-stack))
  1118. (setq calc-stack (nthcdr n calc-stack))))
  1119. (defun calc-kbd-if ()
  1120. (interactive)
  1121. (calc-wrapper
  1122. (let ((cond (calc-top-n 1)))
  1123. (calc-pop-stack 1)
  1124. (if (math-is-true cond)
  1125. (if defining-kbd-macro
  1126. (message "If true..."))
  1127. (if defining-kbd-macro
  1128. (message "Condition is false; skipping to Z: or Z] ..."))
  1129. (calc-kbd-skip-to-else-if t)))))
  1130. (defun calc-kbd-else-if ()
  1131. (interactive)
  1132. (calc-kbd-if))
  1133. (defun calc-kbd-skip-to-else-if (else-okay)
  1134. (let ((count 0)
  1135. ch)
  1136. (while (>= count 0)
  1137. (setq ch (read-char))
  1138. (if (= ch -1)
  1139. (error "Unterminated Z[ in keyboard macro"))
  1140. (if (= ch ?Z)
  1141. (progn
  1142. (setq ch (read-char))
  1143. (cond ((= ch ?\[)
  1144. (setq count (1+ count)))
  1145. ((= ch ?\])
  1146. (setq count (1- count)))
  1147. ((= ch ?\:)
  1148. (and (= count 0)
  1149. else-okay
  1150. (setq count -1)))
  1151. ((eq ch 7)
  1152. (keyboard-quit))))))
  1153. (and defining-kbd-macro
  1154. (if (= ch ?\:)
  1155. (message "Else...")
  1156. (message "End-if...")))))
  1157. (defun calc-kbd-end-if ()
  1158. (interactive)
  1159. (if defining-kbd-macro
  1160. (message "End-if...")))
  1161. (defun calc-kbd-else ()
  1162. (interactive)
  1163. (if defining-kbd-macro
  1164. (message "Else; skipping to Z] ..."))
  1165. (calc-kbd-skip-to-else-if nil))
  1166. (defun calc-kbd-repeat ()
  1167. (interactive)
  1168. (let (count)
  1169. (calc-wrapper
  1170. (setq count (math-trunc (calc-top-n 1)))
  1171. (or (Math-integerp count)
  1172. (error "Count must be an integer"))
  1173. (if (Math-integer-negp count)
  1174. (setq count 0))
  1175. (or (integerp count)
  1176. (setq count 1000000))
  1177. (calc-pop-stack 1))
  1178. (calc-kbd-loop count)))
  1179. (defun calc-kbd-for (dir)
  1180. (interactive "P")
  1181. (let (init final)
  1182. (calc-wrapper
  1183. (setq init (calc-top-n 2)
  1184. final (calc-top-n 1))
  1185. (or (and (math-anglep init) (math-anglep final))
  1186. (error "Initial and final values must be real numbers"))
  1187. (calc-pop-stack 2))
  1188. (calc-kbd-loop nil init final (and dir (prefix-numeric-value dir)))))
  1189. (defun calc-kbd-loop (rpt-count &optional initial final dir)
  1190. (interactive "P")
  1191. (setq rpt-count (if rpt-count (prefix-numeric-value rpt-count) 1000000))
  1192. (let* ((count 0)
  1193. (parts nil)
  1194. (body "")
  1195. (open last-command-event)
  1196. (counter initial)
  1197. ch)
  1198. (or executing-kbd-macro
  1199. (message "Reading loop body..."))
  1200. (while (>= count 0)
  1201. (setq ch (read-char))
  1202. (if (= ch -1)
  1203. (error "Unterminated Z%c in keyboard macro" open))
  1204. (if (= ch ?Z)
  1205. (progn
  1206. (setq ch (read-char)
  1207. body (concat body "Z" (char-to-string ch)))
  1208. (cond ((memq ch '(?\< ?\( ?\{))
  1209. (setq count (1+ count)))
  1210. ((memq ch '(?\> ?\) ?\}))
  1211. (setq count (1- count)))
  1212. ((and (= ch ?/)
  1213. (= count 0))
  1214. (setq parts (nconc parts (list (concat (substring body 0 -2)
  1215. "Z]")))
  1216. body ""))
  1217. ((eq ch 7)
  1218. (keyboard-quit))))
  1219. (setq body (concat body (char-to-string ch)))))
  1220. (if (/= ch (cdr (assq open '( (?\< . ?\>) (?\( . ?\)) (?\{ . ?\}) ))))
  1221. (error "Mismatched Z%c and Z%c in keyboard macro" open ch))
  1222. (or executing-kbd-macro
  1223. (message "Looping..."))
  1224. (setq body (concat (substring body 0 -2) "Z]"))
  1225. (and (not executing-kbd-macro)
  1226. (= rpt-count 1000000)
  1227. (null parts)
  1228. (null counter)
  1229. (progn
  1230. (message "Warning: Infinite loop! Not executing")
  1231. (setq rpt-count 0)))
  1232. (or (not initial) dir
  1233. (setq dir (math-compare final initial)))
  1234. (calc-wrapper
  1235. (while (> rpt-count 0)
  1236. (let ((part parts))
  1237. (if counter
  1238. (if (cond ((eq dir 0) (Math-equal final counter))
  1239. ((eq dir 1) (Math-lessp final counter))
  1240. ((eq dir -1) (Math-lessp counter final)))
  1241. (setq rpt-count 0)
  1242. (calc-push counter)))
  1243. (while (and part (> rpt-count 0))
  1244. (execute-kbd-macro (car part))
  1245. (if (math-is-true (calc-top-n 1))
  1246. (setq rpt-count 0)
  1247. (setq part (cdr part)))
  1248. (calc-pop-stack 1))
  1249. (if (> rpt-count 0)
  1250. (progn
  1251. (execute-kbd-macro body)
  1252. (if counter
  1253. (let ((step (calc-top-n 1)))
  1254. (calc-pop-stack 1)
  1255. (setq counter (calcFunc-add counter step)))
  1256. (setq rpt-count (1- rpt-count))))))))
  1257. (or executing-kbd-macro
  1258. (message "Looping...done"))))
  1259. (defun calc-kbd-end-repeat ()
  1260. (interactive)
  1261. (error "Unbalanced Z> in keyboard macro"))
  1262. (defun calc-kbd-end-for ()
  1263. (interactive)
  1264. (error "Unbalanced Z) in keyboard macro"))
  1265. (defun calc-kbd-end-loop ()
  1266. (interactive)
  1267. (error "Unbalanced Z} in keyboard macro"))
  1268. (defun calc-kbd-break ()
  1269. (interactive)
  1270. (calc-wrapper
  1271. (let ((cond (calc-top-n 1)))
  1272. (calc-pop-stack 1)
  1273. (if (math-is-true cond)
  1274. (error "Keyboard macro aborted")))))
  1275. (defvar calc-kbd-push-level 0)
  1276. ;; The variables var-q0 through var-q9 are the "quick" variables.
  1277. (defvar var-q0 nil)
  1278. (defvar var-q1 nil)
  1279. (defvar var-q2 nil)
  1280. (defvar var-q3 nil)
  1281. (defvar var-q4 nil)
  1282. (defvar var-q5 nil)
  1283. (defvar var-q6 nil)
  1284. (defvar var-q7 nil)
  1285. (defvar var-q8 nil)
  1286. (defvar var-q9 nil)
  1287. (defun calc-kbd-push (arg)
  1288. (interactive "P")
  1289. (calc-wrapper
  1290. (let* ((defs (and arg (> (prefix-numeric-value arg) 0)))
  1291. (var-q0 var-q0)
  1292. (var-q1 var-q1)
  1293. (var-q2 var-q2)
  1294. (var-q3 var-q3)
  1295. (var-q4 var-q4)
  1296. (var-q5 var-q5)
  1297. (var-q6 var-q6)
  1298. (var-q7 var-q7)
  1299. (var-q8 var-q8)
  1300. (var-q9 var-q9)
  1301. (calc-internal-prec (if defs 12 calc-internal-prec))
  1302. (calc-word-size (if defs 32 calc-word-size))
  1303. (calc-angle-mode (if defs 'deg calc-angle-mode))
  1304. (calc-simplify-mode (if defs nil calc-simplify-mode))
  1305. (calc-algebraic-mode (if arg nil calc-algebraic-mode))
  1306. (calc-incomplete-algebraic-mode (if arg nil
  1307. calc-incomplete-algebraic-mode))
  1308. (calc-symbolic-mode (if defs nil calc-symbolic-mode))
  1309. (calc-matrix-mode (if defs nil calc-matrix-mode))
  1310. (calc-prefer-frac (if defs nil calc-prefer-frac))
  1311. (calc-complex-mode (if defs nil calc-complex-mode))
  1312. (calc-infinite-mode (if defs nil calc-infinite-mode))
  1313. (count 0)
  1314. (body "")
  1315. ch)
  1316. (if (or executing-kbd-macro defining-kbd-macro)
  1317. (progn
  1318. (if defining-kbd-macro
  1319. (message "Reading body..."))
  1320. (while (>= count 0)
  1321. (setq ch (read-char))
  1322. (if (= ch -1)
  1323. (error "Unterminated Z` in keyboard macro"))
  1324. (if (= ch ?Z)
  1325. (progn
  1326. (setq ch (read-char)
  1327. body (concat body "Z" (char-to-string ch)))
  1328. (cond ((eq ch ?\`)
  1329. (setq count (1+ count)))
  1330. ((eq ch ?\')
  1331. (setq count (1- count)))
  1332. ((eq ch 7)
  1333. (keyboard-quit))))
  1334. (setq body (concat body (char-to-string ch)))))
  1335. (if defining-kbd-macro
  1336. (message "Reading body...done"))
  1337. (let ((calc-kbd-push-level 0))
  1338. (execute-kbd-macro (substring body 0 -2))))
  1339. (let ((calc-kbd-push-level (1+ calc-kbd-push-level)))
  1340. (message "Saving modes; type Z' to restore")
  1341. (recursive-edit))))))
  1342. (defun calc-kbd-pop ()
  1343. (interactive)
  1344. (if (> calc-kbd-push-level 0)
  1345. (progn
  1346. (message "Mode settings restored")
  1347. (exit-recursive-edit))
  1348. (error "Unbalanced Z' in keyboard macro")))
  1349. ;; (defun calc-kbd-report (msg)
  1350. ;; (interactive "sMessage: ")
  1351. ;; (calc-wrapper
  1352. ;; (math-working msg (calc-top-n 1))))
  1353. (defun calc-kbd-query ()
  1354. (interactive)
  1355. (let ((defining-kbd-macro nil)
  1356. (executing-kbd-macro nil)
  1357. (msg (calc-top 1)))
  1358. (if (not (eq (car-safe msg) 'vec))
  1359. (error "No prompt string provided")
  1360. (setq msg (math-vector-to-string msg))
  1361. (calc-wrapper
  1362. (calc-pop-stack 1)
  1363. (calc-alg-entry nil (and (not (equal msg "")) msg))))))
  1364. ;;;; Logical operations.
  1365. (defun calcFunc-eq (a b &rest more)
  1366. (if more
  1367. (let* ((args (cons a (cons b (copy-sequence more))))
  1368. (res 1)
  1369. (p args)
  1370. p2)
  1371. (while (and (cdr p) (not (eq res 0)))
  1372. (setq p2 p)
  1373. (while (and (setq p2 (cdr p2)) (not (eq res 0)))
  1374. (setq res (math-two-eq (car p) (car p2)))
  1375. (if (eq res 1)
  1376. (setcdr p (delq (car p2) (cdr p)))))
  1377. (setq p (cdr p)))
  1378. (if (eq res 0)
  1379. 0
  1380. (if (cdr args)
  1381. (cons 'calcFunc-eq args)
  1382. 1)))
  1383. (or (math-two-eq a b)
  1384. (if (and (or (math-looks-negp a) (math-zerop a))
  1385. (or (math-looks-negp b) (math-zerop b)))
  1386. (list 'calcFunc-eq (math-neg a) (math-neg b))
  1387. (list 'calcFunc-eq a b)))))
  1388. (defun calcFunc-neq (a b &rest more)
  1389. (if more
  1390. (let* ((args (cons a (cons b more)))
  1391. (res 0)
  1392. (all t)
  1393. (p args)
  1394. p2)
  1395. (while (and (cdr p) (not (eq res 1)))
  1396. (setq p2 p)
  1397. (while (and (setq p2 (cdr p2)) (not (eq res 1)))
  1398. (setq res (math-two-eq (car p) (car p2)))
  1399. (or res (setq all nil)))
  1400. (setq p (cdr p)))
  1401. (if (eq res 1)
  1402. 0
  1403. (if all
  1404. 1
  1405. (cons 'calcFunc-neq args))))
  1406. (or (cdr (assq (math-two-eq a b) '((0 . 1) (1 . 0))))
  1407. (if (and (or (math-looks-negp a) (math-zerop a))
  1408. (or (math-looks-negp b) (math-zerop b)))
  1409. (list 'calcFunc-neq (math-neg a) (math-neg b))
  1410. (list 'calcFunc-neq a b)))))
  1411. (defun math-two-eq (a b)
  1412. (if (eq (car-safe a) 'vec)
  1413. (if (eq (car-safe b) 'vec)
  1414. (if (= (length a) (length b))
  1415. (let ((res 1))
  1416. (while (and (setq a (cdr a) b (cdr b)) (not (eq res 0)))
  1417. (if res
  1418. (setq res (math-two-eq (car a) (car b)))
  1419. (if (eq (math-two-eq (car a) (car b)) 0)
  1420. (setq res 0))))
  1421. res)
  1422. 0)
  1423. (if (Math-objectp b)
  1424. 0
  1425. nil))
  1426. (if (eq (car-safe b) 'vec)
  1427. (if (Math-objectp a)
  1428. 0
  1429. nil)
  1430. (let ((res (math-compare a b)))
  1431. (if (= res 0)
  1432. 1
  1433. (if (and (= res 2) (not (and (Math-scalarp a) (Math-scalarp b))))
  1434. nil
  1435. 0))))))
  1436. (defun calcFunc-lt (a b)
  1437. (let ((res (math-compare a b)))
  1438. (if (= res -1)
  1439. 1
  1440. (if (= res 2)
  1441. (if (and (or (math-looks-negp a) (math-zerop a))
  1442. (or (math-looks-negp b) (math-zerop b)))
  1443. (list 'calcFunc-gt (math-neg a) (math-neg b))
  1444. (list 'calcFunc-lt a b))
  1445. 0))))
  1446. (defun calcFunc-gt (a b)
  1447. (let ((res (math-compare a b)))
  1448. (if (= res 1)
  1449. 1
  1450. (if (= res 2)
  1451. (if (and (or (math-looks-negp a) (math-zerop a))
  1452. (or (math-looks-negp b) (math-zerop b)))
  1453. (list 'calcFunc-lt (math-neg a) (math-neg b))
  1454. (list 'calcFunc-gt a b))
  1455. 0))))
  1456. (defun calcFunc-leq (a b)
  1457. (let ((res (math-compare a b)))
  1458. (if (= res 1)
  1459. 0
  1460. (if (= res 2)
  1461. (if (and (or (math-looks-negp a) (math-zerop a))
  1462. (or (math-looks-negp b) (math-zerop b)))
  1463. (list 'calcFunc-geq (math-neg a) (math-neg b))
  1464. (list 'calcFunc-leq a b))
  1465. 1))))
  1466. (defun calcFunc-geq (a b)
  1467. (let ((res (math-compare a b)))
  1468. (if (= res -1)
  1469. 0
  1470. (if (= res 2)
  1471. (if (and (or (math-looks-negp a) (math-zerop a))
  1472. (or (math-looks-negp b) (math-zerop b)))
  1473. (list 'calcFunc-leq (math-neg a) (math-neg b))
  1474. (list 'calcFunc-geq a b))
  1475. 1))))
  1476. (defun calcFunc-rmeq (a)
  1477. (if (math-vectorp a)
  1478. (math-map-vec 'calcFunc-rmeq a)
  1479. (if (assq (car-safe a) calc-tweak-eqn-table)
  1480. (if (and (eq (car-safe (nth 2 a)) 'var)
  1481. (math-objectp (nth 1 a)))
  1482. (nth 1 a)
  1483. (nth 2 a))
  1484. (if (eq (car-safe a) 'calcFunc-assign)
  1485. (nth 2 a)
  1486. (if (eq (car-safe a) 'calcFunc-evalto)
  1487. (nth 1 a)
  1488. (list 'calcFunc-rmeq a))))))
  1489. (defun calcFunc-land (a b)
  1490. (cond ((Math-zerop a)
  1491. a)
  1492. ((Math-zerop b)
  1493. b)
  1494. ((math-is-true a)
  1495. b)
  1496. ((math-is-true b)
  1497. a)
  1498. (t (list 'calcFunc-land a b))))
  1499. (defun calcFunc-lor (a b)
  1500. (cond ((Math-zerop a)
  1501. b)
  1502. ((Math-zerop b)
  1503. a)
  1504. ((math-is-true a)
  1505. a)
  1506. ((math-is-true b)
  1507. b)
  1508. (t (list 'calcFunc-lor a b))))
  1509. (defun calcFunc-lnot (a)
  1510. (if (Math-zerop a)
  1511. 1
  1512. (if (math-is-true a)
  1513. 0
  1514. (let ((op (and (= (length a) 3)
  1515. (assq (car a) calc-tweak-eqn-table))))
  1516. (if op
  1517. (cons (nth 2 op) (cdr a))
  1518. (list 'calcFunc-lnot a))))))
  1519. (defun calcFunc-if (c e1 e2)
  1520. (if (Math-zerop c)
  1521. e2
  1522. (if (and (math-is-true c) (not (Math-vectorp c)))
  1523. e1
  1524. (or (and (Math-vectorp c)
  1525. (math-constp c)
  1526. (let ((ee1 (if (Math-vectorp e1)
  1527. (if (= (length c) (length e1))
  1528. (cdr e1)
  1529. (calc-record-why "*Dimension error" e1))
  1530. (list e1)))
  1531. (ee2 (if (Math-vectorp e2)
  1532. (if (= (length c) (length e2))
  1533. (cdr e2)
  1534. (calc-record-why "*Dimension error" e2))
  1535. (list e2))))
  1536. (and ee1 ee2
  1537. (cons 'vec (math-if-vector (cdr c) ee1 ee2)))))
  1538. (list 'calcFunc-if c e1 e2)))))
  1539. (defun math-if-vector (c e1 e2)
  1540. (and c
  1541. (cons (if (Math-zerop (car c)) (car e2) (car e1))
  1542. (math-if-vector (cdr c)
  1543. (or (cdr e1) e1)
  1544. (or (cdr e2) e2)))))
  1545. (defun math-normalize-logical-op (a)
  1546. (or (and (eq (car a) 'calcFunc-if)
  1547. (= (length a) 4)
  1548. (let ((a1 (math-normalize (nth 1 a))))
  1549. (if (Math-zerop a1)
  1550. (math-normalize (nth 3 a))
  1551. (if (Math-numberp a1)
  1552. (math-normalize (nth 2 a))
  1553. (if (and (Math-vectorp (nth 1 a))
  1554. (math-constp (nth 1 a)))
  1555. (calcFunc-if (nth 1 a)
  1556. (math-normalize (nth 2 a))
  1557. (math-normalize (nth 3 a)))
  1558. (let ((calc-simplify-mode 'none))
  1559. (list 'calcFunc-if a1
  1560. (math-normalize (nth 2 a))
  1561. (math-normalize (nth 3 a)))))))))
  1562. a))
  1563. (defun calcFunc-in (a b)
  1564. (or (and (eq (car-safe b) 'vec)
  1565. (let ((bb b))
  1566. (while (and (setq bb (cdr bb))
  1567. (not (if (memq (car-safe (car bb)) '(vec intv))
  1568. (eq (calcFunc-in a (car bb)) 1)
  1569. (Math-equal a (car bb))))))
  1570. (if bb 1 (and (math-constp a) (math-constp bb) 0))))
  1571. (and (eq (car-safe b) 'intv)
  1572. (let ((res (math-compare a (nth 2 b))) res2)
  1573. (cond ((= res -1)
  1574. 0)
  1575. ((and (= res 0)
  1576. (or (/= (nth 1 b) 2)
  1577. (Math-lessp (nth 2 b) (nth 3 b))))
  1578. (if (memq (nth 1 b) '(2 3)) 1 0))
  1579. ((= (setq res2 (math-compare a (nth 3 b))) 1)
  1580. 0)
  1581. ((and (= res2 0)
  1582. (or (/= (nth 1 b) 1)
  1583. (Math-lessp (nth 2 b) (nth 3 b))))
  1584. (if (memq (nth 1 b) '(1 3)) 1 0))
  1585. ((/= res 1)
  1586. nil)
  1587. ((/= res2 -1)
  1588. nil)
  1589. (t 1))))
  1590. (and (Math-equal a b)
  1591. 1)
  1592. (and (math-constp a) (math-constp b)
  1593. 0)
  1594. (list 'calcFunc-in a b)))
  1595. (defun calcFunc-typeof (a)
  1596. (cond ((Math-integerp a) 1)
  1597. ((eq (car a) 'frac) 2)
  1598. ((eq (car a) 'float) 3)
  1599. ((eq (car a) 'hms) 4)
  1600. ((eq (car a) 'cplx) 5)
  1601. ((eq (car a) 'polar) 6)
  1602. ((eq (car a) 'sdev) 7)
  1603. ((eq (car a) 'intv) 8)
  1604. ((eq (car a) 'mod) 9)
  1605. ((eq (car a) 'date) (if (Math-integerp (nth 1 a)) 10 11))
  1606. ((eq (car a) 'var)
  1607. (if (memq (nth 2 a) '(var-inf var-uinf var-nan)) 12 100))
  1608. ((eq (car a) 'vec) (if (math-matrixp a) 102 101))
  1609. (t (math-calcFunc-to-var (car a)))))
  1610. (defun calcFunc-integer (a)
  1611. (if (Math-integerp a)
  1612. 1
  1613. (if (Math-objvecp a)
  1614. 0
  1615. (list 'calcFunc-integer a))))
  1616. (defun calcFunc-real (a)
  1617. (if (Math-realp a)
  1618. 1
  1619. (if (Math-objvecp a)
  1620. 0
  1621. (list 'calcFunc-real a))))
  1622. (defun calcFunc-constant (a)
  1623. (if (math-constp a)
  1624. 1
  1625. (if (Math-objvecp a)
  1626. 0
  1627. (list 'calcFunc-constant a))))
  1628. (defun calcFunc-refers (a b)
  1629. (if (math-expr-contains a b)
  1630. 1
  1631. (if (eq (car-safe a) 'var)
  1632. (list 'calcFunc-refers a b)
  1633. 0)))
  1634. (defun calcFunc-negative (a)
  1635. (if (math-looks-negp a)
  1636. 1
  1637. (if (or (math-zerop a)
  1638. (math-posp a))
  1639. 0
  1640. (list 'calcFunc-negative a))))
  1641. (defun calcFunc-variable (a)
  1642. (if (eq (car-safe a) 'var)
  1643. 1
  1644. (if (Math-objvecp a)
  1645. 0
  1646. (list 'calcFunc-variable a))))
  1647. (defun calcFunc-nonvar (a)
  1648. (if (eq (car-safe a) 'var)
  1649. (list 'calcFunc-nonvar a)
  1650. 1))
  1651. (defun calcFunc-istrue (a)
  1652. (if (math-is-true a)
  1653. 1
  1654. 0))
  1655. ;;;; User-programmability.
  1656. ;;; Compiling Lisp-like forms to use the math library.
  1657. (defun math-do-defmath (func args body)
  1658. (require 'calc-macs)
  1659. (let* ((fname (intern (concat "calcFunc-" (symbol-name func))))
  1660. (doc (if (stringp (car body)) (list (car body))))
  1661. (clargs (mapcar 'math-clean-arg args))
  1662. (body (math-define-function-body
  1663. (if (stringp (car body)) (cdr body) body)
  1664. clargs)))
  1665. (list 'progn
  1666. (if (and (consp (car body))
  1667. (eq (car (car body)) 'interactive))
  1668. (let ((inter (car body)))
  1669. (setq body (cdr body))
  1670. (if (or (> (length inter) 2)
  1671. (integerp (nth 1 inter)))
  1672. (let ((hasprefix nil) (hasmulti nil))
  1673. (if (stringp (nth 1 inter))
  1674. (progn
  1675. (cond ((equal (nth 1 inter) "p")
  1676. (setq hasprefix t))
  1677. ((equal (nth 1 inter) "m")
  1678. (setq hasmulti t))
  1679. (t (error
  1680. "Can't handle interactive code string \"%s\""
  1681. (nth 1 inter))))
  1682. (setq inter (cdr inter))))
  1683. (if (not (integerp (nth 1 inter)))
  1684. (error
  1685. "Expected an integer in interactive specification"))
  1686. (append (list 'defun
  1687. (intern (concat "calc-"
  1688. (symbol-name func)))
  1689. (if (or hasprefix hasmulti)
  1690. '(&optional n)
  1691. ()))
  1692. doc
  1693. (if (or hasprefix hasmulti)
  1694. '((interactive "P"))
  1695. '((interactive)))
  1696. (list
  1697. (append
  1698. '(calc-slow-wrapper)
  1699. (and hasmulti
  1700. (list
  1701. (list 'setq
  1702. 'n
  1703. (list 'if
  1704. 'n
  1705. (list 'prefix-numeric-value
  1706. 'n)
  1707. (nth 1 inter)))))
  1708. (list
  1709. (list 'calc-enter-result
  1710. (if hasmulti 'n (nth 1 inter))
  1711. (nth 2 inter)
  1712. (if hasprefix
  1713. (list 'append
  1714. (list 'quote (list fname))
  1715. (list 'calc-top-list-n
  1716. (nth 1 inter))
  1717. (list 'and
  1718. 'n
  1719. (list
  1720. 'list
  1721. (list
  1722. 'math-normalize
  1723. (list
  1724. 'prefix-numeric-value
  1725. 'n)))))
  1726. (list 'cons
  1727. (list 'quote fname)
  1728. (list 'calc-top-list-n
  1729. (if hasmulti
  1730. 'n
  1731. (nth 1 inter)))))))))))
  1732. (append (list 'defun
  1733. (intern (concat "calc-" (symbol-name func)))
  1734. args)
  1735. doc
  1736. (list
  1737. inter
  1738. (cons 'calc-wrapper body))))))
  1739. (append (list 'defun fname clargs)
  1740. doc
  1741. (math-do-arg-list-check args nil nil)
  1742. body))))
  1743. (defun math-clean-arg (arg)
  1744. (if (consp arg)
  1745. (math-clean-arg (nth 1 arg))
  1746. arg))
  1747. (defun math-do-arg-check (arg var is-opt is-rest)
  1748. (if is-opt
  1749. (let ((chk (math-do-arg-check arg var nil nil)))
  1750. (list (cons 'and
  1751. (cons var
  1752. (if (cdr chk)
  1753. (setq chk (list (cons 'progn chk)))
  1754. chk)))))
  1755. (and (consp arg)
  1756. (let* ((rest (math-do-arg-check (nth 1 arg) var is-opt is-rest))
  1757. (qual (car arg))
  1758. (qqual (list 'quote qual))
  1759. (qual-name (symbol-name qual))
  1760. (chk (intern (concat "math-check-" qual-name))))
  1761. (if (fboundp chk)
  1762. (append rest
  1763. (list
  1764. (if is-rest
  1765. (list 'setq var
  1766. (list 'mapcar (list 'quote chk) var))
  1767. (list 'setq var (list chk var)))))
  1768. (if (fboundp (setq chk (intern (concat "math-" qual-name))))
  1769. (append rest
  1770. (list
  1771. (if is-rest
  1772. (list 'mapcar
  1773. (list 'function
  1774. (list 'lambda '(x)
  1775. (list 'or
  1776. (list chk 'x)
  1777. (list 'math-reject-arg
  1778. 'x qqual))))
  1779. var)
  1780. (list 'or
  1781. (list chk var)
  1782. (list 'math-reject-arg var qqual)))))
  1783. (if (and (string-match "\\`not-\\(.*\\)\\'" qual-name)
  1784. (fboundp (setq chk (intern
  1785. (concat "math-"
  1786. (math-match-substring
  1787. qual-name 1))))))
  1788. (append rest
  1789. (list
  1790. (if is-rest
  1791. (list 'mapcar
  1792. (list 'function
  1793. (list 'lambda '(x)
  1794. (list 'and
  1795. (list chk 'x)
  1796. (list 'math-reject-arg
  1797. 'x qqual))))
  1798. var)
  1799. (list 'and
  1800. (list chk var)
  1801. (list 'math-reject-arg var qqual)))))
  1802. (error "Unknown qualifier `%s'" qual-name))))))))
  1803. (defun math-do-arg-list-check (args is-opt is-rest)
  1804. (cond ((null args) nil)
  1805. ((consp (car args))
  1806. (append (math-do-arg-check (car args)
  1807. (math-clean-arg (car args))
  1808. is-opt is-rest)
  1809. (math-do-arg-list-check (cdr args) is-opt is-rest)))
  1810. ((eq (car args) '&optional)
  1811. (math-do-arg-list-check (cdr args) t nil))
  1812. ((eq (car args) '&rest)
  1813. (math-do-arg-list-check (cdr args) nil t))
  1814. (t (math-do-arg-list-check (cdr args) is-opt is-rest))))
  1815. (defconst math-prim-funcs
  1816. '( (~= . math-nearly-equal)
  1817. (% . math-mod)
  1818. (lsh . calcFunc-lsh)
  1819. (ash . calcFunc-ash)
  1820. (logand . calcFunc-and)
  1821. (logandc2 . calcFunc-diff)
  1822. (logior . calcFunc-or)
  1823. (logxor . calcFunc-xor)
  1824. (lognot . calcFunc-not)
  1825. (equal . equal) ; need to leave these ones alone!
  1826. (eq . eq)
  1827. (and . and)
  1828. (or . or)
  1829. (if . if)
  1830. (^ . math-pow)
  1831. (expt . math-pow)
  1832. ))
  1833. (defconst math-prim-vars
  1834. '( (nil . nil)
  1835. (t . t)
  1836. (&optional . &optional)
  1837. (&rest . &rest)
  1838. ))
  1839. (defun math-define-function-body (body env)
  1840. (let ((body (math-define-body body env)))
  1841. (if (math-body-refers-to body 'math-return)
  1842. (list (cons 'catch (cons '(quote math-return) body)))
  1843. body)))
  1844. ;; The variable math-exp-env is local to math-define-body, but is
  1845. ;; used by math-define-exp, which is called (indirectly) by
  1846. ;; by math-define-body.
  1847. (defvar math-exp-env)
  1848. (defun math-define-body (body math-exp-env)
  1849. (math-define-list body))
  1850. (defun math-define-list (body &optional quote)
  1851. (cond ((null body)
  1852. nil)
  1853. ((and (eq (car body) ':)
  1854. (stringp (nth 1 body)))
  1855. (cons (let* ((math-read-expr-quotes t)
  1856. (exp (math-read-plain-expr (nth 1 body) t)))
  1857. (math-define-exp exp))
  1858. (math-define-list (cdr (cdr body)))))
  1859. (quote
  1860. (cons (cond ((consp (car body))
  1861. (math-define-list (cdr body) t))
  1862. (t
  1863. (car body)))
  1864. (math-define-list (cdr body))))
  1865. (t
  1866. (cons (math-define-exp (car body))
  1867. (math-define-list (cdr body))))))
  1868. (defun math-define-exp (exp)
  1869. (cond ((consp exp)
  1870. (let ((func (car exp)))
  1871. (cond ((memq func '(quote function))
  1872. (if (and (consp (nth 1 exp))
  1873. (eq (car (nth 1 exp)) 'lambda))
  1874. (cons 'quote
  1875. (math-define-lambda (nth 1 exp) math-exp-env))
  1876. exp))
  1877. ((memq func '(let let* for foreach))
  1878. (let ((head (nth 1 exp))
  1879. (body (cdr (cdr exp))))
  1880. (if (memq func '(let let*))
  1881. ()
  1882. (setq func (cdr (assq func '((for . math-for)
  1883. (foreach . math-foreach)))))
  1884. (if (not (listp (car head)))
  1885. (setq head (list head))))
  1886. (macroexpand
  1887. (cons func
  1888. (cons (math-define-let head)
  1889. (math-define-body body
  1890. (nconc
  1891. (math-define-let-env head)
  1892. math-exp-env)))))))
  1893. ((and (memq func '(setq setf))
  1894. (math-complicated-lhs (cdr exp)))
  1895. (if (> (length exp) 3)
  1896. (cons 'progn (math-define-setf-list (cdr exp)))
  1897. (math-define-setf (nth 1 exp) (nth 2 exp))))
  1898. ((eq func 'condition-case)
  1899. (cons func
  1900. (cons (nth 1 exp)
  1901. (math-define-body (cdr (cdr exp))
  1902. (cons (nth 1 exp)
  1903. math-exp-env)))))
  1904. ((eq func 'cond)
  1905. (cons func
  1906. (math-define-cond (cdr exp))))
  1907. ((and (consp func) ; ('spam a b) == force use of plain spam
  1908. (eq (car func) 'quote))
  1909. (cons func (math-define-list (cdr exp))))
  1910. ((symbolp func)
  1911. (let ((args (math-define-list (cdr exp)))
  1912. (prim (assq func math-prim-funcs)))
  1913. (cond (prim
  1914. (cons (cdr prim) args))
  1915. ((eq func 'floatp)
  1916. (list 'eq (car args) '(quote float)))
  1917. ((eq func '+)
  1918. (math-define-binop 'math-add 0
  1919. (car args) (cdr args)))
  1920. ((eq func '-)
  1921. (if (= (length args) 1)
  1922. (cons 'math-neg args)
  1923. (math-define-binop 'math-sub 0
  1924. (car args) (cdr args))))
  1925. ((eq func '*)
  1926. (math-define-binop 'math-mul 1
  1927. (car args) (cdr args)))
  1928. ((eq func '/)
  1929. (math-define-binop 'math-div 1
  1930. (car args) (cdr args)))
  1931. ((eq func 'min)
  1932. (math-define-binop 'math-min 0
  1933. (car args) (cdr args)))
  1934. ((eq func 'max)
  1935. (math-define-binop 'math-max 0
  1936. (car args) (cdr args)))
  1937. ((eq func '<)
  1938. (if (and (math-numberp (nth 1 args))
  1939. (math-zerop (nth 1 args)))
  1940. (list 'math-negp (car args))
  1941. (cons 'math-lessp args)))
  1942. ((eq func '>)
  1943. (if (and (math-numberp (nth 1 args))
  1944. (math-zerop (nth 1 args)))
  1945. (list 'math-posp (car args))
  1946. (list 'math-lessp (nth 1 args) (nth 0 args))))
  1947. ((eq func '<=)
  1948. (list 'not
  1949. (if (and (math-numberp (nth 1 args))
  1950. (math-zerop (nth 1 args)))
  1951. (list 'math-posp (car args))
  1952. (list 'math-lessp
  1953. (nth 1 args) (nth 0 args)))))
  1954. ((eq func '>=)
  1955. (list 'not
  1956. (if (and (math-numberp (nth 1 args))
  1957. (math-zerop (nth 1 args)))
  1958. (list 'math-negp (car args))
  1959. (cons 'math-lessp args))))
  1960. ((eq func '=)
  1961. (if (and (math-numberp (nth 1 args))
  1962. (math-zerop (nth 1 args)))
  1963. (list 'math-zerop (nth 0 args))
  1964. (if (and (integerp (nth 1 args))
  1965. (/= (% (nth 1 args) 10) 0))
  1966. (cons 'math-equal-int args)
  1967. (cons 'math-equal args))))
  1968. ((eq func '/=)
  1969. (list 'not
  1970. (if (and (math-numberp (nth 1 args))
  1971. (math-zerop (nth 1 args)))
  1972. (list 'math-zerop (nth 0 args))
  1973. (if (and (integerp (nth 1 args))
  1974. (/= (% (nth 1 args) 10) 0))
  1975. (cons 'math-equal-int args)
  1976. (cons 'math-equal args)))))
  1977. ((eq func '1+)
  1978. (list 'math-add (car args) 1))
  1979. ((eq func '1-)
  1980. (list 'math-add (car args) -1))
  1981. ((eq func 'not) ; optimize (not (not x)) => x
  1982. (if (eq (car-safe args) func)
  1983. (car (nth 1 args))
  1984. (cons func args)))
  1985. ((and (eq func 'elt) (cdr (cdr args)))
  1986. (math-define-elt (car args) (cdr args)))
  1987. (t
  1988. (macroexpand
  1989. (let* ((name (symbol-name func))
  1990. (cfunc (intern (concat "calcFunc-" name)))
  1991. (mfunc (intern (concat "math-" name))))
  1992. (cond ((fboundp cfunc)
  1993. (cons cfunc args))
  1994. ((fboundp mfunc)
  1995. (cons mfunc args))
  1996. ((or (fboundp func)
  1997. (string-match "\\`calcFunc-.*" name))
  1998. (cons func args))
  1999. (t
  2000. (cons cfunc args)))))))))
  2001. (t (cons func (math-define-list (cdr exp))))))) ;;args
  2002. ((symbolp exp)
  2003. (let ((prim (assq exp math-prim-vars))
  2004. (name (symbol-name exp)))
  2005. (cond (prim
  2006. (cdr prim))
  2007. ((memq exp math-exp-env)
  2008. exp)
  2009. ((string-match "-" name)
  2010. exp)
  2011. (t
  2012. (intern (concat "var-" name))))))
  2013. ((integerp exp)
  2014. (if (or (<= exp -1000000) (>= exp 1000000))
  2015. (list 'quote (math-normalize exp))
  2016. exp))
  2017. (t exp)))
  2018. (defun math-define-cond (forms)
  2019. (and forms
  2020. (cons (math-define-list (car forms))
  2021. (math-define-cond (cdr forms)))))
  2022. (defun math-complicated-lhs (body)
  2023. (and body
  2024. (or (not (symbolp (car body)))
  2025. (math-complicated-lhs (cdr (cdr body))))))
  2026. (defun math-define-setf-list (body)
  2027. (and body
  2028. (cons (math-define-setf (nth 0 body) (nth 1 body))
  2029. (math-define-setf-list (cdr (cdr body))))))
  2030. (defun math-define-setf (place value)
  2031. (setq place (math-define-exp place)
  2032. value (math-define-exp value))
  2033. (cond ((symbolp place)
  2034. (list 'setq place value))
  2035. ((eq (car-safe place) 'nth)
  2036. (list 'setcar (list 'nthcdr (nth 1 place) (nth 2 place)) value))
  2037. ((eq (car-safe place) 'elt)
  2038. (list 'setcar (list 'nthcdr (nth 2 place) (nth 1 place)) value))
  2039. ((eq (car-safe place) 'car)
  2040. (list 'setcar (nth 1 place) value))
  2041. ((eq (car-safe place) 'cdr)
  2042. (list 'setcdr (nth 1 place) value))
  2043. (t
  2044. (error "Bad place form for setf: %s" place))))
  2045. (defun math-define-binop (op ident arg1 rest)
  2046. (if rest
  2047. (math-define-binop op ident
  2048. (list op arg1 (car rest))
  2049. (cdr rest))
  2050. (or arg1 ident)))
  2051. (defun math-define-let (vlist)
  2052. (and vlist
  2053. (cons (if (consp (car vlist))
  2054. (cons (car (car vlist))
  2055. (math-define-list (cdr (car vlist))))
  2056. (car vlist))
  2057. (math-define-let (cdr vlist)))))
  2058. (defun math-define-let-env (vlist)
  2059. (and vlist
  2060. (cons (if (consp (car vlist))
  2061. (car (car vlist))
  2062. (car vlist))
  2063. (math-define-let-env (cdr vlist)))))
  2064. (defun math-define-lambda (exp exp-env)
  2065. (nconc (list (nth 0 exp) ; 'lambda
  2066. (nth 1 exp)) ; arg list
  2067. (math-define-function-body (cdr (cdr exp))
  2068. (append (nth 1 exp) exp-env))))
  2069. (defun math-define-elt (seq idx)
  2070. (if idx
  2071. (math-define-elt (list 'elt seq (car idx)) (cdr idx))
  2072. seq))
  2073. ;;; Useful programming macros.
  2074. (defmacro math-while (head &rest body)
  2075. (let ((body (cons 'while (cons head body))))
  2076. (if (math-body-refers-to body 'math-break)
  2077. (cons 'catch (cons '(quote math-break) (list body)))
  2078. body)))
  2079. ;; (put 'math-while 'lisp-indent-hook 1)
  2080. (defmacro math-for (head &rest body)
  2081. (let ((body (if head
  2082. (math-handle-for head body)
  2083. (cons 'while (cons t body)))))
  2084. (if (math-body-refers-to body 'math-break)
  2085. (cons 'catch (cons '(quote math-break) (list body)))
  2086. body)))
  2087. ;; (put 'math-for 'lisp-indent-hook 1)
  2088. (defun math-handle-for (head body)
  2089. (let* ((var (nth 0 (car head)))
  2090. (init (nth 1 (car head)))
  2091. (limit (nth 2 (car head)))
  2092. (step (or (nth 3 (car head)) 1))
  2093. (body (if (cdr head)
  2094. (list (math-handle-for (cdr head) body))
  2095. body))
  2096. (all-ints (and (integerp init) (integerp limit) (integerp step)))
  2097. (const-limit (or (integerp limit)
  2098. (and (eq (car-safe limit) 'quote)
  2099. (math-realp (nth 1 limit)))))
  2100. (const-step (or (integerp step)
  2101. (and (eq (car-safe step) 'quote)
  2102. (math-realp (nth 1 step)))))
  2103. (save-limit (if const-limit limit (make-symbol "<limit>")))
  2104. (save-step (if const-step step (make-symbol "<step>"))))
  2105. (cons 'let
  2106. (cons (append (if const-limit nil (list (list save-limit limit)))
  2107. (if const-step nil (list (list save-step step)))
  2108. (list (list var init)))
  2109. (list
  2110. (cons 'while
  2111. (cons (if all-ints
  2112. (if (> step 0)
  2113. (list '<= var save-limit)
  2114. (list '>= var save-limit))
  2115. (list 'not
  2116. (if const-step
  2117. (if (or (math-posp step)
  2118. (math-posp
  2119. (cdr-safe step)))
  2120. (list 'math-lessp
  2121. save-limit
  2122. var)
  2123. (list 'math-lessp
  2124. var
  2125. save-limit))
  2126. (list 'if
  2127. (list 'math-posp
  2128. save-step)
  2129. (list 'math-lessp
  2130. save-limit
  2131. var)
  2132. (list 'math-lessp
  2133. var
  2134. save-limit)))))
  2135. (append body
  2136. (list (list 'setq
  2137. var
  2138. (list (if all-ints
  2139. '+
  2140. 'math-add)
  2141. var
  2142. save-step)))))))))))
  2143. (defmacro math-foreach (head &rest body)
  2144. (let ((body (math-handle-foreach head body)))
  2145. (if (math-body-refers-to body 'math-break)
  2146. (cons 'catch (cons '(quote math-break) (list body)))
  2147. body)))
  2148. ;; (put 'math-foreach 'lisp-indent-hook 1)
  2149. (defun math-handle-foreach (head body)
  2150. (let ((var (nth 0 (car head)))
  2151. (data (nth 1 (car head)))
  2152. (body (if (cdr head)
  2153. (list (math-handle-foreach (cdr head) body))
  2154. body)))
  2155. (cons 'let
  2156. (cons (list (list var data))
  2157. (list
  2158. (cons 'while
  2159. (cons var
  2160. (append body
  2161. (list (list 'setq
  2162. var
  2163. (list 'cdr var)))))))))))
  2164. (defun math-body-refers-to (body thing)
  2165. (or (equal body thing)
  2166. (and (consp body)
  2167. (or (math-body-refers-to (car body) thing)
  2168. (math-body-refers-to (cdr body) thing)))))
  2169. (defun math-break (&optional value)
  2170. (throw 'math-break value))
  2171. (defun math-return (&optional value)
  2172. (throw 'math-return value))
  2173. (defun math-composite-inequalities (x op)
  2174. (if (memq (nth 1 op) '(calcFunc-eq calcFunc-neq))
  2175. (if (eq (car x) (nth 1 op))
  2176. (append x (list (math-read-expr-level (nth 3 op))))
  2177. (throw 'syntax "Syntax error"))
  2178. (list 'calcFunc-in
  2179. (nth 2 x)
  2180. (if (memq (nth 1 op) '(calcFunc-lt calcFunc-leq))
  2181. (if (memq (car x) '(calcFunc-lt calcFunc-leq))
  2182. (math-make-intv
  2183. (+ (if (eq (car x) 'calcFunc-leq) 2 0)
  2184. (if (eq (nth 1 op) 'calcFunc-leq) 1 0))
  2185. (nth 1 x) (math-read-expr-level (nth 3 op)))
  2186. (throw 'syntax "Syntax error"))
  2187. (if (memq (car x) '(calcFunc-gt calcFunc-geq))
  2188. (math-make-intv
  2189. (+ (if (eq (nth 1 op) 'calcFunc-geq) 2 0)
  2190. (if (eq (car x) 'calcFunc-geq) 1 0))
  2191. (math-read-expr-level (nth 3 op)) (nth 1 x))
  2192. (throw 'syntax "Syntax error"))))))
  2193. (provide 'calc-prog)
  2194. ;;; calc-prog.el ends here