home *** CD-ROM | disk | FTP | other *** search
- ;; PC-LISP.L for PC-LISP.EXE V2.15
- ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ;; A small library of functions to help fill in the gap between PC and
- ;; Franz Lisp. These functions are not documented in the PC-LISP.DOC file but
- ;; any Franz manual will cover them in detail. Especially the backquote
- ;; and other macro definitions towards the end of the file. These functions
- ;; were written pretty hastily so there could be bugs. Check them out for
- ;; yourself to make sure they behave in the way you are used to with Franz.
- ;;
- ;; This file is automatically loaded by PC-LISP.EXE. It should either
- ;; be located in the current working directory, or in a library directory
- ;; whose path is set in the LISP_LIB environment variable. All load files
- ;; should be put in one of your LISP_LIB directories. You could also strip
- ;; comments and white space from this file to make it load faster. This
- ;; is important if you load this file every time you run PC-LISP.
- ;;
- ;; Peter Ashwood-Smith
- ;; November 1986
- ;;
- ;; Pretty Print: (pp [(F file) (E expr) (P port)] symbol)
- ;; ~~~~~~~~~~~~
- ;; Print in a readable way the function associated with 'symbol'. If
- ;; the parameter (F file) is specified the output goes to file 'file. If
- ;; the parameter (P port) is specified the output goes to the open port
- ;; 'port'. If the parameter (E expr) is specified the expression 'expr'
- ;; is evaluated before the function is pretty printed. Makes use of the
- ;; predefined symbol poport whose binding is 'stdout'.
-
- (setq displace-macros t) ; override Franz default (faster do loops)
-
- (defun pp fexpr(l)
- (prog (expr name port alt)
- (setq port poport)
- (cond ((= (length l) 1) (setq name (car l)))
- ((= (length l) 2) (setq name (cadr l) alt (car l)))
- (t (return nil))
- )
- (cond ((null (getd name)) (return nil)))
- (setq expr (cons 'def (cons name (list (getd name)))))
- (cond ((null alt) (go SKIP)))
- (cond ((eq (car alt) 'F) (setq port (fileopen (cadr alt) 'w)))
- ((eq (car alt) 'P) (setq port (cadr alt)))
- ((eq (car alt) 'E) (eval (cadr alt)))
- (t (return nil)))
- (cond ((null port) (patom "cannot open port\n") (return nil)))
- SKIP (pp-form expr port 0)
- (cond ((not (equal port poport)) (close port)))
- (return t)
- )
- )
-
- ;; _SCL_ Spit Character Loop
- ;; ~~~~~~~~~~~~~~~~~~~~~~~~~
- ;; Prints 'char' 'n' times on port 'port', used by msg for (N) and (B)
-
- (defun _SCL_(port char n)
- (prog nil
- nxt: (cond ((zerop n) (return)))
- (patom char port)
- (setq n (1- n))
- (go nxt:)
- )
- )
-
- ;; (msg [B|N|D] [ (P pt) (B n) | (N n)] s*)
- ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ;; Prints a message on standard output port 'poport'. Where N is a new
- ;; line, (N n) means n new lines. B is a blank, (B n) means n blanks
- ;; D means (Dran port) unsupported in PC-LISP. (P pt) means switch output
- ;; to port pt rather than poport. s, is any s expression which will be
- ;; evaluated and then printed on current output port.
-
- (defun msg fexpr(l)
- (prog (s op)
- (setq op poport)
- nxt: (cond ((null l)(return)))
- (setq s (car l) l (cdr l))
- (cond ((eq s 'N) (patom "\n" op))
- ((eq s 'B) (patom " " op))
- ((eq s 'D) (patom "msg : Drain unsupported\n"))
- ((listp s)
- (cond ((eq (car s) 'P)(setq op (cadr s)))
- ((eq (car s) 'B)(_SCL_ op " " (cadr s)))
- ((eq (car s) 'N)(_SCL_ op "\n" (cadr s)))
- (t (patom (eval s) op))
- )
- )
- (t (patom (eval s) op))
- )
- (go nxt:)
- )
- )
-
- ;; (lineread [port])
- ;; ~~~~~~~~~~~~~~~~~
- ;; Very simple line read function. Takes atoms from the piport or port until
- ;; a new line is encountered. It returns these atoms or S-expressions as a
- ;; list 'ret.
-
- (defun lineread fexpr(l)
- (prog (port ret)
- (setq port piport)
- (cond ((not (null l)) (setq port (eval (car l)))))
- (setq ret (list (read port)))
- nxt: (cond ((eq (readc port) '|\n|)(return ret)))
- (setq ret (append ret (list (read port))))
- (go nxt:)
- )
- )
-
- ;; ----------- ASSORTED SMALL FUNCTIONS ------------
-
- (defun tailp(l1 l2)(cond ((null l2) nil)((eq l1 l2) l1)(t(tailp l1(cdr l2]
- (defun bcdp(x) nil)
- (defun bigp(x) nil)
- (defun dtpr(x) (and (listp x) (not (null x))))
- (defun consp(x) (and (listp x) (not (null x))))
- (defun litatom(n) (and(atom n)(not(floatp n]
- (defun purep(n) nil)
- (defun symbolp(n) (litatom n))
- (defun valuep(n) nil)
- (defun vectorp(n) nil)
- (defun typep(n)(type n))
- (defun eqstr(a b)(equal a b))
- (defun neq(a b)(not(eq a b)))
- (defun nequal(a b)(not(equal a b)))
- (defun append1(a b)(append a (list b)))
- (defun ncons(a)(cons a nil))
- (defun xcons(a b)(cons b a))
- (defun nthelem(n l) (nth (1- n) l))
- (defun minus(n)(- 0 n))
- (defun onep(n)(= 1 n))
- (defun infile(f)(fileopen f 'r))
- (defun pntlen(a) (flatsize a))
- (defun probef(f &aux tmp)(setq tmp (fileopen f 'r))(and tmp (close tmp)))
- (defun shell()(exec "COMMAND.COM")) ; must have a COMMAND.COM on PATH!
-
- (defun error n
- (cond ((= n 1) (patom (arg 1)) (terpri) (err nil))
- ((= n 2) (patom (arg 1)) (patom (arg 2)) (terpri) (err nil))
- (t (error "error bad args"))]
-
- (defun signp(test exp)
- (cond ((eq test 'ge) (or (zerop exp)(plusp exp)))
- ((eq test 'g ) (plusp exp))
- ((eq test 'n ) (not (zerop exp)))
- ((eq test 'e ) (zerop exp))
- ((eq test 'le) (or (zerop exp)(minusp exp)))
- ((eq test 'l) (minusp exp))
- (t (princ "-- error signp bad test ---\n"))))
-
- ;; ----------- ASSORTED SMALL MACROS --------------
-
- (defun >& macro(l) (cons '> (cdr l)))
- (defun >= macro(l) (cons 'not (list (cons '< (cdr l)))))
- (defun >=& macro(l) (cons 'not (list (cons '< (cdr l)))))
- (defun <& macro(l) (cons '< (cdr l)))
- (defun <= macro(l) (cons 'not (list (cons '> (cdr l)))))
- (defun <=& macro(l) (cons 'not (list (cons '> (cdr l)))))
- (defun =& macro(l) (cons '= (cdr l)))
-
- (defun terpri macro(l) ; makes (terpri [port])
- (append (list 'princ "\n")(cdr l))) ; into (princ "\n" [port])
- (defun tyo macro(l) ; makes (princ (asci f) [port])
- (cons 'princ (cons (cons 'ascii (list (cadr l))) (cddr l))))
- (defun store macro(l) ; makes (store (x -dims-) exp)
- (cons (caadr l) ; into (x exp -dims-)
- (append (cddr l) (cdadr l))))
- (defun arraycall macro(l) ; makes (arraycall f a -n-)
- (cddr l)) ; into (a -n-)
-
- ;; BACKQUOTE READ MACRO AND PARTS
- ;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ;; This file describes the back quote macro for PC-LISP. It works in
- ;; exactly the same way as the FRANZ backquote macro works. Basically the
- ;; backquote macro ` is supposed to work together with the comma , and at
- ;; @ macros. As follows: Backquote has the same effect as ' except that any
- ;; elements or sub elements that are preceeded by , are evaluated. If an
- ;; element is preceeded by ,@ then the element is evaluated and should
- ;; evaluate to a list. This list is spliced into the built list. I use
- ;; cons to do list building and append to do list splicing. For example
- ;; the input: `(a ,b c) will be read in as (a (*unquote* b) c) by the
- ;; back quote read macro because the comma macro will have read the b and
- ;; built up the list (*unquote* b). Next the back quote macro passes control
- ;; to the _BQB_ function (Back Quote Builder). This will construct the list
- ;; (cons 'a (cons b (cons 'c nil))) which when evaluated gives the desired
- ;; result. If the , were followed by an @ then the @ would build the form
- ;; (*splice* b). Then the , would get this form and the function _CB_ comma
- ;; builder would then make then pass the form unchanged. Next the backquote
- ;; builder _BQB_ would get the form (a (*splice* b) c) and build the form
- ;; (cons 'a (append b (cons 'c nil))) which will cause the value of b to be
- ;; spliced into the list rather than forming a sublist element as desired.
-
- (defun _BQB_(Sexp)
- (cond ((null Sexp) Sexp)
- ((atom Sexp) (list 'quote Sexp))
- ((eq (car Sexp) '*unquote*)
- (cadr Sexp))
- ((and(listp (car Sexp)) (eq (caar Sexp) '*splice*))
- (list 'append (cadar Sexp)
- (_BQB_ (cdr Sexp))))
- ( t (list 'cons (_BQB_ (car Sexp))
- (_BQB_ (cdr Sexp))))
- )
- )
-
- (defun _CB_(Sexp)
- (cond ((null Sexp) Sexp)
- ((atom Sexp) (list '*unquote* Sexp))
- ((eq (car Sexp) '*splice*) Sexp)
- (t (list '*unquote* Sexp))
- )
- )
-
- (setsyntax '|`| 'vmacro '(lambda()(_BQB_ (read))))
- (setsyntax '|,| 'vmacro '(lambda()(_CB_ (read))))
- (setsyntax '|@| 'vmacro '(lambda()(list '*splice* (read))))
-
-
- ;; macro : (let ((p1 v1)(p2 v2)...(pn vn)) e1 e2 ... en)
- ;; ~~~~~
- ;; Let macro introduces local variables. Much used in Franz code it
- ;; basically creates a lambda expression of the form:
- ;;
- ;; ((lambda(p1 p2 ... pn) e1 e2 ... en) v1 v2 ...vn)
- ;; Note that (p1 v1) may be of the form p1 in which case the variable
- ;; is bound to nil.
-
- (defun let macro(l)
- `((lambda ,(mapcar '_lvar (cadr l))
- ,@(cddr l)
- )
- ,@(mapcar '_lval (cadr l]
-
- (defun _lvar (l)(cond ((atom l) l) (t (car l]
-
- (defun _lval (l)(cond ((atom l) nil) (t (cadr l]
-
- ;; macro defmacro
- ;; ~~~~~~~~~~~~~~
- ;; Like defun except that it declares a macro. This is more convenient
- ;; than using the defun name macro(l) because access to variables can be
- ;; named.
-
- (defun defmacro fexpr(l)
- (putd (car l)
- (cons 'macro
- (list '(defmacroarg)
- `((lambda ,(__dmlats (cadr l))
- ,@(cddr l))
- ,@(__dmal (cadr l))]
-
- (defun defcmacro fexpr(l) ; no such thing as compiler yet but
- (putd (car l) ; keeps interpreter happy
- (cons 'macro
- (list '(defmacroarg)
- `((lambda ,(__dmlats (cadr l))
- ,@(cddr l))
- ,@(__dmal (cadr l))]
-
- (defun __dma(l a)
- (cond ((null l) nil)
- ((atom l) (setq __dmalhold (cons a __dmalhold)))
- (t (__dma (car l) (cons 'car (list a)))
- (__dma (cdr l) (cons 'cdr (list a)))]
-
- (defun __dmal(l &aux __dmalhold)
- (__dma l '(cdr defmacroarg))
- (reverse __dmalhold ]
-
- (defun __dmlats(l)
- (cond ((null l) nil)
- ((atom l) (list l))
- ( t (append (__dmlats (car l)) (__dmlats (cdr l)))]
-
- ;; (do "symbol" "exp1" "exp2" "test" -"exps"-) ; case 1
- ;; (do -"(symbol [exp1 [exp2]])"- "test" -"exps"-) ; case 2
- ;;
- (defun _do2a_(l) (cond ((cdr l)(cons (car l) (list(cadr l))))(t nil]
- (defun _do2b_(l) (cond ((cddr l)(cons (car l) (list(caddr l))))(t nil]
-
- (defun _do2_(l) ; complex do loop case, many locals
- `(prog ,(mapcar 'car (cadr l))
- (PAR-setq ,@(apply 'append (mapcar '_do2a_ (cadr l))))
- _dlab_
- (cond (,(caaddr l) (return ,@(cdaddr l)) ))
- ,@(cdddr l)
- (PAR-setq ,@(apply 'append (mapcar '_do2b_ (cadr l))))
- (go _dlab_)
- )
- )
-
- (defun _do1_(l) ; simple do loop case, one local
- `(prog (,(nth 1 l))
- (setq ,(nth 1 l) ,(nth 2 l))
- _dlab_ (cond (,(nth 4 l) (return)))
- ,@(cdddddr l)
- (setq ,(nth 1 l) ,(nth 3 l))
- (go _dlab_)
- )
- )
-
- (defun do macro(l) ; select simple/complex case.
- (cond ((atom (cadr l)) (_do1_ l))
- (t (_do2_ l))))
-
- ;; This macro allow the following forms:
- ;; (if a then b) ==> (cond (a b))
- ;; (if a thenret) ==> (cond (a))
- ;; (if a then b else c) ==> (cond (a b) (t c))
- ;; (if a then b b2 ==> (cond (a b b2) (c d d2) (t e))
- ;; elseif c then d d2
- ;; else e)
- ;;
- ;; I stole this from the SLANG package and changed its name to 'if from
- ;; 'If.
- ;;
- (defun if macro (lis)
- (prog (majlis minlis revl)
- (do ((revl (reverse lis) (cdr revl)))
- ((null revl))
- (cond ((eq (car revl) 'else)
- (setq majlis `((t ,@minlis) ,@majlis)
- minlis nil))
- ((or (eq (car revl) 'then) (eq (car revl) 'thenret))
- (setq revl (cdr revl)
- majlis `((,(car revl) ,@minlis) ,@majlis)
- minlis nil))
- ((eq (car revl) 'elseif))
- ((eq (car revl) 'if)
- (setq majlis `(cond ,@majlis)))
- (t (setq minlis `( ,(car revl) ,@minlis)))))
- ; we displace the previous macro, that is we actually replace
- ; the if list structure with the corresponding cond, meaning
- ; that the expansion is done only once
- (rplaca lis (car majlis))
- (rplacd lis (cdr majlis))
- (return majlis)))
-
- ;; A couple of rareley used definitions but just to complete the chapter
- ;; on mapping functions, here they are:
- ;;
- (defun mapcan macro(l) `(apply 'nconc (mapcar ,@(cdr l))))
- (defun mapcon macro(l) `(apply 'nconc (maplist ,@(cdr l))))
-
- ;; The progS functions again to fill in some gaps
- ;;
- (defun progn macro(l) `(prog nil ,@(cdr l)))
- (defmacro prog1(a . b) `(prog (__p1ret) (setq __p1ret ,a) ,@b __p1ret))
- (defmacro prog2(a b . c) `(prog (__p2ret) ,a (setq __p2ret ,b) ,@c __p2ret))
-
-