1 /* $Id: expr.c,v 1.9 1994/06/24 12:26:55 ceriel Exp $ */
3 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4 * See the copyright notice in the ACK home directory, in the file "Copyright".
11 static void rvalue(), assignable(), inputable(), outputable(), subscriptable();
12 static void assigned();
15 /* The new_* functions make use of the used() and assinged() functions to
16 * make known what is done to a variable.
19 struct expr *new_node(op, left, right, byte)
21 register struct expr *left, *right;
23 /* Makes a new node with given operator, left and right operand.
24 * Constant folding is done if possible.
27 if (op!=FOR && constant(left) && (right==nil || constant(right))) {
31 if (right) rc=right->u.cst; else rc = 0;
34 case '+': lc+=rc; break;
35 case '-': lc-=rc; break;
36 case '*': lc*=rc; break;
38 report("division by zero");
42 case BS: lc%=rc; break;
43 case '<': lc= lc<rc ? -1L : 0L; break;
44 case '>': lc= lc>rc ? -1L : 0L; break;
45 case LE: lc= lc<=rc ? -1L : 0L; break;
46 case GE: lc= lc>=rc ? -1L : 0L; break;
47 case NE: lc= lc!=rc ? -1L : 0L; break;
48 case '=': lc= lc==rc ? -1L : 0L; break;
49 case AFTER: lc= (lc-rc)>0 ? -1L : 0L; break;
50 case BA: lc&=rc; break;
51 case BO: lc|=rc; break;
52 case BX: lc^=rc; break;
53 case AND: lc= lc&&rc ? -1L : 0L; break;
54 case OR: lc= lc||rc ? -1L : 0L; break;
55 case LS: lc<<=rc; break;
56 case RS: lc>>=rc; break;
57 case '~': lc= -lc; break;
58 case NOT: lc= ~lc; break;
60 report("illegal operator on constants");
67 register struct expr *pe;
68 int type=0, arr_siz=1;
71 case '+': case '-': case '*': case '/':
72 case BS: case '<': case '>': case LE:
73 case GE: case NE: case '=': case AFTER:
74 case BA: case BO: case BX: case AND:
75 case OR: case LS: case RS:
86 assignable(left, right);
90 subscriptable(left, right, byte, &type, &arr_siz);
93 pe= (struct expr *) Malloc(sizeof *pe);
100 pe->u.node.right=right;
106 struct expr *new_var(var)
107 register struct symbol *var;
108 /* Given a variable an expression node is constructed. Note the changes in
109 * type! T_VAR becomes T_VALUE with flag T_LVALUE.
112 register struct expr *pe;
114 pe= (struct expr *) Malloc(sizeof *pe);
118 if ((var->s_type&T_TYPE)==T_VAR || var->s_type&T_NOTDECL) {
119 pe->type=(var->s_type&(~T_TYPE));
120 pe->type|=T_VALUE|T_LVALUE;
122 pe->type=var->s_type;
124 pe->arr_siz=var->s_arr_siz;
131 struct expr *new_const(cst)
133 /* Make a constant, which is a VALUE, of course. */
135 register struct expr *pe;
137 pe= (struct expr *) Malloc(sizeof *pe);
146 struct expr *new_table(kind, tab)
148 register struct table *tab;
149 /* One table is being made, it is no doubt a VALUEd ARRay, but maybe even a
150 * BYTE array. A label is reserved for it and the individual elements are
154 register struct expr *pe;
156 pe= (struct expr *) Malloc(sizeof *pe);
159 pe->type=T_VALUE|T_ARR;
160 if (kind==E_BTAB) pe->type|=T_BYTE;
161 dot_label(new_dot_label(&pe->u.tab));
165 register struct table *junk=tab;
167 rom(kind==E_BTAB ? 1 : vz, tab->val);
177 struct expr *copy_const(e) struct expr *e;
178 /* If you double it up, you've got one you can throw away. (Or do something
182 register struct expr *c;
184 c= (struct expr *) Malloc(sizeof *c);
190 struct expr *new_now()
191 /* Now is the time to make a VALUE cell for the clock. */
193 register struct expr *pe;
195 pe= (struct expr *) Malloc(sizeof *pe);
203 struct expr *new_io(out, chan, args)
205 register struct expr *chan;
206 struct expr_list *args;
207 /* Either c ? v0; v1; v2; ... (out=0) or c ! e0; e1; e2; ... (out=1). */
209 register struct expr *pe;
211 if ( ( (chan->type&T_TYPE) != T_CHAN || (chan->type&T_ARR) )
212 && ! (chan->type&T_NOTDECL)
214 report("channel variable expected");
217 pe= (struct expr *) Malloc(sizeof *pe);
228 struct expr *new_call(proc, args)
230 struct expr_list *args;
231 /* Dial proc(arg1, arg2, ...) and you'll hear the tone of this function.
232 * Dialing yourself is not allowed, but it will work if you ignore the
233 * compiler generated noise.
236 register struct expr *pe;
238 pe= (struct expr *) Malloc(sizeof *pe);
242 check_recursion(proc);
246 pe->u.call.c_proc=proc;
247 pe->u.call.c_args=args;
252 void table_add(aapt, val) register struct table ***aapt; long val;
253 /* Adds a value to a table using a hook to a hook. */
255 register struct table *pt;
257 pt= (struct table *) Malloc(sizeof *pt);
266 void expr_list_add(aaelp, arg)
267 register struct expr_list ***aaelp;
269 /* Another add, this time for actual arguments and the like. */
271 register struct expr_list *elp;
273 elp= (struct expr_list *) Malloc(sizeof *elp);
281 void check_io(out, arg) int out; struct expr *arg;
289 void check_wait(e) struct expr *e;
291 if ((e->type&T_TYPE)!=T_VALUE)
292 report("WAIT process needs valued operand");
295 static void assigned(e) register struct expr *e;
296 /* Tries to tell e that it is assigned to. */
298 if (e->kind==E_VAR || (e->kind==E_NODE && e->u.node.op=='['
299 && (e=e->u.node.left)->kind==E_VAR)
301 register struct symbol *var;
303 if ((var=e->u.var)->s_type&T_REP) {
304 warning("replicator index %s may not be assigned",
306 var->s_type&= ~T_REP;
308 var->s_type|=T_ASSIGNED;
312 void used(e) register struct expr *e;
314 if (e->kind==E_VAR || (e->kind==E_NODE && e->u.node.op=='['
315 && (e=e->u.node.left)->kind==E_VAR)
317 register struct symbol *var;
319 if ( ! ( (var=e->u.var)->s_type&(T_ASSIGNED|T_BUILTIN))
320 && (var->s_type&T_TYPE)==T_VAR
321 && var->s_info.vc.st.level==curr_level)
322 warning("%s used before assigned", var->s_name);
323 var->s_type|=(T_USED|T_ASSIGNED);
327 static void rvalue(e) register struct expr *e;
329 if ((e->type&T_TYPE)!=T_VALUE || e->type&T_ARR)
330 report("illegal operand of arithmetic operator");
334 static void assignable(l, r) register struct expr *l, *r;
335 /* See if l can be assigned r. */
337 if ( ! ( (l->type&T_LVALUE && (r->type&T_TYPE)==T_VALUE
338 && (l->type&T_ARR)==(r->type&T_ARR))
339 || (l->type|r->type)&T_NOTDECL
341 report("operands of assignment are not conformable");
343 if (l->type&T_ARR && ! ( (l->type|r->type)&T_NOTDECL ) ) {
344 register lsiz=l->arr_siz, rsiz=r->arr_siz;
346 if (lsiz!=0 && rsiz!=0 && lsiz!=rsiz)
347 report("arrays have incompatible sizes");
354 static void inputable(e) struct expr *e;
356 if ( ! (e->type&T_LVALUE) )
357 report("operand of input process can't be assigned");
362 static void outputable(e) struct expr *e;
364 if ( ! ( (e->type&T_TYPE)==T_VALUE ) )
365 report("operand of output process has no value");
369 static void subscriptable(l, r, byte, atype, arr_siz)
370 register struct expr *l, *r;
372 int *atype, *arr_siz;
373 /* Tries to subscript l by r, returning type and array size for slices. */
375 register type= (l->type&T_TYPE)|byte;
377 if ( !(l->type&(T_ARR|T_NOTDECL) ) )
378 report("indexing on a non-array");
380 if ( ! ( (r->type&T_TYPE)==T_VALUE
381 || (r->kind==E_NODE && r->u.node.op==FOR)
383 report("index is not computable");
385 type|=(l->type&T_LVALUE);
387 if (r->kind==E_NODE && r->u.node.op==FOR) {
389 if (r->u.node.right->kind!=E_CONST)
390 report("slice must be of constant size");
392 *arr_siz=r->u.node.right->u.cst;
393 used(r->u.node.left);
399 void check_param(aform, act, err)
400 struct par_list **aform;
401 register struct expr *act;
403 /* Test if formal parameter *aform corresponds with actual act. Err returns
404 * error status. The aform hook is set to the next formal after the check.
407 register struct par_list *form= *aform;
408 register struct expr *left;
409 register struct symbol *var;
410 static char NONCORR[]="actual and formal parameter don't correspond";
414 report("too many actual parameters");
420 if ((form->pr_type&T_ARR)!=(act->type&T_ARR) && !(act->type&T_NOTDECL) ) {
423 switch (form->pr_type&T_TYPE) {
426 (act->type&T_TYPE)==T_VALUE
427 && act->type&T_LVALUE
428 && !(act->type&T_BYTE)
435 if((act->type&T_TYPE)!=T_CHAN && !(act->type&T_NOTDECL))
440 if ((act->type&T_TYPE)!=T_VALUE)
446 *aform= form->pr_next;
449 void destroy(e) register struct expr *e;
450 /* Opposite of making. */
455 destroy(e->u.node.left);
456 destroy(e->u.node.right);
460 destroy(e->kind==E_IO ? e->u.io.chan : e->u.call.c_proc);
462 register struct expr_list *elp, *junk;
464 elp= e->kind==E_IO ? e->u.io.args : e->u.call.c_args;