Annotation of researchv10dc/cmd/icon/src/tran/code.c, revision 1.1.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.