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