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