1 ;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;;
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;; The data in this file contains enhancements. ;;;;;
5 ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;;
6 ;;; All rights reserved ;;;;;
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 ;; ** (c) Copyright 1982 Massachusetts Institute of Technology **
13 ;;note in converting this file (originally suprv.lisp) to common lisp
14 ;;for the lisp machine, I removed a lot of the old stuff which did not
15 ;;apply, and tried to eliminate any / quoting. Most of the relevant
16 ;;stuff is in system.lisp for the lispm and nil friends.--wfs
20 #-gcl
(:compile-toplevel
:execute
)
21 (setq old-ibase
*read-base
* old-base
*print-base
*)
22 (setq *read-base
* 10.
*print-base
* 10.
))
24 (declare-top (special bindlist loclist errset
*mopl
*
25 $values $functions $arrays $gradefs $dependencies
26 $rules $props $ratvars
28 $gensumnum checkfactors $features featurel
29 tellratlist $dontfactor
30 dispflag savefile $%% $error
31 opers
*ratweights $ratweights
33 transp $contexts $setcheck $macros autoload
))
36 (defvar *refchkl
* nil
)
42 (defvar lessorder nil
)
43 (defvar greatorder nil
)
44 (defvar *in-translate-file
* nil
)
45 (defvar *linelabel
* nil
)
47 (defmvar $disptime nil
)
50 (defmvar $backtrace
'$backtrace
)
51 (defmvar $debugmode nil
)
53 (defmvar $loadprint nil
)
54 (defmvar $nolabels nil
)
55 (defmvar $aliases
'((mlist simp
)))
58 '((mlist simp
) $labels $values $functions $macros $arrays
59 $myoptions $props $aliases $rules $gradefs
60 $dependencies $let_rule_packages $structures
))
62 (defmvar $labels
(list '(mlist simp
)))
65 (defmvar $%
'$%
"The last out-line computed, corresponds to lisp *"
69 "The alphabetic prefix of the names of expressions typed by the user.")
71 (defmvar $outchar
'$%o
72 "The alphabetic prefix of the names of expressions returned by the system.")
74 (defmvar $linechar
'$%t
75 "The alphabetic prefix of the names of intermediate displayed expressions.")
77 (defmvar $linenum
1 "the line number of the last expression."
80 (defmvar $file_output_append nil
81 "Flag to tell file-writing functions whether to append or clobber the output file.")
83 ;; This version of meval* makes sure, that the facts from the global variable
84 ;; *local-signs* are cleared with a call to clearsign. The facts are added by
85 ;; asksign and friends. The function meval* is only used for top level
86 ;; evaluations. For other cases the function meval can be used.
88 (defmvar $ratvarswitch t
) ; If T, start an evaluation with a fresh list VARLIST.
91 ;; Make sure that clearsign is called after the evaluation.
93 (let (*refchkl
* checkfactors
)
94 (if $ratvarswitch
(setq varlist
(cdr $ratvars
)))
96 ;; Clear the facts from asksign and friends.
100 (setq *linelabel
* ($concat
'|| x $linenum
))
102 (when (or (null (cdr $labels
))
103 (when (member *linelabel
* (cddr $labels
) :test
#'equal
)
104 (setf $labels
(delete *linelabel
* $labels
:count
1 :test
#'eq
)) t
)
105 (not (eq *linelabel
* (cadr $labels
))))
106 (setq $labels
(cons (car $labels
) (cons *linelabel
* (cdr $labels
))))))
110 (mtell-open "(~A) " (subseq (print-invert-case *linelabel
*) 1)))
117 (defun addlabel (label)
118 (setq $labels
(cons (car $labels
) (cons label
(delete label
(cdr $labels
) :count
1 :test
#'eq
)))))
122 (do ((n (tyi) (tyi))) (nil)
123 (cond ((or (char= n
#\newline
) (and (> (char-code n
) 31) (char/= n
#\rubout
)))
125 ((char= n
#\page
) (format t
"~|") (throw 'retry nil
)))))
133 (princ (break-prompt))
135 (return (char= (tyi*) #\newline
)))
138 (defun checklabel (x) ; CHECKLABEL returns T iff label is not in use
141 (boundp ($concat
'|| x $linenum
)))))
143 (defun gctimep (timep tim
)
144 (cond ((and (eq timep
'$all
) (not (zerop tim
))) (princ (intl:gettext
"Total time = ")) t
)
145 (t (princ (intl:gettext
"Time = ")) nil
)))
147 ; Following GENERIC-AUTOLOAD is copied from orthopoly/orthopoly-init.lisp.
148 ; Previous version didn't take Clisp, CMUCL, or SBCL into account.
150 (defvar *autoloaded-files
* ())
152 (defun generic-autoload (file &aux type
)
153 (unless (member file
*autoloaded-files
* :test
#'equal
)
154 (push file
*autoloaded-files
*)
155 (setq file
(pathname (cdr file
)))
156 (setq type
(pathname-type file
))
157 (let ((bin-ext #+gcl
"o"
158 #+cmu
(c::backend-fasl-file-type c
::*target-backend
*)
161 #+openmcl
(pathname-type ccl
::*.fasl-pathname
*)
162 #+lispworks
(pathname-type (compile-file-pathname "foo.lisp"))
163 #-
(or gcl cmu clisp allegro openmcl lispworks
) ""))
164 (if (member type
(list bin-ext
"lisp" "lsp") :test
'equalp
)
165 (let ((*read-base
* 10.
)) #-sbcl
(load file
) #+sbcl
(with-compilation-unit nil
(load file
)))
168 (defvar autoload
'generic-autoload
)
170 (defun load-function (func mexprp
) ; The dynamic loader
171 (declare (ignore mexprp
))
172 (let ((file (get func
'autoload
)))
173 (if file
(funcall autoload
(cons func file
)))))
175 (defmspec $loadfile
(form)
176 (loadfile (namestring (maxima-string (meval (cadr form
)))) nil
177 (not (member $loadprint
'(nil $autoload
) :test
#'equal
))))
179 (defmfun $setup_autoload
(filename &rest functions
)
180 (let ((file ($file_search filename
)))
181 (dolist (func functions
)
182 (nonsymchk func
'$setup_autoload
)
183 (putprop (setq func
($verbify func
)) file
'autoload
)
184 (add2lnc func $props
)))
190 (mapcar #'(lambda (x)
192 (cond ((numberp x
) x
)
193 ((numberp (setq y
(car (errset (readlist (mexploden x
))))))
198 (defun mfboundp (func)
199 (or (mgetl func
'(mexpr mmacro
))
200 (getl func
'(translated-mmacro mfexpr
* mfexpr
*s
))))
202 (defun loadfile (file findp printp
)
203 (and findp
(member $loadprint
'(nil $loadfile
) :test
#'equal
) (setq printp nil
))
204 ;; Should really get the truename of FILE.
205 (if printp
(format t
(intl:gettext
"loadfile: loading ~A.~%") file
))
206 (let* ((path (pathname file
))
207 (*package
* (find-package :maxima
))
208 ($load_pathname path
)
210 (tem (errset #-sbcl
(load (pathname file
)) #+sbcl
(with-compilation-unit nil
(load (pathname file
))))))
211 (or tem
(merror (intl:gettext
"loadfile: failed to load ~A") (namestring path
)))
214 (defmfun $directory
(path)
215 (cons '(mlist) (mapcar 'namestring
(directory ($filename_merge path
)))))
217 (defmspec $kill
(form)
218 (clear) ;; get assume db into consistent state
219 (mapc #'kill1
(cdr form
))
222 ;;; The following *builtin- variables are used to keep/restore builtin
223 ;;; symbols and values during kill operations. Their values are set at
224 ;;; the end of init-cl.lisp, after all symbols have been defined.
226 (defvar *builtin-symbols
* nil
)
227 (defvar *builtin-symbol-props
* (make-hash-table))
228 (defvar *builtin-$props
* nil
)
229 (defvar *builtin-$rules
* nil
)
230 (defvar *builtin-symbols-with-values
* nil
)
231 (defvar *builtin-symbol-values
* (make-hash-table))
232 (defvar *builtin-numeric-constants
* '($%e $%pi $%phi $%gamma
))
234 (defun kill1-atom (x)
235 (let ((z (or (and (member x
(cdr $aliases
) :test
#'equal
) (get x
'noun
)) (get x
'verb
))))
236 (when (or (null allbutl
) (not (member z allbutl
:test
#'equal
)))
240 (when (member x
(cdr $contexts
) :test
#'equal
)
242 (when (mget x
'$rule
)
243 (let ((y (ruleof x
)))
244 (cond (y ($remrule y x
))
245 (t (when (not (member x
*builtin-$rules
* :test
#'equal
))
247 (setf $rules
(delete x $rules
:count
1 :test
#'eq
)))))))
248 (when (and (get x
'operators
) (rulechk x
))
250 (when (mget x
'trace
)
252 (when (get x
'translated
)
253 (when (not (member x
*builtin-symbols
* :test
#'equal
))
254 (remove-transl-fun-props x
)
255 (remove-transl-array-fun-props x
)))
256 (when (not (get x
'sysconst
))
257 (remprop x
'lineinfo
)
259 (dolist (u '(bindtest nonarray evfun evflag opers special mode
))
262 (when (and (remprop x u
)
263 (let ((xopval (get x
'operators
)))
264 (or (eq xopval
'simpargs1
) (eq xopval nil
))))
265 (remprop x
'operators
)))
266 (when (member x
(cdr $props
) :test
#'equal
)
269 (i-$remove
(list x $features
)))
270 (let ((y (get x
'op
)))
272 (not (member y
*mopl
* :test
#'equal
))
273 (member y
(cdr $props
) :test
#'equal
))
276 (setf $arrays
(delete x $arrays
:count
1 :test
#'eq
))
278 (setf *autoloaded-files
*
279 (delete (assoc x
*autoloaded-files
* :test
#'eq
) *autoloaded-files
* :count
1 :test
#'equal
))
281 (delete (assoc (ncons x
) $functions
:test
#'equal
) $functions
:count
1 :test
#'equal
))
283 (delete (assoc (ncons x
) $macros
:test
#'equal
) $macros
:count
1 :test
#'equal
))
284 (let ((y (assoc (ncons x
) $gradefs
:test
#'equal
)))
287 (setf $gradefs
(delete y $gradefs
:count
1 :test
#'equal
))))
289 (delete (assoc (ncons x
) $dependencies
:test
#'equal
) $dependencies
:count
1 :test
#'equal
))
290 (let ((y (assoc-if #'(lambda (e) (equal x
(car e
))) (cdr $structures
))))
292 (remprop x
'dimension
)
293 (remprop x
'defstruct-template
)
294 (remprop x
'defstruct-default
)
295 (remprop x
'translate
)
296 (setf $structures
(delete y $structures
:count
1 :test
#'equal
))))
297 (when (and (member x
*builtin-symbols
* :test
#'equal
)
298 (gethash x
*builtin-symbol-props
*))
299 (setf (symbol-plist x
)
300 (copy-tree (gethash x
*builtin-symbol-props
*))))
301 (when (member x
*builtin-numeric-constants
*)
302 (initialize-numeric-constant x
)) ;; reset db value for $%pi, $%e, etc
306 (if (and (stringp x
) (not (getopr0 x
))) (return-from kill1 nil
))
309 (cond ((and allbutl
(member x allbutl
:test
#'equal
)))
310 ((eq (setq x
(getopr x
)) '$labels
)
311 (dolist (u (cdr $labels
))
312 (cond ((and allbutl
(member u allbutl
:test
#'equal
))
313 (setq z
(nconc z
(ncons u
))))
314 (t (makunbound u
) (remprop u
'time
)
315 (remprop u
'nodisp
))))
316 (setq $labels
(cons '(mlist simp
) z
) $linenum
0))
317 ((member x
'($values $arrays $aliases $rules $props
318 $let_rule_packages
) :test
#'equal
)
319 (mapc #'kill1
(cdr (symbol-value x
))))
320 ((member x
'($functions $macros $gradefs $dependencies $structures
) :test
#'equal
)
321 (mapc #'(lambda (y) (kill1 (caar y
))) (cdr (symbol-value x
))))
323 ((eq x
'$tellrats
) (setq tellratlist nil
))
324 ((eq x
'$ratvars
) (setq $ratvars
'((mlist simp
)) varlist nil
))
325 ((eq x
'$ratweights
) (setq *ratweights nil
326 $ratweights
'((mlist simp
))))
328 (cond ((not (equal (cdr $features
) featurel
))
329 (setq $features
(cons '(mlist simp
) (copy-list featurel
))))))
330 ((or (eq x t
) (eq x
'$all
))
331 (mapc #'kill1
(cdr $infolists
))
332 (setq $ratvars
'((mlist simp
)) varlist nil genvar nil
333 checkfactors nil greatorder nil lessorder nil $gensumnum
0
334 *ratweights nil $ratweights
336 tellratlist nil $dontfactor
'((mlist)) $setcheck nil
)
338 ((setq z
(assoc x
'(($inlabels . $inchar
) ($outlabels . $outchar
) ($linelabels . $linechar
)) :test
#'eq
))
339 (mapc #'(lambda (y) (remvalue y
'$kill
))
340 (getlabels* (eval (cdr z
)) nil
)))
341 ((and (fixnump x
) (>= x
0)) (remlabels x
))
342 ((atom x
) (kill1-atom x
))
343 ((and (eq (caar x
) 'mlist
) (fixnump (cadr x
))
344 (or (and (null (cddr x
))
345 (setq x
(append x
(ncons (cadr x
)))))
346 (and (fixnump (caddr x
))
347 (not (> (cadr x
) (caddr x
))))))
348 (let (($linenum
(caddr x
))) (remlabels (- (caddr x
) (cadr x
)))))
349 ((setq z
(mgetl (caar x
) '(hashar array
))) (remarrelem z x
))
352 (hash-table-p (setq z
(symbol-value (caar x
)))))
353 ; Evaluate the subscripts (as is done in ARRSTORE)
354 (let ((indices (mevalargs (cdr x
))))
355 (if (gethash 'dim1 z
)
356 (remhash (car indices
) z
)
357 (remhash indices z
))))
358 ((eq (caar x
) '$
@) (mrecord-kill x
))
359 ((and (eq (caar x
) '$allbut
)
360 (not (dolist (u (cdr x
))
361 (if (not (symbolp u
)) (return t
)))))
362 (let ((allbutl (cdr x
))) (kill1 t
)))
363 (t (improper-arg-err x
'$kill
))))
369 (setq l
(list (exploden $inchar
)
371 (exploden $linechar
)))
372 loop
(setq x
(mexploden $linenum
))
375 (remvalue (implode (append (car l
) x
)) '$kill
))
376 (if (or (minusp (setq n
(1- n
))) (= $linenum
0)) (return nil
))
380 (defun remvalue (x fn
)
381 (cond ((not (symbolp x
)) (improper-arg-err x fn
))
384 (cond ((or (setq y
(member x
(cdr $values
) :test
#'equal
))
385 (member x
(cdr $labels
) :test
#'equal
))
386 (cond (y (setf $values
(delete x $values
:count
1 :test
#'eq
)))
387 (t (setf $labels
(delete x $labels
:count
1 :test
#'eq
))
388 (remprop x
'time
) (remprop x
'nodisp
)))
390 (when (member x
*builtin-symbols-with-values
* :test
#'equal
)
391 (setf (symbol-value x
)
392 (gethash x
*builtin-symbol-values
*)))
396 (when (member x
*builtin-symbols-with-values
* :test
#'equal
)
397 (setf (symbol-value x
)
398 (gethash x
*builtin-symbol-values
*)))
400 (transp (setf (symbol-value x
) x
) t
)
401 ((eq x
'$default_let_rule_package
) t
)
402 ;; Next case: X is bound to itself but X is not on values list.
403 ;; Translation code does that; I don't know why.
404 ;; Silently let it stand and hope it doesn't cause trouble.
405 ((eq (symbol-value x
) x
) t
)
407 (mtell (intl:gettext
"remvalue: ~M doesn't appear to be a known variable; just unbind it anyway.~%") x
)
412 (or (mget rule
'ruleof
)
413 (let* ((pattern (cadr (mget rule
'$rule
)))
414 (op (if (atom pattern
) nil
(caar pattern
))) l
)
415 (and (setq l
(get op
'rules
))
416 (member rule l
:test
#'equal
) op
))))
418 (defmfun $debugmode
(x)
422 (defun debugmode1 (assign-var y
)
423 (declare (ignore assign-var
))
426 (defun errlfun1 (mpdls)
427 (do ((l bindlist
(cdr l
))
429 ((eq l
(car mpdls
)) (munbind l1
))
430 (setq l1
(cons (car l
) l1
)))
432 ((eq loclist
(cdr mpdls
)))
436 (cond ((get x
'alias
))
441 (implode (cons #\$
(exploden x
))))
443 ;; (DEFMSPEC $F (FORM) (SETQ FORM (FEXPRCHECK FORM)) ...)
444 ;; makes sure that F was called with exactly one argument and
445 ;; returns that argument.
447 (defun fexprcheck (form)
448 (if (or (null (cdr form
)) (cddr form
))
449 (merror (intl:gettext
"~:M: expected just one argument; found: ~M") (caar form
) form
)
452 (defun nonsymchk (x fn
)
454 (merror (intl:gettext
"~:M: argument must be a symbol; found: ~M") fn x
)))
456 (defmfun $print
(&rest args
)
459 (let ((l args
) $stringdisp
) ;; Don't print out strings with quotation marks!
462 (rplacd l
(cons " " (cdr l
))))
463 (displa (cons '(mtext) l
))
464 (cadr (reverse l
)))))
466 (defmspec $playback
(x)
467 (declare (special $showtime
))
469 (prog (l l1 l2 numbp slowp nostringp inputp timep grindp inchar largp
)
470 (setq inchar
(getlabcharn $inchar
)) ; Only the 1st alphabetic char. of $INCHAR is tested
471 (setq timep $showtime grindp $grind
)
472 (do ((x x
(cdr x
)))( (null x
))
473 (cond ((fixnump (car x
)) (setq numbp
(car x
)))
475 ((eq (car x
) '$slow
) (setq slowp t
))
476 ((eq (car x
) '$nostring
) (setq nostringp t
))
477 ((eq (car x
) '$grind
) (setq grindp t
))
478 ((eq (car x
) '$input
) (setq inputp t
))
479 ((member (car x
) '($showtime $time
) :test
#'equal
) (setq timep
(or timep t
)))
480 ((member (car x
) '($gctime $totaltime
) :test
#'equal
) (setq timep
'$all
))
481 ((setq l2
(listargp (car x
)))
482 (setq l1
(nconc l1
(getlabels (car l2
) (cdr l2
) nil
)) largp t
))
483 (t (improper-arg-err (car x
) '$playback
))))
484 (cond ((and largp
(null numbp
)) (go loop
))
485 ((and (setq l
(cdr $labels
)) (not $nolabels
)) (setq l
(cdr l
))))
486 (when (or (null numbp
) (< (length l
) numbp
))
487 (setq l1
(reverse l
)) (go loop
))
488 (do ((i numbp
(1- i
)) (l2)) ((zerop i
) (setq l1
(nconc l1 l2
)))
489 (setq l2
(cons (car l
) l2
) l
(cdr l
)))
490 loop
(if (null l1
) (return '$done
))
492 (incharp (char= (getlabcharn (car l1
)) inchar
)))
494 (cond ((and (not nostringp
) incharp
)
495 (let ((*linelabel
* (car l1
))) (mterpri) (printlabel))
497 (mgrind (meval1 (car l1
)) nil
)
498 (mapc #'(lambda (x) (write-char x
)) (mstring (meval1 (car l1
))))) ;gcl doesn't like a
499 ; simple write-char, therefore wrapped it up in a lambda - are_muc
500 (if (get (car l1
) 'nodisp
) (princ "$") (princ ";"))
503 (prog2 (when (and timep
(setq l
(get (car l1
) 'time
)))
504 (setq x
(gctimep timep
(cdr l
)))
505 (mtell (intl:gettext
"~A seconds") (car l
))
506 (if x
(mtell (intl:gettext
" GC time = ~A seconds") (cdr l
)))
508 (not (or inputp
(get (car l1
) 'nodisp
)))))
509 (mterpri) (displa (list '(mlabel) (car l1
) (meval1 (car l1
)))))
511 (when (and slowp
(cdr l1
) (not (continuep)))
512 (return '$terminated
))
518 (if (and ($listp x
) (fixnump (cadr x
))
519 (or (and (null (cddr x
)) (setq high
(cadr x
)))
520 (and (fixnump (setq high
(caddr x
)))
521 (not (> (cadr x
) high
)))))
522 (cons (cadr x
) high
))))
524 (defmspec $alias
(form)
525 (if (oddp (length (setq form
(cdr form
))))
526 (merror (intl:gettext
"alias: expected an even number of arguments.")))
527 (do ((l nil
(cons (alias (pop form
) (pop form
))
530 `((mlist simp
),@(nreverse l
)))))
533 (cond ((nonsymchk x
'$alias
))
534 ((nonsymchk y
'$alias
))
535 ((eq x y
) y
) ; x is already the alias of y
536 ((get x
'reversealias
)
537 (merror (intl:gettext
"alias: ~M already has an alias.") x
))
538 (t (putprop x y
'alias
)
539 (putprop y x
'reversealias
)
543 (defun remalias (x &optional remp
)
544 (let ((y (and (or remp
(member x
(cdr $aliases
) :test
#'equal
)) (get x
'reversealias
))))
545 (cond ((and y
(eq x
'%derivative
))
546 (remprop x
'reversealias
)
547 (setf $aliases
(delete x $aliases
:count
1 :test
#'eq
))
548 (remprop '$diff
'alias
) '$diff
)
549 (y (remprop x
'reversealias
)
551 (setf $aliases
(delete x $aliases
:count
1 :test
#'eq
))
552 (remprop (setq x y
) 'alias
) (remprop x
'verb
) x
))))
554 (defun stripdollar (x)
555 (cond ((not (atom x
))
556 (cond ((and (eq (caar x
) 'bigfloat
) (not (minusp (cadr x
)))) (implode (fpformat x
)))
557 (t (merror (intl:gettext
"STRIPDOLLAR: argument must be an atom; found: ~M") x
))))
561 ((member (get-first-char x
) '(#\$
#\%
) :test
#'char
=)
562 (intern (subseq (string x
) 1)))
566 (mapcar #'fullstrip1 x
))
568 (defun fullstrip1 (x)
569 (or (and (numberp x
) x
)
570 (let ((y (get x
'reversealias
))) (if y
(stripdollar y
)))
574 (or (and (numberp x
) (exploden x
))
578 (let ($stringdisp $lispdisp
)
581 ;;; Note that this function had originally stripped a prefix of '|M|. This
582 ;;; was intended for operators such as 'MABS, but with the case flipping
583 ;;; performed by explodec this test would always fail. Dependent code has
584 ;;; been written assuming the '|M| prefix is not stripped so this test has
585 ;;; been disabled for now.
587 (defmfun $nounify
(x)
588 (if (not (or (symbolp x
) (stringp x
)))
589 (merror (intl:gettext
"nounify: argument must be a symbol or a string; found: ~M") x
))
590 (setq x
(amperchk x
))
591 (cond ((get x
'verb
))
594 (let* ((y (explodec x
))
595 (u #+nil
(member (car y
) '($ |M| |m|
) :test
'eq
)
597 (cond ((or u
(not (eq (car y
) '%
)))
598 (setq y
(implode (cons '%
(if u
(cdr y
) y
))))
599 (putprop y x
'noun
) (putprop x y
'verb
))
602 (defmfun $verbify
(x)
603 (if (not (or (symbolp x
) (stringp x
)))
604 (merror (intl:gettext
"verbify: argument must be a symbol or a string; found: ~M") x
))
605 (setq x
(amperchk x
))
606 (cond ((get x
'noun
))
608 ((and (char= (char (symbol-name x
) 0) #\%
)
610 ($nounify
(implode (cons #\$
(cdr (exploden x
)))))
614 (defmspec $string
(form)
616 (setq form
(strmeval (fexprcheck form
)))
617 (setq form
(if $grind
(strgrind form
) (mstring form
)))
618 (coerce form
'string
)))
624 (rplaca l
(ascii (car l
))))
628 (cond ((atom x
) (meval1 x
))
629 ((member (caar x
) '(msetq mdefine mdefmacro
) :test
#'equal
) x
)
633 (mapc #'(lambda (x) (putprop (car x
) (cadr x
) 'alias
)
634 (putprop (cadr x
) (car x
) 'reversealias
))
635 '(($block mprog
) ($lambda lambda
)
637 ($go mgo
) ($signum %signum
)
638 ($return mreturn
) ($factorial mfactorial
)
639 ($ibase
*read-base
*) ($obase
*print-base
*)
641 ($mode_declare $modedeclare
)))
643 (mapc #'(lambda (x) (putprop (car x
) (cadr x
) 'alias
))
644 '(($ratcoeff $ratcoef
) ($ratnum $ratnumer
) ($true t
)
645 ($derivative $diff
) ($prod $product
)
646 ($bothcoeff $bothcoef
)))
648 (defun amperchk (name)
650 ((symbolp name
) name
)
652 (getalias (or (getopr0 name
) (implode (cons #\$
(coerce name
'list
))))))
655 (defmspec $stringout
(x)
658 ((file (namestring (maxima-string (meval (car x
)))))
659 (filespec (if (or (eq $file_output_append
'$true
) (eq $file_output_append t
))
660 `(savefile ,file
:direction
:output
:if-exists
:append
:if-does-not-exist
:create
)
661 `(savefile ,file
:direction
:output
:if-exists
:supersede
:if-does-not-exist
:create
))))
664 `(let (maxima-error l1 truename
)
665 (declare (special $grind $strdisp
))
666 (with-open-file ,filespec
669 (do ((l ',x
(cdr l
)))( (null l
))
670 (cond ((member (car l
) '($all $input
) :test
#'equal
)
671 (setq l
(nconc (getlabels* $inchar t
) (cdr l
))))
672 ((eq (car l
) '$values
)
673 (setq l
(nconc (mapcan
676 (ncons (list '(msetq) x
(symbol-value x
)))))
679 ((eq (car l
) '$functions
)
680 (setq l
(nconc (mapcar
681 #'(lambda (x) (consfundef (caar x
) nil nil
))
686 (ncons (consfundef x t nil
))))
689 #'(lambda (x) (consfundef (caar x
) nil nil
))
692 ((setq l1
(listargp (car l
)))
693 (setq l
(nconc (getlabels (car l1
) (cdr l1
) t
) (cdr l
)))))
694 (if (null l
) (return nil
))
696 (if $grind
(mgrind (strmeval (car l
)) savefile
)
697 (princ (print-invert-case (maknam (mstring (strmeval (car l
)))))
699 (if (or (and (symbolp (car l
)) (get (car l
) 'nodisp
)) (not $strdisp
))
700 (write-char #\$ savefile
)
701 (write-char #\
; savefile)))))
702 (setq maxima-error t
)))
703 (setq truename
(truename savefile
))
705 (if maxima-error
(merror (intl:gettext
"stringout: unspecified error.")))
706 (cl:namestring truename
)))))
708 (defmfun $labels
(label-prefix)
709 (nonsymchk label-prefix
'$labels
)
710 (cons '(mlist simp
) (nreverse (getlabels* label-prefix nil
))))
714 (if (or (not (fixnump x
)) (zerop x
))
715 (improper-arg-err x
'$%th
))
716 (if (> x
0) (setq x
(- x
)))
718 (setq l
(cddr $labels
) outchar
(getlabcharn $outchar
)))
719 loop
(if (null l
) (merror (intl:gettext
"%th: no such previous output: ~M") x
))
720 (if (and (char= (getlabcharn (car l
)) outchar
) (= (setq x
(1+ x
)) 0))
721 ; Only the 1st alphabetic character of $OUTCHAR is tested.
722 (return (meval (car l
))))
726 (defun getlabels (n1 n2 flag
) ; FLAG = T for STRINGOUT, = NIL for PLAYBACK and SAVE.
727 (do ((i n1
(1+ i
)) (l1)
728 (l (if flag
(list (exploden $inchar
))
729 (list (exploden $inchar
) (exploden $linechar
)
730 (exploden $outchar
)))))
731 ((> i n2
) (nreverse l1
))
732 (do ((l l
(cdr l
)) (x (mexploden i
)) (z)) ((null l
))
733 (if (boundp (setq z
(implode (append (car l
) x
))))
734 (setq l1
(cons z l1
))))))
736 (defun getlabels* (label-prefix flag
) ; FLAG = T only for STRINGOUT
738 ((label-prefix-name (symbol-name label-prefix
))
739 (label-prefix-length (length label-prefix-name
)))
740 (do ((l (if flag
(cddr $labels
) (cdr $labels
)) (cdr l
)) (l1))
742 (let ((label-name-1 (symbol-name (car l
))))
745 (<= label-prefix-length
(length label-name-1
))
746 (string= label-name-1 label-prefix-name
:end1 label-prefix-length
))
747 (setq l1
(cons (car l
) l1
)))))))
749 (defun getlabcharn (label)
750 (let ((c (char (symbol-name label
) 1)))
752 (char (symbol-name label
) 2)
755 ; Evaluate form while catching throws to some specific tags (called
756 ; "errcatch tags"). If no throw to an errcatch tag is caught, then
757 ; the values from form are returned. If a throw to an errcatch tag
758 ; is caught, then a Maxima error is signaled.
760 ; The errcatch tags are ERRORSW, MACSYMA-QUIT and RAT-ERR.
761 (defmacro with-errcatch-tag-$errors
(form)
762 (let ((block-name (gensym)))
764 ; RAT-ERROR-TO-MERROR will catch any throws to RAT-ERR and
765 ; call merror with a specific error message.
769 (return-from ,block-name
,form
))))
770 ; If we're here, then we don't know any information about the
771 ; error, so just call MERROR with a vague error message. This
772 ; message will not be printed by MERROR, but it will be stored
773 ; in Maxima's error variable.
775 (merror (intl:gettext
"An error was caught by errcatch."))))))
777 ; This is similar to the classic errset, but errcatch handles lisp and
779 (defmacro errcatch
(form)
780 `(let ((errcatch (cons bindlist loclist
))
782 (declare (special errcatch
*mdebug
*))
783 (handler-case (list (with-errcatch-tag-$errors
,form
))
785 ; If this was signaled by MERROR, then it has already handled
786 ; the setting of the error variable and the printing of any error
787 ; messages (as applicable).
789 ; If for some reason this wasn't signaled by MERROR, then it's the
790 ; signaler's responsibility to handle error messages.
792 ; Either way, we just need to clean up here.
796 ; We store the error report message in the error variable and
797 ; print the message if errormsg is true. Then we clean up.
798 (setq $error
(list '(mlist simp
) (princ-to-string e
)))
804 (defmspec $errcatch
(form)
805 (cons '(mlist) (errcatch (mevaln (cdr form
)))))
807 (defmacro mcatch
(form)
808 `(let ((mcatch (cons bindlist loclist
)))
810 (catch 'mcatch
(rat-error-to-merror ,form
))
813 (defmspec $catch
(form)
814 (mcatch (mevaln (cdr form
))))
816 (defmfun $throw
(exp)
817 (if (null mcatch
) (merror (intl:gettext
"throw: not within 'catch'; expression: ~M") exp
))
826 (setq x
(get x
'time
))
829 (list '(mlist simp
) (car x
) (cdr x
))))
835 (incf thistime
(- (get-internal-run-time) tim
))))
839 (princ *maxima-epilog
*)
841 (mtell (intl:gettext
"quit: No known quit function for this Lisp.~%")))
843 ;; File-processing stuff.
849 (defmspec $status
(form)
850 (setq form
(cdr form
))
851 (let* ((keyword (car form
))
852 (feature (cadr form
)))
853 (when (not (symbolp keyword
))
854 (merror (intl:gettext
"status: first argument must be a symbol; found: ~M") keyword
))
855 (when (not (or (stringp feature
) (symbolp feature
)))
857 (intl:gettext
"status: second argument must be symbol or a string; found: ~M") feature
))
859 ($feature
(cond ((null feature
) (dollarify *features
*))
860 ((member (intern (if (stringp feature
)
861 (maybe-invert-string-case feature
)
862 (symbol-name (fullstrip1 feature
)))
864 *features
* :test
#'equal
) t
)))
865 (t (merror (intl:gettext
"status: unknown argument: ~M") keyword
)))))
867 (defquote $sstatus
(keyword item
)
868 (cond ((equal keyword
'$feature
)
869 (pushnew ($mkey item
) *features
*) t
)
870 ((equal keyword
'$nofeature
)
871 (setq *features
* (delete ($mkey item
) *features
*)) t
)
873 (merror (intl:gettext
"sstatus: unknown argument: ~M") keyword
))))
875 (dolist (l '($sin $cos $tan $log $plog $sec $csc $cot $sinh $cosh
876 $tanh $sech $csch $coth $asin $acos $atan $acot $acsc $asec $asinh
877 $acosh $atanh $acsch $asech $acoth $binomial $gamma $genfact $del
))
878 (let ((x ($nounify l
)))
880 (putprop x l
'reversealias
)))
885 ($nounify
'$integrate
)
888 (defprop $diff %derivative verb
)
889 (defprop %derivative $diff noun
)
891 (mapc #'(lambda (x) (putprop (car x
) (cadr x
) 'assign
))
892 '(($debugmode debugmode1
)
893 ($fpprec fpprec1
) ($poislim poislim1
)
894 ($default_let_rule_package let-rule-setter
)
895 ($current_let_rule_package let-rule-setter
)
896 ($let_rule_packages let-rule-setter
)))
898 (mapc #'(lambda (x) (putprop x
'neverset
'assign
)) (cdr $infolists
))
900 (defprop $contexts neverset assign
)
904 #-gcl
(:compile-toplevel
:execute
)
905 (setq *print-base
* old-base
*read-base
* old-ibase
))