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