|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #
3: /*
4: * pi - Pascal interpreter code translator
5: *
6: * Charles Haley, Bill Joy UCB
7: * Version 1.2 November 1978
8: */
9:
10: #include "whoami"
11: #include "0.h"
12: #include "tree.h"
13:
14: int cntstat;
15: short cnts = 2;
16: #include "opcode.h"
17:
18: /*
19: * Statement list
20: */
21: statlist(r)
22: int *r;
23: {
24: register *sl;
25:
26: for (sl=r; sl != NIL; sl=sl[2])
27: statement(sl[1]);
28: }
29:
30: /*
31: * Statement
32: */
33: statement(r)
34: int *r;
35: {
36: register *s;
37: register struct nl *snlp;
38:
39: s = r;
40: snlp = nlp;
41: top:
42: if (cntstat) {
43: cntstat = 0;
44: putcnt();
45: }
46: if (s == NIL)
47: return;
48: line = s[1];
49: if (s[0] == T_LABEL) {
50: labeled(s[2]);
51: s = s[3];
52: noreach = 0;
53: cntstat = 1;
54: goto top;
55: }
56: if (noreach) {
57: noreach = 0;
58: warning();
59: error("Unreachable statement");
60: }
61: switch (s[0]) {
62: case T_PCALL:
63: putline();
64: proc(s);
65: break;
66: case T_ASGN:
67: putline();
68: asgnop(s);
69: break;
70: case T_GOTO:
71: putline();
72: gotoop(s[2]);
73: noreach = 1;
74: cntstat = 1;
75: break;
76: default:
77: level++;
78: switch (s[0]) {
79: default:
80: panic("stat");
81: case T_IF:
82: case T_IFEL:
83: ifop(s);
84: break;
85: case T_WHILE:
86: whilop(s);
87: noreach = 0;
88: break;
89: case T_REPEAT:
90: repop(s);
91: break;
92: case T_FORU:
93: case T_FORD:
94: forop(s);
95: noreach = 0;
96: break;
97: case T_BLOCK:
98: statlist(s[2]);
99: break;
100: case T_CASE:
101: putline();
102: caseop(s);
103: break;
104: case T_WITH:
105: withop(s);
106: break;
107: case T_ASRT:
108: putline();
109: asrtop(s);
110: break;
111: }
112: --level;
113: if (gotos[cbn])
114: ungoto();
115: break;
116: }
117: /*
118: * Free the temporary name list entries defined in
119: * expressions, e.g. STRs, and WITHPTRs from withs.
120: */
121: nlfree(snlp);
122: }
123:
124: ungoto()
125: {
126: register struct nl *p;
127:
128: for (p = gotos[cbn]; p != NIL; p = p->chain)
129: if ((p->nl_flags & NFORWD) != 0) {
130: if (p->value[NL_GOLEV] != NOTYET)
131: if (p->value[NL_GOLEV] > level)
132: p->value[NL_GOLEV] = level;
133: } else
134: if (p->value[NL_GOLEV] != DEAD)
135: if (p->value[NL_GOLEV] > level)
136: p->value[NL_GOLEV] = DEAD;
137: }
138:
139: putcnt()
140: {
141:
142: if (monflg == 0)
143: return;
144: cnts++;
145: put2(O_COUNT, cnts);
146: }
147:
148: putline()
149: {
150:
151: # ifdef OBJ
152: if (opt('p') != 0)
153: put2(O_LINO, line);
154: # endif
155: }
156:
157: /*
158: * With varlist do stat
159: *
160: * With statement requires an extra word
161: * in automatic storage for each level of withing.
162: * These indirect pointers are initialized here, and
163: * the scoping effect of the with statement occurs
164: * because lookup examines the field names of the records
165: * associated with the WITHPTRs on the withlist.
166: */
167: withop(s)
168: int *s;
169: {
170: register *p;
171: register struct nl *r;
172: int i;
173: int *swl;
174: long soffset;
175:
176: putline();
177: swl = withlist;
178: soffset = sizes[cbn].om_off;
179: for (p = s[2]; p != NIL; p = p[2]) {
180: sizes[cbn].om_off -= sizeof ( int * );
181: # ifdef PPC
182: putlbracket();
183: # endif
184: put2(O_LV | cbn <<9, i = sizes[cbn].om_off);
185: r = lvalue(p[1], MOD);
186: if (r == NIL)
187: continue;
188: if (r->class != RECORD) {
189: error("Variable in with statement refers to %s, not to a record", nameof(r));
190: continue;
191: }
192: r = defnl(0, WITHPTR, r, i);
193: r->nl_next = withlist;
194: withlist = r;
195: # ifdef VAX
196: put1 ( O_AS4 );
197: # endif
198: # ifdef PDP11
199: put1(O_AS2);
200: # endif
201: }
202: if (sizes[cbn].om_off < sizes[cbn].om_max)
203: sizes[cbn].om_max = sizes[cbn].om_off;
204: statement(s[3]);
205: sizes[cbn].om_off = soffset;
206: # ifdef PPC
207: putlbracket();
208: # endif
209: withlist = swl;
210: }
211:
212: extern flagwas;
213: /*
214: * var := expr
215: */
216: asgnop(r)
217: int *r;
218: {
219: register struct nl *p;
220: register *av;
221:
222: if (r == NIL)
223: return (NIL);
224: /*
225: * Asgnop's only function is
226: * to handle function variable
227: * assignments. All other assignment
228: * stuff is handled by asgnop1.
229: */
230: av = r[2];
231: if (av != NIL && av[0] == T_VAR && av[3] == NIL) {
232: p = lookup1(av[2]);
233: if (p != NIL)
234: p->nl_flags = flagwas;
235: if (p != NIL && p->class == FVAR) {
236: /*
237: * Give asgnop1 the func
238: * which is the chain of
239: * the FVAR.
240: */
241: p->nl_flags |= NUSED|NMOD;
242: p = p->chain;
243: if (p == NIL) {
244: rvalue(r[3], NIL);
245: return;
246: }
247: put2(O_LV | bn << 9, p->value[NL_OFFS]);
248: if (isa(p->type, "i") && width(p->type) == 1)
249: asgnop1(r, nl+T2INT);
250: else
251: asgnop1(r, p->type);
252: return;
253: }
254: }
255: asgnop1(r, NIL);
256: }
257:
258: /*
259: * Asgnop1 handles all assignments.
260: * If p is not nil then we are assigning
261: * to a function variable, otherwise
262: * we look the variable up ourselves.
263: */
264: struct nl *
265: asgnop1(r, p)
266: int *r;
267: register struct nl *p;
268: {
269: register struct nl *p1;
270:
271: if (r == NIL)
272: return (NIL);
273: if (p == NIL) {
274: p = lvalue(r[2], MOD|ASGN|NOUSE);
275: if (p == NIL) {
276: rvalue(r[3], NIL);
277: return (NIL);
278: }
279: }
280: p1 = rvalue(r[3], p);
281: if (p1 == NIL)
282: return (NIL);
283: if (incompat(p1, p, r[3])) {
284: cerror("Type of expression clashed with type of variable in assignment");
285: return (NIL);
286: }
287: switch (classify(p)) {
288: case TBOOL:
289: case TCHAR:
290: case TINT:
291: case TSCAL:
292: rangechk(p, p1);
293: case TDOUBLE:
294: case TPTR:
295: gen(O_AS2, O_AS2, width(p), width(p1));
296: break;
297: default:
298: put2(O_AS, width(p));
299: }
300: # ifdef PPC
301: putexpr();
302: # endif
303: return (p); /* Used by for statement */
304: }
305:
306: /*
307: * for var := expr [down]to expr do stat
308: */
309: forop(r)
310: int *r;
311: {
312: register struct nl *t1, *t2;
313: int l1, l2, l3;
314: long soffset;
315: register op;
316: struct nl *p;
317: int *rr, goc, i;
318:
319: p = NIL;
320: goc = gocnt;
321: if (r == NIL)
322: goto aloha;
323: putline();
324: /*
325: * Start with assignment
326: * of initial value to for variable
327: */
328: t1 = asgnop1(r[2], NIL);
329: if (t1 == NIL) {
330: rvalue(r[3], NIL);
331: statement(r[4]);
332: goto aloha;
333: }
334: rr = r[2]; /* Assignment */
335: rr = rr[2]; /* Lhs variable */
336: if (rr[3] != NIL) {
337: error("For variable must be unqualified");
338: rvalue(r[3], NIL);
339: statement(r[4]);
340: goto aloha;
341: }
342: p = lookup(rr[2]);
343: p->value[NL_FORV] = 1;
344: if (isnta(t1, "bcis")) {
345: error("For variables cannot be %ss", nameof(t1));
346: statement(r[4]);
347: goto aloha;
348: }
349: /*
350: * Allocate automatic
351: * space for limit variable
352: */
353: sizes[cbn].om_off -= 4;
354: # ifdef PPC
355: putlbracket();
356: # endif
357: if (sizes[cbn].om_off < sizes[cbn].om_max)
358: sizes[cbn].om_max = sizes[cbn].om_off;
359: i = sizes[cbn].om_off;
360: /*
361: * Initialize the limit variable
362: */
363: put2(O_LV | cbn<<9, i);
364: t2 = rvalue(r[3], NIL);
365: if (incompat(t2, t1, r[3])) {
366: cerror("Limit type clashed with index type in 'for' statement");
367: statement(r[4]);
368: goto aloha;
369: }
370: put1(width(t2) <= 2 ? O_AS24 : O_AS4);
371: # ifdef PPC
372: putexpr();
373: # endif
374: /*
375: * See if we can skip the loop altogether
376: */
377: rr = r[2];
378: if (rr != NIL)
379: rvalue(rr[2], NIL);
380: put2(O_RV4 | cbn<<9, i);
381: gen(NIL, r[0] == T_FORU ? T_LE : T_GE, width(t1), 4);
382: /*
383: * L1 will be patched to skip the body of the loop.
384: * L2 marks the top of the loop when we go around.
385: */
386: put2(O_IF, (l1 = getlab()));
387: putlab(l2 = getlab());
388: putcnt();
389: statement(r[4]);
390: /*
391: * now we see if we get to go again
392: */
393: if (opt('t') == 0) {
394: /*
395: * Easy if we dont have to test
396: */
397: put2(O_RV4 | cbn<<9, i);
398: if (rr != NIL)
399: lvalue(rr[2], MOD);
400: put2((r[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(t1) >> 1), l2);
401: } else {
402: line = r[1];
403: putline();
404: if (rr != NIL)
405: rvalue(rr[2], NIL);
406: put2(O_RV4 | cbn << 9, i);
407: gen(NIL, (r[0] == T_FORU ? T_LT : T_GT), width(t1), 4);
408: l3 = put2(O_IF, getlab());
409: lvalue((int *) rr[2], MOD);
410: rvalue(rr[2], NIL);
411: put2(O_CON2, 1);
412: t2 = gen(NIL, r[0] == T_FORU ? T_ADD: T_SUB, width(t1), 2);
413: rangechk(t1, t2); /* The point of all this */
414: gen(O_AS2, O_AS2, width(t1), width(t2));
415: put2(O_TRA, l2);
416: patch(l3);
417: }
418: sizes[cbn].om_off += 4;
419: # ifdef PPC
420: putlbracket();
421: # endif
422: patch(l1);
423: aloha:
424: noreach = 0;
425: if (p != NIL)
426: p->value[NL_FORV] = 0;
427: if (goc != gocnt)
428: putcnt();
429: }
430:
431: /*
432: * if expr then stat [ else stat ]
433: */
434: ifop(r)
435: int *r;
436: {
437: register struct nl *p;
438: register l1, l2;
439: int nr, goc;
440:
441: goc = gocnt;
442: if (r == NIL)
443: return;
444: putline();
445: p = rvalue(r[2], NIL);
446: if (p == NIL) {
447: statement(r[3]);
448: noreach = 0;
449: statement(r[4]);
450: noreach = 0;
451: return;
452: }
453: if (isnta(p, "b")) {
454: error("Type of expression in if statement must be Boolean, not %s", nameof(p));
455: statement(r[3]);
456: noreach = 0;
457: statement(r[4]);
458: noreach = 0;
459: return;
460: }
461: l1 = put2(O_IF, getlab());
462: putcnt();
463: statement(r[3]);
464: nr = noreach;
465: if (r[4] != NIL) {
466: /*
467: * else stat
468: */
469: --level;
470: ungoto();
471: ++level;
472: l2 = put2(O_TRA, getlab());
473: patch(l1);
474: noreach = 0;
475: statement(r[4]);
476: noreach &= nr;
477: l1 = l2;
478: } else
479: noreach = 0;
480: patch(l1);
481: if (goc != gocnt)
482: putcnt();
483: }
484:
485: /*
486: * while expr do stat
487: */
488: whilop(r)
489: int *r;
490: {
491: register struct nl *p;
492: register l1, l2;
493: int goc;
494:
495: goc = gocnt;
496: if (r == NIL)
497: return;
498: putlab(l1 = getlab());
499: putline();
500: p = rvalue(r[2], NIL);
501: if (p == NIL) {
502: statement(r[3]);
503: noreach = 0;
504: return;
505: }
506: if (isnta(p, "b")) {
507: error("Type of expression in while statement must be Boolean, not %s", nameof(p));
508: statement(r[3]);
509: noreach = 0;
510: return;
511: }
512: put2(O_IF, (l2 = getlab()));
513: putcnt();
514: statement(r[3]);
515: put2(O_TRA, l1);
516: patch(l2);
517: if (goc != gocnt)
518: putcnt();
519: }
520:
521: /*
522: * repeat stat* until expr
523: */
524: repop(r)
525: int *r;
526: {
527: register struct nl *p;
528: register l;
529: int goc;
530:
531: goc = gocnt;
532: if (r == NIL)
533: return;
534: l = putlab(getlab());
535: putcnt();
536: statlist(r[2]);
537: line = r[1];
538: p = rvalue(r[3], NIL);
539: if (p == NIL)
540: return;
541: if (isnta(p,"b")) {
542: error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p));
543: return;
544: }
545: put2(O_IF, l);
546: if (goc != gocnt)
547: putcnt();
548: }
549:
550: /*
551: * assert expr
552: */
553: asrtop(r)
554: register int *r;
555: {
556: register struct nl *q;
557:
558: if (opt('s')) {
559: standard();
560: error("Assert statement is non-standard");
561: }
562: if (!opt('t'))
563: return;
564: r = r[2];
565: q = rvalue((int *) r, NLNIL);
566: if (q == NIL)
567: return;
568: if (isnta(q, "b"))
569: error("Assert expression must be Boolean, not %ss", nameof(q));
570: put1(O_ASRT);
571: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.