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

unix.superglobalmegacorp.com

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