Annotation of 43BSDTahoe/ucb/lisp/franz/eval.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *rcsid =
        !             3:    "$Header: eval.c,v 1.6 83/09/07 17:54:42 sklower Exp $";
        !             4: #endif
        !             5: 
        !             6: /*                                     -[Thu Aug 18 10:07:22 1983 by jkf]-
        !             7:  *     eval.c                          $Locker:  $
        !             8:  * evaluator
        !             9:  *
        !            10:  * (c) copyright 1982, Regents of the University of California
        !            11:  */
        !            12: 
        !            13: #include "global.h"
        !            14: #include <signal.h>
        !            15: #include "frame.h"
        !            16: 
        !            17: 
        !            18: 
        !            19: /*
        !            20:  *     eval
        !            21:  * returns the value of the pointer passed as the argument.            
        !            22:  *
        !            23:  */
        !            24: 
        !            25: lispval
        !            26: eval(actarg)
        !            27: lispval actarg;
        !            28: {
        !            29: #define argptr handy
        !            30:     register lispval a = actarg;
        !            31:     register lispval handy;
        !            32:     register struct nament *namptr;
        !            33:     register struct argent *workp;
        !            34:     struct nament *oldbnp = bnp;
        !            35:     int dopopframe = FALSE;
        !            36:     int type, shortcircuit = TRUE;
        !            37:     lispval Ifcall(), Iarray();
        !            38:     Savestack(4);
        !            39: 
        !            40:     /*debugging 
        !            41:     if (rsetsw && rsetatom->a.clb != nil) {
        !            42:        printf("Eval:");
        !            43:        printr(a,stdout);
        !            44:        printf("\nrsetsw: %d evalhsw: %d\n", rsetsw, evalhsw);
        !            45:        printf("*rset: ");
        !            46:        printr(rsetatom->a.clb,stdout);
        !            47:        printf(" evalhook: ");
        !            48:        printr(evalhatom->a.clb,stdout);
        !            49:        printf(" evalhook call flag^G: %d\n", evalhcallsw);
        !            50:        fflush(stdout); 
        !            51:     };  
        !            52:     */
        !            53: 
        !            54:     /* check if an interrupt is pending         and handle if so */
        !            55:     if(sigintcnt > 0) sigcall(SIGINT);
        !            56: 
        !            57:     if (rsetsw && rsetatom->a.clb != nil)  /* if (*rset t) has been done */
        !            58:     {
        !            59:        pbuf pb;
        !            60:        shortcircuit = FALSE;
        !            61:        if (evalhsw != nil && evalhatom->a.clb != nil)
        !            62:        {
        !            63:                                                /*if (sstatus evalhook t)
        !            64:                                                    and evalhook non-nil */
        !            65:            if (!evalhcallsw)
        !            66:                        /*if we got here after calling evalhook, then
        !            67:                          evalhcallsw will be TRUE, so we want to skip calling
        !            68:                          the hook function, permitting one form to be
        !            69:                          evaluated before the hook fires.
        !            70:                         */
        !            71:            {
        !            72:                /* setup equivalent of (funcall evalhook <arg to eval>) */
        !            73:                (np++)->val = a;                /* push form on namestack */
        !            74:                lbot=np;                        /* set up args to funcall */
        !            75:                (np++)->val = evalhatom->a.clb; /* push evalhook's clb */
        !            76:                (np++)->val = a;                /* eval's arg becomes
        !            77:                                                   2nd arg to funcall */
        !            78:                PUSHDOWN(evalhatom, nil);       /* bind evalhook to nil*/
        !            79:                PUSHDOWN(funhatom, nil);        /* bind funcallhook to nil*/
        !            80:                funhcallsw = TRUE;              /* skip any funcall hook */
        !            81:                handy = Lfuncal();              /* now call funcall */
        !            82:                funhcallsw = FALSE;
        !            83:                POP;
        !            84:                POP;
        !            85:                Restorestack();
        !            86:                return(handy);
        !            87:            };
        !            88:        }
        !            89:        errp = Pushframe(F_EVAL,a,nil);
        !            90:        dopopframe = TRUE;      /* remember to pop later */
        !            91:        if(retval == C_FRETURN)
        !            92:        {
        !            93:            Restorestack();
        !            94:            errp = Popframe();
        !            95:            return(lispretval);
        !            96:        }
        !            97:     };
        !            98:         
        !            99:     evalhcallsw = FALSE;   /* clear indication that evalhook called */
        !           100:     
        !           101:     switch (TYPE(a))
        !           102:     {
        !           103:     case ATOM:
        !           104:        if (rsetsw && rsetatom->a.clb != nil && bptr_atom->a.clb != nil) {
        !           105: 
        !           106:            struct nament *bpntr, *eval1bptr;
        !           107:                                  /* Both rsetsw and rsetatom for efficiency*/
        !           108:                                    /* bptr_atom set by second arg to eval1 */
        !           109:            eval1bptr = (struct nament *) bptr_atom->a.clb->d.cdr;
        !           110:                                    /* eval1bptr is bnp when eval1 was called;
        !           111:                                       if an atom was bound after this,
        !           112:                                       then its clb is valid */
        !           113:            for (bpntr = eval1bptr; bpntr < bnp; bpntr++)
        !           114:                if (bpntr->atm==a) {
        !           115:                    handy = a->a.clb;
        !           116:                    goto gotatom;
        !           117:                };                  /* Value saved in first binding of a,
        !           118:                                       if any, after pointer to eval1,
        !           119:                                       is the valid value, else use its clb */
        !           120:            for (bpntr = (struct nament *)bptr_atom->a.clb->d.car;
        !           121:              bpntr < eval1bptr; bpntr++)
        !           122:                if (bpntr->atm==a) {
        !           123:                    handy=bpntr->val;
        !           124:                    goto gotatom;   /* Simply no way around goto here */
        !           125:                };
        !           126:        };
        !           127:         handy = a->a.clb;
        !           128:     gotatom:
        !           129:         if(handy==CNIL) {
        !           130:             handy = errorh1(Vermisc,"Unbound Variable:",nil,TRUE,0,a);
        !           131:         }
        !           132:        if(dopopframe) errp = Popframe();
        !           133:        Restorestack();
        !           134:         return(handy);
        !           135: 
        !           136:     case VALUE:
        !           137:        if(dopopframe) errp = Popframe();
        !           138:        Restorestack();
        !           139:         return(a->l);
        !           140: 
        !           141:     case DTPR:
        !           142:         (np++)->val = a;               /* push form on namestack */
        !           143:         lbot = np;                     /* define beginning of argstack */
        !           144:         /* oldbnp = bnp;                  redundant - Mitch Marcus */
        !           145:         a = a->d.car;                  /* function name or lambda-expr */
        !           146:         for(EVER)
        !           147:             {
        !           148:             switch(TYPE(a))
        !           149:                 {
        !           150:             case ATOM:
        !           151:                                        /*  get function binding  */
        !           152:                 if(a->a.fnbnd==nil && a->a.clb!=nil) {
        !           153:                     a=a->a.clb;
        !           154:                     if(TYPE(a)==ATOM)
        !           155:                         a=a->a.fnbnd;
        !           156:                 } else
        !           157:                     a = a->a.fnbnd;
        !           158:                 break;
        !           159:             case VALUE:
        !           160:                 a = a->l;              /*  get value  */
        !           161:                 break;
        !           162:                 }
        !           163: 
        !           164:             vtemp = (CNIL-1);       /* sentinel value for error test */
        !           165: 
        !           166:         /*funcal:*/    switch (TYPE(a))
        !           167:                 {
        !           168:             case BCD:    /* function */
        !           169:                 argptr = actarg->d.cdr;
        !           170: 
        !           171:                                    /* decide whether lambda, nlambda or
        !           172:                                       macro and push args onto argstack
        !           173:                                       accordingly.                */
        !           174: 
        !           175:                 if(a->bcd.discipline==nlambda) {
        !           176:                     (np++)->val = argptr;
        !           177:                     TNP;
        !           178:                 } else if(a->bcd.discipline==macro) {
        !           179:                     (np++)->val = actarg;
        !           180:                     TNP;
        !           181:                 } else for(;argptr!=nil; argptr = argptr->d.cdr) {
        !           182:                    /* short circuit evaluations of ATOM, INT, DOUB
        !           183:                     * if not in debugging mode
        !           184:                     */
        !           185:                    if(shortcircuit
        !           186:                       && ((type = TYPE(argptr->d.car)) == ATOM)
        !           187:                       && (argptr->d.car->a.clb != CNIL))
        !           188:                        (np++)->val = argptr->d.car->a.clb;
        !           189:                    else if(shortcircuit &&
        !           190:                                ((type == INT) || (type == STRNG)))
        !           191:                        (np++)->val = argptr->d.car;
        !           192:                    else
        !           193:                        (np++)->val = eval(argptr->d.car);
        !           194:                     TNP;
        !           195:                 }
        !           196:                 /* go for it */
        !           197: 
        !           198:                 if(TYPE(a->bcd.discipline)==STRNG)
        !           199:                     vtemp = Ifcall(a);
        !           200:                 else
        !           201:                     vtemp = (*(lispval (*)())(a->bcd.start))();
        !           202:                 break;
        !           203: 
        !           204:             case ARRAY:
        !           205:                 vtemp = Iarray(a,actarg->d.cdr,TRUE);
        !           206:                 break;
        !           207: 
        !           208:             case DTPR:             /* push args on argstack according to
        !           209:                                       type                */
        !           210:                protect(a);     /* save function definition in case function
        !           211:                                   is redefined */
        !           212:                lbot = np;
        !           213:                 argptr = a->d.car;
        !           214:                 if (argptr==lambda) {
        !           215:                     for(argptr = actarg->d.cdr;
        !           216:                         argptr!=nil; argptr=argptr->d.cdr) {
        !           217:                         
        !           218:                         (np++)->val = eval(argptr->d.car);
        !           219:                         TNP;
        !           220:                     }
        !           221:                 } else if (argptr==nlambda) {
        !           222:                     (np++)->val = actarg->d.cdr;
        !           223:                     TNP;
        !           224:                 } else if (argptr==macro) {
        !           225:                     (np++)->val = actarg;
        !           226:                     TNP;
        !           227:                 } else if (argptr==lexpr) {
        !           228:                     for(argptr = actarg->d.cdr;
        !           229:                       argptr!=nil; argptr=argptr->d.cdr) {
        !           230:                         
        !           231:                         (np++)->val = eval(argptr->d.car);
        !           232:                         TNP;
        !           233:                     }
        !           234:                     handy = newdot();
        !           235:                     handy->d.car = (lispval)lbot;
        !           236:                     handy->d.cdr = (lispval)np;
        !           237:                     PUSHDOWN(lexpr_atom,handy);
        !           238:                     lbot = np;
        !           239:                     (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car);
        !           240: 
        !           241:                 } else break;    /* something is wrong - this isn't a proper function */
        !           242: 
        !           243:                 argptr = (a->d.cdr)->d.car;
        !           244:                 namptr =  bnp;
        !           245:                 workp = lbot;
        !           246:                 if(bnp + (np - lbot)> bnplim)
        !           247:                     binderr();
        !           248:                 for(;argptr != (lispval)nil;
        !           249:                      workp++,argptr = argptr->d.cdr)    /* rebind formal names (shallow) */
        !           250:                 {
        !           251:                     if(argptr->d.car==nil)
        !           252:                         continue;
        !           253:                     /*if(((namptr)->atm = argptr->d.car)==nil)
        !           254:                         error("Attempt to lambda bind nil",FALSE);*/
        !           255:                     namptr->atm = argptr->d.car;
        !           256:                     if (workp < np) {
        !           257:                         namptr->val = namptr->atm->a.clb;
        !           258:                         namptr->atm->a.clb = workp->val;
        !           259:                     } else
        !           260:                         bnp = namptr,
        !           261:                         error("Too few actual parameters",FALSE);
        !           262:                     namptr++;
        !           263:                 }
        !           264:                 bnp = namptr;
        !           265:                 if (workp < np)
        !           266:                     error("Too many actual parameters",FALSE);
        !           267: 
        !           268:                                    /* execute body, implied prog allowed */
        !           269: 
        !           270:                 for (handy = a->d.cdr->d.cdr;
        !           271:                     handy != nil;
        !           272:                     handy = handy->d.cdr) {
        !           273:                         vtemp = eval(handy->d.car);
        !           274:                     }
        !           275:                 }
        !           276:             if (vtemp != (CNIL-1)) {
        !           277:                                /* if we get here with a believable value, */
        !           278:                                /* we must have executed a function. */
        !           279:                 popnames(oldbnp);
        !           280: 
        !           281:                 /* in case some clown trashed t */
        !           282: 
        !           283:                 tatom->a.clb = (lispval) tatom;
        !           284:                 if(a->d.car==macro)
        !           285:                {
        !           286:                    if(Vdisplacemacros->a.clb && (TYPE(vtemp) == DTPR))
        !           287:                    {
        !           288:                        actarg->d.car = vtemp->d.car;
        !           289:                        actarg->d.cdr = vtemp->d.cdr;
        !           290:                    }
        !           291:                    vtemp = eval(vtemp);
        !           292:                }
        !           293:                     /* It is of the most wonderful 
        !           294:                        coincidence that the offset
        !           295:                        for car is the same as for
        !           296:                        discipline so we get bcd macros
        !           297:                        for free here ! */
        !           298:                if(dopopframe) errp = Popframe();
        !           299:                Restorestack();
        !           300:                return(vtemp);
        !           301:            }
        !           302:             popnames(oldbnp);
        !           303:             a = (lispval) errorh1(Verundef,"eval: Undefined function ",nil,TRUE,0,actarg->d.car);
        !           304:             }
        !           305: 
        !           306:         }
        !           307:     if(dopopframe) errp = Popframe();
        !           308:     Restorestack();
        !           309:     return(a);    /* other data types are considered constants */
        !           310: }
        !           311: 
        !           312: /*
        !           313:  *    popnames
        !           314:  * removes from the name stack all entries above the first argument.   
        !           315:  * routine should usually be used to clean up the name stack as it    
        !           316:  * knows about the special cases.  bnp is returned pointing to the
        !           317:  * same place as the argument passed.
        !           318:  */
        !           319: lispval
        !           320: popnames(llimit)
        !           321: register struct nament *llimit;
        !           322: {
        !           323:     register struct nament *rnp;
        !           324: 
        !           325:     for(rnp = bnp; --rnp >= llimit;)
        !           326:         rnp->atm->a.clb = rnp->val;
        !           327:     bnp = llimit;
        !           328: }
        !           329: 
        !           330: 
        !           331: /* dumpnamestack
        !           332:  * utility routine to dump out the namestack.
        !           333:  * from bottom to 5 above np
        !           334:  * should be put elsewhere
        !           335:  */
        !           336: dumpnamestack()
        !           337: {
        !           338:     struct argent *newnp;
        !           339: 
        !           340:     printf("namestack dump:\n");
        !           341:     for(newnp = orgnp ; (newnp < np + 6) && (newnp < nplim) ; newnp++)
        !           342:     {
        !           343:        if(newnp == np) printf("**np:**\n");
        !           344:        printf("[%d]: ",newnp-orgnp);
        !           345:        printr(newnp->val,stdout);
        !           346:        printf("\n");
        !           347:     }
        !           348:     printf("end namestack dump\n");
        !           349: }
        !           350: 
        !           351: 
        !           352: 
        !           353: lispval
        !           354: Lapply()
        !           355: {
        !           356:     register lispval a;
        !           357:     register lispval handy;
        !           358:     lispval vtemp, Ifclosure();
        !           359:     struct nament *oldbnp = bnp;
        !           360:     struct argent *oldlbot = lbot; /* Bottom of my frame! */
        !           361:     struct argent *oldnp = np; /* First free on stack */
        !           362:     int extrapush;             /* if must save function value */
        !           363: 
        !           364:     a = lbot->val;
        !           365:     argptr = lbot[1].val;
        !           366:     if(np-lbot!=2)
        !           367:         errorh2(Vermisc,"Apply: Wrong number of args.",nil,FALSE,
        !           368:                999,a,argptr);
        !           369:     if(TYPE(argptr)!=DTPR && argptr!=nil)
        !           370:         argptr = errorh1(Vermisc,"Apply: non-list of args",nil,TRUE,
        !           371:                 998,argptr);
        !           372:     (np++)->val = a;    /* push form on namestack */
        !           373:     TNP;
        !           374:     lbot = np;        /* bottom of current frame */
        !           375:     for(EVER)
        !           376:         {
        !           377:        extrapush = 0;
        !           378:         if (TYPE(a) == ATOM) { a = a->a.fnbnd; extrapush = 1; }
        !           379:                                        /* get function definition (unless
        !           380:                                           calling form is itself a lambda-
        !           381:                                           expression) */
        !           382:         vtemp = CNIL;                  /* sentinel value for error test */
        !           383:         switch (TYPE(a)) {
        !           384: 
        !           385:         case BCD: 
        !           386:                                        /* push arguments - value of a */
        !           387:             if(a->bcd.discipline==nlambda || a->bcd.discipline==macro) {
        !           388:                 (np++)->val=argptr;
        !           389:                 TNP;
        !           390:             } else for (; argptr!=nil; argptr = argptr->d.cdr) {
        !           391:                 (np++)->val=argptr->d.car;
        !           392:                 TNP;
        !           393:             }
        !           394: 
        !           395:            if(TYPE(a->bcd.discipline) == STRNG)
        !           396:              vtemp = Ifcall(a);        /* foreign function */
        !           397:            else
        !           398:               vtemp = (*(lispval (*)())(a->bcd.start))(); /* go for it */
        !           399:             break;
        !           400: 
        !           401:         case ARRAY:
        !           402:             vtemp = Iarray(a,argptr,FALSE);
        !           403:             break;
        !           404: 
        !           405: 
        !           406:         case DTPR:
        !           407:             if (a->d.car==nlambda || a->d.car==macro) {
        !           408:                 (np++)->val = argptr;
        !           409:                 TNP;
        !           410:             } else if (a->d.car==lambda)
        !           411:                 for (; argptr!=nil; argptr = argptr->d.cdr) {
        !           412:                     (np++)->val = argptr->d.car;
        !           413:                     TNP;
        !           414:                 }
        !           415:             else if(a->d.car==lexpr) {
        !           416:                 for (; argptr!=nil; argptr = argptr->d.cdr) {
        !           417:                     
        !           418:                     (np++)->val = argptr->d.car;
        !           419:                     TNP;
        !           420:                 }
        !           421:                 handy = newdot();
        !           422:                 handy->d.car = (lispval)lbot;
        !           423:                 handy->d.cdr = (lispval)np;
        !           424:                 PUSHDOWN(lexpr_atom,handy);
        !           425:                 lbot = np;
        !           426:                 (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car);
        !           427: 
        !           428:             } else break;    /* something is wrong - this isnt a proper function */
        !           429:             rebind(a->d.cdr->d.car,lbot);
        !           430: 
        !           431:            if (extrapush == 1) { protect(a); extrapush = 2;}
        !           432:             for (handy = a->d.cdr->d.cdr;
        !           433:                 handy != nil;
        !           434:                 handy = handy->d.cdr) {
        !           435:                     vtemp = eval(handy->d.car);    /* go for it */
        !           436:                 }
        !           437:            break;
        !           438:            
        !           439:        case VECTOR:
        !           440:            /* certain vectors are valid (fclosures) */
        !           441:           if(a->v.vector[VPropOff] == fclosure)
        !           442:               vtemp = (lispval) Ifclosure(a,FALSE);
        !           443:           break;
        !           444:                
        !           445:         };
        !           446:        
        !           447:        /* pop off extra value if we pushed it before */
        !           448:        if (extrapush == 2)
        !           449:        {
        !           450:            np--;
        !           451:            extrapush = 0;
        !           452:        };
        !           453:        
        !           454:         if (vtemp != CNIL)
        !           455:                                /* if we get here with a believable value, */
        !           456:                                /* we must have executed a function. */
        !           457:             {
        !           458:             popnames(oldbnp);
        !           459: 
        !           460:             /* in case some clown trashed t */
        !           461: 
        !           462:             tatom->a.clb = (lispval) tatom;
        !           463:            np = oldnp; lbot = oldlbot;
        !           464:             return(vtemp);
        !           465:             }
        !           466:         popnames(oldbnp);
        !           467:         a = (lispval) errorh1(Verundef,"apply: Undefined Function ",
        !           468:                                              nil,TRUE,0,oldlbot->val);
        !           469:     }
        !           470:     /*NOT REACHED*/
        !           471: }
        !           472: 
        !           473: 
        !           474: /*
        !           475:  * Rebind -- rebind formal names
        !           476:  */
        !           477: rebind(argptr,workp)
        !           478: register lispval argptr;        /* argptr points to list of atoms */
        !           479: register struct argent * workp;        /* workp points to position on stack
        !           480:                        where evaluated args begin */
        !           481: {
        !           482:     register struct nament *namptr = bnp;
        !           483: 
        !           484:     for(;argptr != (lispval)nil;
        !           485:          workp++,argptr = argptr->d.cdr)  /* rebind formal names (shallow) */
        !           486:     {
        !           487:         if(argptr->d.car==nil)
        !           488:             continue;
        !           489:         namptr->atm = argptr->d.car;
        !           490:         if (workp < np) {
        !           491:             namptr->val = namptr->atm->a.clb;
        !           492:             namptr->atm->a.clb = workp->val;
        !           493:         } else
        !           494:             bnp = namptr,
        !           495:             error("Too few actual parameters",FALSE);
        !           496:         namptr++;
        !           497:         if(namptr > bnplim)
        !           498:             binderr();
        !           499:     }
        !           500:     bnp = namptr;
        !           501:     if (workp < np)
        !           502:         error("Too many actual parameters",FALSE);
        !           503: }
        !           504: 
        !           505: /* the argument to Lfuncal is now mandatory since nargs
        !           506:  * wont work on RISC. If it is given  then it is 
        !           507:  * the name of the function to call and lbot points to the first arg.
        !           508:  * if it is not given, then lbot points to the function to call
        !           509:  */
        !           510: lispval
        !           511: Ifuncal(fcn)
        !           512: lispval fcn;
        !           513: {
        !           514:     register lispval a;
        !           515:     register lispval handy; 
        !           516:     struct nament *oldbnp = bnp;       /* MUST be first local for evalframe */
        !           517:     lispval fcncalled;
        !           518:     lispval Ifcall(),Llist(),Iarray(), Ifclosure();
        !           519:     lispval vtemp;
        !           520:     int typ, dopopframe = FALSE, extrapush;
        !           521:     extern lispval end[];
        !           522:     Savestack(3);
        !           523: 
        !           524:     /*if(nargs()==1)                   /* function I am evaling.    */
        !           525:        a = fcncalled = fcn;
        !           526:     /*else { a = fcncalled = lbot->val; lbot++; }*/
        !           527: 
        !           528:     /*debugging 
        !           529:     if (rsetsw && rsetatom->a.clb != nil) {
        !           530:        printf("funcall:");
        !           531:        printr(a,stdout);
        !           532:        printf("\nrsetsw: %d evalhsw: %d\n", rsetsw, evalhsw);
        !           533:        printf("*rset: ");
        !           534:        printr(rsetatom->a.clb,stdout);
        !           535:        printf(" funhook: ");
        !           536:        printr(funhatom->a.clb,stdout);
        !           537:        printf(" funhook call flag^G: %d\n",funhcallsw);
        !           538:        fflush(stdout); 
        !           539:     };  
        !           540:     */
        !           541: 
        !           542:     /* check if exception pending */
        !           543:     if(sigintcnt > 0 ) sigcall(SIGINT);
        !           544: 
        !           545:     if (rsetsw && rsetatom->a.clb != nil)  /* if (*rset t) has been done */
        !           546:     {          
        !           547:        pbuf pb;
        !           548:        if (evalhsw != nil && funhatom->a.clb != nil)
        !           549:        {
        !           550:                                                /*if (sstatus evalhook t)
        !           551:                                                    and evalhook non-nil */
        !           552:            if (!funhcallsw)
        !           553:                        /*if we got here after calling funcallhook, then
        !           554:                          funhcallsw will be TRUE, so we want to skip calling
        !           555:                          the hook function, permitting one form to be
        !           556:                          evaluated before the hook fires.
        !           557:                         */
        !           558:            {
        !           559:                /* setup equivalent of (funcall funcallhook <args to eval>) */
        !           560:                protect(a);
        !           561:                a = fcncalled = funhatom->a.clb; /* new function to funcall */
        !           562:                PUSHDOWN(funhatom, nil);        /* lambda-bind 
        !           563:                                                 * funcallhook to nil
        !           564:                                                 */
        !           565:                PUSHDOWN(evalhatom, nil);       
        !           566:             /* printf(" now will funcall ");
        !           567:                printr(a,stdout);
        !           568:                putchar('\n');
        !           569:                fflush(stdout); */
        !           570:            };
        !           571:        }
        !           572:        errp = Pushframe(F_FUNCALL,a,nil);
        !           573:        dopopframe = TRUE;      /* remember to pop later */
        !           574:        if(retval == C_FRETURN)
        !           575:        {
        !           576:            popnames(oldbnp);
        !           577:            errp = Popframe();
        !           578:            Restorestack();
        !           579:            return(lispretval);
        !           580:        }
        !           581:     };
        !           582:     
        !           583:     funhcallsw = FALSE;        /* so recursive calls to funcall will cause hook
        !           584:                           to fire */
        !           585:     for(EVER)
        !           586:     {
        !           587:      top:
        !           588:         extrapush = 0;
        !           589:        
        !           590:         typ = TYPE(a);
        !           591:         if (typ == ATOM)
        !           592:        {   /* get function defn (unless calling form */
        !           593:             /* is itself a lambda-expr) */
        !           594:            a = a->a.fnbnd;
        !           595:            typ = TYPE(a);
        !           596:            extrapush = 1;      /* must protect this later */
        !           597:        }
        !           598:         vtemp = CNIL-1;            /* sentinel value for error test */
        !           599:         switch (typ) {
        !           600:         case ARRAY:
        !           601:            protect(a);                 /* stack array descriptor on top */
        !           602:            a = a->ar.accfun;           /* now funcall access function */
        !           603:            goto top;
        !           604:         case BCD:
        !           605:             if(a->bcd.discipline==nlambda)
        !           606:                 {   if(np==lbot) protect(nil);  /* default is nil */
        !           607:                 while(np-lbot!=1 || (lbot->val != nil &&
        !           608:                       TYPE(lbot->val)!=DTPR)) {
        !           609: 
        !           610:                            lbot->val = errorh1(Vermisc,"Bad funcall arg(s) to fexpr.",
        !           611:                                                 nil,TRUE,0,lbot->val);
        !           612:                            
        !           613:                     np = lbot+1;
        !           614:                     }
        !           615:                 }
        !           616:             /* go for it */
        !           617: 
        !           618:             if(TYPE(a->bcd.discipline)==STRNG)
        !           619:                 vtemp = Ifcall(a);
        !           620:             else
        !           621:                 vtemp = (*(lispval (*)())(a->bcd.start))();
        !           622:             if(a->bcd.discipline==macro)
        !           623:                 vtemp = eval(vtemp);
        !           624:             break;
        !           625: 
        !           626: 
        !           627:         case DTPR:
        !           628:             if (a->d.car == lambda) {
        !           629:                 ;/* VOID */
        !           630:             } else if (a->d.car == nlambda || a->d.car==macro) {
        !           631:                 if( np==lbot ) protect(nil);    /* default */
        !           632:                 while(np-lbot!=1 || (lbot->val != nil &&
        !           633:                           TYPE(lbot->val)!=DTPR)) {
        !           634:                     lbot->val = error("Bad funcall arg(s) to fexpr.",TRUE);
        !           635:                     np = lbot+1;
        !           636:                     }
        !           637:             } else if (a->d.car == lexpr) {
        !           638:                 handy = newdot();
        !           639:                 handy->d.car = (lispval) lbot;
        !           640:                 handy->d.cdr = (lispval) np;
        !           641:                 PUSHDOWN(lexpr_atom,handy);
        !           642:                 lbot = np;
        !           643:                 (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car);
        !           644:             } else break;        /* something is wrong - this isn't a proper function */
        !           645:             rebind(a->d.cdr->d.car,lbot);
        !           646: 
        !           647:            /* since the actual arguments are bound to their formal params
        !           648:             * we can pop them off the stack.  However if we are doing
        !           649:             * debugging (that is if we've pushed a frame on the stack)
        !           650:             * then we must not pop off the actual args since they must
        !           651:             * be visible for evalframe to work
        !           652:             */
        !           653:             if(!dopopframe) np = lbot;
        !           654:            if (extrapush == 1) {protect(a);  extrapush = 2;}
        !           655:             for (handy = a->d.cdr->d.cdr;
        !           656:                 handy != nil;
        !           657:                 handy = handy->d.cdr) {
        !           658:                     vtemp = eval(handy->d.car);    /* go for it */
        !           659:                 }
        !           660:             if(a->d.car==macro)
        !           661:                 vtemp = eval(vtemp);
        !           662:            break;
        !           663:            
        !           664:        case VECTOR:
        !           665:           /* A fclosure represented as a vector with the property 'fclosure' */
        !           666:           if(a->v.vector[VPropOff] == fclosure)
        !           667:               vtemp = (lispval) Ifclosure(a,TRUE);
        !           668:           break;
        !           669:           
        !           670:         }
        !           671:        
        !           672:        /* pop off extra value if we pushed it before */
        !           673:        if(extrapush == 2) { np-- ; extrapush = 0; }
        !           674:        
        !           675:         if (vtemp != CNIL-1)
        !           676:             /* if we get here with a believable value, */
        !           677:             /* we must have executed a function. */
        !           678:             {
        !           679:             popnames(oldbnp);
        !           680: 
        !           681:             /* in case some clown trashed t */
        !           682: 
        !           683:             tatom->a.clb = (lispval) tatom;
        !           684: 
        !           685:            if(dopopframe) errp = Popframe();
        !           686:            Restorestack();
        !           687:             return(vtemp);
        !           688:             }
        !           689:         popnames(oldbnp);
        !           690:            a = fcncalled = (lispval) errorh1(Verundef,"funcall: Bad function",
        !           691:                                               nil,TRUE,0,fcncalled);
        !           692:     }
        !           693:     /*NOT REACHED*/
        !           694: }
        !           695: lispval   /* this version called from lisp */
        !           696: Lfuncal()
        !           697: {
        !           698:        lispval handy;
        !           699:        Savestack(0);
        !           700:        
        !           701:        switch(np-lbot)
        !           702:        {
        !           703:            case 0: argerr("funcall");
        !           704:                    break;
        !           705:        }
        !           706:        handy = lbot++->val;
        !           707:        handy = Ifuncal(handy);
        !           708:        Restorestack();
        !           709:        return(handy);
        !           710: }
        !           711: 
        !           712: /* The following must be the next "function" after Lfuncal, for the
        !           713: sake of Levalf.  */
        !           714: fchack () {}
        !           715: 
        !           716: 
        !           717: /*
        !           718:  * Llexfun  :: lisp function lexpr-funcall
        !           719:  * lexpr-funcall is a cross between funcall and apply.
        !           720:  * the last argument is nil or a list of the rest of the arguments.
        !           721:  * we push those arguments on the stack and call funcall
        !           722:  *
        !           723:  */
        !           724: lispval
        !           725: Llexfun()
        !           726: {
        !           727:     register lispval handy;
        !           728:     
        !           729:     switch(np-lbot)
        !           730:     {
        !           731:        case 0: argerr("lexpr-funcall");        /* need at least one arg */
        !           732:                break;
        !           733:        case 1: return(Lfuncal());       /* no args besides function */
        !           734:     }
        !           735:     /* have at least one argument past the function to funcall */
        !           736:     handy = np[-1].val;                /* get last value */
        !           737:     np--;                      /* pop it off stack */
        !           738:     
        !           739:     while((handy != nil) && (TYPE(handy) != DTPR))
        !           740:        handy = errorh1(Vermisc,"lexpr-funcall: last argument is not a list ",
        !           741:                        nil,TRUE,0,handy);
        !           742: 
        !           743:     /* stack arguments */
        !           744:     for( ; handy != nil ; handy = handy->d.cdr) protect(handy->d.car);
        !           745: 
        !           746:     return(Lfuncal());
        !           747: }
        !           748: 
        !           749:        
        !           750: #undef protect
        !           751:        
        !           752: /* protect 
        !           753:  * pushes the first argument onto namestack, thereby protecting from gc
        !           754:  */
        !           755: lispval
        !           756: protect(a)
        !           757: lispval a;
        !           758: {
        !           759:     (np++)->val = a;
        !           760:        if (np >=  nplim)
        !           761:         namerr();
        !           762: }
        !           763: 
        !           764: /* unprot
        !           765:  * returns the top thing on the name stack.  Underflow had better not
        !           766:  * occur.
        !           767:  */
        !           768: lispval
        !           769: unprot()
        !           770:     {
        !           771:     return((--np)->val);
        !           772:     }
        !           773: 
        !           774: lispval
        !           775: linterp()
        !           776:     {
        !           777:     error("BYTE INTERPRETER CALLED ERRONEOUSLY",FALSE);
        !           778:     }
        !           779: 
        !           780: /* Undeff - called from qfuncl when it detects a call to a undefined
        !           781:     function from compiled code, we print out a message and
        !           782:     will continue only if returned a symbol (ATOM in C parlance).
        !           783: */
        !           784: lispval
        !           785: Undeff(atmn)
        !           786: lispval atmn;
        !           787: {
        !           788:     do {atmn =errorh1(Verundef,"Undefined function called from compiled code ",
        !           789:                                      nil,TRUE,0,atmn);}
        !           790:        while(TYPE(atmn) != ATOM);
        !           791:     return(atmn);                    
        !           792: }
        !           793: 
        !           794: /* VARARGS1 */
        !           795: bindfix(firstarg)
        !           796: lispval firstarg;
        !           797: {
        !           798:     register lispval *argp = &firstarg;
        !           799:     register struct nament *mybnp = bnp;
        !           800:     while(*argp != nil) {
        !           801:         mybnp->atm = *argp++;
        !           802:         mybnp->val = mybnp->atm->a.clb;
        !           803:         mybnp->atm->a.clb = *argp++;
        !           804:         bnp = mybnp++;
        !           805:     }
        !           806: }
        !           807: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.