#ifndef lint static char *rcsid = "$Header: fex2.c,v 1.3 83/09/07 17:55:38 sklower Exp $"; #endif /* -[Mon Jan 31 21:54:52 1983 by layer]- * fex2.c $Locker: $ * nlambda functions * * (c) copyright 1982, Regents of the University of California */ #include "global.h" #define NDOVARS 30 #include "frame.h" /* * Ndo maclisp do function. */ lispval Ndo() { register lispval current, where, handy; register struct nament *mybnp; lispval temp, atom; lispval body, endtest, endform, varstuff, renewals[NDOVARS] ; struct argent *getem, *startnp; struct nament *savedbnp = bnp; int count, repeatdo, index; extern struct frame *errp; pbuf pb; Savestack(3); current = lbot->val; varstuff = current->d.car; switch( TYPE(varstuff) ) { case ATOM: /* This is old style maclisp do; atom is var, cadr(current) = init; caddr(current) = repeat etc. */ if(varstuff==nil) goto newstyle; current = current->d.cdr; /* car(current) is now init */ PUSHDOWN(varstuff,eval(current->d.car)); /* Init var. */ *renewals = (current = current->d.cdr)->d.car; /* get repeat form */ endtest = (current = current->d.cdr)->d.car; body = current->d.cdr; errp = Pushframe(F_PROG,nil,nil); switch (retval) { case C_RET: /* * returning from this prog, value to return * is in lispretval */ errp = Popframe(); popnames(savedbnp); return(lispretval); case C_GO: /* * going to a certain label, label to go to in * in lispretval */ where = body; while ((TYPE(where) == DTPR) & (where->d.car != lispretval)) where = where->d.cdr; if (where->d.car == lispretval) { popnames(errp->svbnp); where = where->d.cdr; goto singbody; } /* label not found in this prog, must * go up to higher prog */ Inonlocalgo(C_GO,lispretval,nil); /* NOT REACHED */ case C_INITIAL: break; /* fall through */ } singtop: if(eval(endtest)!=nil) { errp = Popframe(); popnames(savedbnp); return(nil); } where = body; singbody: while (TYPE(where) == DTPR) { temp = where->d.car; if((TYPE(temp))!=ATOM) eval(temp); where = where->d.cdr; } varstuff->a.clb = eval(*renewals); goto singtop; newstyle: case DTPR: /* New style maclisp do; atom is list of things of the form (var init repeat) */ count = 0; startnp = np; for(where = varstuff; where != nil; where = where->d.cdr) { /* do inits and count do vars. */ /* requires "simultaneous" eval of all inits */ while (TYPE(where->d.car) != DTPR) where->d.car = errorh1(Vermisc,"do: variable forms must be lists ", nil,TRUE,0,where->d.car); handy = where->d.car->d.cdr; temp = nil; if(handy !=nil) temp = eval(handy->d.car); protect(temp); count++; } if(count > NDOVARS) error("More than 15 do vars",FALSE); where = varstuff; getem = startnp; /* base of stack of init forms */ for(index = 0; index < count; index++) { handy = where->d.car; /* get var name from group */ atom = handy->d.car; while((TYPE(atom) != ATOM) || (atom == nil)) atom = errorh1(Vermisc,"do variable must be a non nil symbol ", nil,TRUE,0,atom); PUSHDOWN(atom,getem->val); getem++; handy = handy->d.cdr->d.cdr; if(handy==nil) handy = CNIL; /* be sure not to rebind later */ else handy = handy->d.car; renewals[index] = handy; /* more loop "increments" */ where = where->d.cdr; } np = startnp; /* pop off all init forms */ /* Examine End test and End form */ current = current->d.cdr; handy = current->d.car; body = current->d.cdr; /* * a do form with a test of nil just does the body once * and returns nil */ if (handy == nil) repeatdo = 1; /* just do it once */ else repeatdo = -1; /* do it forever */ endtest = handy->d.car; endform = handy->d.cdr; where = body; errp = Pushframe(F_PROG,nil,nil); while(TRUE) { switch (retval) { case C_RET: /* * returning from this prog, value to return * is in lispretval */ errp = Popframe(); popnames(savedbnp); Restorestack(); return(lispretval); case C_GO: /* * going to a certain label, label to go to in * in lispretval */ where = body; while ((TYPE(where) == DTPR) & (where->d.car != lispretval)) where = where->d.cdr; if (where->d.car == lispretval) { popnames(errp->svbnp); where = where->d.cdr; goto bodystart; } /* label not found in this prog, must * go up to higher prog */ Inonlocalgo(C_GO,lispretval,nil); /* NOT REACHED */ case C_INITIAL: break; /* fall through */ } loop: np = startnp; /* is bumped when doing repeat forms */ if((repeatdo-- == 0) || (eval(endtest) !=nil)) { for(handy = nil; endform!=nil; endform = endform->d.cdr) { handy = eval(endform->d.car); } errp = Popframe(); popnames(savedbnp); Restorestack(); return(handy); } bodystart: while (TYPE(where) == DTPR) { temp = where->d.car; if((TYPE(temp))!=ATOM) eval(temp); where = where->d.cdr; } where = body; getem = np = startnp; /* Simultaneously eval repeat forms */ for(index = 0; index < count; index++) { temp = renewals[index]; if (temp == nil || temp == CNIL) protect(temp); else protect(eval(temp)); } /* now simult. rebind all the atoms */ mybnp = savedbnp; for(index = 0; index < count; index++) { if( getem->val != CNIL ) /* if this atom has a repeat */ mybnp->atm->a.clb = (getem)->val; /* rebind */ mybnp++; getem++; } goto loop; } default: error("do: neither list nor atom follows do", FALSE); } /* NOTREACHED */ } lispval Nprogv() { register lispval where, handy; register struct nament *namptr; register struct argent *vars; struct nament *oldbnp = bnp; Savestack(4); where = lbot->val; protect(eval(where->d.car)); /* list of vars = lbot[1].val */ protect(eval((where = where->d.cdr)->d.car)); /* list of vals */ handy = lbot[2].val; namptr = oldbnp; /* simultaneous eval of all args */ for(;handy!=nil; handy = handy->d.cdr) { (np++)->val = (handy->d.car); /* Note, each element should not be reevaluated like it * was before. - dhl */ /* Before: (np++)->val = eval(handy->d.car);*/ TNP; } /*asm("# Here is where rebinding is done"); /* very cute */ for(handy=lbot[1].val,vars=lbot+3; handy!=nil; handy=handy->d.cdr) { namptr->atm = handy->d.car; ++namptr; /* protect against interrupts while re-lambda binding */ bnp = namptr; namptr[-1].atm = handy->d.car; namptr[-1].val = handy->d.car->a.clb; if(vars < np) handy->d.car->a.clb = vars++->val; else handy->d.car->a.clb = nil; } handy = nil; for(where = where->d.cdr; where != nil; where = where->d.cdr) handy = eval(where->d.car); popnames(oldbnp); Restorestack(); return(handy); } lispval Nprogn() { register lispval result, where; result = nil; for(where = lbot->val; where != nil; where = where->d.cdr) result = eval(where->d.car); return(result); } lispval Nprog2() { register lispval result, where; where = lbot->val; eval(where->d.car); result = eval((where = where->d.cdr)->d.car); protect(result); for(where = where->d.cdr; where != nil; where = where->d.cdr) eval(where->d.car); np--; return(result); } lispval typred(typ,ptr) int typ; lispval ptr; { int tx; if ((tx = TYPE(ptr)) == typ) return(tatom); if ((tx == INT) && (typ == ATOM)) return(tatom); return(nil); } /* * function * In the interpreter, function is the same as quote */ lispval Nfunction() { if((lbot->val == nil) || (lbot->val->d.cdr != nil)) argerr("function"); return(lbot->val->d.car); }