Annotation of 43BSD/ucb/pascal/pdx/sym/tree.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.