|
|
1.1 root 1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hash.l ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2: ; Functions for hashing, inserting, and fetching items into the
3: ; data bases, plus operating on streams.
4: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5: ; Copyright (c) 1983 , The Regents of the University of California.
6: ; All rights reserved.
7: ; Authors: Joseph Faletti and Michael Deering.
8:
9: ; Find the next item on the CDDR list of the stream that matches the CADR of
10: ; the stream and return it, also updating the stream.
11: (de nextitem (stream)
12: (or (streamp stream)
13: (progn (msg t "NEXTITEM: Not a stream: " stream t)
14: (pearlbreak)))
15: (setq stream (cdr stream)) ; Throw away the *STREAM*.
16: (cond ((eq t (car stream)) ; This means function structure.
17: (prog1 (evalfcn (cdr stream))
18: (rplacd (rplaca stream nil) nil)))
19: ((null (cadr stream)) nil) ; Test for empty stream
20: ; Stream built by standardfetch.
21: ; To debug or modify this, you must draw a picture of what
22: ; standardfetch built because of the way it is written.
23: ((not (dtpr (cadr stream)))
24: (prog (item result)
25: (setq item (car stream))
26: (setq *currentpearlstructure* item)
27: (checkrunhandlebasehooks1 '<nextitem *runnextitemhooks*)
28: (while (and (cdr stream)
29: (or (eq (cadr stream) '*db*)
30: (not (match item (cadr stream)))))
31: (rplacd stream (cddr stream)))
32: (setq item (cadr stream))
33: (rplacd stream (cddr stream))
34: (checkrunhandlebasehooks1 '>nextitem *runnextitemhooks*)
35: (return item)))
36: ; Stream built by expandedfetch (or fetcheverywhere).
37: ; To debug or modify this, you must draw a picture of what
38: ; expandedfetch built because of the way it is written.
39: ((not (dtpr (caadr stream)))
40: (prog (item result)
41: (setq item (car stream))
42: (setq *currentpearlstructure* item)
43: (checkrunhandlebasehooks1 '<nextitem *runnextitemhooks*)
44: (while (and (cdr stream)
45: (or (eq (caadr stream) '*db*)
46: (not (expandedmatch item (caadr stream)))))
47: (or (car (rplaca (cdr stream) (cdadr stream)))
48: (rplacd stream (cddr stream))))
49: (setq item (caadr stream))
50: (or (not (cdr stream))
51: (car (rplaca (cdr stream) (cdadr stream)))
52: (rplacd stream (cddr stream)))
53: (checkrunhandlebasehooks1 '>nextitem *runnextitemhooks*)
54: (return item)))))
55:
56: (defmacro hashinfo (slotnum)
57: `(cxr ,slotnum *hashingmarks*))
58:
59: (defmacro sethashinfo (slotnum value)
60: `(rplacx ,slotnum *hashingmarks* ,value))
61:
62: (defmacro slotval (slotnum)
63: `(cxr ,slotnum *slotvalues*))
64:
65: (defmacro storeslot (slotnum value)
66: `(rplacx ,slotnum *slotvalues* ,value))
67:
68: ; If there is anything to hash this slot on, say so and put it in HASHV.
69: (defmacro hashablevalue (slotnum item defblock hashinfo)
70: `(not (memq (setq hashv (gethashvalue ,slotnum ,item ,defblock ,hashinfo))
71: *unhashablevalues*)))
72:
73: ; If this slot is to take part in a hashing combination, (and it is the
74: ; second one in :: or ** hashing), then add it to the right hash bucket.
75: (dm hashslot (none)
76: '(cond ((\=& 0 hashinfo) nil) ; No hashing to be done
77: ((hashablevalue slotnum item defblock hashinfo) ; Sets HASHV
78: (and (gethash* hashinfo)
79: (puthash2 unique hashv db2 item))
80: ; (and (gethash: hashinfo)
81: ; (puthash1 hashv db1 item))
82: (and (gethash** hashinfo)
83: (cond ((null mark**)
84: ; First one found.
85: (setq mark** hashv))
86: ; Second one found
87: ((neq t mark**)
88: (puthash3 unique mark** hashv db2 item)
89: (setq mark** t))
90: ; Third or greater found.
91: ( t (msg t "HASH: More than two **'s in: "
92: (getpname defblock) t))))
93: ; (and (gethash:: hashinfo)
94: ; (cond ((null mark::)
95: ; ; First one found.
96: ; (setq mark:: hashv))
97: ; ; Second one found
98: ; ((neq t mark::)
99: ; (puthash2 mark:: hashv db2 item)
100: ; (setq mark:: t))
101: ; ; Third or greater found.
102: ; ( t (msg t "HASH: More than two ::'s in: "
103: ; (getpname defblock) t))))
104: (and (gethash*** hashinfo)
105: (cond ((null mark***)
106: ; First one found.
107: (setq mark*** (ncons hashv)))
108: ; Later ones found.
109: ( t (tconc mark*** hashv))))
110: )))
111:
112: ; For each of the four ways of hashing, or else just based on the type,
113: ; check to see if the pattern can be hashed that way and if so,
114: ; RETURN the right hashbucket. If the previous one can't be done,
115: ; try the next one but stop with the first that can be done.
116: ; The order is ***, **, ::, &&, *, and :.
117: (dm insidestandardfetch (none)
118: '(cond ((prog2
119: (for slotnum 1 length
120: (and (gethash*** (hashinfo slotnum))
121: (cond ((eq (punbound)
122: (setq hashv (slotval slotnum)))
123: (setq mark nil)
124: (return nil))
125: ((null mark)
126: (setq mark (ncons nil))
127: (tconc mark hashv)
128: nil)
129: ( t (tconc mark hashv)))))
130: mark)
131: (gethashmulti unique (car mark) db2))
132: ((for slotnum 1 length
133: (and (gethash** (hashinfo slotnum))
134: (cond ((eq (punbound)
135: (setq hashv (slotval slotnum)))
136: (return nil))
137: ((null mark) (setq mark hashv) nil)
138: ( t (return (gethash3 unique mark hashv db2)))))))
139: ; ((for slotnum 1 length
140: ; (and (gethash:: (hashinfo slotnum))
141: ; (cond ((eq (punbound)
142: ; (setq hashv (slotval slotnum)))
143: ; (return nil))
144: ; ((null mark) (setq mark hashv) nil)
145: ; ( t (return (gethash2 mark hashv db2)))))))
146: ((and (not (\=& 0 focus))
147: (pboundp (setq hashv (slotval focus))))
148: (recursetoinsidestandardfetch (getslotvalue focus item) db1 db2))
149: ((for slotnum 1 length
150: (and (gethash* (hashinfo slotnum))
151: (and (pboundp (setq hashv
152: (slotval slotnum)))
153: (return (gethash2 unique hashv db2))))))
154: ; ((for slotnum 1 length
155: ; (and (gethash: (hashinfo slotnum))
156: ; (and (pboundp (setq hashv
157: ; (slotval slotnum)))
158: ; (return (gethash1 hashv db1))))))
159: ( t (gethash1 unique db1))))
160:
161: (de recursetoinsidestandardfetch (item db1 db2)
162: (let* ((defblock (getdefinition item))
163: (length (getstructlength defblock))
164: (*slotvalues* (makhunk (1+ length)))
165: (*hashingmarks* (makhunk (1+ length)))
166: (unique (getuniquenum defblock))
167: mark hashv focus hashinfo)
168: (setq focus (gethashfocus defblock))
169: (for slotnum 1 length
170: (setq hashinfo (gethashinfo slotnum defblock))
171: (sethashinfo slotnum hashinfo)
172: (or (and (\=& 0 hashinfo)
173: (not (\=& focus slotnum)))
174: (storeslot slotnum
175: (gethashvalue slotnum item defblock hashinfo))))
176: (insidestandardfetch)))
177:
178: ; Return a pair consisting of the ITEM and a hash-bucket-list that should
179: ; have what we are looking for in it.
180: (de standardfetch (item &optional (db *db*))
181: (cond ((get (pname item) 'functionstruct)
182: (cons '*stream* (cons t item)))
183: ( t (prog (mark defblock bucket db1 db2 hashv result focus
184: length hashinfo unique)
185: (setq defblock (getdefinition item))
186: (setq *currentpearlstructure* item)
187: (checkrunhandlebasehooks1 '<fetch *runfetchhooks*)
188: (setq db1 (getdb1 db))
189: (setq db2 (getdb2 db))
190: (setq length (getstructlength defblock))
191: (setq focus (gethashfocus defblock))
192: (for slotnum 1 length
193: (setq hashinfo (gethashinfo slotnum defblock))
194: (sethashinfo slotnum hashinfo)
195: (or (and (\=& 0 hashinfo)
196: (not (\=& focus slotnum)))
197: (storeslot slotnum
198: (gethashvalue slotnum item
199: defblock hashinfo))))
200: (setq unique (getuniquenum defblock))
201: (setq bucket (insidestandardfetch))
202: (checkrunhandlebasehooks1 '>fetch *runfetchhooks*)
203: (return (cons '*stream* (cons item bucket)))))))
204:
205: (aliasdef 'fetch 'standardfetch)
206:
207: (de expandedfetch (item &optional (db *db*))
208: (cond ((get (pname item) 'functionstruct)
209: (cons '*stream* (cons t item)))
210: ( t (prog (mark defblock defblocklist buckets db1 db2 hashv result
211: focus length hashinfo)
212: (setq defblock (getdefinition item))
213: (setq *currentpearlstructure* item)
214: (checkrunhandlebasehooks1 '<fetch *runfetchhooks*)
215: (setq db1 (getdb1 db))
216: (setq db2 (getdb2 db))
217: (setq length (getstructlength defblock))
218: (setq focus (gethashfocus defblock))
219: (for slotnum 1 length
220: (setq hashinfo (gethashinfo slotnum defblock))
221: (sethashinfo slotnum hashinfo)
222: (or (and (\=& 0 hashinfo)
223: (not (\=& focus slotnum)))
224: (storeslot slotnum
225: (gethashvalue slotnum item
226: defblock hashinfo))))
227: (setq defblocklist (cons defblock
228: (getexpansionlist defblock)))
229: ; Note that instead of being one list, buckets is a
230: ; list of lists.
231: (setq buckets
232: (mapcar
233: (funl (expandeddefblock)
234: (let ((unique (getuniquenum expandeddefblock)))
235: (insidestandardfetch)))
236: defblocklist))
237: (dremove nil buckets)
238: (checkrunhandlebasehooks1 '>fetch *runfetchhooks*)
239: (return (cons '*stream* (cons item buckets)))))))
240:
241: ; Find the object EVERYWHERE it might be: ; (Well, only 1 for each hash method).
242: ; For each of the four ways of hashing, plus just based on the type,
243: ; check to see if the pattern can be hashed that way and if so,
244: ; return the right hash bucket. A list of these lists is made.
245: ; NIL's are removed in the main function.
246: ; The order is ***, **, ::, &&, *, and :.
247: (dm insidefetcheverywhere (none)
248: '(let ((bucketlist (ncons nil)))
249: (for slotnum 1 length
250: (and (gethash*** (hashinfo slotnum))
251: (cond ((eq (punbound)
252: (setq hashv (slotval slotnum)))
253: (setq mark nil)
254: (return nil))
255: ((null mark) (setq mark (ncons hashv)) nil)
256: ( t (tconc mark hashv)))))
257: (and mark
258: (tconc bucketlist
259: (gethashmulti unique (car mark) db2))
260: (setq mark nil))
261: (for slotnum 1 length
262: (and (gethash** (hashinfo slotnum))
263: (cond ((eq (punbound)
264: (setq hashv (slotval slotnum)))
265: (return nil))
266: ((null mark) (setq mark hashv) nil)
267: ( t (tconc bucketlist
268: (gethash3 unique mark hashv db2))
269: (setq mark nil)
270: (return nil)))))
271: (and (not (\=& 0 focus))
272: (pboundp (setq hashv (slotval focus)))
273: (tconc bucketlist
274: (recursetoinsidestandardfetch (getslotvalue focus item)
275: db1 db2)))
276: (for slotnum 1 length
277: (and (gethash* (hashinfo slotnum))
278: (and (pboundp (setq hashv
279: (slotval slotnum)))
280: (tconc bucketlist
281: (gethash2 unique hashv db2)))))
282: (tconc bucketlist
283: (gethash1 unique db1))
284: (car bucketlist)))
285:
286: ; Return a list consisting of the ITEM and a list of hash-bucket-list
287: ; that must have what we are looking for in it if it's there.
288: (de fetcheverywhere (item &optional (db *db*))
289: (cond ((get (pname item) 'functionstruct)
290: (cons '*stream* (cons t item)))
291: ( t (prog (mark defblock buckets db1 db2 hashv result focus
292: length hashinfo unique)
293: (setq defblock (getdefinition item))
294: (setq length (getstructlength defblock))
295: (setq focus (gethashfocus defblock))
296: (for slotnum 1 length
297: (setq hashinfo (gethashinfo slotnum defblock))
298: (sethashinfo slotnum hashinfo)
299: (or (and (\=& 0 hashinfo)
300: (not (\=& focus slotnum)))
301: (storeslot slotnum
302: (gethashvalue slotnum item
303: defblock hashinfo))))
304: (setq *currentpearlstructure* item)
305: (checkrunhandlebasehooks1 '<fetch *runfetchhooks*)
306: (setq db1 (getdb1 db))
307: (setq db2 (getdb2 db))
308: (setq unique (getuniquenum defblock))
309: (setq buckets (insidefetcheverywhere))
310: (dremove nil buckets)
311: (checkrunhandlebasehooks1 '>fetch *runfetchhooks*)
312: (return (cons '*stream* (cons item buckets)))))))
313:
314: ; Discover if a hash alias is to be used.
315: (dm noalias (none)
316: '(cond ((>& alias 0)
317: (cond ((gethash< hashinfo)
318: (cond ((gethash> hashinfo) nil) ; < > cancels
319: ( t t)))
320: ( t nil)))
321: ( t (cond ((gethash< hashinfo) t)
322: ( t (cond ((gethash> hashinfo) nil) ; < > cancels
323: ( t t)))))))
324:
325: ; Get the value that should be hashed for the given slot of ITEM
326: ; else return unbound.
327: (de gethashvalue (slotnum item defblock hashinfo)
328: (let
329: ((potential (getvalue slotnum item))
330: alias)
331: (cond ((null potential) nil)
332: ((pboundp potential)
333: (let ((potdef (getdefinition potential)))
334: (selectq (getslottype slotnum defblock)
335: (0 (setq alias (gethashalias potdef))
336: (cond ((or (noalias)
337: (\=& 0 alias))
338: (getuniquenum potdef))
339: ( t
340: (setq alias (abs alias))
341: (gethashvalue alias potential potdef
342: (gethashinfo alias potdef)))))
343: (1 (getuniquenum potential)) ; Symbol.
344: (2 potential) ; Integer.
345: (3 (punbound)) ; Lisp not hashed.
346: (otherwise nil)))) ; SetOf not hashed (YET).
347: ( t (punbound)))))
348:
349: ; Fetch the first item matching the pattern.
350: (defmacro firstfetch (pattern)
351: `(nextitem (fetch ,pattern)))
352:
353: (defmacro fetchcreate (&rest rest)
354: `(fetch (create .,rest)))
355:
356: (defmacro inlinefetchcreate (&rest rest)
357: `(fetch (quote ,(create rest))))
358:
359: (defmacro inlinecreate (&rest rest)
360: `(quote ,(create rest)))
361:
362: ; Build a value to pass to the function for the parameter for this slot.
363: (dm fcnslot (none)
364: '(let ((slotv (getvalue slotnum item))
365: (type (getslottype slotnum defblock)))
366: (cond ((eq slotv (punbound)) (punbound))
367: ((and (<& type 4)
368: (or (not (\=& 0 type))
369: (not (get (getpname (getdefinition slotv))
370: 'functionstruct)))) slotv)
371: ((\=& 0 type)
372: (evalfcn slotv))
373: ((\=& 0 (boole 1 3 type))
374: (mapcar (function evalfcn) slotv))
375: ( t slotv))))
376:
377: ; Evaluate a function structure.
378: (de evalfcn (item)
379: (cond ((dtpr item) (mapcar (function evalfcn) item))
380: ((not (get (getpname (getdefinition item)) 'functionstruct)) item)
381: ( t (let* ((defblock (getdefinition item))
382: (length (getstructlength defblock))
383: (fcncall (ncons nil))
384: slotv)
385: (tconc fcncall (getpname defblock))
386: (for slotnum 1 length
387: (tconc fcncall (fcnslot)))
388: (apply* (caar fcncall) (cdar fcncall))))))
389:
390: ; A kludge to be removed (with disguisedas) when we implement VIEWS.
391: (defmacro getstructorsymnum (strsym)
392: `(cond ((psymbolp ,strsym) (getuniquenum ,strsym))
393: ( t (getuniquenum (getdefinition ,strsym)))))
394:
395: ; (DISGUISEDAS Filler Struct DB) means "Is filler a struct?
396: ; if there is an item in the data base DB of the form
397: ; (STRUCT (<first slot> FILLER) ... )
398: ; then return it. If not, return NIL.
399: (de disguisedas (filler struct &optional (db *db*))
400: (prog (fillernum bucket db2 item value)
401: (setq db2 (getdb2 db))
402: (setq fillernum (getstructorsymnum filler))
403: (setq bucket (remq '*db*
404: (gethash2 (getuniquenum struct) fillernum db2)))
405: loop
406: (cond ((null bucket) (return nil))
407: ((and (eq struct (getdefinition (setq item (pop bucket))))
408: (neq (punbound) (setq value (getvalue 1 item)))
409: (eq (getstructorsymnum value) fillernum))
410: (return item))
411: ( t (go loop)))))
412:
413: (de insertbyfocus (focus item db1 db2)
414: (prog (unique mark** mark:: mark*** defblock
415: value hashinfo hashv focusslotnum)
416: (setq defblock (getdefinition focus))
417: (setq unique (getuniquenum defblock))
418: (puthash1 unique db1 item)
419: (and (not (\=& 0 (setq focusslotnum (gethashfocus defblock))))
420: (pboundp (setq value (getvalue focusslotnum focus)))
421: (insertbyfocus value item db1 db2))
422: (for slotnum 1 (getstructlength defblock)
423: (setq hashinfo (gethashinfo slotnum defblock))
424: (cond ((\=& 0 hashinfo) nil)
425: ((hashablevalue slotnum focus defblock hashinfo) ; Sets HASHV
426: (and (gethash* hashinfo)
427: (puthash2 unique hashv db2 item))
428: ; (and (gethash: hashinfo)
429: ; (puthash1 hashv db1 item))
430: (and (gethash** hashinfo)
431: (cond ((null mark**)
432: ; First one found.
433: (setq mark** hashv))
434: ; Second one found
435: ((neq t mark**)
436: (puthash3 unique mark** hashv db2 item)
437: (setq mark** t))
438: ; Third or greater found.
439: ( t (msg t "HASH: More than two **'s in: "
440: (getpname defblock) t))))
441: ; (and (gethash:: hashinfo)
442: ; (cond ((null mark::)
443: ; ; First one found.
444: ; (setq mark:: hashv))
445: ; ; Second one found
446: ; ((neq t mark::)
447: ; (puthash2 mark:: hashv db2 item)
448: ; (setq mark:: t))
449: ; ; Third or greater found.
450: ; ( t (msg t "HASH: More than two ::'s in: "
451: ; (getpname defblock) t))))
452: (and (gethash*** hashinfo)
453: (cond ((null mark***)
454: ; First one found.
455: (setq mark*** (ncons hashv)))
456: ; Later ones found.
457: ( t (tconc mark*** hashv))))
458: )))
459: (and mark***
460: (puthashmulti unique (car mark***) db2 item))))
461:
462: ; We must put this struct into the data base somewhere,
463: ; perhaps in several places.
464: (de insertdb (item &optional (db *db*))
465: (or item
466: (progn (msg t "Trying to INSERTDB a nil item: " item t)
467: (pearlbreak)))
468: (and (dtpr item)
469: (progn (msg t "Trying to INSERTDB a cons-cell: " item t)
470: (pearlbreak)))
471: (cond ((get (getpname (getdefinition item)) 'functionstruct)
472: (evalfcn item))
473: ( t
474: (prog (unique mark** mark:: mark*** defblock db1 db2
475: value hashinfo hashv result focus)
476: (setq defblock (getdefinition item))
477: (setq *currentpearlstructure* item)
478: (checkrunhandlebasehooks1 '<insertdb *runinsertdbhooks*)
479: (setq unique (getuniquenum defblock))
480: (setq db1 (getdb1 db))
481: (setq db2 (getdb2 db))
482: (puthash1 unique db1 item)
483: (and (not (\=& 0 (setq focus (gethashfocus defblock))))
484: (pboundp (setq value (getvalue focus item)))
485: (insertbyfocus value item db1 db2))
486:
487: (for slotnum 1 (getstructlength defblock)
488: (setq hashinfo (gethashinfo slotnum defblock))
489: (hashslot))
490: (and mark***
491: (puthashmulti unique (car mark***) db2 item))
492: (checkrunhandlebasehooks1 '>insertdb *runinsertdbhooks*)
493: (return item)))))
494:
495: ; For each way that this slot can be hashed, destructively remove the
496: ; item from the correct bucket. Expects SLOTNUM, DEFBLOCK, ITEM,
497: ; MARK**, MARK::, MARK***, HASHV, UNIQUE, DB1, DB2.
498: (dm removeslot (none)
499: '(cond ((\=& 0 hashinfo) nil) ; No hashing to be done
500: ((hashablevalue slotnum item defblock hashinfo) ; Sets HASHV
501: (and (gethash* hashinfo)
502: (delq item (gethash2 unique hashv db2)))
503: ; (and (gethash: hashinfo)
504: ; (delq item (gethash1 hashv db1)))
505: (and (gethash** hashinfo)
506: (cond ((null mark**)
507: (setq mark** hashv))
508: ((neq t mark**)
509: (delq item (gethash3 unique mark** hashv db2))
510: (setq mark** t))
511: ( t (msg t "More than two **'s in: "
512: (getpname defblock) t))))
513: ; (and (gethash:: hashinfo)
514: ; (cond ((null mark::)
515: ; (setq mark:: hashv))
516: ; ((neq t mark::)
517: ; (delq item (gethash2 mark:: hashv db2))
518: ; (setq mark:: t))
519: ; ( t (msg t "More than two ::'s in: "
520: ; (getpname defblock) t))))
521: (and (gethash*** hashinfo)
522: (cond ((null mark***)
523: ; First one found.
524: (setq mark*** (ncons hashv)))
525: ; Later ones found.
526: ( t (tconc mark*** hashv))))
527: )))
528:
529: (de removebyfocus (focus item db1 db2)
530: (prog (unique mark** mark:: mark*** defblock hashinfo hashv focusslotnum)
531: (setq defblock (getdefinition focus))
532: (setq unique (getuniquenum defblock))
533: (dremove item (gethash1 unique db1))
534: (and (not (\=& 0 (setq focusslotnum (gethashfocus defblock))))
535: (removebyfocus (getvalue focusslotnum focus) item db1 db2))
536: (for slotnum 1 (getstructlength defblock)
537: (setq hashinfo (gethashinfo slotnum defblock))
538: (cond ((\=& 0 hashinfo) nil)
539: ((hashablevalue slotnum focus defblock hashinfo) ; Sets HASHV
540: (and (gethash* hashinfo)
541: (delq item (gethash2 unique hashv db2)))
542: ; (and (gethash: hashinfo)
543: ; (delq item (gethash1 hashv db1)))
544: (and (gethash** hashinfo)
545: (cond ((null mark**)
546: (setq mark** hashv))
547: ((neq t mark**)
548: (delq item (gethash3 unique mark** hashv db2))
549: (setq mark** t))
550: ( t (msg t "More than two **'s in: "
551: (getpname defblock) t))))
552: ; (and (gethash:: hashinfo)
553: ; (cond ((null mark::)
554: ; (setq mark:: hashv))
555: ; ((neq t mark::)
556: ; (delq item (gethash2 mark:: hashv db2))
557: ; (setq mark:: t))
558: ; ( t (msg t "More than two ::'s in: "
559: ; (getpname defblock) t))))
560: (and (gethash*** hashinfo)
561: (cond ((null mark***)
562: ; First one found.
563: (setq mark*** (ncons hashv)))
564: ; Later ones found.
565: ( t (tconc mark*** hashv))))
566: )))
567: (and mark***
568: (delq item (gethashmulti unique mark*** db2)))
569: ))
570:
571: ; We may have to remove this struct from several places so look
572: ; every place it might have been hashed.
573: (de removedb (item &optional (db *db*))
574: (or item
575: (progn (msg t "Trying to REMOVEDB a nil item: " item t)
576: (pearlbreak)))
577: (and (dtpr item)
578: (progn (msg t "Trying to REMOVEDB a cons-cell: " item t)
579: (pearlbreak)))
580: (or (structurep item)
581: (progn (msg t "Trying to REMOVEDB a non-structure: " item t)
582: (pearlbreak)))
583: (cond ((get (getpname (getdefinition item)) 'functionstruct) nil)
584: ( t
585: (prog (unique mark** mark:: mark*** defblock db1 db2
586: hashinfo hashv result focus)
587: (setq defblock (getdefinition item))
588: (setq *currentpearlstructure* item)
589: (checkrunhandlebasehooks1 '<removedb *runremovedbhooks*)
590: (setq unique (getuniquenum defblock))
591: (or db
592: (setq db *db*))
593: (setq db1 (getdb1 db))
594: (setq db2 (getdb2 db))
595: (delq item (gethash1 unique db1))
596: (and (not (\=& 0 (setq focus (gethashfocus defblock))))
597: (removebyfocus (getvalue focus item) item db1 db2))
598: (for slotnum 1 (getstructlength defblock)
599: (setq hashinfo (gethashinfo slotnum defblock))
600: (removeslot))
601: (and mark***
602: (delq item (gethashmulti unique mark*** db2)))
603: (checkrunhandlebasehooks1 '>removedb *runremovedbhooks*)
604: (return item)))))
605:
606: ; Find the next item on the CDDR list of the stream that is STREQUAL to
607: ; the CADR of the stream and return it, also updating the stream.
608: (de nextequal (stream)
609: (or (streamp stream)
610: (progn (msg t "NEXTEQUAL: not a stream: " stream t)
611: (pearlbreak)))
612: (setq stream (cdr stream)) ; Throw away the *STREAM*.
613: (cond ((eq t (car stream)) ; This means function structure.
614: (prog1 (evalfcn (cdr stream))
615: (rplacd (rplaca stream nil) nil)))
616: ((null (cadr stream)) nil) ; Test for empty stream
617: ; Stream built by standardfetch.
618: ; To debug or modify this, you must draw a picture of what
619: ; standardfetch built because of the way it is written.
620: ((not (dtpr (cadr stream)))
621: (prog (item result)
622: (setq item (car stream))
623: (setq *currentpearlstructure* item)
624: (checkrunhandlebasehooks1 '<nextequal *runnextequalhooks*)
625: (while (and (cdr stream)
626: (or (eq (cadr stream) '*db*)
627: (not (strequal item (cadr stream)))))
628: (rplacd stream (cddr stream)))
629: (cond ((cadr stream)
630: (setq item (cadr stream)))
631: ( t (setq item nil)))
632: (rplacd stream (cddr stream))
633: (checkrunhandlebasehooks1 '>nextequal *runnextequalhooks*)
634: (return item)))
635: ; Stream built by expandedfetch (or fetcheverywhere).
636: ; To debug or modify this, you must draw a picture of what
637: ; expandedfetch built because of the way it is written.
638: ((not (dtpr (caadr stream)))
639: (prog (item result)
640: (setq item (car stream))
641: (setq *currentpearlstructure* item)
642: (checkrunhandlebasehooks1 '<nextequal *runnextequalhooks*)
643: (while (and (cdr stream)
644: (or (eq (caadr stream) '*db*)
645: (not (strequal item (caadr stream)))))
646: (or (car (rplaca (cdr stream) (cdadr stream)))
647: (rplacd stream (cddr stream))))
648: (cond ((cadr stream)
649: (setq item (caadr stream)))
650: ( t (setq item nil)))
651: (or (not (cdr stream))
652: (car (rplaca (cdr stream) (cdadr stream)))
653: (rplacd stream (cddr stream)))
654: (checkrunhandlebasehooks1 '>nextequal *runnextequalhooks*)
655: (return item)))))
656:
657: ; Find out if an EQUAL ITEM is in the DB by using FETCH and then
658: ; applying NEXTEQUAL.
659: (de indb (item &optional (db *db*))
660: (prog (result newitem answer)
661: (setq *currentpearlstructure* item)
662: (checkrunhandlebasehooks1 '<indb *runindbhooks*)
663: (setq newitem nil)
664: (and (setq answer (nextequal (fetch item db)))
665: (setq newitem (setq item answer)))
666: (checkrunhandlebasehooks1 '>indb *runindbhooks*)
667: (and newitem
668: (neq item newitem)
669: (setq answer item))
670: (return answer)))
671:
672: ; (FOREACH STREAM FCN) applies FCN to each element returned by
673: ; NEXTITEM from STREAM.
674: (df foreach (l)
675: (let ((stream (eval (car l)))
676: (fcn (cadr l))
677: item)
678: (while (setq item (nextitem stream))
679: (apply* fcn (ncons item)))))
680:
681: ; Convert a stream to a list of actual matchers.
682: (de streamtolist (stream)
683: (let ((result (ncons nil))
684: item)
685: (while (setq item (nextitem stream))
686: (tconc result item))
687: (car result)))
688:
689:
690: ; vi: set lisp:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.