Annotation of 42BSD/ucb/lisp/franz/eval2.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *rcsid =
                      3:    "$Header: eval2.c,v 1.6 83/09/12 14:18: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:                                bcopy(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:                        bcopy(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: bcopy(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: 
                    239:     
                    240: /* Ifclosure :: evaluate a fclosure  (new version)
                    241:  * the argument clos is a vector whose property is the atom fclosure
                    242:  * the form of the vector is
                    243:  *   0: function to run
                    244:  * then for each symbol there is on vector entry containing a
                    245:  * pointer to a sequence of two list cells of this form:
                    246:  *     (name value . count)
                    247:  * name is the symbol name to close over
                    248:  * value is the saved value of the closure
                    249:  *     (if the closure is 'active', the current value will be in the
                    250:  *      symbol itself)
                    251:  * count is a fixnum box (which can be destructively modified safely)
                    252:  *  it is normally 0.  Each time the variable is put on the stack, it is
                    253:  *  incremented.  It is decremented each time the the closure is left.
                    254:  *  If the closure is invoked recusively without a rebinding of the
                    255:  *  closure variable X, then the count will not be incremented.
                    256:  *
                    257:  * when entering a fclosure, for each variable there are three
                    258:  * possibities:
                    259:  *  (a) this is the first instance of this closed variable
                    260:  *  (b) this is the second or greater recursive instance of
                    261:  *      this closure variable, however it hasn't been normally lambda
                    262:  *     bound since the last closure invocation
                    263:  *  (c) like (b) but it has been lambda bound before the most recent
                    264:  *     closure.
                    265:  *
                    266:  * case (a) can be determined by seeing if the count is 0.
                    267:  * if the count is >0 then we must scan from the top of the stack down
                    268:  * until we find either the closure or a lambda binding of the variable
                    269:  * this determines whether it is case (b) or (c).
                    270:  *
                    271:  * There are three actions to perform in this routine:
                    272:  * 1.  determine the closure type (a,b or c) and do any binding necessary
                    273:  * 2.  call the closure function
                    274:  * 3.  unbind any necessary closure variables.
                    275:  *
                    276:  * Now, the details of those actions:
                    277:  * 1. for case (b), do nothing as we are still working with the correct
                    278:  *    value
                    279:  *    for case (a), pushdown the symbol and give it the value from
                    280:  *     the closure, inc the closure count
                    281:  *      push a closure marker on the bindstack too.
                    282:  *    for case (c), must locate the correct value to set by searching
                    283:  *      for the last lambda binding before the previous closure.
                    284:  *      pushdown the symbol and that value, inc the closure count
                    285:  *      push a closure marker on the bindstack too.
                    286:  *    a closure marker has atom == int:closure-marker and value pointing
                    287:  *      to the closure list.  This will be noticed when unbinding.
                    288:  *
                    289:  *  3. unbinding is just like popnames except if a closure marker is
                    290:  *     seen, then this must be done:
                    291:  *     if the count is 1, just store the symbol's value in the closure
                    292:  *      and decrement the count.
                    293:  *      if the count is >1, then search up the stack for the last
                    294:  *      lambda before the next occurance of this closure variable
                    295:  *      and set its value to the current value of the closure.
                    296:  *      decrement the closure count.
                    297:  *
                    298:  * clos is the fclosure, funcallp is TRUE if this is called from funcall,
                    299:  * otherwise it is called from apply
                    300:  */
                    301: 
                    302: #define Case_A 0
                    303: #define Case_B 1
                    304: #define Case_C 2
                    305: 
                    306: lispval
                    307: Ifclosure(clos,funcallp)
                    308: register lispval clos;
                    309: {
                    310:     struct nament *oldbnp = bnp, *lbnp, *locatevar();
                    311:     register int i;
                    312:     register lispval vect;
                    313:     int numvars, vlength, tcase, foundc;
                    314:     lispval handy, atm_dtpr, value_dtpr, Ifuncal(), Lapply();
                    315:     Savestack(3);
                    316: 
                    317:     /* bind variables to their values given in the fclosure */
                    318:     vlength = VecTotSize(clos->vl.vectorl[VSizeOff]);
                    319:     /* vector length must be positive (it has to have a function at least) */
                    320:     if (vlength < 1)
                    321:        errorh1(Vermisc,"funcall: fclosure has wrong size ",nil,FALSE,0, clos);
                    322: 
                    323:     numvars = (vlength - 1);   /* number of varibles */
                    324:     
                    325:     for (i = 1 ; i < vlength ; i += 1)
                    326:     {
                    327:        atm_dtpr = clos->v.vector[i];   /* car is symbol name */
                    328:        value_dtpr = atm_dtpr->d.cdr;   /* car: value, cdr:  fixnum count */
                    329: 
                    330:        if(value_dtpr->d.cdr->i == 0)
                    331:                tcase = Case_A;         /* first call */
                    332:        else {
                    333:            lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
                    334:            if (!foundc)
                    335:            {
                    336:                /* didn't find the expected closure, count must be
                    337:                   wrong, correct it and assume case (a)
                    338:                 */
                    339:                tcase = Case_A;
                    340:                value_dtpr->d.cdr->i = 0;
                    341:            }
                    342:            else if(lbnp) tcase = Case_C ; /* found intermediate lambda bnd*/
                    343:            else tcase = Case_B;           /* no intermediate lambda bind */
                    344:        }
                    345: 
                    346:        /* now bind the value if necessary */
                    347:        switch(tcase) {
                    348:            case Case_A: PUSHDOWN(atm_dtpr->d.car,value_dtpr->d.car);
                    349:                         PUSHVAL(clos_marker,atm_dtpr);
                    350:                         value_dtpr->d.cdr->i += 1;
                    351:                         break;
                    352:                         
                    353:            case Case_B: break;         /* nothing to do */
                    354: 
                    355:            case Case_C: /* push first bound value after last close */
                    356:                         PUSHDOWN(atm_dtpr->d.car,lbnp->val);
                    357:                         PUSHVAL(clos_marker,atm_dtpr);
                    358:                         value_dtpr->d.cdr->i += 1;
                    359:                         break;
                    360:        }
                    361:     }
                    362: 
                    363:     if(funcallp)
                    364:        handy = Ifuncal(clos->v.vector[0]);
                    365:     else {
                    366:        handy = lbot[-2].val;   /* get args to apply.  This is hacky and may
                    367:                                           fail if apply is changed */
                    368:        lbot = np;
                    369:        protect(clos->v.vector[0]);
                    370:        protect(handy);
                    371:        handy = Lapply();
                    372:     }
                    373: 
                    374:     xpopnames(oldbnp); /* pop names with consideration for closure markers */
                    375:     
                    376:     if(!funcallp) Restorestack();
                    377:     return(handy);
                    378: }
                    379: 
                    380: /* xpopnames :: pop values from bindstack, but look out for
                    381:  *  closure markers.  This is  used (instead of the faster popnames)
                    382:  * when we know there will be closure markers or when we can't
                    383:  * be sure that there won't be closure markers (eg. in non-local go's)
                    384:  */
                    385: xpopnames(llimit)
                    386: register struct nament *llimit;
                    387: {
                    388:     register struct nament *rnp, *lbnp;
                    389:     lispval atm_dtpr, value_dtpr;
                    390:     int foundc;
                    391: 
                    392:     for(rnp = bnp; --rnp >= llimit;)
                    393:     {
                    394:         if(rnp->atm == clos_marker)
                    395:        {
                    396:            atm_dtpr = rnp->val;
                    397:            value_dtpr = atm_dtpr->d.cdr;
                    398:            if(value_dtpr->d.cdr->i <= 1)
                    399:            {
                    400:                /* this is the only occurance of this closure variable
                    401:                 * just restore current value to this closure.
                    402:                 */
                    403:                value_dtpr->d.car = atm_dtpr->d.car->a.clb;
                    404:            }
                    405:            else {
                    406:                /* locate the last lambda before the next occurance of
                    407:                 * this closure and store the current symbol's value
                    408:                 * there
                    409:                 */
                    410:                lbnp = locatevar(atm_dtpr,&foundc,rnp-2);
                    411:                if(!foundc)
                    412:                {
                    413:                    /* strange, there wasn't a closure to be found.
                    414:                     * well, we will fix things up so the count is
                    415:                     * right.
                    416:                     */
                    417:                    value_dtpr->d.car = atm_dtpr->d.car->a.clb;
                    418:                    value_dtpr->d.cdr->i = 1;
                    419:                }
                    420:                else if (lbnp) {
                    421:                    /* note how the closures value isn't necessarily
                    422:                     * stored in the closure, it may be stored on
                    423:                     * the bindstack
                    424:                     */
                    425:                    lbnp->val = atm_dtpr->d.car->a.clb;
                    426:                }
                    427:                /* the case where lbnp is 0 should never happen, but
                    428:                   if it does, we can just do nothing safely
                    429:                 */
                    430:            }
                    431:            value_dtpr->d.cdr->i -= 1;
                    432:        } else rnp->atm->a.clb = rnp->val;  /* the normal case */
                    433:     }
                    434:     bnp = llimit;
                    435: }
                    436: 
                    437: 
                    438: struct nament *
                    439: locatevar(clos,foundc,rnp)
                    440: struct nament *rnp;
                    441: lispval clos;
                    442: int *foundc;
                    443: {
                    444:     register struct nament  *retbnp;
                    445:     lispval symb;
                    446: 
                    447:     retbnp = (struct nament *) 0;
                    448:     *foundc = 0;
                    449:     
                    450:     symb = clos->d.car;
                    451:     
                    452:     for(  ; rnp >= orgbnp ; rnp--)
                    453:     {
                    454:        if((rnp->atm == clos_marker) && (rnp->val == clos))
                    455:        {
                    456:            *foundc = 1;        /* found the closure */
                    457:            return(retbnp);
                    458:        }
                    459:        if(rnp->atm == symb) retbnp = rnp;
                    460:     }
                    461:     return(retbnp);    
                    462: }
                    463: 
                    464: lispval
                    465: LIfss()
                    466: {
                    467:        register lispval atm_dtpr, value_dtpr;
                    468:        struct nament *oldbnp = bnp, *lbnp;
                    469:        int tcase, foundc = 0;
                    470:        lispval newval;
                    471:        int argc = 1;
                    472:        Savestack(2);
                    473: 
                    474:        switch(np-lbot) {
                    475:        case 2:
                    476:                newval = np[-1].val;
                    477:                argc++;
                    478:        case 1:
                    479:                atm_dtpr = lbot->val;
                    480:                value_dtpr = atm_dtpr->d.cdr;
                    481:                break;
                    482:        default:
                    483:                argerr("int:fclosure-symbol-stuff");
                    484:        }
                    485:        /* this code is copied from Ifclosure */
                    486: 
                    487:        if(value_dtpr->d.cdr->i==0)
                    488:                tcase = Case_A; /* closure is not active */
                    489:        else {
                    490:                lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
                    491:                if (!foundc)
                    492:                {
                    493:                        /* didn't find closure, count must be wrong,
                    494:                           correct it and assume case (a).*/
                    495:                        tcase = Case_A;
                    496:                        value_dtpr->d.cdr->i = 0;
                    497:                }
                    498:                else if(lbnp) tcase = Case_C; /* found intermediate lambda*/
                    499:                else tcase = Case_B;
                    500:        }
                    501: 
                    502:        switch(tcase) {
                    503:        case Case_B:
                    504:                if(argc==2) return(atm_dtpr->d.car->a.clb = newval);
                    505:                return(atm_dtpr->d.car->a.clb);
                    506: 
                    507:        case Case_A:
                    508:                if(argc==2) return(value_dtpr->d.car = newval);
                    509:                return(value_dtpr->d.car);
                    510: 
                    511:        case Case_C:
                    512:                if(argc==2) return(lbnp->val = newval);
                    513:                return(lbnp->val);
                    514:        }
                    515:        /*NOTREACHED*/
                    516: }

unix.superglobalmegacorp.com

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