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