15527Slinton /* Copyright (c) 1982 Regents of the University of California */
25527Slinton 
3*6580Slinton static char sccsid[] = "@(#)predicates.c 1.4 04/23/82";
45527Slinton 
55527Slinton /*
65527Slinton  * The basic tests on a symbol.
75527Slinton  */
85527Slinton 
95527Slinton #include "defs.h"
105527Slinton #include "sym.h"
115527Slinton #include "symtab.h"
125564Slinton #include "btypes.h"
135527Slinton #include "classes.h"
145527Slinton #include "sym.rep"
155527Slinton 
165527Slinton /*
175527Slinton  * Test if a symbol is a parameter.  This is true if there
185527Slinton  * is a cycle from s->func to s via chain pointers.
195527Slinton  */
205527Slinton 
215527Slinton BOOLEAN isparam(s)
225527Slinton SYM *s;
235527Slinton {
245885Slinton     register SYM *t;
255527Slinton 
265885Slinton     for (t = s->func; t != NIL; t = t->chain) {
275885Slinton 	if (t == s) {
285885Slinton 	    return(TRUE);
295527Slinton 	}
305885Slinton     }
315885Slinton     return(FALSE);
325527Slinton }
335527Slinton 
345527Slinton /*
355527Slinton  * Test if a symbol is a var parameter, i.e. has class REF.
365527Slinton  */
375527Slinton 
385527Slinton BOOLEAN isvarparam(s)
395527Slinton SYM *s;
405527Slinton {
415885Slinton     return (BOOLEAN) s->class == REF;
425527Slinton }
435527Slinton 
445527Slinton /*
455885Slinton  * Test if a symbol is a variable (actually any addressible quantity
465885Slinton  * with do).
475885Slinton  */
485885Slinton 
495885Slinton BOOLEAN isvariable(s)
505885Slinton SYM *s;
515885Slinton {
525885Slinton     return s->class == VAR || s->class == FVAR || s->class == REF;
535885Slinton }
545885Slinton 
555885Slinton /*
565527Slinton  * Test if a symbol is a block, e.g. function, procedure, or the
575527Slinton  * main program.
585527Slinton  */
595527Slinton 
605527Slinton BOOLEAN isblock(s)
615527Slinton register SYM *s;
625527Slinton {
635885Slinton     return(s->class == FUNC || s->class == PROC || s->class == PROG);
645527Slinton }
655527Slinton 
665527Slinton /*
675527Slinton  * Test if a symbol is builtin, that is, a predefined type or
685527Slinton  * reserved word.
695527Slinton  */
705527Slinton 
715527Slinton BOOLEAN isbuiltin(s)
725527Slinton SYM *s;
735527Slinton {
745885Slinton     return(s->blkno == 0 && s->class != PROG && s->class != VAR);
755527Slinton }
765527Slinton 
775527Slinton /*
785527Slinton  * Compatible tests if two types are compatible.  The issue
795527Slinton  * is complicated a bit by ranges.
805527Slinton  *
815527Slinton  * Integers and reals are not compatible since they cannot always be mixed.
825527Slinton  */
835527Slinton 
845527Slinton BOOLEAN compatible(t1, t2)
855527Slinton register SYM *t1, *t2;
865527Slinton {
87*6580Slinton     register BOOLEAN b;
88*6580Slinton 
89*6580Slinton     if (isvariable(t1)) {
90*6580Slinton 	t1 = t1->type;
91*6580Slinton     }
92*6580Slinton     if (isvariable(t2)) {
93*6580Slinton 	t2 = t2->type;
94*6580Slinton     }
955885Slinton     if (t1 == t2) {
96*6580Slinton 	b = TRUE;
97*6580Slinton     } else {
98*6580Slinton 	t1 = rtype(t1);
99*6580Slinton 	t2 = rtype(t2);
100*6580Slinton 	if (t1->type == t2->type) {
101*6580Slinton 	    if (t1->class == RANGE && t2->class == RANGE) {
102*6580Slinton 		b = TRUE;
103*6580Slinton 	    } else if ((t1->class == SCAL || t1->class == CONST) &&
104*6580Slinton 	      (t2->class == SCAL || t2->class == CONST)) {
105*6580Slinton 		b = TRUE;
106*6580Slinton 	    } else if (t1->type == t_char &&
107*6580Slinton 	      t1->class == ARRAY && t2->class == ARRAY) {
108*6580Slinton 		b = TRUE;
109*6580Slinton 	    } else {
110*6580Slinton 		b = FALSE;
111*6580Slinton 	    }
112*6580Slinton     /*
113*6580Slinton      * A kludge here for "nil".  Should be handled better.
114*6580Slinton      * Opens a pandora's box for integer/pointer compatibility.
115*6580Slinton      */
116*6580Slinton 	} else if ((t1->class == RANGE && t2->class == PTR) ||
117*6580Slinton 	  (t2->class == RANGE && t1->class == PTR)) {
118*6580Slinton 	    b = TRUE;
119*6580Slinton 	} else {
120*6580Slinton 	    b = FALSE;
1215527Slinton 	}
1225885Slinton     }
123*6580Slinton     return b;
1245527Slinton }
1255527Slinton 
1265527Slinton /*
1275527Slinton  * Predicate to test if a symbol should be printed.  We don't print
1285527Slinton  * files, for example, simply because there's no good way to do it.
1295527Slinton  * The symbol must be within the given function.
1305527Slinton  */
1315527Slinton 
1325527Slinton BOOLEAN should_print(s, f)
1335527Slinton SYM *s;
1345527Slinton SYM *f;
1355527Slinton {
1365885Slinton     SYM *t;
1375527Slinton 
1385885Slinton     if (s->func != f || (s->class != VAR && s->class != FVAR)) {
1395885Slinton 	return(FALSE);
1405885Slinton     } else if (s->chain != NIL) {
1415885Slinton 	return(FALSE);
1425885Slinton     } else {
1435885Slinton 	t = rtype(s->type);
1445885Slinton 	if (t == NIL || t->class == FILET || t->class == SET) {
1455885Slinton 	    return(FALSE);
1465527Slinton 	} else {
1475885Slinton 	    return(TRUE);
1485527Slinton 	}
1495885Slinton     }
1505527Slinton }
1515527Slinton 
1525527Slinton /*
1535527Slinton  * Test if the name of a symbol is uniquely defined or not.
1545527Slinton  */
1555527Slinton 
1565527Slinton BOOLEAN isambiguous(s)
1575527Slinton SYM *s;
1585527Slinton {
1595885Slinton     SYM *t;
1605527Slinton 
1615885Slinton     t = st_lookup(symtab, s->symbol);
1625885Slinton     if (t == NIL) {
1635885Slinton 	panic("symbol name vanished");
1645885Slinton     }
1655885Slinton     while (t != NIL && (s == t || !streq(t->symbol, s->symbol))) {
1665885Slinton 	t = t->next_sym;
1675885Slinton     }
1685885Slinton     return t != NIL;
1695527Slinton }
170