|
|
1.1 ! root 1: static char *sccsid = "@(#)eval.c 34.2 10/21/80"; ! 2: ! 3: #include "global.h" ! 4: #include <signal.h> ! 5: /************************************************************************/ ! 6: /* */ ! 7: /* file: eval.i */ ! 8: /* contents: evaluator and namestack maintenance routines */ ! 9: /* */ ! 10: /************************************************************************/ ! 11: ! 12: ! 13: /* eval *****************************************************************/ ! 14: /* returns the value of the pointer passed as the argument. */ ! 15: ! 16: ! 17: lispval ! 18: eval(actarg) ! 19: lispval actarg; ! 20: { ! 21: #define argptr handy ! 22: register lispval a = actarg; ! 23: register lispval handy; ! 24: register struct nament *namptr; ! 25: register struct argent *workp; ! 26: register struct argent *lbot; ! 27: register struct argent *np; ! 28: /* struct argent *poplbot; Why this here? - M. Marcus */ ! 29: struct nament *oldbnp = bnp; ! 30: lispval Ifcall(), Iarray(); ! 31: ! 32: /*debugging ! 33: if (rsetsw && rsetatom->a.clb != nil) { ! 34: printf("Eval:"); ! 35: printr(a,stdout); ! 36: printf("\nrsetsw: %d evalhsw: %d\n", rsetsw, evalhsw); ! 37: printf("*rset: "); ! 38: printr(rsetatom->a.clb,stdout); ! 39: printf(" evalhook: "); ! 40: printr(evalhatom->a.clb,stdout); ! 41: printf(" evalhook call flag^G: "); ! 42: printr(evalhcall->a.clb, stdout); ! 43: fflush(stdout); ! 44: }; */ ! 45: ! 46: /* check if an interrupt is pending and handle if so */ ! 47: if(sigintcnt > 0) sigcall(SIGINT); ! 48: ! 49: if (rsetsw && rsetatom->a.clb != nil){ /* if (*rset t) has been done */ ! 50: if (evalhsw != nil && evalhatom->a.clb != nil) ! 51: /*if (sstatus evalhook t) ! 52: and evalhook non-nil */ ! 53: if (evalhcall->a.clb == tatom) ! 54: /*if this is a call to evalhook, don't call evalhook ! 55: function, but clobber evalhcall atom, so recursive ! 56: calls to eval cause evalhook function to fire. */ ! 57: evalhcall->a.clb = nil; ! 58: else { ! 59: /* setup equivalent of (funcall evalhook <arg to eval>) */ ! 60: (np++)->val = a; /* push form on namestack */ ! 61: lbot=np; /* set up args to funcall */ ! 62: (np++)->val = evalhatom->a.clb; /* push evalhook's clb */ ! 63: (np++)->val = a; /* eval's arg becomes ! 64: 2nd arg to funcall */ ! 65: PUSHDOWN(evalhatom, nil); /* lambda-bind evalhook to nil*/ ! 66: handy = Lfuncal(); /* now call funcall */ ! 67: POP; ! 68: return(handy); ! 69: }; ! 70: }; ! 71: ! 72: switch (TYPE(a)) ! 73: { ! 74: case ATOM: ! 75: if (rsetsw && rsetatom->a.clb != nil && bptr_atom->a.clb != nil) { ! 76: ! 77: struct nament *bpntr, *eval1bptr; ! 78: /* Both rsetsw and rsetatom for efficiency*/ ! 79: /* bptr_atom set by second arg to eval1 */ ! 80: eval1bptr = (struct nament *) bptr_atom->a.clb->d.cdr; ! 81: /* eval1bptr is bnp when eval1 was called; ! 82: if an atom was bound after this, ! 83: then its clb is valid */ ! 84: for (bpntr = eval1bptr; bpntr < bnp; bpntr++) ! 85: if (bpntr->atm==a) { ! 86: handy = a->a.clb; ! 87: goto gotatom; ! 88: }; /* Value saved in first binding of a, ! 89: if any, after pointer to eval1, ! 90: is the valid value, else use its clb */ ! 91: for (bpntr = (struct nament *)bptr_atom->a.clb->d.car; ! 92: bpntr < eval1bptr; bpntr++) ! 93: if (bpntr->atm==a) { ! 94: handy=bpntr->val; ! 95: goto gotatom; /* Simply no way around goto here */ ! 96: }; ! 97: }; ! 98: handy = a->a.clb; ! 99: gotatom: ! 100: if(handy==CNIL) { ! 101: handy = errorh(Vermisc,"Unbound Variable:",nil,TRUE,0,a); ! 102: } ! 103: return(handy); ! 104: ! 105: case VALUE: ! 106: return(a->l); ! 107: ! 108: case DTPR: ! 109: (np++)->val = a; /* push form on namestack */ ! 110: lbot = np; /* define beginning of argstack */ ! 111: /* oldbnp = bnp; redundant - Mitch Marcus */ ! 112: a = a->d.car; /* function name or lambda-expr */ ! 113: for(EVER) ! 114: { ! 115: switch(TYPE(a)) ! 116: { ! 117: case ATOM: ! 118: /* get function binding */ ! 119: if(a->a.fnbnd==nil && a->a.clb!=nil) { ! 120: a=a->a.clb; ! 121: if(TYPE(a)==ATOM) ! 122: a=a->a.fnbnd; ! 123: } else ! 124: a = a->a.fnbnd; ! 125: break; ! 126: case VALUE: ! 127: a = a->l; /* get value */ ! 128: break; ! 129: } ! 130: ! 131: vtemp = (CNIL-1); /* sentinel value for error test */ ! 132: ! 133: funcal: switch (TYPE(a)) ! 134: { ! 135: case BCD: /* function */ ! 136: argptr = actarg->d.cdr; ! 137: ! 138: /* decide whether lambda, nlambda or ! 139: macro and push args onto argstack ! 140: accordingly. */ ! 141: ! 142: if(a->bcd.discipline==nlambda) { ! 143: (np++)->val = argptr; ! 144: TNP; ! 145: } else if(a->bcd.discipline==macro) { ! 146: (np++)->val = actarg; ! 147: TNP; ! 148: } else for(;argptr!=nil; argptr = argptr->d.cdr) { ! 149: (np++)->val = eval(argptr->d.car); ! 150: TNP; ! 151: } ! 152: /* go for it */ ! 153: ! 154: if(TYPE(a->bcd.discipline)==STRNG) ! 155: vtemp = Ifcall(a); ! 156: else ! 157: vtemp = (*(lispval (*)())(a->bcd.entry))(); ! 158: break; ! 159: ! 160: case ARRAY: ! 161: vtemp = Iarray(a,actarg->d.cdr,TRUE); ! 162: break; ! 163: ! 164: case DTPR: /* push args on argstack according to ! 165: type */ ! 166: argptr = a->d.car; ! 167: if (argptr==lambda) { ! 168: for(argptr = actarg->d.cdr; ! 169: argptr!=nil; argptr=argptr->d.cdr) { ! 170: ! 171: (np++)->val = eval(argptr->d.car); ! 172: TNP; ! 173: } ! 174: } else if (argptr==nlambda) { ! 175: (np++)->val = actarg->d.cdr; ! 176: TNP; ! 177: } else if (argptr==macro) { ! 178: (np++)->val = actarg; ! 179: TNP; ! 180: } else if (argptr==lexpr) { ! 181: for(argptr = actarg->d.cdr; ! 182: argptr!=nil; argptr=argptr->d.cdr) { ! 183: ! 184: (np++)->val = eval(argptr->d.car); ! 185: TNP; ! 186: } ! 187: handy = newdot(); ! 188: handy->d.car = (lispval)lbot; ! 189: handy->d.cdr = (lispval)np; ! 190: PUSHDOWN(lexpr_atom,handy); ! 191: lbot = np; ! 192: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); ! 193: ! 194: } else break; /* something is wrong - this isn't a proper function */ ! 195: ! 196: argptr = (a->d.cdr)->d.car; ! 197: namptr = bnp; ! 198: workp = lbot; ! 199: if(bnp + (np - lbot)> bnplim) ! 200: binderr(); ! 201: for(;argptr != (lispval)nil; ! 202: workp++,argptr = argptr->d.cdr) /* rebind formal names (shallow) */ ! 203: { ! 204: if(argptr->d.car==nil) ! 205: continue; ! 206: /*if(((namptr)->atm = argptr->d.car)==nil) ! 207: error("Attempt to lambda bind nil",FALSE);*/ ! 208: namptr->atm = argptr->d.car; ! 209: if (workp < np) { ! 210: namptr->val = namptr->atm->a.clb; ! 211: namptr->atm->a.clb = workp->val; ! 212: } else ! 213: bnp = namptr, ! 214: error("Too few actual parameters",FALSE); ! 215: namptr++; ! 216: } ! 217: bnp = namptr; ! 218: if (workp < np) ! 219: error("Too many actual parameters",FALSE); ! 220: ! 221: /* execute body, implied prog allowed */ ! 222: ! 223: for (handy = a->d.cdr->d.cdr; ! 224: handy != nil; ! 225: handy = handy->d.cdr) { ! 226: vtemp = eval(handy->d.car); ! 227: } ! 228: } ! 229: if (vtemp != (CNIL-1)) { ! 230: /* if we get here with a believable value, */ ! 231: /* we must have executed a function. */ ! 232: popnames(oldbnp); ! 233: ! 234: /* in case some clown trashed t */ ! 235: ! 236: tatom->a.clb = (lispval) tatom; ! 237: if(a->d.car==macro) ! 238: return(eval(vtemp)); ! 239: /* It is of the most wonderful ! 240: coincidence that the offset ! 241: for car is the same as for ! 242: discipline so we get bcd macros ! 243: for free here ! */ ! 244: else return(vtemp); ! 245: } ! 246: popnames(oldbnp); ! 247: a = (lispval) errorh(Verundef,"eval: Undefined function ",nil,TRUE,0,actarg->d.car); ! 248: } ! 249: ! 250: } ! 251: return(a); /* other data types are considered constants */ ! 252: } ! 253: ! 254: ! 255: ! 256: ! 257: /* popnames *************************************************************/ ! 258: /* removes from the name stack all entries above the first argument. */ ! 259: /* routine should usually be used to clean up the name stack as it */ ! 260: /* knows about the special cases. np is returned pointing to the */ ! 261: /* same place as the argument passed. */ ! 262: lispval ! 263: popnames(llimit) ! 264: register struct nament *llimit; ! 265: { ! 266: register struct nament *rnp; ! 267: ! 268: for(rnp = bnp; --rnp >= llimit;) ! 269: rnp->atm->a.clb = rnp->val; ! 270: bnp = llimit; ! 271: } ! 272: ! 273: ! 274: /************************************************************************/ ! 275: /* */ ! 276: /* file: apply.c */ ! 277: /* Caveat -- Work in Progress -- not guaranteed! not tested! */ ! 278: /* */ ! 279: /* apply ***************************************************************/ ! 280: lispval ! 281: Lapply() ! 282: { ! 283: register lispval a; ! 284: register lispval handy; ! 285: register struct argent *workp; ! 286: register struct nament *namptr; ! 287: register struct argent *lbot; ! 288: register struct argent *np; ! 289: lispval vtemp; ! 290: struct nament *oldbnp = bnp; ! 291: struct argent *oldlbot = lbot; /* Bottom of my frame! */ ! 292: ! 293: a = lbot->val; ! 294: argptr = lbot[1].val; ! 295: if(np-lbot!=2) ! 296: errorh(Vermisc,"Apply: Wrong number of args.",nil,FALSE, ! 297: 999,a,argptr); ! 298: if(TYPE(argptr)!=DTPR && argptr!=nil) ! 299: argptr = errorh(Vermisc,"Apply: non-list of args",nil,TRUE, ! 300: 998,argptr); ! 301: (np++)->val = a; /* push form on namestack */ ! 302: TNP; ! 303: lbot = np; /* bottom of current frame */ ! 304: for(EVER) ! 305: { ! 306: if (TYPE(a) == ATOM) a = a->a.fnbnd; ! 307: /* get function definition (unless ! 308: calling form is itself a lambda- ! 309: expression) */ ! 310: vtemp = CNIL; /* sentinel value for error test */ ! 311: switch (TYPE(a)) { ! 312: ! 313: case BCD: ! 314: /* push arguments - value of a */ ! 315: if(a->bcd.discipline==nlambda || a->bcd.discipline==macro) { ! 316: (np++)->val=argptr; ! 317: TNP; ! 318: } else for (; argptr!=nil; argptr = argptr->d.cdr) { ! 319: (np++)->val=argptr->d.car; ! 320: TNP; ! 321: } ! 322: ! 323: if(TYPE(a->bcd.discipline) == STRNG) ! 324: vtemp = Ifcall(a); /* foreign function */ ! 325: else ! 326: vtemp = (*(lispval (*)())(a->bcd.entry))(); /* go for it */ ! 327: break; ! 328: ! 329: case ARRAY: ! 330: vtemp = Iarray(a,argptr,FALSE); ! 331: break; ! 332: ! 333: ! 334: case DTPR: ! 335: if (a->d.car==nlambda || a->d.car==macro) { ! 336: (np++)->val = argptr; ! 337: TNP; ! 338: } else if (a->d.car==lambda) ! 339: for (; argptr!=nil; argptr = argptr->d.cdr) { ! 340: (np++)->val = argptr->d.car; ! 341: TNP; ! 342: } ! 343: else if(a->d.car==lexpr) { ! 344: for (; argptr!=nil; argptr = argptr->d.cdr) { ! 345: ! 346: (np++)->val = argptr->d.car; ! 347: TNP; ! 348: } ! 349: handy = newdot(); ! 350: handy->d.car = (lispval)lbot; ! 351: handy->d.cdr = (lispval)np; ! 352: PUSHDOWN(lexpr_atom,handy); ! 353: lbot = np; ! 354: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); ! 355: ! 356: } else break; /* something is wrong - this isn't a proper function */ ! 357: rebind(a->d.cdr->d.car,lbot); ! 358: np = lbot; ! 359: for (handy = a->d.cdr->d.cdr; ! 360: handy != nil; ! 361: handy = handy->d.cdr) { ! 362: vtemp = eval(handy->d.car); /* go for it */ ! 363: } ! 364: } ! 365: if (vtemp != CNIL) ! 366: /* if we get here with a believable value, */ ! 367: /* we must have executed a function. */ ! 368: { ! 369: popnames(oldbnp); ! 370: ! 371: /* in case some clown trashed t */ ! 372: ! 373: tatom->a.clb = (lispval) tatom; ! 374: return(vtemp); ! 375: } ! 376: popnames(oldbnp); ! 377: a = (lispval) errorh(Verundef,"apply: Undefined Function ", ! 378: nil,TRUE,0,oldlbot->val); ! 379: } ! 380: /*NOT REACHED*/ ! 381: } ! 382: ! 383: ! 384: /* ! 385: * Rebind -- rebind formal names ! 386: */ ! 387: rebind(argptr,workp) ! 388: register lispval argptr; /* argptr points to list of atoms */ ! 389: register struct argent * workp; /* workp points to position on stack ! 390: where evaluated args begin */ ! 391: { ! 392: register lispval vtemp; ! 393: register struct nament *namptr = bnp; ! 394: register struct argent *lbot; ! 395: register struct argent *np; ! 396: ! 397: for(;argptr != (lispval)nil; ! 398: workp++,argptr = argptr->d.cdr) /* rebind formal names (shallow) */ ! 399: { ! 400: if(argptr->d.car==nil) ! 401: continue; ! 402: namptr->atm = argptr->d.car; ! 403: if (workp < np) { ! 404: namptr->val = namptr->atm->a.clb; ! 405: namptr->atm->a.clb = workp->val; ! 406: } else ! 407: bnp = namptr, ! 408: error("Too few actual parameters",FALSE); ! 409: namptr++; ! 410: if(namptr > bnplim) ! 411: binderr(); ! 412: } ! 413: bnp = namptr; ! 414: if (workp < np) ! 415: error("Too many actual parameters",FALSE); ! 416: } ! 417: ! 418: /* the argument to Lfuncal is optional, if it is given then it is ! 419: * the name of the function to call and lbot points to the first arg. ! 420: * if it is not given, then lbot points to the function to call ! 421: */ ! 422: lispval ! 423: Lfuncal(fcn) ! 424: lispval fcn; ! 425: { ! 426: register lispval a; ! 427: register lispval handy; ! 428: register struct argent *oldlbot; ! 429: register struct nament **namptr; ! 430: register struct argent *lbot; ! 431: register struct argent *np; ! 432: struct nament *oldbnp = bnp; /* MUST be first local for evalframe */ ! 433: lispval fcncalled; ! 434: lispval Ifcall(),Llist(),Iarray(); ! 435: lispval vtemp; ! 436: int typ; ! 437: extern lispval end[]; ! 438: ! 439: /*debugging stufff ! 440: printf("In funcal: "); ! 441: printr(lbot->val,stdout); ! 442: fflush(stdout); ! 443: printf("\n"); */ ! 444: ! 445: /* atrocity to avoid call to nargs() */ ! 446: /*define nargs() (* (char *) (&fcn -1))*/ ! 447: ! 448: oldlbot = lbot; /* bottom of my namestack frame */ ! 449: if((&fcn)[-1]==(lispval)1) /* function I am evaling. */ ! 450: a = fcncalled = fcn; ! 451: else { ! 452: a = fcncalled = lbot->val; ! 453: lbot++; ! 454: } ! 455: ! 456: /* check if exception pending */ ! 457: if(sigintcnt > 0 ) sigcall(SIGINT); ! 458: ! 459: for(EVER) ! 460: { ! 461: top: ! 462: typ = TYPE(a); ! 463: if (typ == ATOM) a = a->a.fnbnd, typ = TYPE(a); ! 464: ! 465: /* get function defn (unless calling form */ ! 466: /* is itself a lambda-expr) */ ! 467: vtemp = CNIL-1; /* sentinel value for error test */ ! 468: switch (typ) { ! 469: case ARRAY: ! 470: protect(a); /* stack array descriptor on top */ ! 471: a = a->ar.accfun; /* now funcall access function */ ! 472: goto top; ! 473: case BCD: ! 474: if(a->bcd.discipline==nlambda) ! 475: { if(np==lbot) protect(nil); /* default is nil */ ! 476: while(np-lbot!=1 || (lbot->val != nil && ! 477: TYPE(lbot->val)!=DTPR)) { ! 478: ! 479: lbot->val = errorh(Vermisc,"Bad funcall arg(s) to fexpr.", ! 480: nil,TRUE,0,lbot->val); ! 481: ! 482: np = lbot+1; ! 483: } ! 484: } ! 485: /* go for it */ ! 486: ! 487: if(TYPE(a->bcd.discipline)==STRNG) ! 488: vtemp = Ifcall(a); ! 489: else ! 490: vtemp = (*(lispval (*)())(a->bcd.entry))(); ! 491: if(a->bcd.discipline==macro) ! 492: vtemp = eval(vtemp); ! 493: break; ! 494: ! 495: ! 496: case DTPR: ! 497: if (a->d.car == lambda) { ! 498: ;/* VOID */ ! 499: } else if (a->d.car == nlambda || a->d.car==macro) { ! 500: if( np==lbot ) protect(nil); /* default */ ! 501: while(np-lbot!=1 || (lbot->val != nil && ! 502: TYPE(lbot->val)!=DTPR)) { ! 503: lbot->val = error("Bad funcall arg(s) to fexpr.",TRUE); ! 504: np = lbot+1; ! 505: } ! 506: } else if (a->d.car == lexpr) { ! 507: handy = newdot(); ! 508: handy->d.car = (lispval) lbot; ! 509: handy->d.cdr = (lispval) np; ! 510: PUSHDOWN(lexpr_atom,handy); ! 511: lbot = np; ! 512: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); ! 513: } else break; /* something is wrong - this isn't a proper function */ ! 514: rebind(a->d.cdr->d.car,lbot); ! 515: np = lbot; ! 516: for (handy = a->d.cdr->d.cdr; ! 517: handy != nil; ! 518: handy = handy->d.cdr) { ! 519: vtemp = eval(handy->d.car); /* go for it */ ! 520: } ! 521: if(a->d.car==macro) ! 522: vtemp = eval(vtemp); ! 523: } ! 524: if (vtemp != CNIL-1) ! 525: /* if we get here with a believable value, */ ! 526: /* we must have executed a function. */ ! 527: { ! 528: popnames(oldbnp); ! 529: ! 530: /* in case some clown trashed t */ ! 531: ! 532: tatom->a.clb = (lispval) tatom; ! 533: /*debugging ! 534: if(a>(lispval) end){printf(" leaving:"); ! 535: printr(a,stdout); ! 536: fflush(stdout);} */ ! 537: return(vtemp); ! 538: } ! 539: popnames(oldbnp); ! 540: a = fcncalled = (lispval) errorh(Verundef,"funcall: Bad function", ! 541: nil,TRUE,0,fcncalled); ! 542: } ! 543: /*NOT REACHED*/ ! 544: } ! 545: ! 546: /* The following must be the next "function" after Lfuncal, for the ! 547: sake of Levalf. */ ! 548: fchack () {} ! 549: ! 550: #undef protect ! 551: ! 552: /* protect **************************************************************/ ! 553: /* pushes the first argument onto namestack, thereby protecting from gc */ ! 554: lispval ! 555: protect(a) ! 556: lispval a; ! 557: { ! 558: /* (np++)->val = a; ! 559: if (np >= nplim) ! 560: namerr(); ! 561: */ ! 562: asm(" movl 4(ap),(r6)+"); ! 563: asm(" cmpl r6,_nplim"); ! 564: asm(" jlss out1"); ! 565: asm(" calls $0,_namerr"); ! 566: asm("out1: ret"); ! 567: } ! 568: ! 569: ! 570: /* unprot ****************************************************************/ ! 571: /* returns the top thing on the name stack. Underflow had better not */ ! 572: /* occur. */ ! 573: lispval ! 574: unprot() ! 575: { ! 576: asm(" movl -(r6),r0"); ! 577: } ! 578: ! 579: lispval ! 580: linterp() ! 581: { ! 582: error("BYTE INTERPRETER CALLED ERRONEOUSLY",FALSE); ! 583: } ! 584: ! 585: /* Undeff - called from qfuncl when it detects a call to a undefined ! 586: function from compiled code, we print out a message and ! 587: dont allow continuation ! 588: */ ! 589: lispval ! 590: Undeff(atmn) ! 591: lispval atmn; ! 592: { ! 593: return(errorh(Verundef,"Undefined function called from compiled code ", ! 594: nil,TRUE,0,atmn)); ! 595: } ! 596: bindfix(firstarg) ! 597: lispval firstarg; ! 598: { ! 599: register lispval *argp = &firstarg; ! 600: register struct nament *mybnp = bnp; ! 601: while(*argp != nil) { ! 602: mybnp->atm = *argp++; ! 603: mybnp->val = mybnp->atm->a.clb; ! 604: mybnp->atm->a.clb = *argp++; ! 605: bnp = mybnp++; ! 606: } ! 607: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.