xref: /csrg-svn/usr.bin/pascal/pdx/sym/tree.c (revision 5783)
15531Slinton /* Copyright (c) 1982 Regents of the University of California */
25531Slinton 
3*5783Slinton static char sccsid[] = "@(#)tree.c 1.2 02/13/82";
45531Slinton 
55531Slinton /*
65531Slinton  * This module contains the interface between the SYM routines and
75531Slinton  * the parse tree routines.  It would be nice if such a crude
85531Slinton  * interface were not necessary, but some parts of tree building are
95531Slinton  * language and hence SYM-representation dependent.  It's probably
105531Slinton  * better to have tree-representation dependent code here than vice versa.
115531Slinton  */
125531Slinton 
135531Slinton #include "defs.h"
145531Slinton #include "tree.h"
155531Slinton #include "sym.h"
165531Slinton #include "btypes.h"
175531Slinton #include "classes.h"
185531Slinton #include "sym.rep"
195531Slinton #include "tree/tree.rep"
205531Slinton 
215531Slinton typedef char *ARGLIST;
225531Slinton 
23*5783Slinton #define nextarg(arglist, type)  ((type *) (arglist += sizeof(type)))[-1]
245531Slinton 
255531Slinton LOCAL SYM *mkstring();
265531Slinton LOCAL SYM *namenode();
275531Slinton 
285531Slinton /*
295531Slinton  * Determine the type of a parse tree.  While we're at, check
305531Slinton  * the parse tree out.
315531Slinton  */
325531Slinton 
335531Slinton SYM *treetype(p, ap)
345531Slinton register NODE *p;
355531Slinton register ARGLIST ap;
365531Slinton {
37*5783Slinton     switch(p->op) {
38*5783Slinton 	case O_NAME: {
39*5783Slinton 	    SYM *s;
405531Slinton 
41*5783Slinton 	    s = nextarg(ap, SYM *);
42*5783Slinton 	    s = which(s);
43*5783Slinton 	    return namenode(p, s);
44*5783Slinton 	    /* NOTREACHED */
45*5783Slinton 	}
465531Slinton 
47*5783Slinton 	case O_WHICH:
48*5783Slinton 	    p->nameval = nextarg(ap, SYM *);
49*5783Slinton 	    p->nameval = which(p->nameval);
50*5783Slinton 	    return NIL;
515531Slinton 
52*5783Slinton 	case O_LCON:
53*5783Slinton 	    return t_int;
545531Slinton 
55*5783Slinton 	case O_FCON:
56*5783Slinton 	    return t_real;
575531Slinton 
58*5783Slinton 	case O_SCON: {
59*5783Slinton 	    char *cpy;
60*5783Slinton 	    SYM *s;
615531Slinton 
62*5783Slinton 	    cpy = strdup(p->sconval);
63*5783Slinton 	    p->sconval = cpy;
64*5783Slinton 	    s = mkstring(p->sconval);
65*5783Slinton 	    if (s == t_char) {
66*5783Slinton 		p->op = O_LCON;
67*5783Slinton 		p->lconval = p->sconval[0];
68*5783Slinton 	    }
69*5783Slinton 	    return s;
70*5783Slinton 	}
715531Slinton 
72*5783Slinton 	case O_INDIR:
73*5783Slinton 	    p->left = nextarg(ap, NODE *);
74*5783Slinton 	    chkclass(p->left, PTR);
75*5783Slinton 	    return rtype(p->left->nodetype)->type;
765531Slinton 
77*5783Slinton 	case O_RVAL: {
78*5783Slinton 	    NODE *p1, *q;
795531Slinton 
80*5783Slinton 	    p1 = p->left;
81*5783Slinton 	    p->nodetype = p1->nodetype;
82*5783Slinton 	    if (p1->op == O_NAME) {
83*5783Slinton 		if (p1->nodetype->class == FUNC) {
84*5783Slinton 		    p->op = O_CALL;
85*5783Slinton 		    p->right = NIL;
86*5783Slinton 		} else if (p1->nameval->class == CONST) {
87*5783Slinton 		    if (p1->nameval->type == t_real->type) {
88*5783Slinton 			p->op = O_FCON;
89*5783Slinton 			p->fconval = p1->nameval->symvalue.fconval;
90*5783Slinton 			p->nodetype = t_real;
91*5783Slinton 			dispose(p1);
92*5783Slinton 		    } else {
93*5783Slinton 			p->op = O_LCON;
94*5783Slinton 			p->lconval = p1->nameval->symvalue.iconval;
95*5783Slinton 			p->nodetype = p1->nameval->type;
96*5783Slinton 			dispose(p1);
97*5783Slinton 		    }
985531Slinton 		}
99*5783Slinton 	    }
100*5783Slinton 	    return p->nodetype;
101*5783Slinton 	    /* NOTREACHED */
102*5783Slinton 	}
1035531Slinton 
104*5783Slinton 	case O_CALL: {
105*5783Slinton 	    SYM *s;
1065531Slinton 
107*5783Slinton 	    p->left = nextarg(ap, NODE *);
108*5783Slinton 	    p->right = nextarg(ap, NODE *);
109*5783Slinton 	    s = p->left->nodetype;
110*5783Slinton 	    if (isblock(s) && isbuiltin(s)) {
111*5783Slinton 		p->op = (OP) s->symvalue.token.tokval;
112*5783Slinton 		tfree(p->left);
113*5783Slinton 		p->left = p->right;
114*5783Slinton 		p->right = NIL;
115*5783Slinton 	    }
116*5783Slinton 	    return s->type;
117*5783Slinton 	}
1185531Slinton 
119*5783Slinton 	case O_ITOF:
120*5783Slinton 	    return t_real;
1215531Slinton 
122*5783Slinton 	case O_NEG: {
123*5783Slinton 	    SYM *s;
1245531Slinton 
125*5783Slinton 	    p->left = nextarg(ap, NODE *);
126*5783Slinton 	    s = p->left->nodetype;
127*5783Slinton 	    if (!compatible(s, t_int)) {
128*5783Slinton 		if (!compatible(s, t_real)) {
129*5783Slinton 		    trerror("%t is improper type", p->left);
130*5783Slinton 		} else {
131*5783Slinton 		    p->op = O_NEGF;
1325531Slinton 		}
133*5783Slinton 	    }
134*5783Slinton 	    return s;
135*5783Slinton 	}
1365531Slinton 
137*5783Slinton 	case O_ADD:
138*5783Slinton 	case O_SUB:
139*5783Slinton 	case O_MUL:
140*5783Slinton 	case O_LT:
141*5783Slinton 	case O_LE:
142*5783Slinton 	case O_GT:
143*5783Slinton 	case O_GE:
144*5783Slinton 	case O_EQ:
145*5783Slinton 	case O_NE:
146*5783Slinton 	{
147*5783Slinton 	    BOOLEAN t1real, t2real;
148*5783Slinton 	    SYM *t1, *t2;
1495531Slinton 
150*5783Slinton 	    p->left = nextarg(ap, NODE *);
151*5783Slinton 	    p->right = nextarg(ap, NODE *);
152*5783Slinton 	    t1 = rtype(p->left->nodetype);
153*5783Slinton 	    t2 = rtype(p->right->nodetype);
154*5783Slinton 	    t1real = (t1 == t_real);
155*5783Slinton 	    t2real = (t2 == t_real);
156*5783Slinton 	    if (t1real || t2real) {
157*5783Slinton 		p->op++;
158*5783Slinton 		if (!t1real) {
159*5783Slinton 		    p->left = build(O_ITOF, p->left);
160*5783Slinton 		} else if (!t2real) {
161*5783Slinton 		    p->right = build(O_ITOF, p->right);
1625531Slinton 		}
163*5783Slinton 	    } else {
164*5783Slinton 		if (t1real) {
165*5783Slinton 		    convert(&p->left, t_int, O_NOP);
166*5783Slinton 		}
167*5783Slinton 		if (t2real) {
168*5783Slinton 		    convert(&p->right, t_int, O_NOP);
169*5783Slinton 		}
170*5783Slinton 	    }
171*5783Slinton 	    if (p->op >= O_LT) {
172*5783Slinton 		return t_boolean;
173*5783Slinton 	    } else {
174*5783Slinton 		if (t1real || t2real) {
175*5783Slinton 		    return t_real;
176*5783Slinton 		} else {
177*5783Slinton 		    return t_int;
178*5783Slinton 		}
179*5783Slinton 	    }
180*5783Slinton 	    /* NOTREACHED */
181*5783Slinton 	}
1825531Slinton 
183*5783Slinton 	case O_DIVF:
184*5783Slinton 	    p->left = nextarg(ap, NODE *);
185*5783Slinton 	    p->right = nextarg(ap, NODE *);
186*5783Slinton 	    convert(&p->left, t_real, O_ITOF);
187*5783Slinton 	    convert(&p->right, t_real, O_ITOF);
188*5783Slinton 	    return t_real;
1895531Slinton 
190*5783Slinton 	case O_DIV:
191*5783Slinton 	case O_MOD:
192*5783Slinton 	    p->left = nextarg(ap, NODE *);
193*5783Slinton 	    p->right = nextarg(ap, NODE *);
194*5783Slinton 	    convert(&p->left, t_int, O_NOP);
195*5783Slinton 	    convert(&p->right, t_int, O_NOP);
196*5783Slinton 	    return t_int;
1975531Slinton 
198*5783Slinton 	case O_AND:
199*5783Slinton 	case O_OR:
200*5783Slinton 	    p->left = nextarg(ap, NODE *);
201*5783Slinton 	    p->right = nextarg(ap, NODE *);
202*5783Slinton 	    chkboolean(p->left);
203*5783Slinton 	    chkboolean(p->right);
204*5783Slinton 	    return t_boolean;
2055531Slinton 
206*5783Slinton 	default:
207*5783Slinton 	    return NIL;
208*5783Slinton     }
2095531Slinton }
2105531Slinton 
2115531Slinton /*
2125531Slinton  * Create a node for a name.  The symbol for the name has already
2135531Slinton  * been chosen, either implicitly with "which" or explicitly from
2145531Slinton  * the dot routine.
2155531Slinton  */
2165531Slinton 
2175531Slinton LOCAL SYM *namenode(p, s)
2185531Slinton NODE *p;
2195531Slinton SYM *s;
2205531Slinton {
221*5783Slinton     NODE *np;
2225531Slinton 
223*5783Slinton     p->nameval = s;
224*5783Slinton     if (s->class == REF) {
225*5783Slinton 	np = alloc(1, NODE);
226*5783Slinton 	*np = *p;
227*5783Slinton 	p->op = O_INDIR;
228*5783Slinton 	p->left = np;
229*5783Slinton 	np->nodetype = s;
230*5783Slinton     }
231*5783Slinton     if (s->class == CONST || s->class == VAR || s->class == FVAR) {
232*5783Slinton 	return s->type;
233*5783Slinton     } else {
234*5783Slinton 	return s;
235*5783Slinton     }
2365531Slinton }
2375531Slinton 
2385531Slinton /*
2395531Slinton  * Convert a tree to a type via a conversion operator;
2405531Slinton  * if this isn't possible generate an error.
2415531Slinton  *
2425531Slinton  * Note the tree is call by address, hence the #define below.
2435531Slinton  */
2445531Slinton 
2455531Slinton LOCAL convert(tp, typeto, op)
2465531Slinton NODE **tp;
2475531Slinton SYM *typeto;
2485531Slinton OP op;
2495531Slinton {
250*5783Slinton #define tree    (*tp)
2515531Slinton 
252*5783Slinton     SYM *s;
2535531Slinton 
254*5783Slinton     s = rtype(tree->nodetype);
255*5783Slinton     typeto = rtype(typeto);
256*5783Slinton     if (typeto == t_real && compatible(s, t_int)) {
257*5783Slinton 	tree = build(op, tree);
258*5783Slinton     } else if (!compatible(s, typeto)) {
259*5783Slinton 	trerror("%t is improper type");
260*5783Slinton     } else if (op != O_NOP && s != typeto) {
261*5783Slinton 	tree = build(op, tree);
262*5783Slinton     }
2635531Slinton 
2645531Slinton #undef tree
2655531Slinton }
2665531Slinton 
2675531Slinton /*
2685531Slinton  * Construct a node for the Pascal dot operator.
2695531Slinton  *
2705531Slinton  * If the left operand is not a record, but rather a procedure
2715531Slinton  * or function, then we interpret the "." as referencing an
2725531Slinton  * "invisible" variable; i.e. a variable within a dynamically
2735531Slinton  * active block but not within the static scope of the current procedure.
2745531Slinton  */
2755531Slinton 
2765531Slinton NODE *dot(record, field)
2775531Slinton NODE *record;
2785531Slinton SYM *field;
2795531Slinton {
280*5783Slinton     register NODE *p;
281*5783Slinton     register SYM *s;
2825531Slinton 
283*5783Slinton     if (isblock(record->nodetype)) {
284*5783Slinton 	s = findsym(field, record->nodetype);
285*5783Slinton 	if (s == NIL) {
286*5783Slinton 	    error("\"%s\" is not defined in \"%s\"",
287*5783Slinton 		field->symbol, record->nodetype->symbol);
2885531Slinton 	}
289*5783Slinton 	p = alloc(1, NODE);
290*5783Slinton 	p->op = O_NAME;
291*5783Slinton 	p->nodetype = namenode(p, s);
292*5783Slinton     } else {
293*5783Slinton 	s = findclass(field, FIELD);
294*5783Slinton 	if (s == NIL) {
295*5783Slinton 	    error("\"%s\" is not a field", field->symbol);
296*5783Slinton 	}
297*5783Slinton 	field = s;
298*5783Slinton 	chkfield(record, field);
299*5783Slinton 	p = alloc(1, NODE);
300*5783Slinton 	p->op = O_ADD;
301*5783Slinton 	p->nodetype = field->type;
302*5783Slinton 	p->left = record;
303*5783Slinton 	p->right = build(O_LCON, (long) field->symvalue.offset);
304*5783Slinton     }
305*5783Slinton     return p;
3065531Slinton }
3075531Slinton 
3085531Slinton /*
3095531Slinton  * Return a tree corresponding to an array reference and do the
3105531Slinton  * error checking.
3115531Slinton  */
3125531Slinton 
3135531Slinton NODE *subscript(a, slist)
3145531Slinton NODE *a, *slist;
3155531Slinton {
316*5783Slinton     register SYM *t;
317*5783Slinton     register NODE *p;
318*5783Slinton     SYM *etype, *atype, *eltype;
319*5783Slinton     NODE *esub, *olda;
3205531Slinton 
321*5783Slinton     olda = a;
322*5783Slinton     t = rtype(a->nodetype);
323*5783Slinton     if (t->class != ARRAY) {
324*5783Slinton 	trerror("%t is not an array");
325*5783Slinton     }
326*5783Slinton     eltype = t->type;
327*5783Slinton     p = slist;
328*5783Slinton     t = t->chain;
329*5783Slinton     for (; p != NIL && t != NIL; p = p->right, t = t->chain) {
330*5783Slinton 	esub = p->left;
331*5783Slinton 	etype = rtype(esub->nodetype);
332*5783Slinton 	atype = rtype(t);
333*5783Slinton 	if (!compatible(atype, etype)) {
334*5783Slinton 	    trerror("subscript %t is the wrong type", esub);
3355531Slinton 	}
336*5783Slinton 	a = build(O_INDEX, a, esub);
337*5783Slinton 	a->nodetype = eltype;
338*5783Slinton     }
339*5783Slinton     if (p != NIL) {
340*5783Slinton 	trerror("too many subscripts for %t", olda);
341*5783Slinton     } else if (t != NIL) {
342*5783Slinton 	trerror("not enough subscripts for %t", olda);
343*5783Slinton     }
344*5783Slinton     return(a);
3455531Slinton }
3465531Slinton 
3475531Slinton /*
3485531Slinton  * Evaluate a subscript index.
3495531Slinton  */
3505531Slinton 
351*5783Slinton evalindex(arraytype, index)
352*5783Slinton SYM *arraytype;
353*5783Slinton long index;
3545531Slinton {
355*5783Slinton     long lb, ub;
356*5783Slinton     SYM *indextype;
3575531Slinton 
358*5783Slinton     indextype = arraytype->chain;
359*5783Slinton     lb = indextype->symvalue.rangev.lower;
360*5783Slinton     ub = indextype->symvalue.rangev.upper;
361*5783Slinton     if (index < lb || index > ub) {
362*5783Slinton 	error("subscript out of range");
363*5783Slinton     }
364*5783Slinton     return(index - lb);
3655531Slinton }
3665531Slinton 
3675531Slinton /*
3685531Slinton  * Check that a record.field usage is proper.
3695531Slinton  */
3705531Slinton 
3715531Slinton LOCAL chkfield(r, f)
3725531Slinton NODE *r;
3735531Slinton SYM *f;
3745531Slinton {
375*5783Slinton     register SYM *s;
3765531Slinton 
377*5783Slinton     chkclass(r, RECORD);
3785531Slinton 
379*5783Slinton     /*
380*5783Slinton      * Don't do this for compiled code.
381*5783Slinton      */
382*5783Slinton #   if (!isvax)
383*5783Slinton 	for (s = r->nodetype->chain; s != NIL; s = s->chain) {
384*5783Slinton 	    if (s == f) {
385*5783Slinton 		break;
386*5783Slinton 	    }
387*5783Slinton 	}
388*5783Slinton 	if (s == NIL) {
389*5783Slinton 	    error("\"%s\" is not a field in specified record", f->symbol);
390*5783Slinton 	}
391*5783Slinton #   endif
3925531Slinton }
3935531Slinton 
3945531Slinton /*
3955531Slinton  * Check to see if a tree is boolean-valued, if not it's an error.
3965531Slinton  */
3975531Slinton 
3985531Slinton chkboolean(p)
3995531Slinton register NODE *p;
4005531Slinton {
401*5783Slinton     if (p->nodetype != t_boolean) {
402*5783Slinton 	trerror("found %t, expected boolean expression");
403*5783Slinton     }
4045531Slinton }
4055531Slinton 
4065531Slinton /*
4075531Slinton  * Check to make sure the given tree has a type of the given class.
4085531Slinton  */
4095531Slinton 
4105531Slinton LOCAL chkclass(p, class)
4115531Slinton NODE *p;
4125531Slinton int class;
4135531Slinton {
414*5783Slinton     SYM tmpsym;
4155531Slinton 
416*5783Slinton     tmpsym.class = class;
417*5783Slinton     if (p->nodetype->class != class) {
418*5783Slinton 	trerror("%t is not a %s", p, classname(&tmpsym));
419*5783Slinton     }
4205531Slinton }
4215531Slinton 
4225531Slinton /*
4235531Slinton  * Construct a node for the type of a string.  While we're at it,
4245531Slinton  * scan the string for '' that collapse to ', and chop off the ends.
4255531Slinton  */
4265531Slinton 
4275531Slinton LOCAL SYM *mkstring(str)
4285531Slinton char *str;
4295531Slinton {
430*5783Slinton     register char *p, *q;
431*5783Slinton     SYM *s, *t;
432*5783Slinton     static SYM zerosym;
4335531Slinton 
434*5783Slinton     p = str;
435*5783Slinton     q = str + 1;
436*5783Slinton     while (*q != '\0') {
437*5783Slinton 	if (q[0] != '\'' || q[1] != '\'') {
438*5783Slinton 	    *p = *q;
439*5783Slinton 	    p++;
4405531Slinton 	}
441*5783Slinton 	q++;
442*5783Slinton     }
443*5783Slinton     *--p = '\0';
444*5783Slinton     if (p == str + 1) {
445*5783Slinton 	return t_char;
446*5783Slinton     }
447*5783Slinton     s = alloc(1, SYM);
448*5783Slinton     *s = zerosym;
449*5783Slinton     s->class = ARRAY;
450*5783Slinton     s->type = t_char;
451*5783Slinton     s->chain = alloc(1, SYM);
452*5783Slinton     t = s->chain;
453*5783Slinton     *t = zerosym;
454*5783Slinton     t->class = RANGE;
455*5783Slinton     t->type = t_int;
456*5783Slinton     t->symvalue.rangev.lower = 1;
457*5783Slinton     t->symvalue.rangev.upper = p - str + 1;
458*5783Slinton     return s;
4595531Slinton }
4605531Slinton 
4615531Slinton /*
4625531Slinton  * Free up the space allocated for a string type.
4635531Slinton  */
4645531Slinton 
4655531Slinton unmkstring(s)
4665531Slinton SYM *s;
4675531Slinton {
468*5783Slinton     dispose(s->chain);
4695531Slinton }
470