xref: /inferno-os/utils/acid/expr.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
1  #include <lib9.h>
2  #include <bio.h>
3  #include <ctype.h>
4  #include "mach.h"
5  #define Extern extern
6  #include "acid.h"
7  
8  static int fsize[] =
9  {
10  	0,0,0,0,0,0,0,0,	/* 0-7 */
11  	0,0,0,0,0,0,0,0,	/* 8-15 */
12  	0,0,0,0,0,0,0,0,	/* 16-23 */
13  	0,0,0,0,0,0,0,0,	/* 24-31 */
14  	0,0,0,0,0,0,0,0,	/* 32-39 */
15  	0,0,0,0,0,0,0,0,	/* 40-47 */
16  	0,0,0,0,0,0,0,0,	/* 48-55 */
17  	0,0,0,0,0,0,0,0,	/* 56-63 */
18  	0,			/* 64 */
19  	4,			/* 65	['A'] 4, */
20  	4,			/* 66	['B'] 4, */
21  	1,			/* 67	['C'] 1, */
22  	4,			/* 68	['D'] 4, */
23  	0,			/* 69 */
24  	8,			/* 70	['F'] 8, */
25  	8,			/* 71	['G'] 8, */
26  	0,0,0,0,0,0,0,		/* 72-78 */
27  	4,			/* 79	['O'] 4, */
28  	0,			/* 80 */
29  	4,			/* 81	['Q'] 4, */
30  	4,			/* 82	['R'] 4, */
31  	4,			/* 83	['S'] 4, */
32  	0,			/* 84 */
33  	4,			/* 85	['U'] 4, */
34  	8,			/* 86	['V'] 8, */
35  	0,			/* 87 */
36  	4,			/* 88	['X'] 4, */
37  	8,			/* 89	['Y'] 8, */
38  	8,			/* 90	['Z'] 8, */
39  	0,0,0,0,0,0,		/* 91-96 */
40  	4,			/* 97	['a'] 4, */
41  	1,			/* 98	['b'] 1, */
42  	1,			/* 99	['c'] 1, */
43  	2,			/* 100	['d'] 2, */
44  	0,			/* 101 */
45  	4,			/* 102	['f'] 4, */
46  	4,			/* 103	['g'] 4, */
47  	0,0,0,0,0,0,0,		/* 104-110 */
48  	2,			/* 111	['o'] 2, */
49  	0,			/* 112 */
50  	2,			/* 113	['q'] 2, */
51  	2,			/* 114	['r'] 2, */
52  	4,			/* 115	['s'] 4, */
53  	0,			/* 116 */
54  	2,			/* 117	['u'] 2, */
55  	0,0,			/* 118-119 */
56  	2,			/* 120	['x'] 2, */
57  };
58  
59  int
60  fmtsize(Value *v)
61  {
62  	int ret;
63  
64  	switch(v->vstore.fmt) {
65  	default:
66  		return  fsize[v->vstore.fmt];
67  	case 'i':
68  	case 'I':
69  		if(v->type != TINT || machdata == 0)
70  			error("no size for i fmt pointer ++/--");
71  		ret = (*machdata->instsize)(cormap, v->vstore.u0.sival);
72  		if(ret < 0) {
73  			ret = (*machdata->instsize)(symmap, v->vstore.u0.sival);
74  			if(ret < 0)
75  				error("%r");
76  		}
77  		return ret;
78  	}
79  }
80  
81  void
82  chklval(Node *lp)
83  {
84  	if(lp->op != ONAME)
85  		error("need l-value");
86  }
87  
88  void
89  olist(Node *n, Node *res)
90  {
91  	expr(n->left, res);
92  	expr(n->right, res);
93  }
94  
95  void
96  oeval(Node *n, Node *res)
97  {
98  	expr(n->left, res);
99  	if(res->type != TCODE)
100  		error("bad type for eval");
101  	expr(res->nstore.u0.scc, res);
102  }
103  
104  void
105  ocast(Node *n, Node *res)
106  {
107  	if(n->sym->lt == 0)
108  		error("%s is not a complex type", n->sym->name);
109  
110  	expr(n->left, res);
111  	res->nstore.comt = n->sym->lt;
112  	res->nstore.fmt = 'a';
113  }
114  
115  void
116  oindm(Node *n, Node *res)
117  {
118  	Map *m;
119  	Node l;
120  
121  	m = cormap;
122  	if(m == 0)
123  		m = symmap;
124  	expr(n->left, &l);
125  	if(l.type != TINT)
126  		error("bad type for *");
127  	if(m == 0)
128  		error("no map for *");
129  	indir(m, l.nstore.u0.sival, l.nstore.fmt, res);
130  	res->nstore.comt = l.nstore.comt;
131  }
132  
133  void
134  oindc(Node *n, Node *res)
135  {
136  	Map *m;
137  	Node l;
138  
139  	m = symmap;
140  	if(m == 0)
141  		m = cormap;
142  	expr(n->left, &l);
143  	if(l.type != TINT)
144  		error("bad type for @");
145  	if(m == 0)
146  		error("no map for @");
147  	indir(m, l.nstore.u0.sival, l.nstore.fmt, res);
148  	res->nstore.comt = l.nstore.comt;
149  }
150  
151  void
152  oframe(Node *n, Node *res)
153  {
154  	char *p;
155  	Node *lp;
156  	long ival;
157  	Frtype *f;
158  
159  	p = n->sym->name;
160  	while(*p && *p == '$')
161  		p++;
162  	lp = n->left;
163  	if(localaddr(cormap, p, lp->sym->name, &ival, rget) < 0)
164  		error("colon: %r");
165  
166  	res->nstore.u0.sival = ival;
167  	res->op = OCONST;
168  	res->nstore.fmt = 'X';
169  	res->type = TINT;
170  
171  	/* Try and set comt */
172  	for(f = n->sym->local; f; f = f->next) {
173  		if(f->var == lp->sym) {
174  			res->nstore.comt = f->type;
175  			res->nstore.fmt = 'a';
176  			break;
177  		}
178  	}
179  }
180  
181  void
182  oindex(Node *n, Node *res)
183  {
184  	Node l, r;
185  
186  	expr(n->left, &l);
187  	expr(n->right, &r);
188  
189  	if(r.type != TINT)
190  		error("bad type for []");
191  
192  	switch(l.type) {
193  	default:
194  		error("lhs[] has bad type");
195  	case TINT:
196  		indir(cormap, l.nstore.u0.sival+(r.nstore.u0.sival*fsize[l.nstore.fmt]), l.nstore.fmt, res);
197  		res->nstore.comt = l.nstore.comt;
198  		res->nstore.fmt = l.nstore.fmt;
199  		break;
200  	case TLIST:
201  		nthelem(l.nstore.u0.sl, r.nstore.u0.sival, res);
202  		break;
203  	case TSTRING:
204  		res->nstore.u0.sival = 0;
205  		if(r.nstore.u0.sival >= 0 && r.nstore.u0.sival < l.nstore.u0.sstring->len) {
206  			int xx8;	/* to get around bug in vc */
207  			xx8 = r.nstore.u0.sival;
208  			res->nstore.u0.sival = l.nstore.u0.sstring->string[xx8];
209  		}
210  		res->op = OCONST;
211  		res->type = TINT;
212  		res->nstore.fmt = 'c';
213  		break;
214  	}
215  }
216  
217  void
218  oappend(Node *n, Node *res)
219  {
220  	Node r, l;
221  
222  	expr(n->left, &l);
223  	expr(n->right, &r);
224  	if(l.type != TLIST)
225  		error("must append to list");
226  	append(res, &l, &r);
227  }
228  
229  void
230  odelete(Node *n, Node *res)
231  {
232  	Node l, r;
233  
234  	expr(n->left, &l);
235  	expr(n->right, &r);
236  	if(l.type != TLIST)
237  		error("must delete from list");
238  	if(r.type != TINT)
239  		error("delete index must be integer");
240  
241  	delete(l.nstore.u0.sl, r.nstore.u0.sival, res);
242  }
243  
244  void
245  ohead(Node *n, Node *res)
246  {
247  	Node l;
248  
249  	expr(n->left, &l);
250  	if(l.type != TLIST)
251  		error("head needs list");
252  	res->op = OCONST;
253  	if(l.nstore.u0.sl) {
254  		res->type = l.nstore.u0.sl->type;
255  		res->nstore = l.nstore.u0.sl->lstore;
256  	}
257  	else {
258  		res->type = TLIST;
259  		res->nstore.u0.sl = 0;
260  	}
261  }
262  
263  void
264  otail(Node *n, Node *res)
265  {
266  	Node l;
267  
268  	expr(n->left, &l);
269  	if(l.type != TLIST)
270  		error("tail needs list");
271  	res->op = OCONST;
272  	res->type = TLIST;
273  	if(l.nstore.u0.sl)
274  		res->nstore.u0.sl = l.nstore.u0.sl->next;
275  	else
276  		res->nstore.u0.sl = 0;
277  }
278  
279  void
280  oconst(Node *n, Node *res)
281  {
282  	res->op = OCONST;
283  	res->type = n->type;
284  	res->nstore = n->nstore;
285  	res->nstore.comt = n->nstore.comt;
286  }
287  
288  void
289  oname(Node *n, Node *res)
290  {
291  	Value *v;
292  
293  	v = n->sym->v;
294  	if(v->set == 0)
295  		error("%s used but not set", n->sym->name);
296  	res->op = OCONST;
297  	res->type = v->type;
298  	res->nstore = v->vstore;
299  	res->nstore.comt = v->vstore.comt;
300  }
301  
302  void
303  octruct(Node *n, Node *res)
304  {
305  	res->op = OCONST;
306  	res->type = TLIST;
307  	res->nstore.u0.sl = construct(n->left);
308  }
309  
310  void
311  oasgn(Node *n, Node *res)
312  {
313  	Node *lp, r;
314  	Value *v;
315  
316  	lp = n->left;
317  	switch(lp->op) {
318  	case OINDM:
319  		windir(cormap, lp->left, n->right, res);
320  		break;
321  	case OINDC:
322  		windir(symmap, lp->left, n->right, res);
323  		break;
324  	default:
325  		chklval(lp);
326  		v = lp->sym->v;
327  		expr(n->right, &r);
328  		v->set = 1;
329  		v->type = r.type;
330  		v->vstore = r.nstore;
331  		res->op = OCONST;
332  		res->type = v->type;
333  		res->nstore = v->vstore;
334  		res->nstore.comt = v->vstore.comt;
335  	}
336  }
337  
338  void
339  oadd(Node *n, Node *res)
340  {
341  	Node l, r;
342  
343  	expr(n->left, &l);
344  	expr(n->right, &r);
345  	res->nstore.fmt = l.nstore.fmt;
346  	res->op = OCONST;
347  	res->type = TFLOAT;
348  	switch(l.type) {
349  	default:
350  		error("bad lhs type +");
351  	case TINT:
352  		switch(r.type) {
353  		case TINT:
354  			res->type = TINT;
355  			res->nstore.u0.sival = l.nstore.u0.sival+r.nstore.u0.sival;
356  			break;
357  		case TFLOAT:
358  			res->nstore.u0.sfval = l.nstore.u0.sival+r.nstore.u0.sfval;
359  			break;
360  		default:
361  			error("bad rhs type +");
362  		}
363  		break;
364  	case TFLOAT:
365  		switch(r.type) {
366  		case TINT:
367  			res->nstore.u0.sfval = l.nstore.u0.sfval+r.nstore.u0.sival;
368  			break;
369  		case TFLOAT:
370  			res->nstore.u0.sfval = l.nstore.u0.sfval+r.nstore.u0.sfval;
371  			break;
372  		default:
373  			error("bad rhs type +");
374  		}
375  		break;
376  	case TSTRING:
377  		if(r.type == TSTRING) {
378  			res->type = TSTRING;
379  			res->nstore.fmt = 's';
380  			res->nstore.u0.sstring = stradd(l.nstore.u0.sstring, r.nstore.u0.sstring);
381  			break;
382  		}
383  		error("bad rhs for +");
384  	case TLIST:
385  		res->type = TLIST;
386  		switch(r.type) {
387  		case TLIST:
388  			res->nstore.u0.sl = addlist(l.nstore.u0.sl, r.nstore.u0.sl);
389  			break;
390  		default:
391  			r.left = 0;
392  			r.right = 0;
393  			res->nstore.u0.sl = addlist(l.nstore.u0.sl, construct(&r));
394  			break;
395  		}
396  	}
397  }
398  
399  void
400  osub(Node *n, Node *res)
401  {
402  	Node l, r;
403  
404  	expr(n->left, &l);
405  	expr(n->right, &r);
406  	res->nstore.fmt = l.nstore.fmt;
407  	res->op = OCONST;
408  	res->type = TFLOAT;
409  	switch(l.type) {
410  	default:
411  		error("bad lhs type -");
412  	case TINT:
413  		switch(r.type) {
414  		case TINT:
415  			res->type = TINT;
416  			res->nstore.u0.sival = l.nstore.u0.sival-r.nstore.u0.sival;
417  			break;
418  		case TFLOAT:
419  			res->nstore.u0.sfval = l.nstore.u0.sival-r.nstore.u0.sfval;
420  			break;
421  		default:
422  			error("bad rhs type -");
423  		}
424  		break;
425  	case TFLOAT:
426  		switch(r.type) {
427  		case TINT:
428  			res->nstore.u0.sfval = l.nstore.u0.sfval-r.nstore.u0.sival;
429  			break;
430  		case TFLOAT:
431  			res->nstore.u0.sfval = l.nstore.u0.sfval-r.nstore.u0.sfval;
432  			break;
433  		default:
434  			error("bad rhs type -");
435  		}
436  		break;
437  	}
438  }
439  
440  void
441  omul(Node *n, Node *res)
442  {
443  	Node l, r;
444  
445  	expr(n->left, &l);
446  	expr(n->right, &r);
447  	res->nstore.fmt = l.nstore.fmt;
448  	res->op = OCONST;
449  	res->type = TFLOAT;
450  	switch(l.type) {
451  	default:
452  		error("bad lhs type *");
453  	case TINT:
454  		switch(r.type) {
455  		case TINT:
456  			res->type = TINT;
457  			res->nstore.u0.sival = l.nstore.u0.sival*r.nstore.u0.sival;
458  			break;
459  		case TFLOAT:
460  			res->nstore.u0.sfval = l.nstore.u0.sival*r.nstore.u0.sfval;
461  			break;
462  		default:
463  			error("bad rhs type *");
464  		}
465  		break;
466  	case TFLOAT:
467  		switch(r.type) {
468  		case TINT:
469  			res->nstore.u0.sfval = l.nstore.u0.sfval*r.nstore.u0.sival;
470  			break;
471  		case TFLOAT:
472  			res->nstore.u0.sfval = l.nstore.u0.sfval*r.nstore.u0.sfval;
473  			break;
474  		default:
475  			error("bad rhs type *");
476  		}
477  		break;
478  	}
479  }
480  
481  void
482  odiv(Node *n, Node *res)
483  {
484  	Node l, r;
485  
486  	expr(n->left, &l);
487  	expr(n->right, &r);
488  	res->nstore.fmt = l.nstore.fmt;
489  	res->op = OCONST;
490  	res->type = TFLOAT;
491  	switch(l.type) {
492  	default:
493  		error("bad lhs type /");
494  	case TINT:
495  		switch(r.type) {
496  		case TINT:
497  			res->type = TINT;
498  			if(r.nstore.u0.sival == 0)
499  				error("zero divide");
500  			res->nstore.u0.sival = l.nstore.u0.sival/r.nstore.u0.sival;
501  			break;
502  		case TFLOAT:
503  			if(r.nstore.u0.sfval == 0)
504  				error("zero divide");
505  			res->nstore.u0.sfval = l.nstore.u0.sival/r.nstore.u0.sfval;
506  			break;
507  		default:
508  			error("bad rhs type /");
509  		}
510  		break;
511  	case TFLOAT:
512  		switch(r.type) {
513  		case TINT:
514  			res->nstore.u0.sfval = l.nstore.u0.sfval/r.nstore.u0.sival;
515  			break;
516  		case TFLOAT:
517  			res->nstore.u0.sfval = l.nstore.u0.sfval/r.nstore.u0.sfval;
518  			break;
519  		default:
520  			error("bad rhs type /");
521  		}
522  		break;
523  	}
524  }
525  
526  void
527  omod(Node *n, Node *res)
528  {
529  	Node l, r;
530  
531  	expr(n->left, &l);
532  	expr(n->right, &r);
533  	res->nstore.fmt = l.nstore.fmt;
534  	res->op = OCONST;
535  	res->type = TINT;
536  	if(l.type != TINT || r.type != TINT)
537  		error("bad expr type %");
538  	res->nstore.u0.sival = l.nstore.u0.sival%r.nstore.u0.sival;
539  }
540  
541  void
542  olsh(Node *n, Node *res)
543  {
544  	Node l, r;
545  
546  	expr(n->left, &l);
547  	expr(n->right, &r);
548  	res->nstore.fmt = l.nstore.fmt;
549  	res->op = OCONST;
550  	res->type = TINT;
551  	if(l.type != TINT || r.type != TINT)
552  		error("bad expr type <<");
553  	res->nstore.u0.sival = l.nstore.u0.sival<<r.nstore.u0.sival;
554  }
555  
556  void
557  orsh(Node *n, Node *res)
558  {
559  	Node l, r;
560  
561  	expr(n->left, &l);
562  	expr(n->right, &r);
563  	res->nstore.fmt = l.nstore.fmt;
564  	res->op = OCONST;
565  	res->type = TINT;
566  	if(l.type != TINT || r.type != TINT)
567  		error("bad expr type >>");
568  	res->nstore.u0.sival = l.nstore.u0.sival>>r.nstore.u0.sival;
569  }
570  
571  void
572  olt(Node *n, Node *res)
573  {
574  	Node l, r;
575  
576  	expr(n->left, &l);
577  	expr(n->right, &r);
578  
579  	res->nstore.fmt = l.nstore.fmt;
580  	res->op = OCONST;
581  	res->type = TINT;
582  	switch(l.type) {
583  	default:
584  		error("bad lhs type <");
585  	case TINT:
586  		switch(r.type) {
587  		case TINT:
588  			res->nstore.u0.sival = l.nstore.u0.sival < r.nstore.u0.sival;
589  			break;
590  		case TFLOAT:
591  			res->nstore.u0.sival = l.nstore.u0.sival < r.nstore.u0.sfval;
592  			break;
593  		default:
594  			error("bad rhs type <");
595  		}
596  		break;
597  	case TFLOAT:
598  		switch(r.type) {
599  		case TINT:
600  			res->nstore.u0.sival = l.nstore.u0.sfval < r.nstore.u0.sival;
601  			break;
602  		case TFLOAT:
603  			res->nstore.u0.sival = l.nstore.u0.sfval < r.nstore.u0.sfval;
604  			break;
605  		default:
606  			error("bad rhs type <");
607  		}
608  		break;
609  	}
610  }
611  
612  void
613  ogt(Node *n, Node *res)
614  {
615  	Node l, r;
616  
617  	expr(n->left, &l);
618  	expr(n->right, &r);
619  	res->nstore.fmt = 'D';
620  	res->op = OCONST;
621  	res->type = TINT;
622  	switch(l.type) {
623  	default:
624  		error("bad lhs type >");
625  	case TINT:
626  		switch(r.type) {
627  		case TINT:
628  			res->nstore.u0.sival = l.nstore.u0.sival > r.nstore.u0.sival;
629  			break;
630  		case TFLOAT:
631  			res->nstore.u0.sival = l.nstore.u0.sival > r.nstore.u0.sfval;
632  			break;
633  		default:
634  			error("bad rhs type >");
635  		}
636  		break;
637  	case TFLOAT:
638  		switch(r.type) {
639  		case TINT:
640  			res->nstore.u0.sival = l.nstore.u0.sfval > r.nstore.u0.sival;
641  			break;
642  		case TFLOAT:
643  			res->nstore.u0.sival = l.nstore.u0.sfval > r.nstore.u0.sfval;
644  			break;
645  		default:
646  			error("bad rhs type >");
647  		}
648  		break;
649  	}
650  }
651  
652  void
653  oleq(Node *n, Node *res)
654  {
655  	Node l, r;
656  
657  	expr(n->left, &l);
658  	expr(n->right, &r);
659  	res->nstore.fmt = 'D';
660  	res->op = OCONST;
661  	res->type = TINT;
662  	switch(l.type) {
663  	default:
664  		error("bad expr type <=");
665  	case TINT:
666  		switch(r.type) {
667  		case TINT:
668  			res->nstore.u0.sival = l.nstore.u0.sival <= r.nstore.u0.sival;
669  			break;
670  		case TFLOAT:
671  			res->nstore.u0.sival = l.nstore.u0.sival <= r.nstore.u0.sfval;
672  			break;
673  		default:
674  			error("bad expr type <=");
675  		}
676  		break;
677  	case TFLOAT:
678  		switch(r.type) {
679  		case TINT:
680  			res->nstore.u0.sival = l.nstore.u0.sfval <= r.nstore.u0.sival;
681  			break;
682  		case TFLOAT:
683  			res->nstore.u0.sival = l.nstore.u0.sfval <= r.nstore.u0.sfval;
684  			break;
685  		default:
686  			error("bad expr type <=");
687  		}
688  		break;
689  	}
690  }
691  
692  void
693  ogeq(Node *n, Node *res)
694  {
695  	Node l, r;
696  
697  	expr(n->left, &l);
698  	expr(n->right, &r);
699  	res->nstore.fmt = 'D';
700  	res->op = OCONST;
701  	res->type = TINT;
702  	switch(l.type) {
703  	default:
704  		error("bad lhs type >=");
705  	case TINT:
706  		switch(r.type) {
707  		case TINT:
708  			res->nstore.u0.sival = l.nstore.u0.sival >= r.nstore.u0.sival;
709  			break;
710  		case TFLOAT:
711  			res->nstore.u0.sival = l.nstore.u0.sival >= r.nstore.u0.sfval;
712  			break;
713  		default:
714  			error("bad rhs type >=");
715  		}
716  		break;
717  	case TFLOAT:
718  		switch(r.type) {
719  		case TINT:
720  			res->nstore.u0.sival = l.nstore.u0.sfval >= r.nstore.u0.sival;
721  			break;
722  		case TFLOAT:
723  			res->nstore.u0.sival = l.nstore.u0.sfval >= r.nstore.u0.sfval;
724  			break;
725  		default:
726  			error("bad rhs type >=");
727  		}
728  		break;
729  	}
730  }
731  
732  void
733  oeq(Node *n, Node *res)
734  {
735  	Node l, r;
736  
737  	expr(n->left, &l);
738  	expr(n->right, &r);
739  	res->nstore.fmt = 'D';
740  	res->op = OCONST;
741  	res->type = TINT;
742  	res->nstore.u0.sival = 0;
743  	switch(l.type) {
744  	default:
745  		break;
746  	case TINT:
747  		switch(r.type) {
748  		case TINT:
749  			res->nstore.u0.sival = l.nstore.u0.sival == r.nstore.u0.sival;
750  			break;
751  		case TFLOAT:
752  			res->nstore.u0.sival = l.nstore.u0.sival == r.nstore.u0.sfval;
753  			break;
754  		default:
755  			break;
756  		}
757  		break;
758  	case TFLOAT:
759  		switch(r.type) {
760  		case TINT:
761  			res->nstore.u0.sival = l.nstore.u0.sfval == r.nstore.u0.sival;
762  			break;
763  		case TFLOAT:
764  			res->nstore.u0.sival = l.nstore.u0.sfval == r.nstore.u0.sfval;
765  			break;
766  		default:
767  			break;
768  		}
769  		break;
770  	case TSTRING:
771  		if(r.type == TSTRING) {
772  			res->nstore.u0.sival = scmp(r.nstore.u0.sstring, l.nstore.u0.sstring);
773  			break;
774  		}
775  		break;
776  	case TLIST:
777  		if(r.type == TLIST) {
778  			res->nstore.u0.sival = listcmp(l.nstore.u0.sl, r.nstore.u0.sl);
779  			break;
780  		}
781  		break;
782  	}
783  	if(n->op == ONEQ)
784  		res->nstore.u0.sival = !res->nstore.u0.sival;
785  }
786  
787  
788  void
789  oland(Node *n, Node *res)
790  {
791  	Node l, r;
792  
793  	expr(n->left, &l);
794  	expr(n->right, &r);
795  	res->nstore.fmt = l.nstore.fmt;
796  	res->op = OCONST;
797  	res->type = TINT;
798  	if(l.type != TINT || r.type != TINT)
799  		error("bad expr type &");
800  	res->nstore.u0.sival = l.nstore.u0.sival&r.nstore.u0.sival;
801  }
802  
803  void
804  oxor(Node *n, Node *res)
805  {
806  	Node l, r;
807  
808  	expr(n->left, &l);
809  	expr(n->right, &r);
810  	res->nstore.fmt = l.nstore.fmt;
811  	res->op = OCONST;
812  	res->type = TINT;
813  	if(l.type != TINT || r.type != TINT)
814  		error("bad expr type ^");
815  	res->nstore.u0.sival = l.nstore.u0.sival^r.nstore.u0.sival;
816  }
817  
818  void
819  olor(Node *n, Node *res)
820  {
821  	Node l, r;
822  
823  	expr(n->left, &l);
824  	expr(n->right, &r);
825  	res->nstore.fmt = l.nstore.fmt;
826  	res->op = OCONST;
827  	res->type = TINT;
828  	if(l.type != TINT || r.type != TINT)
829  		error("bad expr type |");
830  	res->nstore.u0.sival = l.nstore.u0.sival|r.nstore.u0.sival;
831  }
832  
833  void
834  ocand(Node *n, Node *res)
835  {
836  	Node l, r;
837  
838  	res->nstore.fmt = l.nstore.fmt;
839  	res->op = OCONST;
840  	res->type = TINT;
841  	res->nstore.u0.sival = 0;
842  	expr(n->left, &l);
843  	if(bool(&l) == 0)
844  		return;
845  	expr(n->right, &r);
846  	if(bool(&r) == 0)
847  		return;
848  	res->nstore.u0.sival = 1;
849  }
850  
851  void
852  onot(Node *n, Node *res)
853  {
854  	Node l;
855  
856  	res->op = OCONST;
857  	res->type = TINT;
858  	res->nstore.u0.sival = 0;
859  	expr(n->left, &l);
860  	if(bool(&l) == 0)
861  		res->nstore.u0.sival = 1;
862  }
863  
864  void
865  ocor(Node *n, Node *res)
866  {
867  	Node l, r;
868  
869  	res->op = OCONST;
870  	res->type = TINT;
871  	res->nstore.u0.sival = 0;
872  	expr(n->left, &l);
873  	if(bool(&l)) {
874  		res->nstore.u0.sival = 1;
875  		return;
876  	}
877  	expr(n->right, &r);
878  	if(bool(&r)) {
879  		res->nstore.u0.sival = 1;
880  		return;
881  	}
882  }
883  
884  void
885  oeinc(Node *n, Node *res)
886  {
887  	Value *v;
888  
889  	chklval(n->left);
890  	v = n->left->sym->v;
891  	res->op = OCONST;
892  	res->type = v->type;
893  	switch(v->type) {
894  	case TINT:
895  		if(n->op == OEDEC)
896  			v->vstore.u0.sival -= fmtsize(v);
897  		else
898  			v->vstore.u0.sival += fmtsize(v);
899  		break;
900  	case TFLOAT:
901  		if(n->op == OEDEC)
902  			v->vstore.u0.sfval--;
903  		else
904  			v->vstore.u0.sfval++;
905  		break;
906  	default:
907  		error("bad type for pre --/++");
908  	}
909  	res->nstore = v->vstore;
910  }
911  
912  void
913  opinc(Node *n, Node *res)
914  {
915  	Value *v;
916  
917  	chklval(n->left);
918  	v = n->left->sym->v;
919  	res->op = OCONST;
920  	res->type = v->type;
921  	res->nstore = v->vstore;
922  	switch(v->type) {
923  	case TINT:
924  		if(n->op == OPDEC)
925  			v->vstore.u0.sival -= fmtsize(v);
926  		else
927  			v->vstore.u0.sival += fmtsize(v);
928  		break;
929  	case TFLOAT:
930  		if(n->op == OPDEC)
931  			v->vstore.u0.sfval--;
932  		else
933  			v->vstore.u0.sfval++;
934  		break;
935  	default:
936  		error("bad type for post --/++");
937  	}
938  }
939  
940  void
941  ocall(Node *n, Node *res)
942  {
943  	Lsym *s;
944  	Rplace *rsav;
945  
946  	res->op = OCONST;		/* Default return value */
947  	res->type = TLIST;
948  	res->nstore.u0.sl = 0;
949  
950  	chklval(n->left);
951  	s = n->left->sym;
952  
953  	if(s->builtin) {
954  		(*s->builtin)(res, n->right);
955  		return;
956  	}
957  	if(s->proc == 0)
958  		error("no function %s", s->name);
959  
960  	rsav = ret;
961  	call(s->name, n->right, s->proc->left, s->proc->right, res);
962  	ret = rsav;
963  }
964  
965  void
966  ofmt(Node *n, Node *res)
967  {
968  	expr(n->left, res);
969  	res->nstore.fmt = n->right->nstore.u0.sival;
970  }
971  
972  void
973  owhat(Node *n, Node *res)
974  {
975  	res->op = OCONST;		/* Default return value */
976  	res->type = TLIST;
977  	res->nstore.u0.sl = 0;
978  	whatis(n->sym);
979  }
980  
981  void (*expop[])(Node*, Node*) =
982  {
983  	oname,		/* [ONAME]		oname, */
984  	oconst,		/* [OCONST]		oconst, */
985  	omul,		/* [OMUL]		omul, */
986  	odiv,		/* [ODIV]		odiv, */
987  	omod,		/* [OMOD]		omod, */
988  	oadd,		/* [OADD]		oadd, */
989  	osub,		/* [OSUB]		osub, */
990  	orsh,		/* [ORSH]		orsh, */
991  	olsh,		/* [OLSH]		olsh, */
992  	olt,		/* [OLT]		olt, */
993  	ogt,		/* [OGT]		ogt, */
994  	oleq,		/* [OLEQ]		oleq, */
995  	ogeq,		/* [OGEQ]		ogeq, */
996  	oeq,		/* [OEQ]		oeq, */
997  	oeq,		/* [ONEQ]		oeq, */
998  	oland,		/* [OLAND]		oland, */
999  	oxor,		/* [OXOR]		oxor, */
1000  	olor,		/* [OLOR]		olor, */
1001  	ocand,		/* [OCAND]		ocand, */
1002  	ocor,		/* [OCOR]		ocor, */
1003  	oasgn,		/* [OASGN]		oasgn, */
1004  	oindm,		/* [OINDM]		oindm, */
1005  	oeinc,		/* [OEDEC]		oeinc, */
1006  	oeinc,		/* [OEINC]		oeinc, */
1007  	opinc,		/* [OPINC]		opinc, */
1008  	opinc,		/* [OPDEC]		opinc, */
1009  	onot,		/* [ONOT]		onot, */
1010  	0,		/* [OIF]		0, */
1011  	0,		/* [ODO]		0, */
1012  	olist,		/* [OLIST]		olist, */
1013  	ocall,		/* [OCALL]		ocall, */
1014  	octruct,	/* [OCTRUCT]		octruct, */
1015  	0,		/* [OWHILE]		0, */
1016  	0,		/* [OELSE]		0, */
1017  	ohead,		/* [OHEAD]		ohead, */
1018  	otail,		/* [OTAIL]		otail, */
1019  	oappend,	/* [OAPPEND]		oappend, */
1020  	0,		/* [ORET]		0, */
1021  	oindex,		/* [OINDEX]		oindex, */
1022  	oindc,		/* [OINDC]		oindc, */
1023  	odot,		/* [ODOT]		odot, */
1024  	0,		/* [OLOCAL]		0, */
1025  	oframe,		/* [OFRAME]		oframe, */
1026  	0,		/* [OCOMPLEX]		0, */
1027  	odelete,	/* [ODELETE]		odelete, */
1028  	ocast,		/* [OCAST]		ocast, */
1029  	ofmt,		/* [OFMT]		ofmt, */
1030  	oeval,		/* [OEVAL]		oeval, */
1031  	owhat,		/* [OWHAT]		owhat, */
1032  };
1033