Annotation of 43BSD/ucb/lisp/franz/eval2.c, revision 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.