Annotation of 43BSD/contrib/icon/tran/code.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Routines for constructing and traversing parse trees and generating code.
        !             3:  */
        !             4: 
        !             5: #include "itran.h"
        !             6: #include "token.h"
        !             7: #include "tree.h"
        !             8: #include "code.h"
        !             9: #include "sym.h"
        !            10: 
        !            11: static int nextlab;            /* next label allocated by alclab() */
        !            12: 
        !            13: /*
        !            14:  *  tree[1-7] construct parse tree nodes with specified values.  tfree
        !            15:  *   points at the next free word in the parse tree space.  Nodes are
        !            16:  *   built by copying argument values into successive locations starting
        !            17:  *   at tfree.  Parameters a and b are line and column information,
        !            18:  *   while parameters c through f are values to be assigned to n_field[0-3].
        !            19:  *   Note that this could be done with a single routine; a separate routine
        !            20:  *   for each node size is used for speed and simplicity.
        !            21:  */
        !            22: 
        !            23: nodeptr tree1(type)
        !            24: int type;
        !            25:    {
        !            26:    register nodeptr t;
        !            27: 
        !            28:    t = tfree;
        !            29:    tfree = (nodeptr) ((int *)tfree + 1);
        !            30:    if (tfree > tend)
        !            31:       syserr("out of tree space");
        !            32:    t->n_type = type;
        !            33:    return (t);
        !            34:    }
        !            35: 
        !            36: nodeptr tree3(type, a, b)
        !            37: int type, a, b;
        !            38:    {
        !            39:    register nodeptr t;
        !            40: 
        !            41:    t = tfree;
        !            42:    tfree = (nodeptr) ((int *)tfree + 3);
        !            43:    if (tfree > tend)
        !            44:       syserr("out of tree space");
        !            45:    t->n_type = type;
        !            46:    t->n_line = a;
        !            47:    t->n_col = b;
        !            48:    return (t);
        !            49:    }
        !            50: 
        !            51: nodeptr tree4(type, a, b, c)
        !            52: int type, a, b, c;
        !            53:    {
        !            54:    register nodeptr t;
        !            55: 
        !            56:    t = tfree;
        !            57:    tfree = (nodeptr) ((int *)tfree + 4);
        !            58:    if (tfree > tend)
        !            59:       syserr("out of tree space");
        !            60:    t->n_type = type;
        !            61:    t->n_line = a;
        !            62:    t->n_col = b;
        !            63:    t->n_field[0].n_val = c;
        !            64:    return (t);
        !            65:    }
        !            66: 
        !            67: nodeptr tree5(type, a, b, c, d)
        !            68: int type, a, b, c, d;
        !            69:    {
        !            70:    register nodeptr t;
        !            71: 
        !            72:    t = tfree;
        !            73:    tfree = (nodeptr) ((int *)tfree + 5);
        !            74:    if (tfree > tend)
        !            75:       syserr("out of tree space");
        !            76:    t->n_type = type;
        !            77:    t->n_line = a;
        !            78:    t->n_col = b;
        !            79:    t->n_field[0].n_val = c;
        !            80:    t->n_field[1].n_val = d;
        !            81:    return (t);
        !            82:    }
        !            83: 
        !            84: nodeptr tree6(type, a, b, c, d, e)
        !            85: int type, a, b, c, d, e;
        !            86:    {
        !            87:    register nodeptr t;
        !            88: 
        !            89:    t = tfree;
        !            90:    tfree = (nodeptr) ((int *)tfree + 6);
        !            91:    if (tfree > tend)
        !            92:       syserr("out of tree space");
        !            93:    t->n_type = type;
        !            94:    t->n_line = a;
        !            95:    t->n_col = b;
        !            96:    t->n_field[0].n_val = c;
        !            97:    t->n_field[1].n_val = d;
        !            98:    t->n_field[2].n_val = e;
        !            99:    return (t);
        !           100:    }
        !           101: 
        !           102: nodeptr tree7(type, a, b, c, d, e, f)
        !           103: int type, a, b, c, d, e, f;
        !           104:    {
        !           105:    register nodeptr t;
        !           106: 
        !           107:    t = tfree;
        !           108:    tfree = (nodeptr) ((int *)tfree + 7);
        !           109:    if (tfree > tend)
        !           110:       syserr("out of tree space");
        !           111:    t->n_type = type;
        !           112:    t->n_line = a;
        !           113:    t->n_col = b;
        !           114:    t->n_field[0].n_val = c;
        !           115:    t->n_field[1].n_val = d;
        !           116:    t->n_field[2].n_val = e;
        !           117:    t->n_field[3].n_val = f;
        !           118:    return (t);
        !           119:    }
        !           120: 
        !           121: /*
        !           122:  * Clear the tree space by setting the free pointer back to the first word
        !           123:  *  of the tree space.
        !           124:  */
        !           125: 
        !           126: treeinit()
        !           127:    {
        !           128:    tfree = tree;
        !           129:    }
        !           130: 
        !           131: /*
        !           132:  * codegen - traverse tree t, generating code.
        !           133:  */
        !           134: 
        !           135: codegen(t)
        !           136: nodeptr t;
        !           137:    {
        !           138:    nextlab = 1;
        !           139:    traverse(t);
        !           140:    }
        !           141: 
        !           142: /*
        !           143:  * traverse - traverse tree rooted at t and generate code.  This is just
        !           144:  *  plug and chug code for each of the node types.  The tour goes into
        !           145:  *  some detail about the code generation process, in particular, Appendix
        !           146:  *  A describes the parse tree nodes.
        !           147:  */
        !           148: 
        !           149: traverse(t)
        !           150: register nodeptr t;
        !           151:    {
        !           152:    register int lab, n;
        !           153:    struct loopstk loopsave;
        !           154:    static struct loopstk loopstk[LOOPDEPTH];   /* loop stack */
        !           155:    static struct loopstk *loopsp;
        !           156:    static struct casestk casestk[CASEDEPTH];   /* case stack */
        !           157:    static struct casestk *casesp;
        !           158:    static struct creatstk creatstk[CREATDEPTH];        /* create stack */
        !           159:    static struct creatstk *creatsp;
        !           160: 
        !           161:    n = 1;
        !           162:    switch (TYPE(t)) {
        !           163: 
        !           164:       case N_ACTIVAT:                  /* co-expression activation */
        !           165:          if (VAL0(TREE0(t)) == AUGACT)
        !           166:             emit("pnull");
        !           167:          traverse(TREE2(t));           /* evaluate result expression */
        !           168:          if (VAL0(TREE0(t)) == AUGACT)
        !           169:             emit("sdup");
        !           170:          traverse(TREE1(t));           /* evaluate activate expression */
        !           171:          setline(LINE(t));
        !           172:          emit("coact");
        !           173:          if (VAL0(TREE0(t)) == AUGACT)
        !           174:             emit("asgn");
        !           175:          break;
        !           176: 
        !           177:       case N_ALT:                      /* alternation */
        !           178:          lab = alclab(2);
        !           179:          emitl("mark", lab);
        !           180:          loopsp->markcount++;
        !           181:          traverse(TREE0(t));           /* evaluate first alternative */
        !           182:          loopsp->markcount--;
        !           183:          emit("esusp");                        /*  and suspend with its result */
        !           184:          emitl("goto", lab+1);
        !           185:          emitlab(lab);
        !           186:          traverse(TREE1(t));           /* evaluate second alternative */
        !           187:          emitlab(lab+1);
        !           188:          break;
        !           189: 
        !           190:       case N_AUGOP:                    /* augmented assignment */
        !           191:       case N_BINOP:                    /*  or a binary operator */
        !           192:          emit("pnull");
        !           193:          traverse(TREE1(t));
        !           194:          if (TYPE(t) == N_AUGOP)
        !           195:             emit("dup");
        !           196:          traverse(TREE2(t));
        !           197:          setline(LINE(t));
        !           198:          binop(VAL0(TREE0(t)));
        !           199:          break;
        !           200: 
        !           201:       case N_BAR:                      /* repeated alternation */
        !           202:          lab = alclab(1);
        !           203:          emitlab(lab);
        !           204:          emitl("mark", 0);             /* fail if expr fails first time */
        !           205:          loopsp->markcount++;
        !           206:          traverse(TREE0(t));           /* evaluate first alternative */
        !           207:          loopsp->markcount--;
        !           208:          emitl("chfail", lab);         /* change to loop on failure */
        !           209:          emit("esusp");                        /* suspend result */
        !           210:          break;
        !           211: 
        !           212:       case N_BREAK:                    /* break expression */
        !           213:          if (loopsp->breaklab <= 0)
        !           214:             lerr(LINE(t), "invalid context for break");
        !           215:          else {
        !           216:             emitn("unmark", loopsp->markcount);
        !           217:             loopsave = *loopsp--;
        !           218:             traverse(TREE0(t));
        !           219:             *++loopsp = loopsave;
        !           220:             emitl("goto", loopsp->breaklab);
        !           221:             }
        !           222:          break;
        !           223: 
        !           224:       case N_CASE:                     /* case expression */
        !           225:          lab = alclab(1);
        !           226:          casesp++;
        !           227:          casesp->endlab = lab;
        !           228:          casesp->deftree = NULL;
        !           229:          emitl("mark", 0);
        !           230:          loopsp->markcount++;
        !           231:          traverse(TREE0(t));           /* evaluate control expression */
        !           232:          loopsp->markcount--;
        !           233:          emit("eret");
        !           234:          traverse(TREE1(t));           /* do rest of case (CLIST) */
        !           235:          if (casesp->deftree != NULL) {        /* evaluate default clause */
        !           236:             emit("pop");
        !           237:             traverse(casesp->deftree);
        !           238:             }
        !           239:          else
        !           240:             emit("efail");
        !           241:          emitlab(lab);                 /* end label */
        !           242:          casesp--;
        !           243:          break;
        !           244: 
        !           245:       case N_CCLS:                     /* case expression clause */
        !           246:          if (TYPE(TREE0(t)) == N_RES &&        /* default clause */
        !           247:              VAL0(TREE0(t)) == DEFAULT) {
        !           248:             if (casesp->deftree != NULL)
        !           249:                lerr(LINE(t), "more than one default clause");
        !           250:             else
        !           251:                casesp->deftree = TREE1(t);
        !           252:             }
        !           253:          else {                                /* case clause */
        !           254:             lab = alclab(1);
        !           255:             emitl("mark", lab);
        !           256:             loopsp->markcount++;
        !           257:             emit("ccase");
        !           258:             traverse(TREE0(t));                /* evaluate selector */
        !           259:             setline(LINE(t));
        !           260:             emit("eqv");
        !           261:             loopsp->markcount--;
        !           262:             emitn("unmark", 1);
        !           263:             emit("pop");
        !           264:             traverse(TREE1(t));                /* evaluate expression */
        !           265:             emitl("goto", casesp->endlab); /* goto end label */
        !           266:             emitlab(lab);              /* label for next clause */
        !           267:             }
        !           268:          break;
        !           269: 
        !           270:       case N_CLIST:                    /* list of case clauses */
        !           271:          traverse(TREE0(t));
        !           272:          traverse(TREE1(t));
        !           273:          break;
        !           274: 
        !           275:       case N_CONJ:                     /* conjunction */
        !           276:          if (VAL0(TREE0(t)) == AUGAND)
        !           277:             emit("pnull");
        !           278:          traverse(TREE1(t));
        !           279:          if (VAL0(TREE0(t)) != AUGAND)
        !           280:             emit("pop");
        !           281:          traverse(TREE2(t));
        !           282:          if (VAL0(TREE0(t)) == AUGAND)
        !           283:             emit("asgn");
        !           284:          break;
        !           285: 
        !           286:       case N_CREATE:                   /* create expression */
        !           287:          creatsp++;
        !           288:          creatsp->nextlab = loopsp->nextlab;
        !           289:          creatsp->breaklab = loopsp->breaklab;
        !           290:          loopsp->nextlab = 0;          /* make break and next illegal */
        !           291:          loopsp->breaklab = 0;
        !           292:          lab = alclab(3);
        !           293:          emitl("goto", lab+2);         /* skip over code for coexpression */
        !           294:          emitlab(lab);                 /* entry point */
        !           295:          emit("pop");                  /* pop the result from activation */
        !           296:          emitl("mark", lab+1);
        !           297:          loopsp->markcount++;
        !           298:          traverse(TREE0(t));           /* traverse code for coexpression */
        !           299:          loopsp->markcount--;
        !           300:          emit("incres");               /* increment number of results */
        !           301:          setline(LINE(t));
        !           302:          emit("coret");                        /* return to activator */
        !           303:          emit("efail");                        /* drive coexpression */
        !           304:          emitlab(lab+1);               /* loop on exhaustion */
        !           305:          setline(0);
        !           306:          setline(LINE(t));
        !           307:          emit("cofail");               /* and fail each time */
        !           308:          emitl("goto", lab+1);
        !           309:          emitlab(lab+2);
        !           310:          setline(0);
        !           311:          setline(LINE(t));
        !           312:          emitl("create", lab);         /* create entry block */
        !           313:          loopsp->nextlab = creatsp->nextlab;   /* legalize break and next */
        !           314:          loopsp->breaklab = creatsp->breaklab;
        !           315:          creatsp--;
        !           316:          break;
        !           317: 
        !           318:       case N_CSET:                     /* cset literal */
        !           319:          emitn("cset", VAL0(t));
        !           320:          break;
        !           321: 
        !           322:       case N_ELIST:                    /* expression list */
        !           323:          n = traverse(TREE0(t));
        !           324:          n += traverse(TREE1(t));
        !           325:          break;
        !           326: 
        !           327:       case N_EMPTY:                    /* a missing expression */
        !           328:          emit("pnull");
        !           329:          break;
        !           330: 
        !           331:       case N_FIELD:                    /* field reference */
        !           332:          emit("pnull");
        !           333:          traverse(TREE0(t));
        !           334:          setline(LINE(t));
        !           335:          emits("field", STR0(TREE1(t)));
        !           336:          break;
        !           337: 
        !           338:       case N_ID:                       /* identifier */
        !           339:          emitn("var", VAL0(t));
        !           340:          break;
        !           341: 
        !           342:       case N_IF:                       /* if expression */
        !           343:          if (TYPE(TREE2(t)) == N_EMPTY)
        !           344:             lab = 0;
        !           345:          else
        !           346:             lab = alclab(2);
        !           347:          emitl("mark", lab);
        !           348:          loopsp->markcount++;
        !           349:          traverse(TREE0(t));
        !           350:          loopsp->markcount--;
        !           351:          emitn("unmark", 1);
        !           352:          traverse(TREE1(t));
        !           353:          if (lab > 0) {
        !           354:             emitl("goto", lab+1);
        !           355:             emitlab(lab);
        !           356:             traverse(TREE2(t));
        !           357:             emitlab(lab+1);
        !           358:             }
        !           359:          break;
        !           360: 
        !           361:       case N_INT:                      /* integer literal */
        !           362:          emitn("int", VAL0(t));
        !           363:          break;
        !           364: 
        !           365:       case N_INVOK:                    /* procedure call, possibly MGDE */
        !           366:          if (TYPE(TREE0(t)) != N_EMPTY)
        !           367:             traverse(TREE0(t));
        !           368:          else
        !           369:             emit("pushn1");            /* assume -1(e1,...,en) */
        !           370:          n = traverse(TREE1(t));
        !           371:          setline(LINE(t));
        !           372:          emitn("invoke", n);
        !           373:          n = 1;
        !           374:          break;
        !           375: 
        !           376:       case N_KEY:                      /* keyword reference */
        !           377:          setline(LINE(t));
        !           378:          emitn("keywd", VAL0(t));
        !           379:          break;
        !           380: 
        !           381:       case N_LIMIT:                    /* limitation */
        !           382:          traverse(TREE1(t));
        !           383:          setline(LINE(t));
        !           384:          emit("limit");
        !           385:          emitl("mark", 0);
        !           386:          loopsp->markcount++;
        !           387:          traverse(TREE0(t));
        !           388:          loopsp->markcount--;
        !           389:          emit("lsusp");
        !           390:          break;
        !           391: 
        !           392:       case N_LIST:                     /* list construction */
        !           393:          emit("pnull");
        !           394:          if (TYPE(TREE0(t)) == N_EMPTY)
        !           395:             n = 0;
        !           396:          else
        !           397:             n = traverse(TREE0(t));
        !           398:          setline(LINE(t));
        !           399:          emitn("llist", n);
        !           400:          n = 1;
        !           401:          break;
        !           402: 
        !           403:       case N_LOOP:                     /* loop */
        !           404:          switch (VAL0(TREE0(t))) {
        !           405:             case EVERY:
        !           406:                lab = alclab(2);
        !           407:                loopsp++;
        !           408:                loopsp->ltype = EVERY;
        !           409:                loopsp->nextlab = lab;
        !           410:                loopsp->breaklab = lab + 1;
        !           411:                loopsp->markcount = 1;
        !           412:                emitl("mark", 0);
        !           413:                traverse(TREE1(t));
        !           414:                emit("pop");
        !           415:                if (TYPE(TREE2(t)) != N_EMPTY) {   /* every e1 do e2 */
        !           416:                   emitl("mark", 0);
        !           417:                   loopsp->ltype = N_LOOP;
        !           418:                   loopsp->markcount++;
        !           419:                   traverse(TREE2(t));
        !           420:                   loopsp->markcount--;
        !           421:                   emitn("unmark", 1);
        !           422:                   }
        !           423:                emitlab(loopsp->nextlab);
        !           424:                emit("efail");
        !           425:                emitlab(loopsp->breaklab);
        !           426:                loopsp--;
        !           427:                break;
        !           428: 
        !           429:             case REPEAT:
        !           430:                lab = alclab(3);
        !           431:                loopsp++;
        !           432:                loopsp->ltype = N_LOOP;
        !           433:                loopsp->nextlab = lab + 1;
        !           434:                loopsp->breaklab = lab + 2;
        !           435:                loopsp->markcount = 1;
        !           436:                emitlab(lab);
        !           437:                setline(0);
        !           438:                setline(LINE(t));
        !           439:                emitl("mark", lab);
        !           440:                traverse(TREE1(t));
        !           441:                emitlab(loopsp->nextlab);
        !           442:                emitn("unmark", 1);
        !           443:                emitl("goto", lab);
        !           444:                emitlab(loopsp->breaklab);
        !           445:                loopsp--;
        !           446:                break;
        !           447: 
        !           448:             case WHILE:
        !           449:                lab = alclab(3);
        !           450:                loopsp++;
        !           451:                loopsp->ltype = N_LOOP;
        !           452:                loopsp->nextlab = lab + 1;
        !           453:                loopsp->breaklab = lab + 2;
        !           454:                loopsp->markcount = 1;
        !           455:                emitlab(lab);
        !           456:                setline(0);
        !           457:                setline(LINE(t));
        !           458:                emitl("mark", 0);
        !           459:                traverse(TREE1(t));
        !           460:                if (TYPE(TREE2(t)) != N_EMPTY) {
        !           461:                   emitn("unmark", 1);
        !           462:                   emitl("mark", lab);
        !           463:                   traverse(TREE2(t));
        !           464:                   }
        !           465:                emitlab(loopsp->nextlab);
        !           466:                emitn("unmark", 1);
        !           467:                emitl("goto", lab);
        !           468:                emitlab(loopsp->breaklab);
        !           469:                loopsp--;
        !           470:                break;
        !           471: 
        !           472:             case UNTIL:
        !           473:                lab = alclab(4);
        !           474:                loopsp++;
        !           475:                loopsp->ltype = N_LOOP;
        !           476:                loopsp->nextlab = lab + 2;
        !           477:                loopsp->breaklab = lab + 3;
        !           478:                loopsp->markcount = 1;
        !           479:                emitlab(lab);
        !           480:                setline(0);
        !           481:                setline(LINE(t));
        !           482:                emitl("mark", lab+1);
        !           483:                traverse(TREE1(t));
        !           484:                emitn("unmark", 1);
        !           485:                emit("efail");
        !           486:                emitlab(lab+1);
        !           487:                emitl("mark", lab);
        !           488:                traverse(TREE2(t));
        !           489:                emitlab(loopsp->nextlab);
        !           490:                emitn("unmark", 1);
        !           491:                emitl("goto", lab);
        !           492:                emitlab(loopsp->breaklab);
        !           493:                loopsp--;
        !           494:                break;
        !           495:             }
        !           496:          break;
        !           497: 
        !           498:       case N_NEXT:                     /* next expression */
        !           499:          if (loopsp < loopstk || loopsp->nextlab <= 0)
        !           500:             lerr(LINE(t), "invalid context for next");
        !           501:          else {
        !           502:             if (loopsp->ltype != EVERY && loopsp->markcount > 1)
        !           503:                emitn("unmark", loopsp->markcount - 1);
        !           504:             emitl("goto", loopsp->nextlab);
        !           505:             }
        !           506:          break;
        !           507: 
        !           508:       case N_NOT:                      /* not expression */
        !           509:          lab = alclab(1);
        !           510:          emitl("mark", lab);
        !           511:          loopsp->markcount++;
        !           512:          traverse(TREE0(t));
        !           513:          loopsp->markcount--;
        !           514:          emitn("unmark", 1);
        !           515:          emit("efail");
        !           516:          emitlab(lab);
        !           517:          emit("pnull");
        !           518:          break;
        !           519: 
        !           520:       case N_PROC:                     /* procedure */
        !           521:          loopsp = loopstk;
        !           522:          loopsp->nextlab = 0;
        !           523:          loopsp->breaklab = 0;
        !           524:          loopsp->markcount = 0;
        !           525:          casesp = casestk;
        !           526:          creatsp = creatstk;
        !           527:          fprintf(codefile, "proc %s\n", STR0(TREE0(t)));
        !           528:          lout(codefile);
        !           529:          cout(codefile);
        !           530:          emit("declend");
        !           531:          emits("file", *filep);
        !           532:          setline(0);
        !           533:          setline(LINE(t));
        !           534:          if (TYPE(TREE1(t)) != N_EMPTY) {
        !           535:             lab = alclab(1);
        !           536:             emitl("init?", lab);
        !           537:             emitl("mark", lab);
        !           538:             traverse(TREE1(t));
        !           539:             emitn("unmark", 1);
        !           540:             emitlab(lab);
        !           541:             }
        !           542:          if (TYPE(TREE2(t)) != N_EMPTY)
        !           543:             traverse(TREE2(t));
        !           544:          setline(LINE(TREE3(t)));
        !           545:          emit("pfail");
        !           546:          emit("end");
        !           547:          if (!silence)
        !           548:             fprintf(stderr, "  %s (%d/%d)\n", STR0(TREE0(t)),
        !           549:                 (int *)tfree - (int *)tree, tsize);
        !           550:          break;
        !           551: 
        !           552:       case N_REAL:                     /* real literal */
        !           553:          emitn("real", VAL0(t));
        !           554:          break;
        !           555: 
        !           556:       case N_RET:                      /* return expression */
        !           557:          if (creatsp > creatstk)
        !           558:             lerr(LINE(t), "invalid context for return or fail");
        !           559:          if (VAL0(TREE0(t)) != FAIL) {
        !           560:             lab = alclab(1);
        !           561:             emitl("mark", lab);
        !           562:             loopsp->markcount++;
        !           563:             traverse(TREE1(t));
        !           564:             loopsp->markcount--;
        !           565:             setline(LINE(t));
        !           566:             emit("pret");
        !           567:             emitlab(lab);
        !           568:             }
        !           569:          setline(0);
        !           570:          setline(LINE(t));
        !           571:          emit("pfail");
        !           572:          break;
        !           573: 
        !           574:       case N_SCAN:                     /* scanning expression */
        !           575:          if (VAL0(TREE0(t)) == SCANASGN)
        !           576:             emit("pnull");
        !           577:          traverse(TREE1(t));
        !           578:          if (VAL0(TREE0(t)) == SCANASGN)
        !           579:             emit("sdup");
        !           580:          setline(LINE(t));
        !           581:          emit("bscan");
        !           582:          traverse(TREE2(t));
        !           583:          setline(LINE(t));
        !           584:          emit("escan");
        !           585:          if (VAL0(TREE0(t)) == SCANASGN)
        !           586:             emit("asgn");
        !           587:          break;
        !           588: 
        !           589:       case N_SECT:                     /* section operation */
        !           590:          emit("pnull");
        !           591:          traverse(TREE1(t));
        !           592:          traverse(TREE2(t));
        !           593:          if (VAL0(TREE0(t)) == PCOLON || VAL0(TREE0(t)) == MCOLON)
        !           594:             emit("dup");
        !           595:          traverse(TREE3(t));
        !           596:          setline(LINE(TREE0(t)));
        !           597:          if (VAL0(TREE0(t)) == PCOLON)
        !           598:             emit("plus");
        !           599:          else if (VAL0(TREE0(t)) == MCOLON)
        !           600:             emit("minus");
        !           601:          setline(LINE(t));
        !           602:          emit("sect");
        !           603:          break;
        !           604: 
        !           605:       case N_SLIST:                    /* semicolon separated list of expressions */
        !           606:          lab = alclab(1);
        !           607:          emitl("mark", lab);
        !           608:          loopsp->markcount++;
        !           609:          traverse(TREE0(t));
        !           610:          loopsp->markcount--;
        !           611:          emitn("unmark", 1);
        !           612:          emitlab(lab);
        !           613:          traverse(TREE1(t));
        !           614:          break;
        !           615: 
        !           616:       case N_STR:                      /* string literal */
        !           617:          emitn("str", VAL0(t));
        !           618:          break;
        !           619: 
        !           620:       case N_SUSP:                     /* suspension expression */
        !           621:          if (creatsp > creatstk)
        !           622:             lerr(LINE(t), "invalid context for suspend");
        !           623:          emitl("mark", 0);
        !           624:          loopsp->markcount++;
        !           625:          traverse(TREE0(t));
        !           626:          loopsp->markcount--;
        !           627:          setline(LINE(t));
        !           628:          emit("psusp");
        !           629:          emit("efail");
        !           630:          break;
        !           631: 
        !           632:       case N_TO:                       /* to expression */
        !           633:          emit("pnull");
        !           634:          traverse(TREE0(t));
        !           635:          traverse(TREE1(t));
        !           636:          emit("push1");
        !           637:          setline(LINE(t));
        !           638:          emit("toby");
        !           639:          break;
        !           640: 
        !           641:       case N_TOBY:                     /* to-by expression */
        !           642:          emit("pnull");
        !           643:          traverse(TREE0(t));
        !           644:          traverse(TREE1(t));
        !           645:          traverse(TREE2(t));
        !           646:          setline(LINE(t));
        !           647:          emit("toby");
        !           648:          break;
        !           649: 
        !           650:       case N_UNOP:                     /* unary operator */
        !           651:          unopa(VAL0(TREE0(t)));
        !           652:          traverse(TREE1(t));
        !           653:          setline(LINE(t));
        !           654:          unopb(VAL0(TREE0(t)));
        !           655:          break;
        !           656: 
        !           657:       default:
        !           658:          emitn("?????", TYPE(t));
        !           659:          syserr("traverse: undefined node type");
        !           660:       }
        !           661:    return (n);
        !           662:    }
        !           663: /*
        !           664:  * binop emits code for binary operators.  For non-augmented operators,
        !           665:  *  the name of operator is emitted.  For augmented operators, an "asgn"
        !           666:  *  is emitted after the name of the operator.
        !           667:  */
        !           668: binop(op)
        !           669: int op;
        !           670:    {
        !           671:    register int asgn;
        !           672:    register char *name;
        !           673: 
        !           674:    asgn = 0;
        !           675:    switch (op) {
        !           676: 
        !           677:       case ASSIGN:
        !           678:          name = "asgn";
        !           679:          break;
        !           680: 
        !           681:       case CARETASGN:
        !           682:          asgn++;
        !           683:       case CARET:
        !           684:          name = "power";
        !           685:          break;
        !           686: 
        !           687:       case CONCATASGN:
        !           688:          asgn++;
        !           689:       case CONCAT:
        !           690:          name = "cat";
        !           691:          break;
        !           692: 
        !           693:       case DIFFASGN:
        !           694:          asgn++;
        !           695:       case DIFF:
        !           696:          name = "diff";
        !           697:          break;
        !           698: 
        !           699:       case AUGEQV:
        !           700:          asgn++;
        !           701:       case EQUIV:
        !           702:          name = "eqv";
        !           703:          break;
        !           704: 
        !           705:       case INTERASGN:
        !           706:          asgn++;
        !           707:       case INTER:
        !           708:          name = "inter";
        !           709:          break;
        !           710: 
        !           711:       case LBRACK:
        !           712:          name = "subsc";
        !           713:          break;
        !           714: 
        !           715:       case LCONCATASGN:
        !           716:          asgn++;
        !           717:       case LCONCAT:
        !           718:          name = "lconcat";
        !           719:          break;
        !           720: 
        !           721:       case AUGSEQ:
        !           722:          asgn++;
        !           723:       case LEXEQ:
        !           724:          name = "lexeq";
        !           725:          break;
        !           726: 
        !           727:       case AUGSGE:
        !           728:          asgn++;
        !           729:       case LEXGE:
        !           730:          name = "lexge";
        !           731:          break;
        !           732: 
        !           733:       case AUGSGT:
        !           734:          asgn++;
        !           735:       case LEXGT:
        !           736:          name = "lexgt";
        !           737:          break;
        !           738: 
        !           739:       case AUGSLE:
        !           740:          asgn++;
        !           741:       case LEXLE:
        !           742:          name = "lexle";
        !           743:          break;
        !           744: 
        !           745:       case AUGSLT:
        !           746:          asgn++;
        !           747:       case LEXLT:
        !           748:          name = "lexlt";
        !           749:          break;
        !           750: 
        !           751:       case AUGSNE:
        !           752:          asgn++;
        !           753:       case LEXNE:
        !           754:          name = "lexne";
        !           755:          break;
        !           756: 
        !           757:       case MINUSASGN:
        !           758:          asgn++;
        !           759:       case MINUS:
        !           760:          name = "minus";
        !           761:          break;
        !           762: 
        !           763:       case MODASGN:
        !           764:          asgn++;
        !           765:       case MOD:
        !           766:          name = "mod";
        !           767:          break;
        !           768: 
        !           769:       case AUGNEQV:
        !           770:          asgn++;
        !           771:       case NOTEQUIV:
        !           772:          name = "neqv";
        !           773:          break;
        !           774: 
        !           775:       case AUGEQ:
        !           776:          asgn++;
        !           777:       case NUMEQ:
        !           778:          name = "numeq";
        !           779:          break;
        !           780: 
        !           781:       case AUGGE:
        !           782:          asgn++;
        !           783:       case NUMGE:
        !           784:          name = "numge";
        !           785:          break;
        !           786: 
        !           787:       case AUGGT:
        !           788:          asgn++;
        !           789:       case NUMGT:
        !           790:          name = "numgt";
        !           791:          break;
        !           792: 
        !           793:       case AUGLE:
        !           794:          asgn++;
        !           795:       case NUMLE:
        !           796:          name = "numle";
        !           797:          break;
        !           798: 
        !           799:       case AUGLT:
        !           800:          asgn++;
        !           801:       case NUMLT:
        !           802:          name = "numlt";
        !           803:          break;
        !           804: 
        !           805:       case AUGNE:
        !           806:          asgn++;
        !           807:       case NUMNE:
        !           808:          name = "numne";
        !           809:          break;
        !           810: 
        !           811:       case PLUSASGN:
        !           812:          asgn++;
        !           813:       case PLUS:
        !           814:          name = "plus";
        !           815:          break;
        !           816: 
        !           817:       case REVASSIGN:
        !           818:          name = "rasgn";
        !           819:          break;
        !           820: 
        !           821:       case REVSWAP:
        !           822:          name = "rswap";
        !           823:          break;
        !           824: 
        !           825:       case SLASHASGN:
        !           826:          asgn++;
        !           827:       case SLASH:
        !           828:          name = "div";
        !           829:          break;
        !           830: 
        !           831:       case STARASGN:
        !           832:          asgn++;
        !           833:       case STAR:
        !           834:          name = "mult";
        !           835:          break;
        !           836: 
        !           837:       case SWAP:
        !           838:          name = "swap";
        !           839:          break;
        !           840: 
        !           841:       case UNIONASGN:
        !           842:          asgn++;
        !           843:       case UNION:
        !           844:          name = "unioncs";
        !           845:          break;
        !           846: 
        !           847:       default:
        !           848:          emitn("?binop", op);
        !           849:          syserr("binop: undefined binary operator");
        !           850:       }
        !           851:    emit(name);
        !           852:    if (asgn)
        !           853:       emit("asgn");
        !           854:    return;
        !           855:    }
        !           856: /*
        !           857:  * unopa and unopb handle code emission for unary operators. unary operator
        !           858:  *  sequences that are the same as binary operator sequences are recognized
        !           859:  *  by the lexical analyzer as binary operators.  For example, ~===x means to
        !           860:  *  do three tab(match(...)) operations and then a cset complement, but the
        !           861:  *  lexical analyzer sees the operator sequence as the "neqv" binary
        !           862:  *  operation.  unopa and unopb unravel tokens of this form.
        !           863:  *
        !           864:  * When a N_UNOP node is encountered, unopa is called to emit the necessary
        !           865:  *  number of "pnull" operations to receive the intermediate results.  This
        !           866:  *  amounts to a pnull for each operation.
        !           867:  */
        !           868: unopa(op)
        !           869: int op;
        !           870:    {
        !           871:    switch (op) {
        !           872:       case NOTEQUIV:           /* unary ~ and three = operators */
        !           873:          emit("pnull");
        !           874:       case LEXNE:              /* unary ~ and two = operators */
        !           875:       case EQUIV:              /* three unary = operators */
        !           876:          emit("pnull");
        !           877:       case NUMNE:              /* unary ~ and = operators */
        !           878:       case UNION:              /* two unary + operators */
        !           879:       case DIFF:               /* two unary - operators */
        !           880:       case LEXEQ:              /* two unary = operators */
        !           881:       case INTER:              /* two unary * operators */
        !           882:          emit("pnull");
        !           883:       case DOT:                        /* unary . operator */
        !           884:       case BACKSLASH:          /* unary \ operator */
        !           885:       case BANG:               /* unary ! operator */
        !           886:       case CARET:              /* unary ^ operator */
        !           887:       case PLUS:               /* unary + operator */
        !           888:       case TILDE:              /* unary ~ operator */
        !           889:       case MINUS:              /* unary - operator */
        !           890:       case NUMEQ:              /* unary = operator */
        !           891:       case STAR:               /* unary * operator */
        !           892:       case QMARK:              /* unary ? operator */
        !           893:       case SLASH:              /* unary / operator */
        !           894:          emit("pnull");
        !           895:          break;
        !           896:       default:
        !           897:          syserr("unopa: undefined unary operator");
        !           898:       }
        !           899:    return;
        !           900:    }
        !           901: /*
        !           902:  * unopb is the back-end code emitter for unary operators.  It emits
        !           903:  *  the operations represented by the token op.  For tokens representing
        !           904:  *  a single operator, the name of the operator is emitted.  For tokens
        !           905:  *  representing a sequence of operators, recursive calls are used.  In
        !           906:  *  such a case, the operator sequence is "scanned" from right to left
        !           907:  *  and unopb is called with the token for the appropriate operation.
        !           908:  *
        !           909:  * For example, consider the sequence of calls and code emission for "~===":
        !           910:  *     unopb(NOTEQUIV)         ~===
        !           911:  *         unopb(NUMEQ)        =
        !           912:  *             emits "tabmat"
        !           913:  *         unopb(NUMEQ)        =
        !           914:  *             emits "tabmat"
        !           915:  *         unopb(NUMEQ)        =
        !           916:  *             emits "tabmat"
        !           917:  *         emits "compl"
        !           918:  */
        !           919: unopb(op)
        !           920: int op;
        !           921:    {
        !           922:    register char *name;
        !           923: 
        !           924:    switch (op) {
        !           925: 
        !           926:       case DOT:                        /* unary . operator */
        !           927:          name = "value";
        !           928:          break;
        !           929: 
        !           930:       case BACKSLASH:          /* unary \ operator */
        !           931:          name = "nonnull";
        !           932:          break;
        !           933: 
        !           934:       case BANG:               /* unary ! operator */
        !           935:          name = "bang";
        !           936:          break;
        !           937: 
        !           938:       case CARET:              /* unary ^ operator */
        !           939:          name = "refresh";
        !           940:          break;
        !           941: 
        !           942:       case UNION:              /* two unary + operators */
        !           943:          unopb(PLUS);
        !           944:       case PLUS:               /* unary + operator */
        !           945:          name = "number";
        !           946:          break;
        !           947: 
        !           948:       case NOTEQUIV:           /* unary ~ and three = operators */
        !           949:          unopb(NUMEQ);
        !           950:       case LEXNE:              /* unary ~ and two = operators */
        !           951:          unopb(NUMEQ);
        !           952:       case NUMNE:              /* unary ~ and = operators */
        !           953:          unopb(NUMEQ);
        !           954:       case TILDE:              /* unary ~ operator (cset compl) */
        !           955:          name = "compl";
        !           956:          break;
        !           957: 
        !           958:       case DIFF:               /* two unary - operators */
        !           959:          unopb(MINUS);
        !           960:       case MINUS:              /* unary - operator */
        !           961:          name = "neg";
        !           962:          break;
        !           963: 
        !           964:       case EQUIV:              /* three unary = operators */
        !           965:          unopb(NUMEQ);
        !           966:       case LEXEQ:              /* two unary = operators */
        !           967:          unopb(NUMEQ);
        !           968:       case NUMEQ:              /* unary = operator */
        !           969:          name = "tabmat";
        !           970:          break;
        !           971: 
        !           972:       case INTER:              /* two unary * operators */
        !           973:          unopb(STAR);
        !           974:       case STAR:               /* unary * operator */
        !           975:          name = "size";
        !           976:          break;
        !           977: 
        !           978:       case QMARK:              /* unary ? operator */
        !           979:          name = "random";
        !           980:          break;
        !           981: 
        !           982:       case SLASH:              /* unary / operator */
        !           983:          name = "null";
        !           984:          break;
        !           985: 
        !           986:       default:
        !           987:          emitn("?unop", op);
        !           988:          syserr("unopb: undefined unary operator");
        !           989:       }
        !           990:    emit(name);
        !           991:    return;
        !           992:    }
        !           993: 
        !           994: /*
        !           995:  * setline emits a "line" instruction for line n.  A "line" instruction is not
        !           996:  *  emitted if the last "line" instruction was also for line n.
        !           997:  */
        !           998: setline(n)
        !           999: int n;
        !          1000:    {
        !          1001:    static lastline = 0;
        !          1002: 
        !          1003:    if (n != lastline) {
        !          1004:       lastline = n;
        !          1005:       if (n > 0)
        !          1006:          emitn("line", n);
        !          1007:       }
        !          1008:    }
        !          1009: /*
        !          1010:  * The emit* routines output ucode to codefile.  The various routines are:
        !          1011:  *
        !          1012:  *  emitlab(l) - emit "lab" instruction for label l.
        !          1013:  *  emit(s) - emit instruction s.
        !          1014:  *  emitl(s,a) - emit instruction s with reference to label a.
        !          1015:  *  emitn(s,n) - emit instruction s with numeric operand a.
        !          1016:  *  emitnl(s,a,b) - emit instruction s with numeric operand a and label b.
        !          1017:  *  emits(s,a) - emit instruction s with string operand a.
        !          1018:  */
        !          1019: emitlab(l)
        !          1020: int l;
        !          1021:    {
        !          1022:    fprintf(codefile, "lab L%d\n", l);
        !          1023:    }
        !          1024: 
        !          1025: emit(s)
        !          1026: char *s;
        !          1027:    {
        !          1028:    fprintf(codefile, "\t%s\n", s);
        !          1029:    }
        !          1030: 
        !          1031: emitl(s, a)
        !          1032: char *s;
        !          1033: int a;
        !          1034:    {
        !          1035:    fprintf(codefile, "\t%s\tL%d\n", s, a);
        !          1036:    }
        !          1037: 
        !          1038: emitn(s, a)
        !          1039: char *s;
        !          1040: int a;
        !          1041:    {
        !          1042:    fprintf(codefile, "\t%s\t%d\n", s, a);
        !          1043:    }
        !          1044: 
        !          1045: emitnl(s, a, b)
        !          1046: char *s;
        !          1047: int a, b;
        !          1048:    {
        !          1049:    fprintf(codefile, "\t%s\t%d,L%d\n", s, a, b);
        !          1050:    }
        !          1051: 
        !          1052: emits(s, a)
        !          1053: char *s, *a;
        !          1054:    {
        !          1055:    fprintf(codefile, "\t%s\t%s\n", s, a);
        !          1056:    }
        !          1057: /*
        !          1058:  * alclab allocates n labels and returns the first.  For the interpreter,
        !          1059:  *  labels are restarted at 1 for each procedure, while in the compiler,
        !          1060:  *  they start at 1 and increase throughout the entire compilation.
        !          1061:  */
        !          1062: alclab(n)
        !          1063: int n;
        !          1064:    {
        !          1065:    register int lab;
        !          1066: 
        !          1067:    lab = nextlab;
        !          1068:    nextlab += n;
        !          1069:    return (lab);
        !          1070:    }

unix.superglobalmegacorp.com

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