|
|
1.1 root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.