|
|
1.1 root 1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vars.l ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2: ; Functions for declaring and creating pattern-matching variables
3: ; and blocks and for freezing and thawing them.
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: ; Convert a question mark variable ?var to either (*global* var) if "var"
10: ; is in *globallist* or else make it local (*var* var).
11: (drm \?
12: (lambda ()
13: (let ((nextchar (tyipeek))
14: var)
15: (cond ((\=& 9. nextchar) '\?)
16: ((\=& 10. nextchar) '\?)
17: ((\=& 13. nextchar) '\?)
18: ((\=& 32. nextchar) '\?)
19: ((\=& 41. nextchar) '\?)
20: ( t (setq var (read))
21: (cond ((memq var *globallist*)
22: (list '*global* var))
23: ( t (list '*var* var))))))))
24:
25: ; VALUEOF and VARVALUE are EXPR and FEXPR versions of a function to
26: ; get the value of the variable VAR in the structure STRUCT.
27: (de valueof (var struct)
28: (getvalofequivorvar
29: (cdr (or (assq var (getalist struct))
30: (assq var (getalistcp struct))
31: (progn (msg t "VALUEOF: Variable " var
32: " does not occur in structure:" struct t)
33: (pearlbreak))))))
34:
35: ; This is a FEXPR version of valueof (above).
36: (df varvalue (l) ; (VAR STRUCT)
37: (let ((var (car l))
38: (struct (eval (cadr l))))
39: (getvalofequivorvar
40: (cdr (or (assq var (getalist struct))
41: (assq var (getalistcp struct))
42: (progn (msg t "VARVALUE: Variable " var
43: " does not occur in structure:" struct t)
44: (pearlbreak)))))))
45:
46: ; Set the given variable, in the given environment (if present) to
47: ; the value given. If no environment given, look first at
48: ; *currentstructure*, then at *currentpearlstructure*, then at
49: ; *blockstack*, else complain.
50: (df setv (l) ; (var 'val 'environment)
51: (let*
52: ((var (car l))
53: (type (car var))
54: (name (cadr var))
55: (val (eval (cadr l)))
56: (environment (eval (caddr l)))
57: varcell
58: oldvarval)
59: (cond ((eq '*global* type) ; global variable.
60: (setq oldvarval (eval name))
61: (set name val))
62: ((eq '*var* type) ; local or block variable.
63: (cond (environment
64: ; optional 3rd argument given for environment.
65: (cond ((structurep environment)
66: (setq varcell
67: (or (assq name (getalist environment))
68: (assq name (getalistcp environment))
69: (progn (msg t "SETV: No variable named: " name
70: " in structure: " t environment t)
71: (pearlbreak)))))
72: ((blockp environment)
73: (setq varcell
74: (or (assq name environment)
75: (progn (msg t "SETV: No variable named: " name
76: " in block: " t environment t)
77: (pearlbreak)))))
78: ( t (msg t "SETV: Given environment is neither "
79: "a block nor a structure: " t environment)
80: (pearlbreak))))
81: ; otherwise, try to find in standard environment.
82: ((setq varcell
83: (or (and (structurep *currentstructure*)
84: (or (assq name (getalist *currentstructure*))
85: (assq name (getalistcp *currentstructure*))
86: ))
87: (and (structurep *currentpearlstructure*)
88: (or (assq name
89: (getalist *currentpearlstructure*))
90: (assq name
91: (getalistcp *currentpearlstructure*))
92: ))
93: (and *blockstack*
94: (assq name (cdar *blockstack*))))))
95: ( t ; Else if not there either, blow up.
96: (msg t "SETV: No variable in the current"
97: " environment named: " name t)
98: (pearlbreak)))
99: ; Successfully found the variable.
100: (and varcell
101: (setq oldvarval (cdr varcell))
102: (rplacd varcell val)))
103: ( t (msg t "SETV: " var " is not a variable." t)
104: (pearlbreak)))
105: (and (equivclassp oldvarval)
106: (mapc (funl (newvar) (cond ((dtpr newvar) ; a local var cell.
107: (and (eq (cdr newvar) oldvarval)
108: (rplacd newvar val)))
109: ( t ; otherwise a global var's name.
110: (and (eq (eval newvar) oldvarval)
111: (set newvar val)))))
112: (cdr oldvarval)))
113: val))
114:
115: ; Get the value of a local variable. Look in the same places as
116: ; SETV above but return nil if not found.
117: (df *var* (l)
118: (let ((var (car l)))
119: (getvalofequivorvar
120: (cdr (or (and (structurep *currentstructure*)
121: (or (assq var (getalist *currentstructure*))
122: (assq var (getalistcp *currentstructure*))))
123: (and (structurep *currentpearlstructure*)
124: (or (assq var (getalist *currentpearlstructure*))
125: (assq var
126: (getalistcp *currentpearlstructure*))))
127: (and *blockstack*
128: (assq var (cdar *blockstack*))))))))
129:
130: ; Get the value of a global variable.
131: (df *global* (l)
132: (getvalofequivorvar
133: (eval (car l))))
134:
135: ; Declare a variable to be GLOBAL by entering it on the *GLOBALLIST*
136: ; and PEARL-unbinding it.
137: (df global (l)
138: (let ((variable (car l)))
139: (set variable (punbound))
140: (push variable *globallist*)
141: variable))
142:
143: ; PEARL-unbind a global variable. ("unbindvars" does the local variables
144: ; in an entire structure (see match.l)).
145: (df unbind (l)
146: (let ((var (car l)))
147: (cond ((memq var *globallist*)
148: (set var (punbound)))
149: ( t (set var (punbound))
150: (and *warn*
151: (msg t "UNBIND: Warning: " var
152: " is not a global variable but unbound it anyway."
153: t))))))
154:
155: ; Determine if the variable is GLOBAL, i.e., on the *GLOBALLIST*
156: (de globalp (variable)
157: (memq variable *globallist*))
158:
159: ; (BLOCK <name> (<LIST OF VARIABLES>)) starts a (possibly embedded)
160: ; set of variables accessible to all structure CREATEd within
161: ; the block. Terminated by a call to (ENDBLOCK <name>).
162: ; The name is optional. If used, then the block may be reaccessed
163: ; with b:<name>.
164:
165: (df block (l)
166: (let ((name (car l))
167: varlist
168: alist)
169: (cond ((reallitatom name) (setq varlist (cadr l)))
170: ( t (setq varlist name)
171: (setq name 'unnamedblock)))
172: (setq alist
173: (nconc (ncons (cons nil (punbound))) ; Cell for Frozen vars.
174: (mapcar (funl (varname) (cons varname (punbound)))
175: varlist)
176: (cond (*blockstack* (cdar *blockstack*))
177: ( t nil))))
178: (and name
179: (set name alist))
180: ; Create a special cons cell, point b:<name> at it and push it.
181: (push (set (blockatom name)
182: (cons name alist))
183: *blockstack*)
184: name))
185:
186: ; (ENDBLOCK <name>) ends the block with name <name>.
187: ; If <name> is * then close one block, regardless of name.
188: ; If <name> is nil then close one unnamed block only.
189: (df endblock (l)
190: (let ((name (car l)))
191: (and (null name)
192: (setq name 'unnamedblock))
193: (cond ((not *blockstack*)
194: (msg t "ENDBLOCK: No blocks to end")
195: (msg ", not even named: " name t)
196: (pearlbreak))
197: ((or (eq name '*)
198: (eq name (caar *blockstack*)))
199: (prog1 (caar *blockstack*)
200: (setq *blockstack* (cdr *blockstack*))))
201: ( t (msg t "ENDBLOCK: Block to be ended, "
202: name " doesn't match innermost block, named: "
203: (caar *blockstack*) t)
204: (pearlbreak)))))
205:
206: ; (ENDANYBLOCKS <name>) ends all blocks back through the block
207: ; with name <name>.
208: ; If <name> is * then end all blocks.
209: ; If <name> is nil then end all blocks back through the
210: ; last unnamed block.
211: (df endanyblocks (l)
212: (let ((name (car l))
213: (block *blockstack*))
214: (cond ((not *blockstack*) nil)
215: ((eq name '*) (setq *blockstack* nil))
216: ((null (while (and block
217: (neq (caar block) name))
218: (setq block (cdr block))))
219: (msg t "ENDANYBLOCKS: No currently open block named "
220: name " to end blocks back to." t)
221: (pearlbreak))
222: ( t (setq *blockstack* (pop block))
223: (caar *blockstack*)))
224: t))
225:
226: ; (ENDALLBLOCKS <name>) ends any open blocks, regardless of name.
227: (de endallblocks ()
228: (setq *blockstack* nil)
229: t)
230:
231: ; (SETBLOCK <blockname>) changes the current scope to that of
232: ; <blockname>, BUT doesn't allow ending former blocks!
233: (df setblock (l)
234: (let ((blockname (car l)))
235: (cond ((and (boundp (blockatom blockname))
236: (blockp (eval (blockatom blockname))))
237: (setq *blockstack* (eval (blockatom blockname))))
238: ( t (msg t "SETBLOCK: There is no block named: " blockname t)
239: (pearlbreak)))))
240:
241: ; Take all the bound variables off the STRUCT'S ALIST, and put them on
242: ; the ALISTCP, preserving unique alist pairs. Also take care of all the
243: ; BLOCK alists. WARNING: This code is tough so be careful with it!
244: (de freezebindings (struct)
245: (let ((oldalist (getalist struct)) ; to be frozen.
246: (unboundalist (ncons nil)) ; to still unbound variables.
247: (boundalist (getalistcp struct)) ; already frozen.
248: rest
249: currentblock)
250: ; While there are more variables to process, and we haven't reached
251: ; a block, add either to "unboundalist" or "boundalist".
252: (while (and oldalist
253: (reallitatom (caar oldalist)))
254: (setq rest (cdr oldalist))
255: (cond ((eq (cdar oldalist) (punbound))
256: (tconc unboundalist (car oldalist)))
257: ( t (setq boundalist (rplacd oldalist boundalist))))
258: (setq oldalist rest))
259: (and oldalist
260: (rplaca unboundalist
261: (nconc (car unboundalist)
262: oldalist))) ; pointer to the enclosing blocks.
263: ; Store new lists.
264: (putalist (car unboundalist) struct)
265: (putalistcp boundalist struct)
266: ; Process blocks one at a time.
267: (while oldalist
268: (setq currentblock oldalist)
269: (setq oldalist (cdr oldalist))
270: (setq unboundalist (ncons nil))
271: (setq boundalist (caar currentblock))
272: (while (and oldalist
273: (reallitatom (caar oldalist)))
274: (setq rest (cdr oldalist))
275: (cond ((eq (cdar oldalist) (punbound))
276: (tconc unboundalist (car oldalist)))
277: ( t (setq boundalist (rplacd oldalist boundalist))))
278: (setq oldalist rest))
279: (and oldalist
280: (rplaca unboundalist
281: (nconc (car unboundalist)
282: oldalist))) ; pointer to the enclosing blocks.
283: ; store frozen vars.
284: (rplaca (car currentblock) boundalist)
285: (rplacd currentblock (car unboundalist)))
286: t))
287:
288: ; Take all the bound variables off the STRUCT's ALIST, and put them on
289: ; the ALISTCP, preserving unique alist pairs.
290: (de freezestruct (struct)
291: (let ((oldalist (getalist struct))
292: (unboundalist (ncons nil))
293: (boundalist (getalistcp struct))
294: rest)
295: (while (and oldalist ; is not NIL, and
296: (reallitatom (caar oldalist))) ; have not reached block
297: (setq rest (cdr oldalist))
298: (cond ((eq (cdar oldalist) (punbound))
299: (tconc unboundalist (car oldalist)))
300: ( t (setq boundalist (rplacd oldalist boundalist))))
301: (setq oldalist rest))
302: (and oldalist
303: (rplaca unboundalist
304: (nconc (car unboundalist)
305: oldalist))) ; pointer to the enclosing blocks.
306: (putalist (car unboundalist) struct)
307: (putalistcp boundalist struct)
308: t))
309:
310: (df freezeblock (blockname)
311: (let (block
312: oldalist
313: unboundalist
314: boundalist
315: rest)
316: (cond ((and (boundp (blockatom (car blockname)))
317: (setq block (eval (blockatom (car blockname))))
318: (blockp block)))
319: ( t (msg t "FREEZEBLOCK: " blockname
320: " is not the name of a block." t)
321: (pearlbreak)))
322: (setq oldalist (cddr block))
323: (setq unboundalist (ncons nil))
324: (setq boundalist (caadr block))
325: (while (and oldalist
326: (reallitatom (caar oldalist)))
327: (setq rest (cdr oldalist))
328: (cond ((eq (cdar oldalist) (punbound))
329: (tconc unboundalist (car oldalist)))
330: ( t (setq boundalist (rplacd oldalist boundalist))))
331: (setq oldalist rest))
332: (and oldalist
333: (rplaca unboundalist
334: (nconc (car unboundalist)
335: oldalist))) ; pointer to the enclosing blocks.
336: (rplaca (cadr block) boundalist) ; store frozen vars.
337: (rplacd (cdr block) (car unboundalist))
338: t))
339:
340: (dm findnextblockstart (none) ; But expects ALIST
341: '(while (and alist
342: (reallitatom (caar alist)))
343: (setq alist (cdr alist))))
344:
345: ; This is for JUST THE STRUCT.
346: (de thawstruct (struct)
347: (let ((alist (getalist struct)))
348: (putalist (nconc (getalistcp struct) alist) struct)
349: (putalistcp nil struct)
350: t))
351:
352: ; Restore the Alist to include all values. (Undo FREEZEBINDINGS)
353: ; This is done for ALL BLOCKs that STRUCT is a member of.
354: (de thawbindings (struct)
355: (let ((alist (getalist struct)))
356: (putalist (nconc (getalistcp struct) alist) struct)
357: (putalistcp nil struct)
358: (while (findnextblockstart)
359: (rplacd alist (nconc (caar alist) (cdr alist)))
360: (rplaca (car alist) nil))
361: t))
362:
363: ; This is for JUST ONE BLOCK.
364: (df thawblock (blockname)
365: (let (alist
366: block)
367: (cond ((and (boundp (blockatom (car blockname)))
368: (setq block (eval (blockatom (car blockname))))
369: (blockp block))
370: block)
371: ( t (msg t "THAWBLOCK: " blockname
372: " is not the name of a block." t)
373: (pearlbreak)))
374: (setq alist (cddr block))
375: (rplacd (cdr block) (nconc (caadr block) alist))
376: (rplaca (cadr block) nil)
377: t))
378:
379:
380: ; vi: set lisp:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.