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:    }

Defined functions

alclab defined in line 1062; used 14 times
binop defined in line 668; used 1 times
codegen defined in line 135; used 1 times
emit defined in line 1025; used 62 times
emitl defined in line 1031; used 32 times
emitlab defined in line 1019; used 26 times
emitn defined in line 1038; used 25 times
emitnl defined in line 1045; never used
emits defined in line 1052; used 2 times
setline defined in line 998; used 33 times
traverse defined in line 149; used 55 times
tree1 defined in line 23; used 2 times
tree3 defined in line 36; used 2 times
tree4 defined in line 51; used 13 times
tree5 defined in line 67; used 15 times
tree6 defined in line 84; used 9 times
tree7 defined in line 102; used 2 times
treeinit defined in line 126; used 1 times
unopa defined in line 868; used 1 times
unopb defined in line 919; used 9 times

Defined variables

nextlab defined in line 11; used 19 times
Last modified: 1984-11-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2179
Valid CSS Valid XHTML 1.0 Strict