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

unix.superglobalmegacorp.com

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