1: #ifndef lint
   2: static char *rcsid =
   3:    "$Header: eval2.c,v 1.8 85/03/24 11:03:02 sklower Exp $";
   4: #endif
   5: 
   6: /*					-[Sat May  7 23:38:37 1983 by jkf]-
   7:  * 	eval2.c				$Locker:  $
   8:  * more of the evaluator
   9:  *
  10:  * (c) copyright 1982, Regents of the University of California
  11:  */
  12: 
  13: 
  14: #include "global.h"
  15: #include "frame.h"
  16: 
  17: /* Iarray - handle array call.
  18:  *  fun - array object
  19:  *  args - arguments to the array call , most likely subscripts.
  20:  *  evalp - flag, if TRUE then the arguments should be evaluated when they
  21:  *	are stacked.
  22:  */
  23: lispval
  24: Iarray(fun,args,evalp)
  25: register lispval fun,args;
  26: {
  27:     Savestack(2);
  28: 
  29:     lbot = np;
  30:     protect(fun->ar.accfun);
  31:     for ( ; args != nil ; args = args->d.cdr)  /* stack subscripts */
  32:       if(evalp) protect(eval(args->d.car));
  33:       else protect(args->d.car);
  34:     protect(fun);
  35:     vtemp = Lfuncal();
  36:     Restorestack();
  37:     return(vtemp);
  38: }
  39: 
  40: 
  41: dumpmydata(thing)
  42: int thing;
  43: {
  44:     register int *ip = &thing;
  45:     register int *lim = ip + nargs();
  46: 
  47:     printf("Dumpdata got %d args:\n",nargs());
  48:     while(ip < lim) printf("%x\n",*ip++);
  49:     return(0);
  50: }
  51: /* Ifcall :: call foreign function/subroutine
  52:  *   Ifcall is handed a binary object which is the function to call.
  53:  * This function has already been determined to be a foreign function
  54:  * by noticing that its discipline field is a string.
  55:  * The arguments to pass have already been evaluated and stacked.  We
  56:  * create on the stack a 'callg' type argument list to give to the
  57:  * function.  What is passed to the foreign function depends on the
  58:  * type of argument.  Certain args are passes directly, others must be
  59:  * copied since the foreign function my want to change them.
  60:  * When the foreign function returns, we may have to box the result,
  61:  * depending on the type of foreign function.
  62:  */
  63: lispval
  64: Ifcall(a)
  65: lispval a;
  66: {
  67:     char *alloca();
  68:     long callg_();
  69:     register int *arglist;
  70:     register int index;
  71:     register struct argent *mynp;
  72:     register lispval ltemp;
  73:     pbuf pb;
  74:     int nargs = np - lbot, kind, mysize, *ap;
  75:     Keepxs();
  76: 
  77:     /* put a frame on the stack which will save np and lbot in a
  78: 	   easy to find place in a standard way */
  79:     errp = Pushframe(F_TO_FORT,nil,nil);
  80:     mynp = lbot;
  81:     kind = (((char *)a->bcd.discipline)[0]);
  82: 
  83:     /* dispatch according to whether call by reference or value semantics */
  84:     switch(kind) {
  85:     case 'f': case 'i': case 's': case 'r':
  86:         arglist = (int *) alloca((nargs + 1) * sizeof(int));
  87:         *arglist = nargs;
  88:         for(index = 1; index <=  nargs; index++) {
  89:             switch(TYPE(ltemp=mynp->val)) {
  90:                 /* fixnums and flonums must be reboxed */
  91:             case INT:
  92:                 stack(0);
  93:                 arglist[index] = (int) sp();
  94:                 *(int *) arglist[index] = ltemp->i;
  95:                 break;
  96:             case DOUB:
  97:                 stack(0);
  98:                 stack(0);
  99:                 arglist[index] = (int) sp();
 100:                 *(double *) arglist[index] = ltemp->r;
 101:                 break;
 102: 
 103:                 /* these cause only part of the structure to be sent */
 104: 
 105:             case ARRAY:
 106:                 arglist[index] = (int) ltemp->ar.data;
 107:                 break;
 108: 
 109: 
 110:             case BCD:
 111:                 arglist[index] = (int) ltemp->bcd.start;
 112:                 break;
 113: 
 114:                 /* anything else should be sent directly */
 115: 
 116:             default:
 117:                 arglist[index] = (int) ltemp;
 118:                 break;
 119:             }
 120:             mynp++;
 121:         }
 122:         break;
 123:     case 'v':
 124:         while(TYPE(mynp->val)!=VECTORI)
 125:             mynp->val = error(
 126: "First arg to c-function-returning-vector must be of type vector-immediate",
 127:                       TRUE);
 128:         nargs--;
 129:         mynp++;
 130:         lbot++;
 131:     case 'c': case 'd':
 132:         /* make one pass over args
 133: 		calculating size of arglist */
 134:         while(mynp < np) switch(TYPE(ltemp=mynp++->val)) {
 135:         case DOUB:
 136:             nargs += ((sizeof(double)/sizeof(int))-1);
 137:             break;
 138:         case VECTORI:
 139:             if(ltemp->v.vector[-1]==Vpbv) {
 140:                 nargs += -1+VecTotSize(ltemp->vl.vectorl[-2]);
 141:             }
 142:         }
 143:         arglist = (int *) alloca((nargs+1)*sizeof(int));
 144:         *arglist = nargs;
 145:         ap = arglist + 1;
 146:         /* make another pass over the args
 147: 		   actually copying the arguments */
 148:         for(mynp = lbot; mynp < np; mynp++)
 149:             switch(TYPE(ltemp=mynp->val)) {
 150:         case INT:
 151:             *ap++ = ltemp->i;
 152:             break;
 153:         case DOUB:
 154:             *(double *)ap = ltemp->r;
 155:             ap += (sizeof (double)) / (sizeof (long));
 156:             break;
 157:         case VECTORI:
 158:             if(ltemp->v.vector[-1]==Vpbv) {
 159:                 mysize = ltemp->vl.vectorl[-2];
 160:                 mysize = sizeof(long) * VecTotSize(mysize);
 161:                 xbcopy(ap,ltemp,mysize);
 162:                 ap = (long *) (mysize + (int) ap);
 163:                 break;
 164:             }
 165:         default:
 166:             *ap++ = (long) ltemp;
 167:         }
 168:     }
 169:     switch(kind) {
 170:         case 'i': /* integer-function */
 171:         case 'c': /* C-function */
 172:             ltemp = inewint(callg_(a->bcd.start,arglist));
 173:             break;
 174: 
 175:         case 'r': /* real-function*/
 176:         case 'd': /* C function declared returning double */
 177:             {
 178:             double result =
 179:                (* ((double (*)()) callg_))(a->bcd.start,arglist);
 180:             ltemp = newdoub();
 181:             ltemp->r = result;
 182:             }
 183:             break;
 184: 
 185:         case 'f':  /* function */
 186:             ltemp = (lispval) callg_(a->bcd.start,arglist);
 187:             break;
 188: 
 189:         case 'v': /* C function returning a structure */
 190:             ap = (long *) callg_(a->bcd.start,arglist);
 191:             ltemp = (--lbot)->val;
 192:             mysize = ltemp->vl.vectorl[-2];
 193:             mysize = sizeof(long) * VecTotSize(mysize);
 194:             xbcopy(ltemp,ap,mysize);
 195:             break;
 196: 
 197:         default:
 198:         case 's': /* subroutine */
 199:             callg_(a->bcd.start,arglist);
 200:             ltemp = tatom;
 201:     }
 202:     errp = Popframe();
 203:     Freexs();
 204:     return(ltemp);
 205: }
 206: 
 207: xbcopy(to,from,size)
 208: register char *to, *from;
 209: register size;
 210: {
 211:     while(--size >= 0) *to++ = *from++;
 212: }
 213: 
 214: lispval
 215: ftolsp_(arg1)
 216: lispval arg1;
 217: {
 218:     int count;
 219:     register lispval *ap = &arg1;
 220:     lispval save;
 221:     pbuf pb;
 222:     Savestack(1);
 223: 
 224:     if((count = nargs())==0) return;;
 225: 
 226:     if(errp->class==F_TO_FORT)
 227:         np = errp->svnp;
 228:     errp = Pushframe(F_TO_LISP,nil,nil);
 229:     lbot = np;
 230:     for(; count > 0; count--)
 231:         np++->val = *ap++;
 232:     save = Lfuncal();
 233:     errp = Popframe();
 234:     Restorestack();
 235:     return(save);
 236: }
 237: 
 238: lispval
 239: ftlspn_(func,arglist)
 240: lispval func;
 241: register long *arglist;
 242: {
 243:     int count;
 244:     lispval save;
 245:     pbuf pb;
 246:     Savestack(1);
 247: 
 248:     if(errp->class==F_TO_FORT)
 249:         np = errp->svnp;
 250:     errp = Pushframe(F_TO_LISP,nil,nil);
 251:     lbot = np;
 252:     np++->val = func;
 253:     count = *arglist++;
 254:     for(; count > 0; count--)
 255:         np++->val = (lispval) (*arglist++);
 256:     save = Lfuncal();
 257:     errp = Popframe();
 258:     Restorestack();
 259:     return(save);
 260: }
 261: 
 262: 
 263: 
 264: /* Ifclosure :: evaluate a fclosure  (new version)
 265:  * the argument clos is a vector whose property is the atom fclosure
 266:  * the form of the vector is
 267:  *   0: function to run
 268:  * then for each symbol there is on vector entry containing a
 269:  * pointer to a sequence of two list cells of this form:
 270:  *	(name value . count)
 271:  * name is the symbol name to close over
 272:  * value is the saved value of the closure
 273:  *	(if the closure is 'active', the current value will be in the
 274:  *	 symbol itself)
 275:  * count is a fixnum box (which can be destructively modified safely)
 276:  *  it is normally 0.  Each time the variable is put on the stack, it is
 277:  *  incremented.  It is decremented each time the the closure is left.
 278:  *  If the closure is invoked recusively without a rebinding of the
 279:  *  closure variable X, then the count will not be incremented.
 280:  *
 281:  * when entering a fclosure, for each variable there are three
 282:  * possibities:
 283:  *  (a) this is the first instance of this closed variable
 284:  *  (b) this is the second or greater recursive instance of
 285:  *      this closure variable, however it hasn't been normally lambda
 286:  *	bound since the last closure invocation
 287:  *  (c) like (b) but it has been lambda bound before the most recent
 288:  *	closure.
 289:  *
 290:  * case (a) can be determined by seeing if the count is 0.
 291:  * if the count is >0 then we must scan from the top of the stack down
 292:  * until we find either the closure or a lambda binding of the variable
 293:  * this determines whether it is case (b) or (c).
 294:  *
 295:  * There are three actions to perform in this routine:
 296:  * 1.  determine the closure type (a,b or c) and do any binding necessary
 297:  * 2.  call the closure function
 298:  * 3.  unbind any necessary closure variables.
 299:  *
 300:  * Now, the details of those actions:
 301:  * 1. for case (b), do nothing as we are still working with the correct
 302:  *    value
 303:  *    for case (a), pushdown the symbol and give it the value from
 304:  *	the closure, inc the closure count
 305:  *      push a closure marker on the bindstack too.
 306:  *    for case (c), must locate the correct value to set by searching
 307:  *      for the last lambda binding before the previous closure.
 308:  *      pushdown the symbol and that value, inc the closure count
 309:  *      push a closure marker on the bindstack too.
 310:  *    a closure marker has atom == int:closure-marker and value pointing
 311:  *      to the closure list.  This will be noticed when unbinding.
 312:  *
 313:  *  3. unbinding is just like popnames except if a closure marker is
 314:  *     seen, then this must be done:
 315:  *	if the count is 1, just store the symbol's value in the closure
 316:  *	 and decrement the count.
 317:  *      if the count is >1, then search up the stack for the last
 318:  *	 lambda before the next occurance of this closure variable
 319:  *	 and set its value to the current value of the closure.
 320:  *	 decrement the closure count.
 321:  *
 322:  * clos is the fclosure, funcallp is TRUE if this is called from funcall,
 323:  * otherwise it is called from apply
 324:  */
 325: 
 326: #define Case_A 0
 327: #define Case_B 1
 328: #define Case_C 2
 329: 
 330: lispval
 331: Ifclosure(clos,funcallp)
 332: register lispval clos;
 333: {
 334:     struct nament *oldbnp = bnp, *lbnp, *locatevar();
 335:     register int i;
 336:     register lispval vect;
 337:     int numvars, vlength, tcase, foundc;
 338:     lispval handy, atm_dtpr, value_dtpr, Ifuncal(), Lapply();
 339:     Savestack(3);
 340: 
 341:     /* bind variables to their values given in the fclosure */
 342:     vlength = VecTotSize(clos->vl.vectorl[VSizeOff]);
 343:     /* vector length must be positive (it has to have a function at least) */
 344:     if (vlength < 1)
 345:     errorh1(Vermisc,"funcall: fclosure has wrong size ",nil,FALSE,0, clos);
 346: 
 347:     numvars = (vlength - 1);    /* number of varibles */
 348: 
 349:     for (i = 1 ; i < vlength ; i += 1)
 350:     {
 351:     atm_dtpr = clos->v.vector[i];   /* car is symbol name */
 352:     value_dtpr = atm_dtpr->d.cdr;   /* car: value, cdr:  fixnum count */
 353: 
 354:     if(value_dtpr->d.cdr->i == 0)
 355:         tcase = Case_A;     /* first call */
 356:     else {
 357:         lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
 358:         if (!foundc)
 359:         {
 360:         /* didn't find the expected closure, count must be
 361: 		   wrong, correct it and assume case (a)
 362: 		 */
 363:         tcase = Case_A;
 364:         value_dtpr->d.cdr->i = 0;
 365:         }
 366:         else if(lbnp) tcase = Case_C ; /* found intermediate lambda bnd*/
 367:         else tcase = Case_B;       /* no intermediate lambda bind */
 368:     }
 369: 
 370:     /* now bind the value if necessary */
 371:     switch(tcase) {
 372:         case Case_A: PUSHDOWN(atm_dtpr->d.car,value_dtpr->d.car);
 373:                  PUSHVAL(clos_marker,atm_dtpr);
 374:              value_dtpr->d.cdr->i += 1;
 375:              break;
 376: 
 377:         case Case_B: break;     /* nothing to do */
 378: 
 379:         case Case_C: /* push first bound value after last close */
 380:                      PUSHDOWN(atm_dtpr->d.car,lbnp->val);
 381:              PUSHVAL(clos_marker,atm_dtpr);
 382:              value_dtpr->d.cdr->i += 1;
 383:              break;
 384:     }
 385:     }
 386: 
 387:     if(funcallp)
 388:        handy = Ifuncal(clos->v.vector[0]);
 389:     else {
 390:        handy = lbot[-2].val;    /* get args to apply.  This is hacky and may
 391:        				   fail if apply is changed */
 392:        lbot = np;
 393:        protect(clos->v.vector[0]);
 394:        protect(handy);
 395:        handy = Lapply();
 396:     }
 397: 
 398:     xpopnames(oldbnp);  /* pop names with consideration for closure markers */
 399: 
 400:     if(!funcallp) Restorestack();
 401:     return(handy);
 402: }
 403: 
 404: /* xpopnames :: pop values from bindstack, but look out for
 405:  *  closure markers.  This is  used (instead of the faster popnames)
 406:  * when we know there will be closure markers or when we can't
 407:  * be sure that there won't be closure markers (eg. in non-local go's)
 408:  */
 409: xpopnames(llimit)
 410: register struct nament *llimit;
 411: {
 412:     register struct nament *rnp, *lbnp;
 413:     lispval atm_dtpr, value_dtpr;
 414:     int foundc;
 415: 
 416:     for(rnp = bnp; --rnp >= llimit;)
 417:     {
 418:         if(rnp->atm == clos_marker)
 419:     {
 420:         atm_dtpr = rnp->val;
 421:         value_dtpr = atm_dtpr->d.cdr;
 422:         if(value_dtpr->d.cdr->i <= 1)
 423:         {
 424:         /* this is the only occurance of this closure variable
 425: 		 * just restore current value to this closure.
 426: 		 */
 427:         value_dtpr->d.car = atm_dtpr->d.car->a.clb;
 428:         }
 429:         else {
 430:         /* locate the last lambda before the next occurance of
 431: 		 * this closure and store the current symbol's value
 432: 		 * there
 433: 		 */
 434:         lbnp = locatevar(atm_dtpr,&foundc,rnp-2);
 435:         if(!foundc)
 436:         {
 437:             /* strange, there wasn't a closure to be found.
 438: 		     * well, we will fix things up so the count is
 439: 		     * right.
 440: 		     */
 441:             value_dtpr->d.car = atm_dtpr->d.car->a.clb;
 442:             value_dtpr->d.cdr->i = 1;
 443:         }
 444:         else if (lbnp) {
 445:             /* note how the closures value isn't necessarily
 446: 		     * stored in the closure, it may be stored on
 447: 		     * the bindstack
 448: 		     */
 449:             lbnp->val = atm_dtpr->d.car->a.clb;
 450:         }
 451:         /* the case where lbnp is 0 should never happen, but
 452: 		   if it does, we can just do nothing safely
 453: 		 */
 454:         }
 455:         value_dtpr->d.cdr->i -= 1;
 456:     } else rnp->atm->a.clb = rnp->val;  /* the normal case */
 457:     }
 458:     bnp = llimit;
 459: }
 460: 
 461: 
 462: struct nament *
 463: locatevar(clos,foundc,rnp)
 464: struct nament *rnp;
 465: lispval clos;
 466: int *foundc;
 467: {
 468:     register struct nament  *retbnp;
 469:     lispval symb;
 470: 
 471:     retbnp = (struct nament *) 0;
 472:     *foundc = 0;
 473: 
 474:     symb = clos->d.car;
 475: 
 476:     for(  ; rnp >= orgbnp ; rnp--)
 477:     {
 478:     if((rnp->atm == clos_marker) && (rnp->val == clos))
 479:     {
 480:         *foundc = 1;    /* found the closure */
 481:         return(retbnp);
 482:     }
 483:     if(rnp->atm == symb) retbnp = rnp;
 484:     }
 485:     return(retbnp);
 486: }
 487: 
 488: lispval
 489: LIfss()
 490: {
 491:     register lispval atm_dtpr, value_dtpr;
 492:     struct nament *oldbnp = bnp, *lbnp;
 493:     int tcase, foundc = 0;
 494:     lispval newval;
 495:     int argc = 1;
 496:     Savestack(2);
 497: 
 498:     switch(np-lbot) {
 499:     case 2:
 500:         newval = np[-1].val;
 501:         argc++;
 502:     case 1:
 503:         atm_dtpr = lbot->val;
 504:         value_dtpr = atm_dtpr->d.cdr;
 505:         break;
 506:     default:
 507:         argerr("int:fclosure-symbol-stuff");
 508:     }
 509:     /* this code is copied from Ifclosure */
 510: 
 511:     if(value_dtpr->d.cdr->i==0)
 512:         tcase = Case_A; /* closure is not active */
 513:     else {
 514:         lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
 515:         if (!foundc)
 516:         {
 517:             /* didn't find closure, count must be wrong,
 518: 			   correct it and assume case (a).*/
 519:             tcase = Case_A;
 520:             value_dtpr->d.cdr->i = 0;
 521:         }
 522:         else if(lbnp) tcase = Case_C; /* found intermediate lambda*/
 523:         else tcase = Case_B;
 524:     }
 525: 
 526:     switch(tcase) {
 527:     case Case_B:
 528:         if(argc==2) return(atm_dtpr->d.car->a.clb = newval);
 529:         return(atm_dtpr->d.car->a.clb);
 530: 
 531:     case Case_A:
 532:         if(argc==2) return(value_dtpr->d.car = newval);
 533:         return(value_dtpr->d.car);
 534: 
 535:     case Case_C:
 536:         if(argc==2) return(lbnp->val = newval);
 537:         return(lbnp->val);
 538:     }
 539:     /*NOTREACHED*/
 540: }

Defined functions

Iarray defined in line 23; used 4 times
Ifcall defined in line 63; used 5 times
Ifclosure defined in line 330; used 4 times
LIfss defined in line 488; never used
dumpmydata defined in line 41; never used
ftlspn_ defined in line 238; never used
ftolsp_ defined in line 214; never used
locatevar defined in line 462; used 4 times
xbcopy defined in line 207; used 2 times
xpopnames defined in line 409; used 2 times

Defined variables

rcsid defined in line 2; never used

Defined macros

Case_A defined in line 326; used 4 times
Case_B defined in line 327; used 2 times
Case_C defined in line 328; used 2 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1329
Valid CSS Valid XHTML 1.0 Strict