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