|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)tree.c 1.6 2/15/83";
4:
5: /*
6: * This module contains the interface between the SYM routines and
7: * the parse tree routines. It would be nice if such a crude
8: * interface were not necessary, but some parts of tree building are
9: * language and hence SYM-representation dependent. It's probably
10: * better to have tree-representation dependent code here than vice versa.
11: */
12:
13: #include "defs.h"
14: #include "tree.h"
15: #include "sym.h"
16: #include "btypes.h"
17: #include "classes.h"
18: #include "sym.rep"
19: #include "tree/tree.rep"
20:
21: typedef char *ARGLIST;
22:
23: #define nextarg(arglist, type) ((type *) (arglist += sizeof(type)))[-1]
24:
25: LOCAL SYM *mkstring();
26: LOCAL SYM *namenode();
27:
28: /*
29: * Determine the type of a parse tree. While we're at, check
30: * the parse tree out.
31: */
32:
33: SYM *treetype(p, ap)
34: register NODE *p;
35: register ARGLIST ap;
36: {
37: switch(p->op) {
38: case O_NAME: {
39: SYM *s;
40:
41: s = nextarg(ap, SYM *);
42: s = which(s);
43: return namenode(p, s);
44: /* NOTREACHED */
45: }
46:
47: case O_WHICH:
48: p->nameval = nextarg(ap, SYM *);
49: p->nameval = which(p->nameval);
50: return NIL;
51:
52: case O_LCON:
53: return t_int;
54:
55: case O_FCON:
56: return t_real;
57:
58: case O_SCON: {
59: char *cpy;
60: SYM *s;
61:
62: cpy = strdup(p->sconval);
63: p->sconval = cpy;
64: s = mkstring(p->sconval);
65: if (s == t_char) {
66: p->op = O_LCON;
67: p->lconval = p->sconval[0];
68: }
69: return s;
70: }
71:
72: case O_INDIR:
73: p->left = nextarg(ap, NODE *);
74: chkclass(p->left, PTR);
75: return rtype(p->left->nodetype)->type;
76:
77: case O_RVAL: {
78: NODE *p1, *q;
79:
80: p1 = p->left;
81: p->nodetype = p1->nodetype;
82: if (p1->op == O_NAME) {
83: if (p1->nodetype->class == FUNC) {
84: p->op = O_CALL;
85: p->right = NIL;
86: } else if (p1->nameval->class == CONST) {
87: if (p1->nameval->type == t_real->type) {
88: p->op = O_FCON;
89: p->fconval = p1->nameval->symvalue.fconval;
90: p->nodetype = t_real;
91: dispose(p1);
92: } else {
93: p->op = O_LCON;
94: p->lconval = p1->nameval->symvalue.iconval;
95: p->nodetype = p1->nameval->type;
96: dispose(p1);
97: }
98: }
99: }
100: return p->nodetype;
101: /* NOTREACHED */
102: }
103:
104: case O_CALL: {
105: SYM *s;
106:
107: p->left = nextarg(ap, NODE *);
108: p->right = nextarg(ap, NODE *);
109: s = p->left->nodetype;
110: if (isblock(s) && isbuiltin(s)) {
111: p->op = (OP) s->symvalue.token.tokval;
112: tfree(p->left);
113: p->left = p->right;
114: p->right = NIL;
115: }
116: return s->type;
117: }
118:
119: case O_ITOF:
120: return t_real;
121:
122: case O_NEG: {
123: SYM *s;
124:
125: p->left = nextarg(ap, NODE *);
126: s = p->left->nodetype;
127: if (!compatible(s, t_int)) {
128: if (!compatible(s, t_real)) {
129: trerror("%t is improper type", p->left);
130: } else {
131: p->op = O_NEGF;
132: }
133: }
134: return s;
135: }
136:
137: case O_ADD:
138: case O_SUB:
139: case O_MUL:
140: case O_LT:
141: case O_LE:
142: case O_GT:
143: case O_GE:
144: case O_EQ:
145: case O_NE:
146: {
147: BOOLEAN t1real, t2real;
148: SYM *t1, *t2;
149:
150: p->left = nextarg(ap, NODE *);
151: p->right = nextarg(ap, NODE *);
152: t1 = rtype(p->left->nodetype);
153: t2 = rtype(p->right->nodetype);
154: t1real = (t1 == t_real);
155: t2real = (t2 == t_real);
156: if (t1real || t2real) {
157: p->op++;
158: if (!t1real) {
159: p->left = build(O_ITOF, p->left);
160: } else if (!t2real) {
161: p->right = build(O_ITOF, p->right);
162: }
163: } else {
164: if (t1real) {
165: convert(&p->left, t_int, O_NOP);
166: }
167: if (t2real) {
168: convert(&p->right, t_int, O_NOP);
169: }
170: }
171: if (p->op >= O_LT) {
172: return t_boolean;
173: } else {
174: if (t1real || t2real) {
175: return t_real;
176: } else {
177: return t_int;
178: }
179: }
180: /* NOTREACHED */
181: }
182:
183: case O_DIVF:
184: p->left = nextarg(ap, NODE *);
185: p->right = nextarg(ap, NODE *);
186: convert(&p->left, t_real, O_ITOF);
187: convert(&p->right, t_real, O_ITOF);
188: return t_real;
189:
190: case O_DIV:
191: case O_MOD:
192: p->left = nextarg(ap, NODE *);
193: p->right = nextarg(ap, NODE *);
194: convert(&p->left, t_int, O_NOP);
195: convert(&p->right, t_int, O_NOP);
196: return t_int;
197:
198: case O_AND:
199: case O_OR:
200: p->left = nextarg(ap, NODE *);
201: p->right = nextarg(ap, NODE *);
202: chkboolean(p->left);
203: chkboolean(p->right);
204: return t_boolean;
205:
206: default:
207: return NIL;
208: }
209: }
210:
211: /*
212: * Create a node for a name. The symbol for the name has already
213: * been chosen, either implicitly with "which" or explicitly from
214: * the dot routine.
215: */
216:
217: LOCAL SYM *namenode(p, s)
218: NODE *p;
219: SYM *s;
220: {
221: NODE *np;
222:
223: p->nameval = s;
224: if (s->class == REF) {
225: np = alloc(1, NODE);
226: *np = *p;
227: p->op = O_INDIR;
228: p->left = np;
229: np->nodetype = s;
230: }
231: if (s->class == CONST || s->class == VAR || s->class == FVAR) {
232: return s->type;
233: } else {
234: return s;
235: }
236: }
237:
238: /*
239: * Convert a tree to a type via a conversion operator;
240: * if this isn't possible generate an error.
241: *
242: * Note the tree is call by address, hence the #define below.
243: */
244:
245: LOCAL convert(tp, typeto, op)
246: NODE **tp;
247: SYM *typeto;
248: OP op;
249: {
250: #define tree (*tp)
251:
252: SYM *s;
253:
254: s = rtype(tree->nodetype);
255: typeto = rtype(typeto);
256: if (typeto == t_real && compatible(s, t_int)) {
257: tree = build(op, tree);
258: } else if (!compatible(s, typeto)) {
259: trerror("%t is improper type");
260: } else if (op != O_NOP && s != typeto) {
261: tree = build(op, tree);
262: }
263:
264: #undef tree
265: }
266:
267: /*
268: * Construct a node for the Pascal dot operator.
269: *
270: * If the left operand is not a record, but rather a procedure
271: * or function, then we interpret the "." as referencing an
272: * "invisible" variable; i.e. a variable within a dynamically
273: * active block but not within the static scope of the current procedure.
274: */
275:
276: NODE *dot(record, field)
277: NODE *record;
278: SYM *field;
279: {
280: register NODE *p;
281: register SYM *s;
282:
283: if (isblock(record->nodetype)) {
284: s = findsym(field, record->nodetype);
285: if (s == NIL) {
286: error("\"%s\" is not defined in \"%s\"",
287: field->symbol, record->nodetype->symbol);
288: }
289: p = alloc(1, NODE);
290: p->op = O_NAME;
291: p->nodetype = namenode(p, s);
292: } else {
293: s = findclass(field, FIELD);
294: if (s == NIL) {
295: error("\"%s\" is not a field", field->symbol);
296: }
297: field = s;
298: chkfield(record, field);
299: p = alloc(1, NODE);
300: p->op = O_ADD;
301: p->nodetype = field->type;
302: p->left = record;
303: p->right = build(O_LCON, (long) field->symvalue.offset);
304: }
305: return p;
306: }
307:
308: /*
309: * Return a tree corresponding to an array reference and do the
310: * error checking.
311: */
312:
313: NODE *subscript(a, slist)
314: NODE *a, *slist;
315: {
316: register SYM *t;
317: register NODE *p;
318: SYM *etype, *atype, *eltype;
319: NODE *esub;
320:
321: t = rtype(a->nodetype);
322: if (t->class != ARRAY) {
323: trerror("%t is not an array", a);
324: }
325: eltype = t->type;
326: p = slist;
327: t = t->chain;
328: for (; p != NIL && t != NIL; p = p->right, t = t->chain) {
329: esub = p->left;
330: etype = rtype(esub->nodetype);
331: atype = rtype(t);
332: if (!compatible(atype, etype)) {
333: trerror("subscript %t is the wrong type", esub);
334: }
335: esub->nodetype = atype;
336: }
337: if (p != NIL) {
338: trerror("too many subscripts for %t", a);
339: } else if (t != NIL) {
340: trerror("not enough subscripts for %t", a);
341: }
342: p = alloc(1, NODE);
343: p->op = O_INDEX;
344: p->left = a;
345: p->right = slist;
346: p->nodetype = eltype;
347: return p;
348: }
349:
350: /*
351: * Evaluate a subscript (possibly more than one index).
352: */
353:
354: long evalindex(arraytype, subs)
355: SYM *arraytype;
356: NODE *subs;
357: {
358: long lb, ub, index, i;
359: SYM *t, *indextype;
360: NODE *p;
361:
362: t = rtype(arraytype);
363: if (t->class != ARRAY) {
364: panic("unexpected class %d in evalindex", t->class);
365: }
366: i = 0;
367: t = t->chain;
368: p = subs;
369: while (t != NIL) {
370: if (p == NIL) {
371: panic("unexpected end of subscript list in evalindex");
372: }
373: indextype = rtype(t);
374: lb = indextype->symvalue.rangev.lower;
375: ub = indextype->symvalue.rangev.upper;
376: eval(p->left);
377: index = popsmall(p->left->nodetype);
378: if (index < lb || index > ub) {
379: error("subscript value %d out of range %d..%d", index, lb, ub);
380: }
381: i = (ub-lb+1)*i + (index-lb);
382: t = t->chain;
383: p = p->right;
384: }
385: return i;
386: }
387:
388: /*
389: * Check that a record.field usage is proper.
390: */
391:
392: LOCAL chkfield(r, f)
393: NODE *r;
394: SYM *f;
395: {
396: register SYM *s;
397:
398: chkclass(r, RECORD);
399:
400: /*
401: * Don't do this for compiled code.
402: */
403: # if (!isvax)
404: for (s = r->nodetype->chain; s != NIL; s = s->chain) {
405: if (s == f) {
406: break;
407: }
408: }
409: if (s == NIL) {
410: error("\"%s\" is not a field in specified record", f->symbol);
411: }
412: # endif
413: }
414:
415: /*
416: * Check to see if a tree is boolean-valued, if not it's an error.
417: */
418:
419: chkboolean(p)
420: register NODE *p;
421: {
422: if (p->nodetype != t_boolean) {
423: trerror("found %t, expected boolean expression");
424: }
425: }
426:
427: /*
428: * Check to make sure the given tree has a type of the given class.
429: */
430:
431: LOCAL chkclass(p, class)
432: NODE *p;
433: int class;
434: {
435: SYM tmpsym;
436:
437: tmpsym.class = class;
438: if (p->nodetype->class != class) {
439: trerror("%t is not a %s", p, classname(&tmpsym));
440: }
441: }
442:
443: /*
444: * Construct a node for the type of a string. While we're at it,
445: * scan the string for '' that collapse to ', and chop off the ends.
446: */
447:
448: LOCAL SYM *mkstring(str)
449: char *str;
450: {
451: register char *p, *q;
452: SYM *s, *t;
453: static SYM zerosym;
454:
455: p = str;
456: q = str + 1;
457: while (*q != '\0') {
458: if (q[0] != '\'' || q[1] != '\'') {
459: *p = *q;
460: p++;
461: }
462: q++;
463: }
464: *--p = '\0';
465: if (p == str + 1) {
466: return t_char;
467: }
468: s = alloc(1, SYM);
469: *s = zerosym;
470: s->class = ARRAY;
471: s->type = t_char;
472: s->chain = alloc(1, SYM);
473: t = s->chain;
474: *t = zerosym;
475: t->class = RANGE;
476: t->type = t_int;
477: t->symvalue.rangev.lower = 1;
478: t->symvalue.rangev.upper = p - str + 1;
479: return s;
480: }
481:
482: /*
483: * Free up the space allocated for a string type.
484: */
485:
486: unmkstring(s)
487: SYM *s;
488: {
489: dispose(s->chain);
490: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.