Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / usr.bin / lisp / pearl / lowlevel.l
CommitLineData
7129096e
C
1;;;;;;;;;;;;;;;;;;;;;;;;;;;; lowlevel.l ;;;;;;;;;;;;;;;;;;;;;;;;;;;
2; Macros (mostly) for accessing structures, symbols and definitions.
3; See the file "template" for a picture of how structures and
4; symbols and data bases are arranged to explain the simplest
5; of the functions below.
6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7; Copyright (c) 1983 , The Regents of the University of California.
8; All rights reserved.
9; Authors: Joseph Faletti and Michael Deering.
10
11; Throughout the code for PEARL:
12; defblock: will contain a definition of a structure,
13; valblock: will contain an instance of a structure,
14; slotnum: will contain a slot number to index into a structure.
15; An attempt has been made throughout the rest to similarly name
16; things to be obvious.
17
18; These macros are designed so that PEARL can be moved to a new Lisp
19; simply by implementing the functions "makhunk", "cxr", and
20; "rplacx" to behave as they do in Franz Lisp.
21
22(defmacro getdefaultinst (defblock)
23 `(cxr 3 ,defblock))
24
25(defmacro getdefinition (valblock)
26 `(cxr 0 ,valblock))
27
28(defmacro allocdef (numofslots)
29 `(makhunk (+ 10 (* 4 ,numofslots))))
30
31(defmacro allocval (numofslots)
32 `(makhunk (+ 4 (* 4 ,numofslots))))
33
34(defmacro puttypetag (tag hunk)
35 `(rplacx 1 ,hunk ,tag))
36
37(defmacro gettypetag (hunk)
38 `(cxr 1 ,hunk))
39
40(defmacro putstructlength (size defblock)
41 `(rplacx 2 ,defblock ,size))
42
43(defmacro getstructlength (defblock)
44 `(cxr 2 ,defblock))
45
46(defmacro putuniquenum (num defblockorsym)
47 `(rplacx 0 ,defblockorsym ,num))
48
49(defmacro getuniquenum (defblockorsym)
50 `(cxr 0 ,defblockorsym))
51
52; Generate a new unique number.
53(dm newnum (none)
54 '(setq *lastsymbolnum* (1+ *lastsymbolnum*)))
55
56; Special atom for each structure's definition.
57(de defatom (symbol)
58 (concat 'd: symbol))
59
60; Special atom for each structure's default instance.
61(de instatom (symbol)
62 (concat 'i: symbol))
63
64; Special atom for each symbol.
65(de symatom (symbol)
66 (concat 's: symbol))
67
68; Special atom for each block.
69(de blockatom (symbol)
70 (concat 'b: symbol))
71
72; Special atom for each ordinal type.
73(de ordatom (symbol)
74 (concat 'o: symbol))
75
76(defmacro putsymbolpname (name block)
77 `(rplacx 2 ,block ,name))
78
79(defmacro getsymbolpname (symbolitem)
80 `(cxr 2 ,symbolitem))
81
82(defmacro putpname (name blk)
83 `(rplacx 5 ,blk ,name))
84
85(defmacro getpname (blk)
86 `(cxr 5 ,blk))
87
88(defmacro putdef (defblock valblock)
89 `(rplacx 0 ,valblock ,defblock))
90
91(defmacro putisa (isa valblock)
92 `(rplacx 4 ,valblock ,isa))
93
94(defmacro getisa (valblock)
95 `(cxr 4 ,valblock))
96
97(defmacro putdefaultinst (valblock defblock)
98 `(rplacx 3 ,defblock ,valblock))
99
100(defmacro puthashalias (hashnum blk)
101 `(rplacx 6 ,blk ,hashnum))
102
103(defmacro gethashalias (blk)
104 `(cxr 6 ,blk))
105
106(defmacro puthashfocus (hashnum blk)
107 `(rplacx 7 ,blk ,hashnum))
108
109(defmacro gethashfocus (blk)
110 `(cxr 7 ,blk))
111
112(defmacro putexpansionlist (explist blk)
113 `(rplacx 8 ,blk ,explist))
114
115(defmacro getexpansionlist (blk)
116 `(cxr 8 ,blk))
117
118(defmacro putbasehooks (hooklist defblk)
119 `(rplacx 9 ,defblk ,hooklist))
120
121(defmacro getbasehooks (defblk)
122 `(cxr 9 ,defblk))
123
124(de addbasehook (conscell item)
125 (let* ((itemdef (getdefinition item))
126 (oldhooks (getbasehooks itemdef)))
127 (cond (oldhooks (nconc1 oldhooks conscell))
128 ( t (putbasehooks itemdef (ncons conscell))))))
129
130(defmacro getslotname (slotnum blk)
131 `(cxr (+ 8 (* 4 ,slotnum)) ,blk))
132
133(defmacro putslotname (slotnum slotname blk)
134 `(rplacx (+ 8 (* 4 ,slotnum)) ,blk ,slotname))
135
136(defmacro addslotname (slotnum slotname blk)
137 `(rplacx (+ 8 (* 4 ,slotnum)) ,blk
138 (cons ,slotname (cxr (+ 8 (* 4 ,slotnum)) ,blk))))
139
140(defmacro putslottype (slotnum typenum blk)
141 `(rplacx (+ 7 (* 4 ,slotnum)) ,blk ,typenum))
142
143(defmacro getslottype (slotnum blk)
144 `(cxr (+ 7 (* 4 ,slotnum)) ,blk))
145
146(defmacro putppset (slotnum setname blk)
147 `(rplacx (+ 9 (* 4 ,slotnum)) ,blk ,setname))
148
149(defmacro getppset (slotnum blk)
150 `(cxr (+ 9 (* 4 ,slotnum)) ,blk))
151
152(defmacro initbothalists (inst)
153 `(rplacx 2 ,inst (ncons nil)))
154
155(defmacro putbothalists (alist inst)
156 `(rplacx 2 ,inst ,alist))
157
158(defmacro getbothalists (inst)
159 `(cxr 2 ,inst))
160
161(defmacro getalist (inst)
162 `(cdr (cxr 2 ,inst)))
163
164(defmacro putalist (alist inst)
165 `(rplacd (cxr 2 ,inst) ,alist))
166
167; This must return the new special conscell.
168(defmacro addalist (var inst)
169 `(let ((specialcell (cons ,var (punbound))))
170 (putalist (cons specialcell (getalist ,inst)) ,inst)
171 specialcell))
172
173; The frozen variables are kept here instead of the regular assoc-list.
174(defmacro getalistcp (inst)
175 `(car (cxr 2 ,inst)))
176
177(defmacro putalistcp (alist inst)
178 `(rplaca (cxr 2 ,inst) ,alist))
179
180(defmacro getabbrev (inst)
181 `(cxr 3 ,inst))
182
183(defmacro putabbrev (abbrev inst)
184 `(rplacx 3 ,inst ,abbrev))
185
186; Put zero as the (initial) hash and format info.
187(defmacro clearhashandformat (slotnum defblock)
188 `(rplacx (+ 6 (* 4 ,slotnum)) ,defblock 0))
189
190(defmacro puthashandformat (slotnum hashnum defblock)
191 `(rplacx (+ 6 (* 4 ,slotnum)) ,defblock ,hashnum))
192
193(defmacro gethashandformat (slotnum defblock)
194 `(cxr (+ 6 (* 4 ,slotnum)) ,defblock))
195
196(defmacro puthashandenforce (slotnum hashnum blk)
197 `(rplacx (+ 6 (* 4 ,slotnum)) ,blk
198 (boole 7 (boole 1 (boole 10. 127. 0)
199 (cxr (+ 6 (* 4 ,slotnum)) ,blk))
200 (boole 1 127. ,hashnum))))
201
202(defmacro puthashinfo (slotnum hashnum blk)
203 `(rplacx (+ 6 (* 4 ,slotnum)) ,blk
204 (boole 7 (boole 1 (boole 10. 63. 0)
205 (cxr (+ 6 (* 4 ,slotnum)) ,blk))
206 (boole 1 63. ,hashnum))))
207
208(defmacro addhash* (hashnum)
209 `(setq ,hashnum (boole 7 1 ,hashnum)))
210
211(defmacro addhash** (hashnum)
212 `(setq ,hashnum (boole 7 2 ,hashnum)))
213
214(defmacro addhash: (hashnum)
215 `(setq ,hashnum (boole 7 4 ,hashnum)))
216
217(defmacro addhash:: (hashnum)
218 `(setq ,hashnum (boole 7 8. ,hashnum)))
219
220(defmacro addhash> (hashnum)
221 `(setq ,hashnum (boole 7 16. ,hashnum)))
222
223(defmacro addhash< (hashnum)
224 `(setq ,hashnum (boole 7 32. ,hashnum)))
225
226(defmacro addhash*** (hashnum)
227 `(setq ,hashnum (boole 7 64. ,hashnum)))
228
229(defmacro addenforce (hashnum)
230 `(setq ,hashnum (boole 7 128. ,hashnum)))
231
232(defmacro gethashinfo (slotnum blk)
233 `(boole 1 63.
234 (cxr (+ 6 (* 4 ,slotnum)) ,blk)))
235
236(defmacro gethash* (hashnum)
237 `(\=& 1 (boole 1 1 ,hashnum)))
238
239(defmacro gethash** (hashnum)
240 `(\=& 2 (boole 1 2 ,hashnum)))
241
242(defmacro gethash: (hashnum)
243 `(\=& 4 (boole 1 4 ,hashnum)))
244
245(defmacro gethash:: (hashnum)
246 `(\=& 8. (boole 1 8. ,hashnum)))
247
248(defmacro gethash> (hashnum)
249 `(\=& 16. (boole 1 16. ,hashnum)))
250
251(defmacro gethash< (hashnum)
252 `(\=& 32. (boole 1 32. ,hashnum)))
253
254(defmacro gethash*** (hashnum)
255 `(\=& 64. (boole 1 64. ,hashnum)))
256
257(defmacro getenforce (slotnum defblock)
258 `(\=& 128. (boole 1 128. (cxr (+ 6 (* 4 ,slotnum)) ,defblock))))
259
260; The format information is eventually intended for custom tailoring of
261; printing of structures but we've never gotten around to adding it.
262; The main idea is whether to print it if it contains the default
263; value, or whether to print to a limited depth, or whether to print
264; at all, etc.
265(defmacro putformatinfo (slotnum hashnum blk)
266 `(rplacx (+ 6 (* 4 ,slotnum)) ,blk
267 (boole 7
268 (boole 1 (boole 10. 192. 0)
269 (cxr (+ 6 (* 4 ,slotnum)) ,blk))
270 (boole 1 192. (lsh ,hashnum 6)))))
271
272(defmacro getformatinfo (slotnum blk)
273 `(lsh (boole 1
274 (boole 10. 192. 0)
275 (cxr (+ 6 (* 4 ,slotnum)) ,blk)) -6))
276
277(defmacro putpred (slotnum value inst)
278 `(rplacx (+ 2 (* 4 ,slotnum)) ,inst ,value))
279
280(defmacro getpred (slotnum inst)
281 `(cxr (+ 2 (* 4 ,slotnum)) ,inst))
282
283(defmacro putslothooks (slotnum slothooklist inst)
284 `(rplacx (+ 3 (* 4 ,slotnum)) ,inst ,slothooklist))
285
286(defmacro getslothooks (slotnum inst)
287 `(cxr (+ 3 (* 4 ,slotnum)) ,inst))
288
289; Values of slots in PEARL structures are of one of four types.
290; The type is stored as an atom in the "slotvaluetype"
291; and describes what type of value will be found in the "slotvalue".
292; The possible types and what is put in "slotvalue" are:
293; CONSTANT A constant value -- the value.
294; LOCAL A local variable -- the variable's alist conscell
295; (name . value).
296; ADJUNCT A constant value plus an adjunct variable
297; -- a conscell with CAR = the constant value
298; and CDR = the adjvar's conscell
299; (name . value).
300; GLOBAL A global variable -- the (atom) name of the global variable.
301;
302
303(defmacro putslotvaluetype (slotnum type inst)
304 `(rplacx (* 4 ,slotnum) ,inst ,type))
305
306(defmacro getslotvaluetype (slotnum inst)
307 `(cxr (* 4 ,slotnum) ,inst))
308
309(defmacro putslotvalue (slotnum value inst)
310 `(rplacx (1+ (* 4 ,slotnum)) ,inst ,value))
311
312(defmacro getslotvalue (slotnum inst)
313 `(cxr (1+ (* 4 ,slotnum)) ,inst))
314
315(dm equivclass (none)
316 ''*equivclass*)
317
318(de equivclassp (potequivclass)
319 (and (dtpr potequivclass)
320 (eq (equivclass) (car potequivclass))))
321
322; returns (punbound) for unified variables instead of the equiv cons cell.
323(defmacro getvalofequivorvar (equivorvar)
324 `(let ((val ,equivorvar))
325 (cond ((equivclassp val) (punbound))
326 ( t val))))
327
328(defmacro getvalue (slotnum inst)
329 `(let ((value (getslotvalue ,slotnum ,inst)))
330 (selectq (getslotvaluetype ,slotnum ,inst)
331 (CONSTANT value) ; A constant value.
332 (LOCAL (getvalofequivorvar (cdr value))) ; A local var.
333 (ADJUNCT (car value)) ; A constant plus adjvar.
334 (GLOBAL (getvalofequivorvar (eval value))) ; A global var.
335 (otherwise (punbound)))))
336
337; Same as getvalue, except that if the slot has an variable in it
338; the atom in "var" gets set to that value.
339(defmacro getvarandvalue (slotnum inst var)
340 `(let ((value (getslotvalue ,slotnum ,inst)))
341 (selectq (getslotvaluetype ,slotnum ,inst)
342 (CONSTANT (set ,var nil)
343 value) ; A constant value.
344 (LOCAL (set ,var value)
345 (getvalofequivorvar (cdr value))) ; A local var.
346 (ADJUNCT (set ,var (cdr value))
347 (car value)) ; A constant plus adjvar.
348 (GLOBAL (set ,var value)
349 (getvalofequivorvar (eval value))) ; A global var.
350 (otherwise (punbound)))))
351
352;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
353; The next bunch of functions are for hashing and building data bases.
354;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
355
356; For each data base, there are three parts (each a hunk):
357; the header which contains the name,
358; whether it is active
359; its parent and children and ...
360; the two parts of the actual data base:
361; DB1 for items hashed under one value.
362; DB2 for items hashed under two or more values.
363; DB1 and DB2 each contain pointers to conscells whose cars are the
364; atom *db* and whose cdrs are the list of items in that bucket.
365
366;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
367; FIRST, the functions to access and add to a hash bucket:
368
369; Items hashed under only one integer are in DB1.
370(defmacro gethash1 (num1 db1)
371 `(cxr (\\ ,num1 *db1size*) ,db1))
372
373; Add the item to the front of the appropriate hash bucket (AFTER the
374; special *db* conscell).
375(defmacro puthash1 (num1 db1 item)
376 `(let ((bucket (gethash1 ,num1 ,db1)))
377 ; Avoid exact duplicates.
378 (or (memq ,item bucket)
379 (rplacd bucket (cons ,item (cdr bucket))))
380 bucket))
381
382; Items hashed under either two or more integers are in DB2.
383(defmacro gethash2 (num1 num2 db2)
384 `(cxr (\\ (+ ,num1 (* ,num2 1024.)) *db2size*)
385 ,db2))
386
387; Add the item to the front of the appropriate hash bucket (AFTER the
388; special *db* conscell).
389(defmacro puthash2 (num1 num2 db2 item)
390 `(let ((bucket (gethash2 ,num1 ,num2 ,db2)))
391 ; Avoid exact duplicates.
392 (or (memq ,item bucket)
393 (rplacd bucket (cons ,item (cdr bucket))))
394 bucket))
395
396(defmacro gethash3 (num1 num2 num3 db2)
397 `(cxr (\\ (+ ,num1
398 (* ,num2 1024.)
399 (* ,num3 1048576.)) ; = 1024 * 1024
400 *db2size*)
401 ,db2))
402
403; Add the item to the front of the appropriate hash bucket (AFTER the
404; special *db* conscell).
405(defmacro puthash3 (num1 num2 num3 db2 item)
406 `(let ((bucket (gethash3 ,num1 ,num2 ,num3 ,db2)))
407 ; Avoid exact duplicates.
408 (or (memq ,item bucket)
409 (rplacd bucket (cons ,item (cdr bucket))))
410 bucket))
411
412(defmacro gethashmulti (num1 others db2)
413 `(cxr (\\ (+ ,num1
414 (apply (function +)
415 (mapcar (function *)
416 ,others *multiproducts*)))
417 *db2size*)
418 ,db2))
419
420; Add the item to the front of the appropriate hash bucket (AFTER the
421; special *db* conscell).
422(defmacro puthashmulti (num1 others db2 item)
423 `(let ((bucket (gethashmulti ,num1 ,others ,db2)))
424 ; Avoid exact duplicates.
425 (or (memq ,item bucket)
426 (rplacd bucket (cons ,item (cdr bucket))))
427 bucket))
428
429;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
430; Now the header info.
431
432(defmacro putdbname (name db)
433 `(rplacx 0 ,db ,name))
434
435(defmacro putdbchildren (childlist db)
436 `(rplacx 2 ,db ,childlist))
437
438(defmacro setdbactive (db)
439 `(rplacx 3 ,db t))
440
441(defmacro cleardbactive (db)
442 `(rplacx 3 ,db nil))
443
444(defmacro putdbparent (parent db)
445 `(rplacx 4 ,db ,parent))
446
447(defmacro putdb1 (db1 db)
448 `(rplacx 5 ,db ,db1))
449
450(defmacro putdb2 (db2 db)
451 `(rplacx 6 ,db ,db2))
452
453(defmacro getdbname (db)
454 `(cxr 0 ,db))
455
456(defmacro getdbchildren (db)
457 `(cxr 2 ,db))
458
459(defmacro getdbactive (db)
460 `(cxr 3 ,db))
461
462(defmacro getdbparent (db)
463 `(cxr 4 ,db))
464
465(defmacro getdb1 (db)
466 `(cxr 5 ,db))
467
468(defmacro getdb2 (db)
469 `(cxr 6 ,db))
470
471; The following predicates do the best we can to check for the type of
472; object by checking what we hope are reasonably unique arrangements
473; of values. In the case of definitions, instances, databases and
474; symbols, a tag is put in the hunk saying what it is. This is
475; assumed to be enough.
476
477(de streamp (potstream)
478 (and (dtpr potstream)
479 (eq '*stream* (car potstream))))
480
481(de databasep (potdb)
482 (and (hunkp potdb)
483 (let ((tag (gettypetag potdb)))
484 (or (eq tag '*pearldb*)
485 (eq tag '*pearlinactivedb*)))))
486
487(de blockp (potblock)
488 (let* ((name (car potblock))
489 (blockname (blockatom name)))
490 (and (boundp blockname)
491 (eq name
492 (car (eval blockname)))
493 (eq potblock
494 (eval blockname)))))
495
496(de definitionp (potdef)
497 (and (hunkp potdef)
498 (eq '*pearldef* (gettypetag potdef))))
499
500(de psymbolp (potsymbol)
501 (and (hunkp potsymbol)
502 (eq '*pearlsymbol* (gettypetag potsymbol))))
503
504(de structurep (potstruct)
505 (and (hunkp potstruct)
506 (eq '*pearlinst* (gettypetag potstruct))))
507
508(de symbolnamep (potname)
509 (let ((symname (symatom potname)))
510 (and (boundp symname)
511 (psymbolp (eval symname)))))
512
513(de structurenamep (potname)
514 (let ((defname (defatom potname)))
515 (and (boundp defname)
516 (definitionp (eval defname)))))
517
518; Determine the print name of an arbitrary object.
519(de pname (item)
520 (cond ((definitionp item) (getpname item))
521 ((structurep item) (getpname (getdefinition item)))
522 ((psymbolp item) (getsymbolpname item))
523 ((databasep item) (getdbname item))
524 ((atom item) item)
525 ((streamp item) (msg t "PNAME: streams do not have pnames: "
526 item t))
527 ( t (msg t "PNAME: " item " does not have a printname"))))
528
529; For loop patterned after (do for ...) in UCI Lisp, except that an
530; initial value is required instead of RPT (and there is no DO).
531(defmacro for (val init final &rest body)
532 `((lambda (,val pforlim)
533 (prog (pforval)
534 pforlab
535 (and (>& ,val pforlim)
536 (return pforval))
537 (setq pforval (progn .,body))
538 (setq ,val (1+ ,val))
539 (go pforlab)))
540 ,init
541 ,final))
542
543; While loop patterned after (do while ...) in UCI Lisp.
544(defmacro while (val &rest body)
545 `(prog (pwhval)
546 pwhlab
547 (and (not ,val)
548 (return pwhval))
549 (setq pwhval (progn .,body))
550 (go pwhlab)))
551
552; vi: set lisp: