BSD 4_3 release
[unix-history] / usr / src / ucb / lisp / lisplib / common0.l
CommitLineData
5ffa1c4c
C
1(setq rcs-common0-
2 "$Header: common0.l,v 1.4 83/12/15 11:09:34 jkf Exp $")
3
4;;
5;; common0.l -[Mon Nov 21 14:06:20 1983 by jkf]-
6;;
7;; Functions which are required to execute the low level lisp macros
8;; and functions.
9;;
10;; This is the first file of functions read in when building a lisp.
11;; If this lisp is to run interpretedly, then we must not use anything
12;; which hasn't be defined in the C lisp kernel, except ';' which is
13;; defined as the comment character before reading this file.
14;; We cannot use defmacro, the backquote or the # macro.
15;;
16;; This file should be as short as possible since it must be written in
17;; a rather primitive way.
18;;
19
20;--- declare : ignore whatever is given, this info is for the compiler
21;
22(def declare (nlambda (x) nil))
23
24(declare (macros t))
25
26;--- memq - arg : (probably a symbol)
27; - lis : list
28; returns part of lis beginning with arg if arg is in lis
29;
30(def memq
31 (lambda ($a$ $l$)
32 (do ((ll $l$ (cdr ll)))
33 ((null ll) nil)
34 (cond ((eq $a$ (car ll)) (return ll))))))
35
36;--- def :: define a function
37; This superceeds franz's definition.
38; It does more error checking and it does lambda conversion
39;
40(def def
41 (nlambda (l)
42 ((lambda (name argl)
43 (cond ((and (symbolp (setq name (car l)))
44 (dtpr (cadr l))
45 (null (cddr l))
46 (memq (caadr l) '(lambda nlambda lexpr macro glambda)))
47 ; make sure lambda list is nil or a dtpr
48 (setq l (cadr l)) ; l points to (lambda (argl) ...)
49 (cond ((null (setq argl (cadr l)))) ; nil check
50 ((dtpr (cadr l)) ; dtpr
51 (cond ((and (eq (car l) 'lambda)
52 (or (memq '&aux argl)
53 (memq '&optional argl)
54 (memq '&rest argl)
55 (memq '&body argl)))
56 ; must lambda convert
57 (setq l (lambdacvt (cdr l))))))
58 (t (error "def: bad lambda list of form in " l)))
59 (putd name l)
60 name)
61 (t (error "def: bad form " l))))
62 nil nil)))
63
64
65;--- defun
66; maclisp style function defintion
67;
68(def defun
69 (macro (l)
70 (prog (name type arglist body specind specnam)
71 (setq name (cadr l) l (cddr l))
72 (cond ((dtpr name)
73 (cond ((memq (cadr name) '(macro expr fexpr lexpr))
74 (setq l (cons (cadr name) l)
75 name (car name)))
76 (t (setq specnam (car name)
77 specind (cadr name)
78 name (concat (gensym) "::" specnam))))))
79 (cond ((null (car l)) (setq type 'lambda))
80 ((eq 'fexpr (car l)) (setq type 'nlambda l (cdr l)))
81 ((eq 'expr (car l)) (setq type 'lambda l (cdr l)))
82 ((eq 'macro (car l)) (setq type 'macro l (cdr l)))
83 ((atom (car l))
84 (setq type 'lexpr
85 l (nconc (list (list (car l)))
86 (cdr l))))
87 (t (setq type 'lambda)))
88 (setq body (list 'def name (cons type l)))
89 (cond (specnam
90 (return (list 'progn ''compile
91 body
92 (list 'putprop
93 (list 'quote specnam)
94 (list 'getd
95 (list 'quote name))
96 (list 'quote specind)))))
97 (t (return body))))))
98
99
100;--- error : print error message and cause an error
101; call is usually (error "string" value)
102;
103(def error
104 ;; form: (error arg1 ...)
105 ;; concat all args together, with spaces between them
106 ;; and cause an error to be signaled
107 (lexpr (n)
108 (do ((i n (1- i))
109 (mesg ""))
110 ((eq i 0) (err-with-message mesg))
111 (setq mesg (concat
112 (cond ((atom (arg i)) (arg i))
113 ((lessp (maknum (arg i)) (maknum nil))
114 ; this tests for the <UNBOUND> value
115 '<UNBOUND>)
116 (t (implode (exploden (arg i)))))
117 " " mesg)))))
118
119(def err
120 ;; (err value [junk])
121 ;; This is here for maclisp compatibility. junk should be nil,
122 ;; but we don't verify.
123 ;; The value is both to be printed and to be returned from the
124 ;; errset. 'err-with-message' should be used for new code
125 (lexpr (n)
126 (cond ((eq n 0)
127 (err-with-message "call to err"))
128 ((or (eq n 1) (eq n 2))
129 (err-with-message (arg 1) (arg 1)))
130 (t (error "wrong number of args to err:" n)))))
131
132
133;--- append : append two or more lists
134; the result will be a copy of all but the last list
135;
136(declare (localf append2args))
137
138(def append
139 (lexpr (nargs)
140 (cond ((eq nargs 2) (append2args (arg 1) (arg 2)))
141 ((zerop nargs) nil)
142 (t (do ((i (1- nargs) (1- i))
143 (res (arg nargs)))
144 ((zerop i) res)
145 (setq res (append2args (arg i) res)))))))
146
147;--- append2args : append just two args
148; a version of append which only works on 2 arguments
149;
150(def append2args
151 (lambda (x y)
152 (prog (l l*)
153 (cond ((null x) (return y))
154 ((atom x) (error "Non-list to append:" x)))
155 (setq l* (setq l (cons (car x) nil)))
156 loop (cond ((atom x) (error "Non-list to append:" x))
157 ((setq x (cdr x))
158 (setq l* (cdr (rplacd l* (cons (car x) nil))))
159 (go loop)))
160 (rplacd l* y)
161 (return l))))
162
163;--- append1 : add object to end of list
164; adds element y to then end of a copy of list x
165;
166(def append1 (lambda (x y) (append x (list y))))
167
168;--- assoc - x : lispval
169; - l : list
170; l is a list of lists. The list is examined and the first
171; sublist whose car equals x is returned.
172;
173(def assoc
174 (lambda (val alist)
175 (do ((al alist (cdr al)))
176 ((null al) nil)
177 (cond ((null (car al)))
178 ((not (dtpr (car al)))
179 (error "bad arg to assoc" al))
180 ((equal val (caar al)) (return (car al)))))))
181
182;--- rassq : like assq but look at the cdr instead of the car
183;
184(def rassq
185 (lambda (form list)
186 (cond ((null list) nil)
187 ((not (dtpr list))
188 (error "rassq: illegal second argument: " list))
189 (t (do ((ll list (cdr ll)))
190 ((null ll) nil)
191 (cond ((eq form (cdar ll)) (return (car ll)))))))))
192;--- concatl - l : list of atoms
193; returns the list of atoms concatentated
194;
195(def concatl
196 (lambda (x) (apply 'concat x)))
197
198;--- length - l : list
199; returns the number of elements in the list.
200;
201(def length
202 (lambda ($l$)
203 (cond ((and $l$ (not (dtpr $l$)))
204 (error "length: non list argument: " $l$))
205 (t (cond ((null $l$) 0)
206 (t (do ((ll (cdr $l$) (cdr ll))
207 (i 1 (1+ i)))
208 ((null ll) i))))))))
209
210;--- memq - arg : (probably a symbol)
211; - lis : list
212; returns part of lis beginning with arg if arg is in lis
213;
214(def memq
215 (lambda ($a$ $l$)
216 (do ((ll $l$ (cdr ll)))
217 ((null ll) nil)
218 (cond ((eq $a$ (car ll)) (return ll))))))
219
220;--- nconc - x1 x2 ...: lists
221; The cdr of the last cons cell of xi is set to xi+1. This is the
222; structure modification version of append
223;
224
225(def nconc
226 (lexpr (nargs)
227 (cond ((eq nargs '2)
228 (cond ((null (arg 1)) (arg 2))
229 (t (do ((tmp (arg 1) (cdr tmp)))
230 ((null (cdr tmp))
231 (rplacd tmp (arg 2))
232 (arg 1))))))
233 ((zerop nargs) nil)
234 (t (do ((i 1 nxt)
235 (nxt 2 (1+ nxt))
236 (res (cons nil (arg 1))))
237 ((eq i nargs) (cdr res))
238 (cond ((arg i) (rplacd (last (arg i)) (arg nxt)))
239 (t (rplacd (last res) (arg nxt)))))))))
240
241
242
243(declare (localf nreverse1)) ; quick fcn shared by nreverse and nreconc
244
245;--- nreconc :: nreverse and nconc
246; (nreconc list elemt) is equiv to (nconc (nreverse list) element)
247;
248(defun nreconc (list element)
249 (cond ((null list) element)
250 (t (nreverse1 list element))))
251
252;--- nreverse - l : list
253; reverse the list in place
254;
255
256(defun nreverse (x)
257 (cond ((null x) x)
258 (t (nreverse1 x nil))))
259
260
261;--- nreverse1
262; common local function to nreconc and nreverse. [This can just be
263; nreconc when I get local global functions allow in the compiler -jkf]
264;
265(defun nreverse1 (x ele)
266 (prog (nxt)
267 loop
268 (setq nxt (cdr x))
269 (rplacd x ele)
270 (setq ele x)
271 (cond (nxt (setq x nxt) (go loop)))
272 (return x)))
273
274;--- liszt-declare :: this is defined in the compiler
275; we give it a null definition in the interpreter
276;
277(def liszt-declare (nlambda (x) nil))