|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: fex1.c,v 1.5 85/03/24 11:03:51 sklower Exp $";
4: #endif
5:
6: /* -[Sat Mar 5 19:50:28 1983 by layer]-
7: * fex1.c $Locker: $
8: * nlambda functions
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13:
14: #include "global.h"
15: #include "frame.h"
16:
17: /* Nprog ****************************************************************/
18: /* This first sets the local variables to nil while saving their old */
19: /* values on the name stack. Then, pointers to various things are */
20: /* saved as this function may be returned to by an "Ngo" or by a */
21: /* "Lreturn". At the end is the loop that cycles through the contents */
22: /* of the prog. */
23:
24: lispval
25: Nprog() {
26: register lispval where, temp;
27: struct nament *savedbnp = bnp;
28: extern struct frame *errp;
29: pbuf pb;
30: extern int retval;
31: extern lispval lispretval;
32:
33: if((np-lbot) < 1) chkarg(1,"prog");
34:
35: /* shallow bind the local variables to nil */
36: if(lbot->val->d.car != nil)
37: {
38: for( where = lbot->val->d.car ; where != nil; where = where->d.cdr )
39: {
40: if(TYPE(where) != DTPR || TYPE(temp=where->d.car) != ATOM)
41: errorh1(Vermisc,
42: "Illegal local variable list in prog ",nil,FALSE,
43: 1,where);
44: PUSHDOWN(temp,nil);
45: }
46: }
47:
48: /* put a frame on the stack which can be 'return'ed to or 'go'ed to */
49: errp = Pushframe(F_PROG,nil,nil);
50:
51: where = lbot->val->d.cdr; /* first thing in the prog body */
52:
53: switch (retval) {
54: case C_RET: /*
55: * returning from this prog, value to return
56: * is in lispretval
57: */
58: errp = Popframe();
59: popnames(savedbnp);
60: return(lispretval);
61:
62: case C_GO: /*
63: * going to a certain label, label to go to in
64: * in lispretval
65: */
66: where = (lbot->val)->d.cdr;
67: while ((TYPE(where) == DTPR)
68: && (where->d.car != lispretval))
69: where = where->d.cdr;
70: if (where->d.car == lispretval) {
71: popnames(errp->svbnp);
72: break;
73: }
74: /* label not found in this prog, must
75: * go up to higher prog
76: */
77: errp = Popframe(); /* go to next frame */
78: Inonlocalgo(C_GO,lispretval,nil);
79:
80: /* NOT REACHED */
81:
82: case C_INITIAL: break;
83:
84: }
85:
86: while (TYPE(where) == DTPR)
87: {
88: temp = where->d.car;
89: if((TYPE(temp))!=ATOM) eval(temp);
90: where = where->d.cdr;
91: }
92: if((where != nil) && (TYPE(where) != DTPR))
93: errorh1(Vermisc,"Illegal form in prog body ", nil,FALSE,0,where);
94: errp = Popframe();
95: popnames(savedbnp); /* pop off locals */
96: return(nil);
97: }
98:
99: lispval globtag;
100: /*
101: Ncatch is now linked to the lisp symbol *catch , which has the form
102: (*catch tag form)
103: tag is evaluated and then the catch entry is set up.
104: then form is evaluated
105: finally the catch entry is removed.
106:
107: *catch is still an nlambda since its arguments should not be evaluated
108: before this routine is called.
109:
110: (catch form [tag]) is translated to (*catch 'tag form) by a macro.
111: */
112: lispval
113: Ncatch()
114: {
115: register lispval tag;
116: pbuf pb;
117: Savestack(3); /* save stack pointers */
118:
119: if((TYPE(lbot->val))!=DTPR) return(nil);
120: protect(tag = eval(lbot->val->d.car)); /* protect tag from gc */
121:
122: errp = Pushframe(F_CATCH,tag,nil);
123:
124: switch(retval) {
125:
126: case C_THROW: /*
127: * value thrown is in lispretval
128: */
129: break;
130:
131: case C_INITIAL: /*
132: * calculate value of expression
133: */
134: lispretval = eval(lbot->val->d.cdr->d.car);
135: }
136:
137:
138: errp = Popframe();
139: Restorestack();
140: return(lispretval);
141: }
142: /* (errset form [flag])
143: if present, flag determines if the error message will be printed
144: if an error reaches the errset.
145: if no error occurs, errset returns a list of one element, the
146: value returned from form.
147: if an error occurs, nil is usually returned although it could
148: be non nil if err threw a non nil value
149: */
150:
151: lispval Nerrset()
152: {
153: lispval temp,flag;
154: pbuf pb;
155: Savestack(0);
156:
157: if(TYPE(lbot->val) != DTPR) return(nil); /* no form */
158:
159: /* evaluate and save flag first */
160: flag = lbot->val->d.cdr;
161: if(TYPE(flag) == DTPR) flag = eval(flag->d.car);
162: else flag = tatom; /* if not present , assume t */
163: protect(flag);
164:
165: errp = Pushframe(F_CATCH,Verall,flag);
166:
167: switch(retval) {
168:
169: case C_THROW: /*
170: * error thrown to this routine, value thrown is
171: * in lispretval
172: */
173: break;
174:
175: case C_INITIAL: /*
176: * normally just evaluate expression and listify it.
177: */
178: temp = eval(lbot->val->d.car);
179: protect(temp);
180: (lispretval = newdot())->d.car = temp;
181: break;
182: }
183:
184: errp = Popframe();
185: Restorestack();
186: return(lispretval);
187: }
188:
189: /* this was changed from throw to *throw 21nov79
190: it is now a lambda and really should be called Lthrow
191: */
192: lispval
193: Nthrow()
194: {
195: switch(np-lbot) {
196: case 0:
197: protect(nil);
198: case 1:
199: protect(nil);
200: case 2: break;
201: default:
202: argerr("throw");
203: }
204: Inonlocalgo(C_THROW,lbot->val,(lbot+1)->val);
205: /* NOT REACHED */
206: }
207:
208:
209:
210: /* Ngo ******************************************************************/
211: /* First argument only is checked - and must be an atom or evaluate */
212: /* to one. */
213: lispval
214: Ngo()
215: {
216: register lispval temp;
217: chkarg(1,"go");
218:
219: temp = (lbot->val)->d.car;
220: if (TYPE(temp) != ATOM)
221: {
222: temp = eval(temp);
223: while(TYPE(temp) != ATOM)
224: temp = errorh1(Vermisc,"Illegal tag to go to",nil,TRUE, 0,lbot->val);
225: }
226: Inonlocalgo(C_GO,temp,nil);
227: /* NOT REACHED */
228: }
229:
230:
231: /* Nreset ***************************************************************/
232: /* All arguments are ignored. This just returns-from-break to depth 0. */
233: lispval
234: Nreset()
235: {
236: Inonlocalgo(C_RESET,inewint(0),nil);
237: }
238:
239:
240:
241: /* Nbreak ***************************************************************/
242: /* If first argument is not nil, this is evaluated and printed. Then */
243: /* error is called with the "breaking" message. */
244:
245: lispval
246: Nbreak()
247: {
248: register lispval hold; register FILE *port;
249: port = okport(Vpoport->a.clb,stdout);
250: fprintf(port,"Breaking:");
251:
252: if ((hold = lbot->val) != nil && ((hold = hold->d.car) != nil))
253: {
254: printr(hold,port);
255: }
256: putc('\n',port);
257: dmpport(port);
258: return(errorh(Verbrk,"",nil,TRUE,0));
259: }
260:
261:
262: /* Nexit ****************************************************************/
263: /* Just calls lispend with no message. */
264: Nexit()
265: {
266: lispend("");
267: }
268:
269:
270: /* Nsys *****************************************************************/
271: /* Just calls lispend with no message. */
272:
273: lispval
274: Nsys()
275: {
276: lispend("");
277: }
278:
279:
280:
281:
282: lispval
283: Ndef() {
284: register lispval arglist, body, name, form;
285:
286: form = lbot->val;
287: name = form->d.car;
288: body = form->d.cdr->d.car;
289: arglist = body->d.cdr->d.car;
290: if((TYPE(arglist))!=DTPR && arglist != nil)
291: error("Warning: defining function with nonlist of args",
292: TRUE);
293: name->a.fnbnd = body;
294: return(name);
295: }
296:
297:
298: lispval
299: Nquote()
300: {
301: return((lbot->val)->d.car);
302: }
303:
304:
305: lispval
306: Nsetq()
307: { register lispval handy, where, value;
308: register int lefttype;
309:
310: value = nil;
311:
312: for(where = lbot->val; where != nil; where = handy->d.cdr) {
313: handy = where->d.cdr;
314: if((TYPE(handy))!=DTPR)
315: error("odd number of args to setq",FALSE);
316: if((lefttype=TYPE(where->d.car))==ATOM) {
317: if(where->d.car==nil)
318: error("Attempt to set nil",FALSE);
319: where->d.car->a.clb = value = eval(handy->d.car);
320: }else if(lefttype==VALUE)
321: where->d.car->l = value = eval(handy->d.car);
322: else errorh1(Vermisc,
323: "Can only setq atoms or values",nil,FALSE,0,
324: where->d.car);
325: }
326: return(value);
327: }
328:
329:
330: lispval
331: Ncond()
332: {
333: register lispval where, last;
334:
335: where = lbot->val;
336: last = nil;
337: for(;;) {
338: if ((TYPE(where))!=DTPR)
339: break;
340: if ((TYPE(where->d.car))!=DTPR)
341: break;
342: if ((last=eval((where->d.car)->d.car)) != nil)
343: break;
344: where = where->d.cdr;
345: }
346:
347: if ((TYPE(where)) != DTPR)
348: return(nil);
349: where = (where->d.car)->d.cdr;
350: while ((TYPE(where))==DTPR) {
351: last = eval(where->d.car);
352: where = where->d.cdr;
353: }
354: return(last);
355: }
356:
357: lispval
358: Nand()
359: {
360: register lispval current, temp;
361:
362: current = lbot->val;
363: temp = tatom;
364: while (current != nil)
365: if ( (temp = current->d.car)!=nil && (temp = eval(temp))!=nil)
366: current = current->d.cdr;
367: else {
368: current = nil;
369: temp = nil;
370: }
371: return(temp);
372: }
373:
374:
375: lispval
376: Nor()
377: {
378: register lispval current, temp;
379:
380: current = lbot->val;
381: temp = nil;
382: while (current != nil)
383: if ( (temp = eval(current->d.car)) == nil)
384: current = current->d.cdr;
385: else
386: break;
387: return(temp);
388: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.