|
|
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.