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

unix.superglobalmegacorp.com

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