xref: /inferno-os/limbo/nodes.c (revision cd03a2dc3bfa8e793b2e4702966706c10d69b314)
137da2899SCharles.Forsyth #include "limbo.h"
237da2899SCharles.Forsyth 
337da2899SCharles.Forsyth static vlong
ipow(vlong x,int n)437da2899SCharles.Forsyth ipow(vlong x, int n)
537da2899SCharles.Forsyth {
637da2899SCharles.Forsyth 	int inv;
737da2899SCharles.Forsyth 	vlong r;
837da2899SCharles.Forsyth 
937da2899SCharles.Forsyth 	inv = 0;
1037da2899SCharles.Forsyth 	if(n < 0){
1137da2899SCharles.Forsyth 		n = -n;
1237da2899SCharles.Forsyth 		inv = 1;
1337da2899SCharles.Forsyth 	}
1437da2899SCharles.Forsyth 	r = 1;
1537da2899SCharles.Forsyth 	for(;;){
1637da2899SCharles.Forsyth 		if(n&1)
1737da2899SCharles.Forsyth 			r *= x;
1837da2899SCharles.Forsyth 		if((n >>= 1) == 0)
1937da2899SCharles.Forsyth 			break;
2037da2899SCharles.Forsyth 		x *= x;
2137da2899SCharles.Forsyth 	}
2237da2899SCharles.Forsyth 	if(inv)
2337da2899SCharles.Forsyth 		r = 1/r;
2437da2899SCharles.Forsyth 	return r;
2537da2899SCharles.Forsyth }
2637da2899SCharles.Forsyth 
2737da2899SCharles.Forsyth double
rpow(double x,int n)2837da2899SCharles.Forsyth rpow(double x, int n)
2937da2899SCharles.Forsyth {
3037da2899SCharles.Forsyth 	int inv;
3137da2899SCharles.Forsyth 	double r;
3237da2899SCharles.Forsyth 
3337da2899SCharles.Forsyth 	inv = 0;
3437da2899SCharles.Forsyth 	if(n < 0){
3537da2899SCharles.Forsyth 		n = -n;
3637da2899SCharles.Forsyth 		inv = 1;
3737da2899SCharles.Forsyth 	}
3837da2899SCharles.Forsyth 	r = 1;
3937da2899SCharles.Forsyth 	for(;;){
4037da2899SCharles.Forsyth 		if(n&1)
4137da2899SCharles.Forsyth 			r *= x;
4237da2899SCharles.Forsyth 		if((n >>= 1) == 0)
4337da2899SCharles.Forsyth 			break;
4437da2899SCharles.Forsyth 		x *= x;
4537da2899SCharles.Forsyth 	}
4637da2899SCharles.Forsyth 	if(inv)
4737da2899SCharles.Forsyth 		r = 1/r;
4837da2899SCharles.Forsyth 	return r;
4937da2899SCharles.Forsyth }
5037da2899SCharles.Forsyth 
5137da2899SCharles.Forsyth Long
real2fix(double v,Type * t)5237da2899SCharles.Forsyth real2fix(double v, Type *t)
5337da2899SCharles.Forsyth {
5437da2899SCharles.Forsyth 	v /= scale(t);
5537da2899SCharles.Forsyth 	v = v < 0 ? v-0.5: v+0.5;
5637da2899SCharles.Forsyth 	return v;
5737da2899SCharles.Forsyth }
5837da2899SCharles.Forsyth 
5937da2899SCharles.Forsyth Long
fix2fix(Long v,Type * f,Type * t)6037da2899SCharles.Forsyth fix2fix(Long v, Type *f, Type *t)
6137da2899SCharles.Forsyth {
6237da2899SCharles.Forsyth 	double r;
6337da2899SCharles.Forsyth 
6437da2899SCharles.Forsyth 	r = (double)v * (scale(f)/scale(t));
6537da2899SCharles.Forsyth 	r = r < 0 ? r-0.5: r+0.5;
6637da2899SCharles.Forsyth 	return r;
6737da2899SCharles.Forsyth }
6837da2899SCharles.Forsyth 
6937da2899SCharles.Forsyth double
fix2real(Long v,Type * f)7037da2899SCharles.Forsyth fix2real(Long v, Type *f)
7137da2899SCharles.Forsyth {
7237da2899SCharles.Forsyth 	return (double)v * scale(f);
7337da2899SCharles.Forsyth }
7437da2899SCharles.Forsyth 
7537da2899SCharles.Forsyth int
istuple(Node * n)7637da2899SCharles.Forsyth istuple(Node *n)
7737da2899SCharles.Forsyth {
7837da2899SCharles.Forsyth 	Decl *d;
7937da2899SCharles.Forsyth 
8037da2899SCharles.Forsyth 	switch(n->op){
8137da2899SCharles.Forsyth 	case Otuple:
8237da2899SCharles.Forsyth 		return 1;
8337da2899SCharles.Forsyth 	case Oname:
8437da2899SCharles.Forsyth 		d = n->decl;
8537da2899SCharles.Forsyth 		if(d->importid != nil)
8637da2899SCharles.Forsyth 			d = d->importid;
8737da2899SCharles.Forsyth 		return d->store == Dconst && (n->ty->kind == Ttuple || n->ty->kind == Tadt);
8837da2899SCharles.Forsyth 	case Odot:
8937da2899SCharles.Forsyth 		return 0;	/* istuple(n->left); */
9037da2899SCharles.Forsyth 	}
9137da2899SCharles.Forsyth 	return 0;
9237da2899SCharles.Forsyth }
9337da2899SCharles.Forsyth 
9437da2899SCharles.Forsyth static Node*
tuplemem(Node * n,Decl * d)9537da2899SCharles.Forsyth tuplemem(Node *n, Decl *d)
9637da2899SCharles.Forsyth {
9737da2899SCharles.Forsyth 	Type *ty;
9837da2899SCharles.Forsyth 	Decl *ids;
9937da2899SCharles.Forsyth 
10037da2899SCharles.Forsyth 	ty = n->ty;
10137da2899SCharles.Forsyth 	n = n->left;
10237da2899SCharles.Forsyth 	for(ids = ty->ids; ids != nil; ids = ids->next){
10337da2899SCharles.Forsyth 		if(ids->sym == d->sym)
10437da2899SCharles.Forsyth 			break;
10537da2899SCharles.Forsyth 		else
10637da2899SCharles.Forsyth 			n = n->right;
10737da2899SCharles.Forsyth 	}
10837da2899SCharles.Forsyth 	if(n == nil)
10937da2899SCharles.Forsyth 		fatal("tuplemem cannot cope !\n");
11037da2899SCharles.Forsyth 	return n->left;
11137da2899SCharles.Forsyth }
11237da2899SCharles.Forsyth 
11337da2899SCharles.Forsyth int
varcom(Decl * v)11437da2899SCharles.Forsyth varcom(Decl *v)
11537da2899SCharles.Forsyth {
11637da2899SCharles.Forsyth 	Node *n, tn;
11737da2899SCharles.Forsyth 
11837da2899SCharles.Forsyth 	n = v->init;
11937da2899SCharles.Forsyth 	n = fold(n);
12037da2899SCharles.Forsyth 	v->init = n;
12137da2899SCharles.Forsyth 	if(debug['v'])
12237da2899SCharles.Forsyth 		print("variable '%D' val %V\n", v, n);
12337da2899SCharles.Forsyth 	if(n == nil)
12437da2899SCharles.Forsyth 		return 1;
12537da2899SCharles.Forsyth 
12637da2899SCharles.Forsyth 	tn = znode;
12737da2899SCharles.Forsyth 	tn.op = Oname;
12837da2899SCharles.Forsyth 	tn.decl = v;
12937da2899SCharles.Forsyth 	tn.src = v->src;
13037da2899SCharles.Forsyth 	tn.ty = v->ty;
13137da2899SCharles.Forsyth 	return initable(&tn, n, 0);
13237da2899SCharles.Forsyth }
13337da2899SCharles.Forsyth 
13437da2899SCharles.Forsyth int
initable(Node * v,Node * n,int allocdep)13537da2899SCharles.Forsyth initable(Node *v, Node *n, int allocdep)
13637da2899SCharles.Forsyth {
13737da2899SCharles.Forsyth 	Node *e;
13837da2899SCharles.Forsyth 
13937da2899SCharles.Forsyth 	switch(n->ty->kind){
14037da2899SCharles.Forsyth 	case Tiface:
14137da2899SCharles.Forsyth 	case Tgoto:
14237da2899SCharles.Forsyth 	case Tcase:
14337da2899SCharles.Forsyth 	case Tcasel:
14437da2899SCharles.Forsyth 	case Tcasec:
14537da2899SCharles.Forsyth 	case Talt:
14637da2899SCharles.Forsyth 	case Texcept:
14737da2899SCharles.Forsyth 		return 1;
14837da2899SCharles.Forsyth 	case Tint:
14937da2899SCharles.Forsyth 	case Tbig:
15037da2899SCharles.Forsyth 	case Tbyte:
15137da2899SCharles.Forsyth 	case Treal:
15237da2899SCharles.Forsyth 	case Tstring:
15337da2899SCharles.Forsyth 	case Tfix:
15437da2899SCharles.Forsyth 		if(n->op != Oconst)
15537da2899SCharles.Forsyth 			break;
15637da2899SCharles.Forsyth 		return 1;
15737da2899SCharles.Forsyth 	case Tadt:
15837da2899SCharles.Forsyth 	case Tadtpick:
15937da2899SCharles.Forsyth 	case Ttuple:
16037da2899SCharles.Forsyth 		if(n->op == Otuple)
16137da2899SCharles.Forsyth 			n = n->left;
16237da2899SCharles.Forsyth 		else if(n->op == Ocall)
16337da2899SCharles.Forsyth 			n = n->right;
16437da2899SCharles.Forsyth 		else
16537da2899SCharles.Forsyth 			break;
16637da2899SCharles.Forsyth 		for(; n != nil; n = n->right)
16737da2899SCharles.Forsyth 			if(!initable(v, n->left, allocdep))
16837da2899SCharles.Forsyth 				return 0;
16937da2899SCharles.Forsyth 		return 1;
17037da2899SCharles.Forsyth 	case Tarray:
17137da2899SCharles.Forsyth 		if(n->op != Oarray)
17237da2899SCharles.Forsyth 			break;
17337da2899SCharles.Forsyth 		if(allocdep >= DADEPTH){
17437da2899SCharles.Forsyth 			nerror(v, "%Vs initializer has arrays nested more than %d deep", v, allocdep);
17537da2899SCharles.Forsyth 			return 0;
17637da2899SCharles.Forsyth 		}
17737da2899SCharles.Forsyth 		allocdep++;
17837da2899SCharles.Forsyth 		usedesc(mktdesc(n->ty->tof));
17937da2899SCharles.Forsyth 		if(n->left->op != Oconst){
18037da2899SCharles.Forsyth 			nerror(v, "%Vs size is not a constant", v);
18137da2899SCharles.Forsyth 			return 0;
18237da2899SCharles.Forsyth 		}
18337da2899SCharles.Forsyth 		for(e = n->right; e != nil; e = e->right)
18437da2899SCharles.Forsyth 			if(!initable(v, e->left->right, allocdep))
18537da2899SCharles.Forsyth 				return 0;
18637da2899SCharles.Forsyth 		return 1;
18737da2899SCharles.Forsyth 	case Tany:
18837da2899SCharles.Forsyth 		return 1;
18937da2899SCharles.Forsyth 	case Tref:
19037da2899SCharles.Forsyth 	case Tlist:
19137da2899SCharles.Forsyth 	case Tpoly:
19237da2899SCharles.Forsyth 	default:
19337da2899SCharles.Forsyth 		nerror(v, "can't initialize %Q", v);
19437da2899SCharles.Forsyth 		return 0;
19537da2899SCharles.Forsyth 	}
19637da2899SCharles.Forsyth 	nerror(v, "%Vs initializer, %V, is not a constant expression", v, n);
19737da2899SCharles.Forsyth 	return 0;
19837da2899SCharles.Forsyth }
19937da2899SCharles.Forsyth 
20037da2899SCharles.Forsyth /*
20137da2899SCharles.Forsyth  * merge together two sorted lists, yielding a sorted list
20237da2899SCharles.Forsyth  */
20337da2899SCharles.Forsyth static Node*
elemmerge(Node * e,Node * f)20437da2899SCharles.Forsyth elemmerge(Node *e, Node *f)
20537da2899SCharles.Forsyth {
20637da2899SCharles.Forsyth 	Node rock, *r;
20737da2899SCharles.Forsyth 
20837da2899SCharles.Forsyth 	r = &rock;
20937da2899SCharles.Forsyth 	while(e != nil && f != nil){
21037da2899SCharles.Forsyth 		if(e->left->left->val <= f->left->left->val){
21137da2899SCharles.Forsyth 			r->right = e;
21237da2899SCharles.Forsyth 			e = e->right;
21337da2899SCharles.Forsyth 		}else{
21437da2899SCharles.Forsyth 			r->right = f;
21537da2899SCharles.Forsyth 			f = f->right;
21637da2899SCharles.Forsyth 		}
21737da2899SCharles.Forsyth 		r = r->right;
21837da2899SCharles.Forsyth 	}
21937da2899SCharles.Forsyth 	if(e != nil)
22037da2899SCharles.Forsyth 		r->right = e;
22137da2899SCharles.Forsyth 	else
22237da2899SCharles.Forsyth 		r->right = f;
22337da2899SCharles.Forsyth 	return rock.right;
22437da2899SCharles.Forsyth }
22537da2899SCharles.Forsyth 
22637da2899SCharles.Forsyth /*
22737da2899SCharles.Forsyth  * recursively split lists and remerge them after they are sorted
22837da2899SCharles.Forsyth  */
22937da2899SCharles.Forsyth static Node*
recelemsort(Node * e,int n)23037da2899SCharles.Forsyth recelemsort(Node *e, int n)
23137da2899SCharles.Forsyth {
23237da2899SCharles.Forsyth 	Node *r, *ee;
23337da2899SCharles.Forsyth 	int i, m;
23437da2899SCharles.Forsyth 
23537da2899SCharles.Forsyth 	if(n <= 1)
23637da2899SCharles.Forsyth 		return e;
23737da2899SCharles.Forsyth 	m = n / 2 - 1;
23837da2899SCharles.Forsyth 	ee = e;
23937da2899SCharles.Forsyth 	for(i = 0; i < m; i++)
24037da2899SCharles.Forsyth 		ee = ee->right;
24137da2899SCharles.Forsyth 	r = ee->right;
24237da2899SCharles.Forsyth 	ee->right = nil;
24337da2899SCharles.Forsyth 	return elemmerge(recelemsort(e, n / 2),
24437da2899SCharles.Forsyth 			recelemsort(r, (n + 1) / 2));
24537da2899SCharles.Forsyth }
24637da2899SCharles.Forsyth 
24737da2899SCharles.Forsyth /*
24837da2899SCharles.Forsyth  * sort the elems by index; wild card is first
24937da2899SCharles.Forsyth  */
25037da2899SCharles.Forsyth Node*
elemsort(Node * e)25137da2899SCharles.Forsyth elemsort(Node *e)
25237da2899SCharles.Forsyth {
25337da2899SCharles.Forsyth 	Node *ee;
25437da2899SCharles.Forsyth 	int n;
25537da2899SCharles.Forsyth 
25637da2899SCharles.Forsyth 	n = 0;
25737da2899SCharles.Forsyth 	for(ee = e; ee != nil; ee = ee->right){
25837da2899SCharles.Forsyth 		if(ee->left->left->op == Owild)
25937da2899SCharles.Forsyth 			ee->left->left->val = -1;
26037da2899SCharles.Forsyth 		n++;
26137da2899SCharles.Forsyth 	}
26237da2899SCharles.Forsyth 	return recelemsort(e, n);
26337da2899SCharles.Forsyth }
26437da2899SCharles.Forsyth 
26537da2899SCharles.Forsyth int
sametree(Node * n1,Node * n2)26637da2899SCharles.Forsyth sametree(Node *n1, Node *n2)
26737da2899SCharles.Forsyth {
26837da2899SCharles.Forsyth 	if(n1 == n2)
26937da2899SCharles.Forsyth 		return 1;
27037da2899SCharles.Forsyth 	if(n1 == nil || n2 == nil)
27137da2899SCharles.Forsyth 		return 0;
27237da2899SCharles.Forsyth 	if(n1->op != n2->op || n1->ty != n2->ty)
27337da2899SCharles.Forsyth 		return 0;
27437da2899SCharles.Forsyth 	if(n1->op == Oconst){
27537da2899SCharles.Forsyth 		switch(n1->ty->kind){
27637da2899SCharles.Forsyth 		case Tbig:
27737da2899SCharles.Forsyth 		case Tbyte:
27837da2899SCharles.Forsyth 		case Tint:
27937da2899SCharles.Forsyth 			return n1->val == n2->val;
28037da2899SCharles.Forsyth 		case Treal:
28137da2899SCharles.Forsyth 			return n1->rval == n2->rval;
28237da2899SCharles.Forsyth 		case Tfix:
28337da2899SCharles.Forsyth 			return n1->val == n2->val && tequal(n1->ty, n2->ty);
28437da2899SCharles.Forsyth 		case Tstring:
28537da2899SCharles.Forsyth 			return n1->decl->sym == n2->decl->sym;
28637da2899SCharles.Forsyth 		}
28737da2899SCharles.Forsyth 		return 0;
28837da2899SCharles.Forsyth 	}
28937da2899SCharles.Forsyth 	return n1->decl == n2->decl && sametree(n1->left, n2->left) && sametree(n1->right, n2->right);
29037da2899SCharles.Forsyth }
29137da2899SCharles.Forsyth 
29237da2899SCharles.Forsyth int
occurs(Decl * d,Node * n)29337da2899SCharles.Forsyth occurs(Decl *d, Node *n)
29437da2899SCharles.Forsyth {
29537da2899SCharles.Forsyth 	if(n == nil)
29637da2899SCharles.Forsyth 		return 0;
29737da2899SCharles.Forsyth 	if(n->op == Oname){
29837da2899SCharles.Forsyth 		if(d == n->decl)
29937da2899SCharles.Forsyth 			return 1;
30037da2899SCharles.Forsyth 		return 0;
30137da2899SCharles.Forsyth 	}
30237da2899SCharles.Forsyth 	return occurs(d, n->left) + occurs(d, n->right);
30337da2899SCharles.Forsyth }
30437da2899SCharles.Forsyth 
30537da2899SCharles.Forsyth /*
30637da2899SCharles.Forsyth  * left and right subtrees the same
30737da2899SCharles.Forsyth  */
30837da2899SCharles.Forsyth Node*
folds(Node * n)30937da2899SCharles.Forsyth folds(Node *n)
31037da2899SCharles.Forsyth {
31137da2899SCharles.Forsyth 	if(hasside(n, 1))
31237da2899SCharles.Forsyth 		return n;
31337da2899SCharles.Forsyth 	switch(n->op){
31437da2899SCharles.Forsyth 	case Oeq:
31537da2899SCharles.Forsyth 	case Oleq:
31637da2899SCharles.Forsyth 	case Ogeq:
31737da2899SCharles.Forsyth 		n->val = 1;
31837da2899SCharles.Forsyth 		break;
31937da2899SCharles.Forsyth 	case Osub:
32037da2899SCharles.Forsyth 		n->val = 0;
32137da2899SCharles.Forsyth 		n->rval = 0.0;
32237da2899SCharles.Forsyth 		break;
32337da2899SCharles.Forsyth 	case Oxor:
32437da2899SCharles.Forsyth 	case Oneq:
32537da2899SCharles.Forsyth 	case Olt:
32637da2899SCharles.Forsyth 	case Ogt:
32737da2899SCharles.Forsyth 		n->val = 0;
32837da2899SCharles.Forsyth 		break;
32937da2899SCharles.Forsyth 	case Oand:
33037da2899SCharles.Forsyth 	case Oor:
33137da2899SCharles.Forsyth 	case Oandand:
33237da2899SCharles.Forsyth 	case Ooror:
33337da2899SCharles.Forsyth 		return n->left;
33437da2899SCharles.Forsyth 	default:
33537da2899SCharles.Forsyth 		return n;
33637da2899SCharles.Forsyth 	}
33737da2899SCharles.Forsyth 	n->op = Oconst;
33837da2899SCharles.Forsyth 	n->left = n->right = nil;
33937da2899SCharles.Forsyth 	n->decl = nil;
34037da2899SCharles.Forsyth 	return n;
34137da2899SCharles.Forsyth }
34237da2899SCharles.Forsyth 
34337da2899SCharles.Forsyth /*
34437da2899SCharles.Forsyth  * constant folding for typechecked expressions,
34537da2899SCharles.Forsyth  */
34637da2899SCharles.Forsyth Node*
fold(Node * n)34737da2899SCharles.Forsyth fold(Node *n)
34837da2899SCharles.Forsyth {
34937da2899SCharles.Forsyth 	if(n == nil)
35037da2899SCharles.Forsyth 		return nil;
35137da2899SCharles.Forsyth 	if(debug['F'])
35237da2899SCharles.Forsyth 		print("fold %n\n", n);
35337da2899SCharles.Forsyth 	n = efold(n);
35437da2899SCharles.Forsyth 	if(debug['F'])
35537da2899SCharles.Forsyth 		print("folded %n\n", n);
35637da2899SCharles.Forsyth 	return n;
35737da2899SCharles.Forsyth }
35837da2899SCharles.Forsyth 
35937da2899SCharles.Forsyth Node*
efold(Node * n)36037da2899SCharles.Forsyth efold(Node *n)
36137da2899SCharles.Forsyth {
36237da2899SCharles.Forsyth 	Decl *d;
36337da2899SCharles.Forsyth 	Node *left, *right;
36437da2899SCharles.Forsyth 
36537da2899SCharles.Forsyth 	if(n == nil)
36637da2899SCharles.Forsyth 		return nil;
36737da2899SCharles.Forsyth 
36837da2899SCharles.Forsyth 	left = n->left;
36937da2899SCharles.Forsyth 	right = n->right;
37037da2899SCharles.Forsyth 	switch(n->op){
37137da2899SCharles.Forsyth 	case Oname:
37237da2899SCharles.Forsyth 		d = n->decl;
37337da2899SCharles.Forsyth 		if(d->importid != nil)
37437da2899SCharles.Forsyth 			d = d->importid;
37537da2899SCharles.Forsyth 		if(d->store != Dconst){
37637da2899SCharles.Forsyth 			if(d->store == Dtag){
37737da2899SCharles.Forsyth 				n->op = Oconst;
37837da2899SCharles.Forsyth 				n->ty = tint;
37937da2899SCharles.Forsyth 				n->val = d->tag;
38037da2899SCharles.Forsyth 			}
38137da2899SCharles.Forsyth 			break;
38237da2899SCharles.Forsyth 		}
38337da2899SCharles.Forsyth 		switch(n->ty->kind){
38437da2899SCharles.Forsyth 		case Tbig:
38537da2899SCharles.Forsyth 			n->op = Oconst;
38637da2899SCharles.Forsyth 			n->val = d->init->val;
38737da2899SCharles.Forsyth 			break;
38837da2899SCharles.Forsyth 		case Tbyte:
38937da2899SCharles.Forsyth 			n->op = Oconst;
39037da2899SCharles.Forsyth 			n->val = d->init->val & 0xff;
39137da2899SCharles.Forsyth 			break;
39237da2899SCharles.Forsyth 		case Tint:
39337da2899SCharles.Forsyth 		case Tfix:
39437da2899SCharles.Forsyth 			n->op = Oconst;
39537da2899SCharles.Forsyth 			n->val = d->init->val;
39637da2899SCharles.Forsyth 			break;
39737da2899SCharles.Forsyth 		case Treal:
39837da2899SCharles.Forsyth 			n->op = Oconst;
39937da2899SCharles.Forsyth 			n->rval = d->init->rval;
40037da2899SCharles.Forsyth 			break;
40137da2899SCharles.Forsyth 		case Tstring:
40237da2899SCharles.Forsyth 			n->op = Oconst;
40337da2899SCharles.Forsyth 			n->decl = d->init->decl;
40437da2899SCharles.Forsyth 			break;
40537da2899SCharles.Forsyth 		case Ttuple:
40637da2899SCharles.Forsyth 			*n = *d->init;
40737da2899SCharles.Forsyth 			break;
40837da2899SCharles.Forsyth 		case Tadt:
40937da2899SCharles.Forsyth 			*n = *d->init;
41037da2899SCharles.Forsyth 			n = rewrite(n);	/* was call */
41137da2899SCharles.Forsyth 			break;
41237da2899SCharles.Forsyth 		case Texception:
41337da2899SCharles.Forsyth 			if(!n->ty->cons)
41437da2899SCharles.Forsyth 				fatal("non-const exception type in efold");
41537da2899SCharles.Forsyth 			n->op = Oconst;
41637da2899SCharles.Forsyth 			break;
41737da2899SCharles.Forsyth 		default:
41837da2899SCharles.Forsyth 			fatal("unknown const type %T in efold", n->ty);
41937da2899SCharles.Forsyth 			break;
42037da2899SCharles.Forsyth 		}
42137da2899SCharles.Forsyth 		break;
42237da2899SCharles.Forsyth 	case Oadd:
42337da2899SCharles.Forsyth 		left = efold(left);
42437da2899SCharles.Forsyth 		right = efold(right);
42537da2899SCharles.Forsyth 		n->left = left;
42637da2899SCharles.Forsyth 		n->right = right;
42737da2899SCharles.Forsyth 		if(n->ty == tstring && right->op == Oconst){
42837da2899SCharles.Forsyth 			if(left->op == Oconst)
42937da2899SCharles.Forsyth 				n = mksconst(&n->src, stringcat(left->decl->sym, right->decl->sym));
43037da2899SCharles.Forsyth 			else if(left->op == Oadd && left->ty == tstring && left->right->op == Oconst){
43137da2899SCharles.Forsyth 				left->right = mksconst(&n->src, stringcat(left->right->decl->sym, right->decl->sym));
43237da2899SCharles.Forsyth 				n = left;
43337da2899SCharles.Forsyth 			}
43437da2899SCharles.Forsyth 		}
43537da2899SCharles.Forsyth 		break;
43637da2899SCharles.Forsyth 	case Olen:
43737da2899SCharles.Forsyth 		left = efold(left);
43837da2899SCharles.Forsyth 		n->left = left;
43937da2899SCharles.Forsyth 		if(left->ty == tstring && left->op == Oconst)
44037da2899SCharles.Forsyth 			n = mkconst(&n->src, utflen(left->decl->sym->name));
44137da2899SCharles.Forsyth 		break;
44237da2899SCharles.Forsyth 	case Oslice:
44337da2899SCharles.Forsyth 		if(right->left->op == Onothing)
44437da2899SCharles.Forsyth 			right->left = mkconst(&right->left->src, 0);
44537da2899SCharles.Forsyth 		n->left = efold(left);
44637da2899SCharles.Forsyth 		n->right = efold(right);
44737da2899SCharles.Forsyth 		break;
44837da2899SCharles.Forsyth 	case Oinds:
44937da2899SCharles.Forsyth 		n->left = left = efold(left);
45037da2899SCharles.Forsyth 		n->right = right = efold(right);
45137da2899SCharles.Forsyth 		if(right->op == Oconst && left->op == Oconst){
45237da2899SCharles.Forsyth 			;
45337da2899SCharles.Forsyth 		}
45437da2899SCharles.Forsyth 		break;
45537da2899SCharles.Forsyth 	case Ocast:
45637da2899SCharles.Forsyth 		n->op = Ocast;
45737da2899SCharles.Forsyth 		left = efold(left);
45837da2899SCharles.Forsyth 		n->left = left;
45937da2899SCharles.Forsyth 		if(n->ty == left->ty || n->ty->kind == Tfix && tequal(n->ty, left->ty))
46037da2899SCharles.Forsyth 			return left;
46137da2899SCharles.Forsyth 		if(left->op == Oconst)
46237da2899SCharles.Forsyth 			return foldcast(n, left);
46337da2899SCharles.Forsyth 		break;
46437da2899SCharles.Forsyth 	case Odot:
46537da2899SCharles.Forsyth 	case Omdot:
46637da2899SCharles.Forsyth 		/*
46737da2899SCharles.Forsyth 		 * what about side effects from left?
46837da2899SCharles.Forsyth 		 */
46937da2899SCharles.Forsyth 		d = right->decl;
47037da2899SCharles.Forsyth 		switch(d->store){
47137da2899SCharles.Forsyth 		case Dconst:
47237da2899SCharles.Forsyth 		case Dtag:
47337da2899SCharles.Forsyth 		case Dtype:
47437da2899SCharles.Forsyth 			/*
47537da2899SCharles.Forsyth 			 * set it up as a name and let that case do the hard work
47637da2899SCharles.Forsyth 			 */
47737da2899SCharles.Forsyth 			n->op = Oname;
47837da2899SCharles.Forsyth 			n->decl = d;
47937da2899SCharles.Forsyth 			n->left = nil;
48037da2899SCharles.Forsyth 			n->right = nil;
48137da2899SCharles.Forsyth 			return efold(n);
48237da2899SCharles.Forsyth 		}
48337da2899SCharles.Forsyth 		n->left = efold(left);
48437da2899SCharles.Forsyth 		if(n->left->op == Otuple)
48537da2899SCharles.Forsyth 			n = tuplemem(n->left, d);
48637da2899SCharles.Forsyth 		else
48737da2899SCharles.Forsyth 			n->right = efold(right);
48837da2899SCharles.Forsyth 		break;
48937da2899SCharles.Forsyth 	case Otagof:
49037da2899SCharles.Forsyth 		if(n->decl != nil){
49137da2899SCharles.Forsyth 			n->op = Oconst;
49237da2899SCharles.Forsyth 			n->left = nil;
49337da2899SCharles.Forsyth 			n->right = nil;
49437da2899SCharles.Forsyth 			n->val = n->decl->tag;
49537da2899SCharles.Forsyth 			return efold(n);
49637da2899SCharles.Forsyth 		}
49737da2899SCharles.Forsyth 		n->left = efold(left);
49837da2899SCharles.Forsyth 		break;
49937da2899SCharles.Forsyth 	case Oif:
50037da2899SCharles.Forsyth 		n->left = left = efold(left);
50137da2899SCharles.Forsyth 		n->right = right = efold(right);
50237da2899SCharles.Forsyth 		if(left->op == Oconst){
50337da2899SCharles.Forsyth 			if(left->val)
50437da2899SCharles.Forsyth 				return right->left;
50537da2899SCharles.Forsyth 			else
50637da2899SCharles.Forsyth 				return right->right;
50737da2899SCharles.Forsyth 		}
50837da2899SCharles.Forsyth 		break;
50937da2899SCharles.Forsyth 	default:
51037da2899SCharles.Forsyth 		n->left = efold(left);
51137da2899SCharles.Forsyth 		n->right = efold(right);
51237da2899SCharles.Forsyth 		break;
51337da2899SCharles.Forsyth 	}
51437da2899SCharles.Forsyth 
51537da2899SCharles.Forsyth 	left = n->left;
51637da2899SCharles.Forsyth 	right = n->right;
51737da2899SCharles.Forsyth 	if(left == nil)
51837da2899SCharles.Forsyth 		return n;
51937da2899SCharles.Forsyth 
52037da2899SCharles.Forsyth 	if(right == nil){
52137da2899SCharles.Forsyth 		if(left->op == Oconst){
52237da2899SCharles.Forsyth 			if(left->ty == tint || left->ty == tbyte || left->ty == tbig)
52337da2899SCharles.Forsyth 				return foldc(n);
52437da2899SCharles.Forsyth 			if(left->ty == treal)
52537da2899SCharles.Forsyth 				return foldr(n);
52637da2899SCharles.Forsyth 		}
52737da2899SCharles.Forsyth 		return n;
52837da2899SCharles.Forsyth 	}
52937da2899SCharles.Forsyth 
53037da2899SCharles.Forsyth 	if(left->op == Oconst){
53137da2899SCharles.Forsyth 		switch(n->op){
53237da2899SCharles.Forsyth 		case Olsh:
53337da2899SCharles.Forsyth 		case Orsh:
53437da2899SCharles.Forsyth 			if(left->val == 0 && !hasside(right, 1))
53537da2899SCharles.Forsyth 				return left;
53637da2899SCharles.Forsyth 			break;
53737da2899SCharles.Forsyth 		case Ooror:
53837da2899SCharles.Forsyth 			if(left->ty == tint || left->ty == tbyte || left->ty == tbig){
53937da2899SCharles.Forsyth 				if(left->val == 0){
54037da2899SCharles.Forsyth 					n = mkbin(Oneq, right, mkconst(&right->src, 0));
54137da2899SCharles.Forsyth 					n->ty = right->ty;
54237da2899SCharles.Forsyth 					n->left->ty = right->ty;
54337da2899SCharles.Forsyth 					return efold(n);
54437da2899SCharles.Forsyth 				}
54537da2899SCharles.Forsyth 				left->val = 1;
54637da2899SCharles.Forsyth 				return left;
54737da2899SCharles.Forsyth 			}
54837da2899SCharles.Forsyth 			break;
54937da2899SCharles.Forsyth 		case Oandand:
55037da2899SCharles.Forsyth 			if(left->ty == tint || left->ty == tbyte || left->ty == tbig){
55137da2899SCharles.Forsyth 				if(left->val == 0)
55237da2899SCharles.Forsyth 					return left;
55337da2899SCharles.Forsyth 				n = mkbin(Oneq, right, mkconst(&right->src, 0));
55437da2899SCharles.Forsyth 				n->ty = right->ty;
55537da2899SCharles.Forsyth 				n->left->ty = right->ty;
55637da2899SCharles.Forsyth 				return efold(n);
55737da2899SCharles.Forsyth 			}
55837da2899SCharles.Forsyth 			break;
55937da2899SCharles.Forsyth 		}
56037da2899SCharles.Forsyth 	}
56137da2899SCharles.Forsyth 	if(left->op == Oconst && right->op != Oconst
56237da2899SCharles.Forsyth 	&& opcommute[n->op]
56337da2899SCharles.Forsyth 	&& n->ty != tstring){
56437da2899SCharles.Forsyth 		n->op = opcommute[n->op];
56537da2899SCharles.Forsyth 		n->left = right;
56637da2899SCharles.Forsyth 		n->right = left;
56737da2899SCharles.Forsyth 		left = right;
56837da2899SCharles.Forsyth 		right = n->right;
56937da2899SCharles.Forsyth 	}
57037da2899SCharles.Forsyth 	if(right->op == Oconst && left->op == n->op && left->right->op == Oconst
57137da2899SCharles.Forsyth 	&& (n->op == Oadd || n->op == Omul || n->op == Oor || n->op == Oxor || n->op == Oand)
57237da2899SCharles.Forsyth 	&& n->ty != tstring){
57337da2899SCharles.Forsyth 		n->left = left->left;
57437da2899SCharles.Forsyth 		left->left = right;
57537da2899SCharles.Forsyth 		right = efold(left);
57637da2899SCharles.Forsyth 		n->right = right;
57737da2899SCharles.Forsyth 		left = n->left;
57837da2899SCharles.Forsyth 	}
57937da2899SCharles.Forsyth 	if(right->op == Oconst){
58037da2899SCharles.Forsyth 		if(n->op == Oexp && left->ty == treal){
58137da2899SCharles.Forsyth 			if(left->op == Oconst)
58237da2899SCharles.Forsyth 				return foldr(n);
58337da2899SCharles.Forsyth 			return n;
58437da2899SCharles.Forsyth 		}
58537da2899SCharles.Forsyth 		if(right->ty == tint || right->ty == tbyte || left->ty == tbig){
58637da2899SCharles.Forsyth 			if(left->op == Oconst)
58737da2899SCharles.Forsyth 				return foldc(n);
58837da2899SCharles.Forsyth 			return foldvc(n);
58937da2899SCharles.Forsyth 		}
59037da2899SCharles.Forsyth 		if(right->ty == treal && left->op == Oconst)
59137da2899SCharles.Forsyth 			return foldr(n);
59237da2899SCharles.Forsyth 	}
59337da2899SCharles.Forsyth 	if(sametree(left, right))
59437da2899SCharles.Forsyth 		return folds(n);
59537da2899SCharles.Forsyth 	return n;
59637da2899SCharles.Forsyth }
59737da2899SCharles.Forsyth 
59837da2899SCharles.Forsyth /*
59937da2899SCharles.Forsyth  * does evaluating the node have any side effects?
60037da2899SCharles.Forsyth  */
60137da2899SCharles.Forsyth int
hasside(Node * n,int strict)60237da2899SCharles.Forsyth hasside(Node *n, int strict)
60337da2899SCharles.Forsyth {
60437da2899SCharles.Forsyth 	for(; n != nil; n = n->right){
60537da2899SCharles.Forsyth 		if(sideeffect[n->op] && (strict || n->op != Oadr && n->op != Oind))
60637da2899SCharles.Forsyth 			return 1;
60737da2899SCharles.Forsyth 		if(hasside(n->left, strict))
60837da2899SCharles.Forsyth 			return 1;
60937da2899SCharles.Forsyth 	}
61037da2899SCharles.Forsyth 	return 0;
61137da2899SCharles.Forsyth }
61237da2899SCharles.Forsyth 
61337da2899SCharles.Forsyth int
hascall(Node * n)61437da2899SCharles.Forsyth hascall(Node *n)
61537da2899SCharles.Forsyth {
61637da2899SCharles.Forsyth 	for(; n != nil; n = n->right){
61737da2899SCharles.Forsyth 		if(n->op == Ocall || n->op == Ospawn)
61837da2899SCharles.Forsyth 			return 1;
61937da2899SCharles.Forsyth 		if(hascall(n->left))
62037da2899SCharles.Forsyth 			return 1;
62137da2899SCharles.Forsyth 	}
62237da2899SCharles.Forsyth 	return 0;
62337da2899SCharles.Forsyth }
62437da2899SCharles.Forsyth 
62537da2899SCharles.Forsyth int
hasasgns(Node * n)62637da2899SCharles.Forsyth hasasgns(Node *n)
62737da2899SCharles.Forsyth {
62837da2899SCharles.Forsyth 	if(n == nil)
62937da2899SCharles.Forsyth 		return 0;
63037da2899SCharles.Forsyth 	if(n->op != Ocall && isused[n->op] && n->op != Onothing)
63137da2899SCharles.Forsyth 		return 1;
63237da2899SCharles.Forsyth 	return hasasgns(n->left) || hasasgns(n->right);
63337da2899SCharles.Forsyth }
63437da2899SCharles.Forsyth 
63537da2899SCharles.Forsyth int
nodes(Node * n)63637da2899SCharles.Forsyth nodes(Node *n)
63737da2899SCharles.Forsyth {
63837da2899SCharles.Forsyth 	if(n == nil)
63937da2899SCharles.Forsyth 		return 0;
64037da2899SCharles.Forsyth 	return 1+nodes(n->left)+nodes(n->right);
64137da2899SCharles.Forsyth }
64237da2899SCharles.Forsyth 
64337da2899SCharles.Forsyth Node*
foldcast(Node * n,Node * left)64437da2899SCharles.Forsyth foldcast(Node *n, Node *left)
64537da2899SCharles.Forsyth {
64637da2899SCharles.Forsyth 	Real r;
64737da2899SCharles.Forsyth 	char *buf, *e;
64837da2899SCharles.Forsyth 
64937da2899SCharles.Forsyth 	switch(left->ty->kind){
65037da2899SCharles.Forsyth 	case Tint:
65137da2899SCharles.Forsyth 		left->val &= 0xffffffff;
65237da2899SCharles.Forsyth 		if(left->val & 0x80000000)
65337da2899SCharles.Forsyth 			left->val |= (Long)0xffffffff << 32;
65437da2899SCharles.Forsyth 		return foldcasti(n, left);
65537da2899SCharles.Forsyth 	case Tbyte:
65637da2899SCharles.Forsyth 		left->val &= 0xff;
65737da2899SCharles.Forsyth 		return foldcasti(n, left);
65837da2899SCharles.Forsyth 	case Tbig:
65937da2899SCharles.Forsyth 		return foldcasti(n, left);
66037da2899SCharles.Forsyth 	case Treal:
66137da2899SCharles.Forsyth 		switch(n->ty->kind){
66237da2899SCharles.Forsyth 		case Tint:
66337da2899SCharles.Forsyth 		case Tbyte:
66437da2899SCharles.Forsyth 		case Tbig:
66537da2899SCharles.Forsyth 			r = left->rval;
66637da2899SCharles.Forsyth 			left->val = r < 0 ? r - .5 : r + .5;
66737da2899SCharles.Forsyth 			break;
66837da2899SCharles.Forsyth 		case Tfix:
66937da2899SCharles.Forsyth 			left->val = real2fix(left->rval, n->ty);
67037da2899SCharles.Forsyth 			break;
67137da2899SCharles.Forsyth 		case Tstring:
67237da2899SCharles.Forsyth 			buf = allocmem(NumSize);
67337da2899SCharles.Forsyth 			e = seprint(buf, buf+NumSize, "%g", left->rval);
67437da2899SCharles.Forsyth 			return mksconst(&n->src, enterstring(buf, e-buf));
67537da2899SCharles.Forsyth 		default:
67637da2899SCharles.Forsyth 			return n;
67737da2899SCharles.Forsyth 		}
67837da2899SCharles.Forsyth 		break;
67937da2899SCharles.Forsyth 	case Tfix:
68037da2899SCharles.Forsyth 		switch(n->ty->kind){
68137da2899SCharles.Forsyth 		case Tint:
68237da2899SCharles.Forsyth 		case Tbyte:
68337da2899SCharles.Forsyth 		case Tbig:
68437da2899SCharles.Forsyth 			left->val = fix2real(left->val, left->ty);
68537da2899SCharles.Forsyth 			break;
68637da2899SCharles.Forsyth 		case Treal:
68737da2899SCharles.Forsyth 			left->rval = fix2real(left->val, left->ty);
68837da2899SCharles.Forsyth 			break;
68937da2899SCharles.Forsyth 		case Tfix:
69037da2899SCharles.Forsyth 			if(tequal(left->ty, n->ty))
69137da2899SCharles.Forsyth 				return left;
69237da2899SCharles.Forsyth 			left->val = fix2fix(left->val, left->ty, n->ty);
69337da2899SCharles.Forsyth 			break;
69437da2899SCharles.Forsyth 		case Tstring:
69537da2899SCharles.Forsyth 			buf = allocmem(NumSize);
69637da2899SCharles.Forsyth 			e = seprint(buf, buf+NumSize, "%g", fix2real(left->val, left->ty));
69737da2899SCharles.Forsyth 			return mksconst(&n->src, enterstring(buf, e-buf));
69837da2899SCharles.Forsyth 		default:
69937da2899SCharles.Forsyth 			return n;
70037da2899SCharles.Forsyth 		}
70137da2899SCharles.Forsyth 		break;
70237da2899SCharles.Forsyth 	case Tstring:
70337da2899SCharles.Forsyth 		switch(n->ty->kind){
70437da2899SCharles.Forsyth 		case Tint:
70537da2899SCharles.Forsyth 		case Tbyte:
70637da2899SCharles.Forsyth 		case Tbig:
70737da2899SCharles.Forsyth 			left->val = strtoi(left->decl->sym->name, 10);
70837da2899SCharles.Forsyth 			break;
70937da2899SCharles.Forsyth 		case Treal:
71037da2899SCharles.Forsyth 			left->rval = strtod(left->decl->sym->name, nil);
71137da2899SCharles.Forsyth 			break;
71237da2899SCharles.Forsyth 		case Tfix:
71337da2899SCharles.Forsyth 			left->val = real2fix(strtod(left->decl->sym->name, nil), n->ty);
71437da2899SCharles.Forsyth 			break;
71537da2899SCharles.Forsyth 		default:
71637da2899SCharles.Forsyth 			return n;
71737da2899SCharles.Forsyth 		}
71837da2899SCharles.Forsyth 		break;
71937da2899SCharles.Forsyth 	default:
72037da2899SCharles.Forsyth 		return n;
72137da2899SCharles.Forsyth 	}
72237da2899SCharles.Forsyth 	left->ty = n->ty;
72337da2899SCharles.Forsyth 	left->src = n->src;
72437da2899SCharles.Forsyth 	return left;
72537da2899SCharles.Forsyth }
72637da2899SCharles.Forsyth 
72737da2899SCharles.Forsyth /*
72837da2899SCharles.Forsyth  * left is some kind of int type
72937da2899SCharles.Forsyth  */
73037da2899SCharles.Forsyth Node*
foldcasti(Node * n,Node * left)73137da2899SCharles.Forsyth foldcasti(Node *n, Node *left)
73237da2899SCharles.Forsyth {
73337da2899SCharles.Forsyth 	char *buf, *e;
73437da2899SCharles.Forsyth 
73537da2899SCharles.Forsyth 	switch(n->ty->kind){
73637da2899SCharles.Forsyth 	case Tint:
73737da2899SCharles.Forsyth 		left->val &= 0xffffffff;
73837da2899SCharles.Forsyth 		if(left->val & 0x80000000)
73937da2899SCharles.Forsyth 			left->val |= (Long)0xffffffff << 32;
74037da2899SCharles.Forsyth 		break;
74137da2899SCharles.Forsyth 	case Tbyte:
74237da2899SCharles.Forsyth 		left->val &= 0xff;
74337da2899SCharles.Forsyth 		break;
74437da2899SCharles.Forsyth 	case Tbig:
74537da2899SCharles.Forsyth 		break;
74637da2899SCharles.Forsyth 	case Treal:
74737da2899SCharles.Forsyth 		left->rval = left->val;
74837da2899SCharles.Forsyth 		break;
74937da2899SCharles.Forsyth 	case Tfix:
75037da2899SCharles.Forsyth 		left->val = real2fix(left->val, n->ty);
75137da2899SCharles.Forsyth 		break;
75237da2899SCharles.Forsyth 	case Tstring:
75337da2899SCharles.Forsyth 		buf = allocmem(NumSize);
75437da2899SCharles.Forsyth 		e = seprint(buf, buf+NumSize, "%lld", left->val);
75537da2899SCharles.Forsyth 		return mksconst(&n->src, enterstring(buf, e-buf));
75637da2899SCharles.Forsyth 	default:
75737da2899SCharles.Forsyth 		return n;
75837da2899SCharles.Forsyth 	}
75937da2899SCharles.Forsyth 	left->ty = n->ty;
76037da2899SCharles.Forsyth 	left->src = n->src;
76137da2899SCharles.Forsyth 	return left;
76237da2899SCharles.Forsyth }
76337da2899SCharles.Forsyth 
76437da2899SCharles.Forsyth /*
76537da2899SCharles.Forsyth  * right is a const int
76637da2899SCharles.Forsyth  */
76737da2899SCharles.Forsyth Node*
foldvc(Node * n)76837da2899SCharles.Forsyth foldvc(Node *n)
76937da2899SCharles.Forsyth {
77037da2899SCharles.Forsyth 	Node *left, *right;
77137da2899SCharles.Forsyth 
77237da2899SCharles.Forsyth 	left = n->left;
77337da2899SCharles.Forsyth 	right = n->right;
77437da2899SCharles.Forsyth 	switch(n->op){
77537da2899SCharles.Forsyth 	case Oadd:
77637da2899SCharles.Forsyth 	case Osub:
77737da2899SCharles.Forsyth 	case Oor:
77837da2899SCharles.Forsyth 	case Oxor:
77937da2899SCharles.Forsyth 	case Olsh:
78037da2899SCharles.Forsyth 	case Orsh:
78137da2899SCharles.Forsyth 	case Ooror:
78237da2899SCharles.Forsyth 		if(right->val == 0)
78337da2899SCharles.Forsyth 			return left;
78437da2899SCharles.Forsyth 		if(n->op == Ooror && !hasside(left, 1))
78537da2899SCharles.Forsyth 			return right;
78637da2899SCharles.Forsyth 		break;
78737da2899SCharles.Forsyth 	case Oand:
78837da2899SCharles.Forsyth 		if(right->val == 0 && !hasside(left, 1))
78937da2899SCharles.Forsyth 			return right;
79037da2899SCharles.Forsyth 		break;
79137da2899SCharles.Forsyth 	case Omul:
79237da2899SCharles.Forsyth 		if(right->val == 1)
79337da2899SCharles.Forsyth 			return left;
79437da2899SCharles.Forsyth 		if(right->val == 0 && !hasside(left, 1))
79537da2899SCharles.Forsyth 			return right;
79637da2899SCharles.Forsyth 		break;
79737da2899SCharles.Forsyth 	case Odiv:
79837da2899SCharles.Forsyth 		if(right->val == 1)
79937da2899SCharles.Forsyth 			return left;
80037da2899SCharles.Forsyth 		break;
80137da2899SCharles.Forsyth 	case Omod:
80237da2899SCharles.Forsyth 		if(right->val == 1 && !hasside(left, 1)){
80337da2899SCharles.Forsyth 			right->val = 0;
80437da2899SCharles.Forsyth 			return right;
80537da2899SCharles.Forsyth 		}
80637da2899SCharles.Forsyth 		break;
80737da2899SCharles.Forsyth 	case Oexp:
80837da2899SCharles.Forsyth 		if(right->val == 0){
80937da2899SCharles.Forsyth 			right->val = 1;
81037da2899SCharles.Forsyth 			return right;
81137da2899SCharles.Forsyth 		}
81237da2899SCharles.Forsyth 		if(right->val == 1)
81337da2899SCharles.Forsyth 			return left;
81437da2899SCharles.Forsyth 		break;
81537da2899SCharles.Forsyth 	case Oandand:
81637da2899SCharles.Forsyth 		if(right->val != 0)
81737da2899SCharles.Forsyth 			return left;
81837da2899SCharles.Forsyth 		if(!hasside(left, 1))
81937da2899SCharles.Forsyth 			return right;
82037da2899SCharles.Forsyth 		break;
82137da2899SCharles.Forsyth 	case Oneq:
82237da2899SCharles.Forsyth 		if(!isrelop[left->op])
82337da2899SCharles.Forsyth 			return n;
82437da2899SCharles.Forsyth 		if(right->val == 0)
82537da2899SCharles.Forsyth 			return left;
82637da2899SCharles.Forsyth 		n->op = Onot;
82737da2899SCharles.Forsyth 		n->right = nil;
82837da2899SCharles.Forsyth 		break;
82937da2899SCharles.Forsyth 	case Oeq:
83037da2899SCharles.Forsyth 		if(!isrelop[left->op])
83137da2899SCharles.Forsyth 			return n;
83237da2899SCharles.Forsyth 		if(right->val != 0)
83337da2899SCharles.Forsyth 			return left;
83437da2899SCharles.Forsyth 		n->op = Onot;
83537da2899SCharles.Forsyth 		n->right = nil;
83637da2899SCharles.Forsyth 		break;
83737da2899SCharles.Forsyth 	}
83837da2899SCharles.Forsyth 	return n;
83937da2899SCharles.Forsyth }
84037da2899SCharles.Forsyth 
84137da2899SCharles.Forsyth /*
84237da2899SCharles.Forsyth  * left and right are const ints
84337da2899SCharles.Forsyth  */
84437da2899SCharles.Forsyth Node*
foldc(Node * n)84537da2899SCharles.Forsyth foldc(Node *n)
84637da2899SCharles.Forsyth {
84737da2899SCharles.Forsyth 	Node *left, *right;
84837da2899SCharles.Forsyth 	Long lv, v;
84937da2899SCharles.Forsyth 	int rv, nb;
85037da2899SCharles.Forsyth 
85137da2899SCharles.Forsyth 	left = n->left;
85237da2899SCharles.Forsyth 	right = n->right;
85337da2899SCharles.Forsyth 	switch(n->op){
85437da2899SCharles.Forsyth 	case Oadd:
85537da2899SCharles.Forsyth 		v = left->val + right->val;
85637da2899SCharles.Forsyth 		break;
85737da2899SCharles.Forsyth 	case Osub:
85837da2899SCharles.Forsyth 		v = left->val - right->val;
85937da2899SCharles.Forsyth 		break;
86037da2899SCharles.Forsyth 	case Omul:
86137da2899SCharles.Forsyth 		v = left->val * right->val;
86237da2899SCharles.Forsyth 		break;
86337da2899SCharles.Forsyth 	case Odiv:
86437da2899SCharles.Forsyth 		if(right->val == 0){
86537da2899SCharles.Forsyth 			nerror(n, "divide by 0 in constant expression");
86637da2899SCharles.Forsyth 			return n;
86737da2899SCharles.Forsyth 		}
86837da2899SCharles.Forsyth 		v = left->val / right->val;
86937da2899SCharles.Forsyth 		break;
87037da2899SCharles.Forsyth 	case Omod:
87137da2899SCharles.Forsyth 		if(right->val == 0){
87237da2899SCharles.Forsyth 			nerror(n, "mod by 0 in constant expression");
87337da2899SCharles.Forsyth 			return n;
87437da2899SCharles.Forsyth 		}
87537da2899SCharles.Forsyth 		v = left->val % right->val;
87637da2899SCharles.Forsyth 		break;
87737da2899SCharles.Forsyth 	case Oexp:
87837da2899SCharles.Forsyth 		if(left->val == 0 && right->val < 0){
87937da2899SCharles.Forsyth 			nerror(n, "0 to negative power in constant expression");
88037da2899SCharles.Forsyth 			return n;
88137da2899SCharles.Forsyth 		}
88237da2899SCharles.Forsyth 		v = ipow(left->val, right->val);
88337da2899SCharles.Forsyth 		break;
88437da2899SCharles.Forsyth 	case Oand:
88537da2899SCharles.Forsyth 		v = left->val & right->val;
88637da2899SCharles.Forsyth 		break;
88737da2899SCharles.Forsyth 	case Oor:
88837da2899SCharles.Forsyth 		v = left->val | right->val;
88937da2899SCharles.Forsyth 		break;
89037da2899SCharles.Forsyth 	case Oxor:
89137da2899SCharles.Forsyth 		v = left->val ^ right->val;
89237da2899SCharles.Forsyth 		break;
89337da2899SCharles.Forsyth 	case Olsh:
89437da2899SCharles.Forsyth 		lv = left->val;
89537da2899SCharles.Forsyth 		rv = right->val;
89637da2899SCharles.Forsyth 		if(rv < 0 || rv >= n->ty->size * 8){
89737da2899SCharles.Forsyth 			nwarn(n, "shift amount %d out of range", rv);
89837da2899SCharles.Forsyth 			rv = 0;
89937da2899SCharles.Forsyth 		}
90037da2899SCharles.Forsyth 		if(rv == 0){
90137da2899SCharles.Forsyth 			v = lv;
90237da2899SCharles.Forsyth 			break;
90337da2899SCharles.Forsyth 		}
90437da2899SCharles.Forsyth 		v = lv << rv;
90537da2899SCharles.Forsyth 		break;
90637da2899SCharles.Forsyth 	case Orsh:
90737da2899SCharles.Forsyth 		lv = left->val;
90837da2899SCharles.Forsyth 		rv = right->val;
90937da2899SCharles.Forsyth 		nb = n->ty->size * 8;
91037da2899SCharles.Forsyth 		if(rv < 0 || rv >= nb){
91137da2899SCharles.Forsyth 			nwarn(n, "shift amount %d out of range", rv);
91237da2899SCharles.Forsyth 			rv = 0;
91337da2899SCharles.Forsyth 		}
91437da2899SCharles.Forsyth 		if(rv == 0){
91537da2899SCharles.Forsyth 			v = lv;
91637da2899SCharles.Forsyth 			break;
91737da2899SCharles.Forsyth 		}
91837da2899SCharles.Forsyth 		v = lv >> rv;
91937da2899SCharles.Forsyth 
92037da2899SCharles.Forsyth 		/*
92137da2899SCharles.Forsyth 		 * properly sign extend c right shifts
92237da2899SCharles.Forsyth 		 */
92337da2899SCharles.Forsyth 		if((n->ty == tint || n->ty == tbig)
92437da2899SCharles.Forsyth 		&& rv != 0
92537da2899SCharles.Forsyth 		&& (lv & (1<<(nb-1)))){
92637da2899SCharles.Forsyth 			lv = 0;
92737da2899SCharles.Forsyth 			lv = ~lv;
92837da2899SCharles.Forsyth 			v |= lv << (nb - rv);
92937da2899SCharles.Forsyth 		}
93037da2899SCharles.Forsyth 		break;
93137da2899SCharles.Forsyth 	case Oneg:
93237da2899SCharles.Forsyth 		v = -left->val;
93337da2899SCharles.Forsyth 		break;
93437da2899SCharles.Forsyth 	case Ocomp:
93537da2899SCharles.Forsyth 		v = ~left->val;
93637da2899SCharles.Forsyth 		break;
93737da2899SCharles.Forsyth 	case Oeq:
93837da2899SCharles.Forsyth 		v = left->val == right->val;
93937da2899SCharles.Forsyth 		break;
94037da2899SCharles.Forsyth 	case Oneq:
94137da2899SCharles.Forsyth 		v = left->val != right->val;
94237da2899SCharles.Forsyth 		break;
94337da2899SCharles.Forsyth 	case Ogt:
94437da2899SCharles.Forsyth 		v = left->val > right->val;
94537da2899SCharles.Forsyth 		break;
94637da2899SCharles.Forsyth 	case Ogeq:
94737da2899SCharles.Forsyth 		v = left->val >= right->val;
94837da2899SCharles.Forsyth 		break;
94937da2899SCharles.Forsyth 	case Olt:
95037da2899SCharles.Forsyth 		v = left->val < right->val;
95137da2899SCharles.Forsyth 		break;
95237da2899SCharles.Forsyth 	case Oleq:
95337da2899SCharles.Forsyth 		v = left->val <= right->val;
95437da2899SCharles.Forsyth 		break;
95537da2899SCharles.Forsyth 	case Oandand:
95637da2899SCharles.Forsyth 		v = left->val && right->val;
95737da2899SCharles.Forsyth 		break;
95837da2899SCharles.Forsyth 	case Ooror:
95937da2899SCharles.Forsyth 		v = left->val || right->val;
96037da2899SCharles.Forsyth 		break;
96137da2899SCharles.Forsyth 	case Onot:
96237da2899SCharles.Forsyth 		v = !left->val;
96337da2899SCharles.Forsyth 		break;
96437da2899SCharles.Forsyth 	default:
96537da2899SCharles.Forsyth 		return n;
96637da2899SCharles.Forsyth 	}
96737da2899SCharles.Forsyth 	if(n->ty == tint){
96837da2899SCharles.Forsyth 		v &= 0xffffffff;
96937da2899SCharles.Forsyth 		if(v & 0x80000000)
97037da2899SCharles.Forsyth 			v |= (Long)0xffffffff << 32;
97137da2899SCharles.Forsyth 	}else if(n->ty == tbyte)
97237da2899SCharles.Forsyth 		v &= 0xff;
97337da2899SCharles.Forsyth 	n->left = nil;
97437da2899SCharles.Forsyth 	n->right = nil;
97537da2899SCharles.Forsyth 	n->decl = nil;
97637da2899SCharles.Forsyth 	n->op = Oconst;
97737da2899SCharles.Forsyth 	n->val = v;
97837da2899SCharles.Forsyth 	return n;
97937da2899SCharles.Forsyth }
98037da2899SCharles.Forsyth 
98137da2899SCharles.Forsyth /*
98237da2899SCharles.Forsyth  * left and right are const reals
98337da2899SCharles.Forsyth  */
98437da2899SCharles.Forsyth Node*
foldr(Node * n)98537da2899SCharles.Forsyth foldr(Node *n)
98637da2899SCharles.Forsyth {
98737da2899SCharles.Forsyth 	Node *left, *right;
98837da2899SCharles.Forsyth 	double rv;
98937da2899SCharles.Forsyth 	Long v;
99037da2899SCharles.Forsyth 
99137da2899SCharles.Forsyth 	rv = 0.;
99237da2899SCharles.Forsyth 	v = 0;
99337da2899SCharles.Forsyth 
99437da2899SCharles.Forsyth 	left = n->left;
99537da2899SCharles.Forsyth 	right = n->right;
99637da2899SCharles.Forsyth 	switch(n->op){
99737da2899SCharles.Forsyth 	case Ocast:
99837da2899SCharles.Forsyth 		return n;
99937da2899SCharles.Forsyth 	case Oadd:
100037da2899SCharles.Forsyth 		rv = left->rval + right->rval;
100137da2899SCharles.Forsyth 		break;
100237da2899SCharles.Forsyth 	case Osub:
100337da2899SCharles.Forsyth 		rv = left->rval - right->rval;
100437da2899SCharles.Forsyth 		break;
100537da2899SCharles.Forsyth 	case Omul:
100637da2899SCharles.Forsyth 		rv = left->rval * right->rval;
100737da2899SCharles.Forsyth 		break;
100837da2899SCharles.Forsyth 	case Odiv:
100937da2899SCharles.Forsyth 		rv = left->rval / right->rval;
101037da2899SCharles.Forsyth 		break;
101137da2899SCharles.Forsyth 	case Oexp:
101237da2899SCharles.Forsyth 		rv = rpow(left->rval, right->val);
101337da2899SCharles.Forsyth 		break;
101437da2899SCharles.Forsyth 	case Oneg:
101537da2899SCharles.Forsyth 		rv = -left->rval;
101637da2899SCharles.Forsyth 		break;
101737da2899SCharles.Forsyth 	case Oinv:
101837da2899SCharles.Forsyth 		if(left->rval == 0.0){
101937da2899SCharles.Forsyth 			error(n->src.start, "divide by 0 in fixed point type");
102037da2899SCharles.Forsyth 			return n;
102137da2899SCharles.Forsyth 		}
102237da2899SCharles.Forsyth 		rv = 1/left->rval;
102337da2899SCharles.Forsyth 		break;
102437da2899SCharles.Forsyth 	case Oeq:
102537da2899SCharles.Forsyth 		v = left->rval == right->rval;
102637da2899SCharles.Forsyth 		break;
102737da2899SCharles.Forsyth 	case Oneq:
102837da2899SCharles.Forsyth 		v = left->rval != right->rval;
102937da2899SCharles.Forsyth 		break;
103037da2899SCharles.Forsyth 	case Ogt:
103137da2899SCharles.Forsyth 		v = left->rval > right->rval;
103237da2899SCharles.Forsyth 		break;
103337da2899SCharles.Forsyth 	case Ogeq:
103437da2899SCharles.Forsyth 		v = left->rval >= right->rval;
103537da2899SCharles.Forsyth 		break;
103637da2899SCharles.Forsyth 	case Olt:
103737da2899SCharles.Forsyth 		v = left->rval < right->rval;
103837da2899SCharles.Forsyth 		break;
103937da2899SCharles.Forsyth 	case Oleq:
104037da2899SCharles.Forsyth 		v = left->rval <= right->rval;
104137da2899SCharles.Forsyth 		break;
104237da2899SCharles.Forsyth 	default:
104337da2899SCharles.Forsyth 		return n;
104437da2899SCharles.Forsyth 	}
104537da2899SCharles.Forsyth 	n->left = nil;
104637da2899SCharles.Forsyth 	n->right = nil;
104737da2899SCharles.Forsyth 
1048*cd03a2dcSforsyth 	if(isNaN(rv))
104937da2899SCharles.Forsyth 		rv = canonnan;
105037da2899SCharles.Forsyth 
105137da2899SCharles.Forsyth 	n->rval = rv;
105237da2899SCharles.Forsyth 	n->val = v;
105337da2899SCharles.Forsyth 
105437da2899SCharles.Forsyth 	n->op = Oconst;
105537da2899SCharles.Forsyth 	return n;
105637da2899SCharles.Forsyth }
105737da2899SCharles.Forsyth 
105837da2899SCharles.Forsyth Node*
varinit(Decl * d,Node * e)105937da2899SCharles.Forsyth varinit(Decl *d, Node *e)
106037da2899SCharles.Forsyth {
106137da2899SCharles.Forsyth 	Node *n;
106237da2899SCharles.Forsyth 
106337da2899SCharles.Forsyth 	n = mkdeclname(&e->src, d);
106437da2899SCharles.Forsyth 	if(d->next == nil)
106537da2899SCharles.Forsyth 		return mkbin(Oas, n, e);
106637da2899SCharles.Forsyth 	return mkbin(Oas, n, varinit(d->next, e));
106737da2899SCharles.Forsyth }
106837da2899SCharles.Forsyth 
106937da2899SCharles.Forsyth /*
107037da2899SCharles.Forsyth  * given: an Oseq list with left == next or the last child
107137da2899SCharles.Forsyth  * make a list with the right == next
107237da2899SCharles.Forsyth  * ie: Oseq(Oseq(a, b),c) ==> Oseq(a, Oseq(b, Oseq(c, nil))))
107337da2899SCharles.Forsyth  */
107437da2899SCharles.Forsyth Node*
rotater(Node * e)107537da2899SCharles.Forsyth rotater(Node *e)
107637da2899SCharles.Forsyth {
107737da2899SCharles.Forsyth 	Node *left;
107837da2899SCharles.Forsyth 
107937da2899SCharles.Forsyth 	if(e == nil)
108037da2899SCharles.Forsyth 		return e;
108137da2899SCharles.Forsyth 	if(e->op != Oseq)
108237da2899SCharles.Forsyth 		return mkunary(Oseq, e);
108337da2899SCharles.Forsyth 	e->right = mkunary(Oseq, e->right);
108437da2899SCharles.Forsyth 	while(e->left->op == Oseq){
108537da2899SCharles.Forsyth 		left = e->left;
108637da2899SCharles.Forsyth 		e->left = left->right;
108737da2899SCharles.Forsyth 		left->right = e;
108837da2899SCharles.Forsyth 		e = left;
108937da2899SCharles.Forsyth 	}
109037da2899SCharles.Forsyth 	return e;
109137da2899SCharles.Forsyth }
109237da2899SCharles.Forsyth 
109337da2899SCharles.Forsyth /*
109437da2899SCharles.Forsyth  * reverse the case labels list
109537da2899SCharles.Forsyth  */
109637da2899SCharles.Forsyth Node*
caselist(Node * s,Node * nr)109737da2899SCharles.Forsyth caselist(Node *s, Node *nr)
109837da2899SCharles.Forsyth {
109937da2899SCharles.Forsyth 	Node *r;
110037da2899SCharles.Forsyth 
110137da2899SCharles.Forsyth 	r = s->right;
110237da2899SCharles.Forsyth 	s->right = nr;
110337da2899SCharles.Forsyth 	if(r == nil)
110437da2899SCharles.Forsyth 		return s;
110537da2899SCharles.Forsyth 	return caselist(r, s);
110637da2899SCharles.Forsyth }
110737da2899SCharles.Forsyth 
110837da2899SCharles.Forsyth /*
110937da2899SCharles.Forsyth  * e is a seq of expressions; make into cons's to build a list
111037da2899SCharles.Forsyth  */
111137da2899SCharles.Forsyth Node*
etolist(Node * e)111237da2899SCharles.Forsyth etolist(Node *e)
111337da2899SCharles.Forsyth {
111437da2899SCharles.Forsyth 	Node *left, *n;
111537da2899SCharles.Forsyth 
111637da2899SCharles.Forsyth 	if(e == nil)
111737da2899SCharles.Forsyth 		return nil;
111837da2899SCharles.Forsyth 	n = mknil(&e->src);
111937da2899SCharles.Forsyth 	n->src.start = n->src.stop;
112037da2899SCharles.Forsyth 	if(e->op != Oseq)
112137da2899SCharles.Forsyth 		return mkbin(Ocons, e, n);
112237da2899SCharles.Forsyth 	e->right = mkbin(Ocons, e->right, n);
112337da2899SCharles.Forsyth 	while(e->left->op == Oseq){
112437da2899SCharles.Forsyth 		e->op = Ocons;
112537da2899SCharles.Forsyth 		left = e->left;
112637da2899SCharles.Forsyth 		e->left = left->right;
112737da2899SCharles.Forsyth 		left->right = e;
112837da2899SCharles.Forsyth 		e = left;
112937da2899SCharles.Forsyth 	}
113037da2899SCharles.Forsyth 	e->op = Ocons;
113137da2899SCharles.Forsyth 	return e;
113237da2899SCharles.Forsyth }
113337da2899SCharles.Forsyth 
113437da2899SCharles.Forsyth Node*
dupn(int resrc,Src * src,Node * n)113537da2899SCharles.Forsyth dupn(int resrc, Src *src, Node *n)
113637da2899SCharles.Forsyth {
113737da2899SCharles.Forsyth 	Node *nn;
113837da2899SCharles.Forsyth 
113937da2899SCharles.Forsyth 	nn = allocmem(sizeof *nn);
114037da2899SCharles.Forsyth 	*nn = *n;
114137da2899SCharles.Forsyth 	if(resrc)
114237da2899SCharles.Forsyth 		nn->src = *src;
114337da2899SCharles.Forsyth 	if(nn->left != nil)
114437da2899SCharles.Forsyth 		nn->left = dupn(resrc, src, nn->left);
114537da2899SCharles.Forsyth 	if(nn->right != nil)
114637da2899SCharles.Forsyth 		nn->right = dupn(resrc, src, nn->right);
114737da2899SCharles.Forsyth 	return nn;
114837da2899SCharles.Forsyth }
114937da2899SCharles.Forsyth 
115037da2899SCharles.Forsyth Node*
mkn(int op,Node * left,Node * right)115137da2899SCharles.Forsyth mkn(int op, Node *left, Node *right)
115237da2899SCharles.Forsyth {
115337da2899SCharles.Forsyth 	Node *n;
115437da2899SCharles.Forsyth 
115537da2899SCharles.Forsyth 	n = allocmem(sizeof *n);
115637da2899SCharles.Forsyth 	*n = znode;
115737da2899SCharles.Forsyth 	n->op = op;
115837da2899SCharles.Forsyth 	n->left = left;
115937da2899SCharles.Forsyth 	n->right = right;
116037da2899SCharles.Forsyth 	return n;
116137da2899SCharles.Forsyth }
116237da2899SCharles.Forsyth 
116337da2899SCharles.Forsyth Node*
mkunary(int op,Node * left)116437da2899SCharles.Forsyth mkunary(int op, Node *left)
116537da2899SCharles.Forsyth {
116637da2899SCharles.Forsyth 	Node *n;
116737da2899SCharles.Forsyth 
116837da2899SCharles.Forsyth 	n = mkn(op, left, nil);
116937da2899SCharles.Forsyth 	n->src = left->src;
117037da2899SCharles.Forsyth 	return n;
117137da2899SCharles.Forsyth }
117237da2899SCharles.Forsyth 
117337da2899SCharles.Forsyth Node*
mkbin(int op,Node * left,Node * right)117437da2899SCharles.Forsyth mkbin(int op, Node *left, Node *right)
117537da2899SCharles.Forsyth {
117637da2899SCharles.Forsyth 	Node *n;
117737da2899SCharles.Forsyth 
117837da2899SCharles.Forsyth 	n = mkn(op, left, right);
117937da2899SCharles.Forsyth 	n->src.start = left->src.start;
118037da2899SCharles.Forsyth 	n->src.stop = right->src.stop;
118137da2899SCharles.Forsyth 	return n;
118237da2899SCharles.Forsyth }
118337da2899SCharles.Forsyth 
118437da2899SCharles.Forsyth Node*
mkdeclname(Src * src,Decl * d)118537da2899SCharles.Forsyth mkdeclname(Src *src, Decl *d)
118637da2899SCharles.Forsyth {
118737da2899SCharles.Forsyth 	Node *n;
118837da2899SCharles.Forsyth 
118937da2899SCharles.Forsyth 	n = mkn(Oname, nil, nil);
119037da2899SCharles.Forsyth 	n->src = *src;
119137da2899SCharles.Forsyth 	n->decl = d;
119237da2899SCharles.Forsyth 	n->ty = d->ty;
119337da2899SCharles.Forsyth 	d->refs++;
119437da2899SCharles.Forsyth 	return n;
119537da2899SCharles.Forsyth }
119637da2899SCharles.Forsyth 
119737da2899SCharles.Forsyth Node*
mknil(Src * src)119837da2899SCharles.Forsyth mknil(Src *src)
119937da2899SCharles.Forsyth {
120037da2899SCharles.Forsyth 	return mkdeclname(src, nildecl);
120137da2899SCharles.Forsyth }
120237da2899SCharles.Forsyth 
120337da2899SCharles.Forsyth Node*
mkname(Src * src,Sym * s)120437da2899SCharles.Forsyth mkname(Src *src, Sym *s)
120537da2899SCharles.Forsyth {
120637da2899SCharles.Forsyth 	Node *n;
120737da2899SCharles.Forsyth 
120837da2899SCharles.Forsyth 	n = mkn(Oname, nil, nil);
120937da2899SCharles.Forsyth 	n->src = *src;
121037da2899SCharles.Forsyth 	if(s->unbound == nil){
121137da2899SCharles.Forsyth 		s->unbound = mkdecl(src, Dunbound, nil);
121237da2899SCharles.Forsyth 		s->unbound->sym = s;
121337da2899SCharles.Forsyth 	}
121437da2899SCharles.Forsyth 	n->decl = s->unbound;
121537da2899SCharles.Forsyth 	return n;
121637da2899SCharles.Forsyth }
121737da2899SCharles.Forsyth 
121837da2899SCharles.Forsyth Node*
mkconst(Src * src,Long v)121937da2899SCharles.Forsyth mkconst(Src *src, Long v)
122037da2899SCharles.Forsyth {
122137da2899SCharles.Forsyth 	Node *n;
122237da2899SCharles.Forsyth 
122337da2899SCharles.Forsyth 	n = mkn(Oconst, nil, nil);
122437da2899SCharles.Forsyth 	n->ty = tint;
122537da2899SCharles.Forsyth 	n->val = v;
122637da2899SCharles.Forsyth 	n->src = *src;
122737da2899SCharles.Forsyth 	return n;
122837da2899SCharles.Forsyth }
122937da2899SCharles.Forsyth 
123037da2899SCharles.Forsyth Node*
mkrconst(Src * src,Real v)123137da2899SCharles.Forsyth mkrconst(Src *src, Real v)
123237da2899SCharles.Forsyth {
123337da2899SCharles.Forsyth 	Node *n;
123437da2899SCharles.Forsyth 
123537da2899SCharles.Forsyth 	n = mkn(Oconst, nil, nil);
123637da2899SCharles.Forsyth 	n->ty = treal;
123737da2899SCharles.Forsyth 	n->rval = v;
123837da2899SCharles.Forsyth 	n->src = *src;
123937da2899SCharles.Forsyth 	return n;
124037da2899SCharles.Forsyth }
124137da2899SCharles.Forsyth 
124237da2899SCharles.Forsyth Node*
mksconst(Src * src,Sym * s)124337da2899SCharles.Forsyth mksconst(Src *src, Sym *s)
124437da2899SCharles.Forsyth {
124537da2899SCharles.Forsyth 	Node *n;
124637da2899SCharles.Forsyth 
124737da2899SCharles.Forsyth 	n = mkn(Oconst, nil, nil);
124837da2899SCharles.Forsyth 	n->ty = tstring;
124937da2899SCharles.Forsyth 	n->decl = mkdecl(src, Dconst, tstring);
125037da2899SCharles.Forsyth 	n->decl->sym = s;
125137da2899SCharles.Forsyth 	n->src = *src;
125237da2899SCharles.Forsyth 	return n;
125337da2899SCharles.Forsyth }
125437da2899SCharles.Forsyth 
125537da2899SCharles.Forsyth int
opconv(Fmt * f)125637da2899SCharles.Forsyth opconv(Fmt *f)
125737da2899SCharles.Forsyth {
125837da2899SCharles.Forsyth 	int op;
125937da2899SCharles.Forsyth 	char buf[32];
126037da2899SCharles.Forsyth 
126137da2899SCharles.Forsyth 	op = va_arg(f->args, int);
126237da2899SCharles.Forsyth 	if(op < 0 || op > Oend) {
126337da2899SCharles.Forsyth 		seprint(buf, buf+sizeof(buf), "op %d", op);
126437da2899SCharles.Forsyth 		return fmtstrcpy(f, buf);
126537da2899SCharles.Forsyth 	}
126637da2899SCharles.Forsyth 	return fmtstrcpy(f, opname[op]);
126737da2899SCharles.Forsyth }
126837da2899SCharles.Forsyth 
126937da2899SCharles.Forsyth int
etconv(Fmt * f)127037da2899SCharles.Forsyth etconv(Fmt *f)
127137da2899SCharles.Forsyth {
127237da2899SCharles.Forsyth 	Node *n;
127337da2899SCharles.Forsyth 	char buf[1024];
127437da2899SCharles.Forsyth 
127537da2899SCharles.Forsyth 	n = va_arg(f->args, Node*);
127637da2899SCharles.Forsyth 	if(n->ty == tany || n->ty == tnone || n->ty == terror)
127737da2899SCharles.Forsyth 		seprint(buf, buf+sizeof(buf), "%V", n);
127837da2899SCharles.Forsyth 	else
127937da2899SCharles.Forsyth 		seprint(buf, buf+sizeof(buf), "%V of type %T", n, n->ty);
128037da2899SCharles.Forsyth 	return fmtstrcpy(f, buf);
128137da2899SCharles.Forsyth }
128237da2899SCharles.Forsyth 
128337da2899SCharles.Forsyth int
expconv(Fmt * f)128437da2899SCharles.Forsyth expconv(Fmt *f)
128537da2899SCharles.Forsyth {
128637da2899SCharles.Forsyth 	Node *n;
128737da2899SCharles.Forsyth 	char buf[4096], *p;
128837da2899SCharles.Forsyth 
128937da2899SCharles.Forsyth 	n = va_arg(f->args, Node*);
129037da2899SCharles.Forsyth 	p = buf;
129137da2899SCharles.Forsyth 	*p = 0;
129237da2899SCharles.Forsyth 	if(f->r == 'V')
129337da2899SCharles.Forsyth 		*p++ = '\'';
129437da2899SCharles.Forsyth 	p = eprint(p, buf+sizeof(buf)-1, n);
129537da2899SCharles.Forsyth 	if(f->r == 'V')
129637da2899SCharles.Forsyth 		*p++ = '\'';
129737da2899SCharles.Forsyth 	*p = 0;
129837da2899SCharles.Forsyth 	return fmtstrcpy(f, buf);
129937da2899SCharles.Forsyth }
130037da2899SCharles.Forsyth 
130137da2899SCharles.Forsyth char*
eprint(char * buf,char * end,Node * n)130237da2899SCharles.Forsyth eprint(char *buf, char *end, Node *n)
130337da2899SCharles.Forsyth {
130437da2899SCharles.Forsyth 	if(n == nil)
130537da2899SCharles.Forsyth 		return buf;
130637da2899SCharles.Forsyth 	if(n->flags & PARENS)
130737da2899SCharles.Forsyth 		buf = secpy(buf, end, "(");
130837da2899SCharles.Forsyth 	switch(n->op){
130937da2899SCharles.Forsyth 	case Obreak:
131037da2899SCharles.Forsyth 	case Ocont:
131137da2899SCharles.Forsyth 		buf = secpy(buf, end, opname[n->op]);
131237da2899SCharles.Forsyth 		if(n->decl != nil){
131337da2899SCharles.Forsyth 			buf = seprint(buf, end, " %s", n->decl->sym->name);
131437da2899SCharles.Forsyth 		}
131537da2899SCharles.Forsyth 		break;
131637da2899SCharles.Forsyth 	case Oexit:
131737da2899SCharles.Forsyth 	case Owild:
131837da2899SCharles.Forsyth 		buf = secpy(buf, end, opname[n->op]);
131937da2899SCharles.Forsyth 		break;
132037da2899SCharles.Forsyth 	case Onothing:
132137da2899SCharles.Forsyth 		break;
132237da2899SCharles.Forsyth 	case Oadr:
132337da2899SCharles.Forsyth 	case Oused:
132437da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
132537da2899SCharles.Forsyth 		break;
132637da2899SCharles.Forsyth 	case Oseq:
132737da2899SCharles.Forsyth 		buf = eprintlist(buf, end, n, ", ");
132837da2899SCharles.Forsyth 		break;
132937da2899SCharles.Forsyth 	case Oname:
133037da2899SCharles.Forsyth 		if(n->decl == nil)
133137da2899SCharles.Forsyth 			buf = secpy(buf, end, "<nil>");
133237da2899SCharles.Forsyth 		else
133337da2899SCharles.Forsyth 			buf = seprint(buf, end, "%s", n->decl->sym->name);
133437da2899SCharles.Forsyth 		break;
133537da2899SCharles.Forsyth 	case Oconst:
133637da2899SCharles.Forsyth 		if(n->ty->kind == Tstring){
133737da2899SCharles.Forsyth 			buf = stringpr(buf, end, n->decl->sym);
133837da2899SCharles.Forsyth 			break;
133937da2899SCharles.Forsyth 		}
134037da2899SCharles.Forsyth 		if(n->decl != nil && n->decl->sym != nil){
134137da2899SCharles.Forsyth 			buf = seprint(buf, end, "%s", n->decl->sym->name);
134237da2899SCharles.Forsyth 			break;
134337da2899SCharles.Forsyth 		}
134437da2899SCharles.Forsyth 		switch(n->ty->kind){
134537da2899SCharles.Forsyth 		case Tint:
134637da2899SCharles.Forsyth 		case Tbyte:
134737da2899SCharles.Forsyth 			buf = seprint(buf, end, "%ld", (long)n->val);
134837da2899SCharles.Forsyth 			break;
134937da2899SCharles.Forsyth 		case Tbig:
135037da2899SCharles.Forsyth 			buf = seprint(buf, end, "%lld", n->val);
135137da2899SCharles.Forsyth 			break;
135237da2899SCharles.Forsyth 		case Treal:
135337da2899SCharles.Forsyth 			buf = seprint(buf, end, "%g", n->rval);
135437da2899SCharles.Forsyth 			break;
135537da2899SCharles.Forsyth 		case Tfix:
135637da2899SCharles.Forsyth 			buf = seprint(buf, end, "%ld(%g)", (long)n->val, n->ty->val->rval);
135737da2899SCharles.Forsyth 			break;
135837da2899SCharles.Forsyth 		default:
135937da2899SCharles.Forsyth 			buf = secpy(buf, end, opname[n->op]);
136037da2899SCharles.Forsyth 			break;
136137da2899SCharles.Forsyth 		}
136237da2899SCharles.Forsyth 		break;
136337da2899SCharles.Forsyth 	case Ocast:
136437da2899SCharles.Forsyth 		buf = seprint(buf, end, "%T ", n->ty);
136537da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
136637da2899SCharles.Forsyth 		break;
136737da2899SCharles.Forsyth 	case Otuple:
136837da2899SCharles.Forsyth 		if(n->ty != nil && n->ty->kind == Tadt)
136937da2899SCharles.Forsyth 			buf = seprint(buf, end, "%s", n->ty->decl->sym->name);
137037da2899SCharles.Forsyth 		buf = seprint(buf, end, "(");
137137da2899SCharles.Forsyth 		buf = eprintlist(buf, end, n->left, ", ");
137237da2899SCharles.Forsyth 		buf = secpy(buf, end, ")");
137337da2899SCharles.Forsyth 		break;
137437da2899SCharles.Forsyth 	case Ochan:
137537da2899SCharles.Forsyth 		if(n->left){
137637da2899SCharles.Forsyth 			buf = secpy(buf, end, "chan [");
137737da2899SCharles.Forsyth 			buf = eprint(buf, end, n->left);
137837da2899SCharles.Forsyth 			buf = secpy(buf, end, "] of ");
137937da2899SCharles.Forsyth 			buf = seprint(buf, end, "%T", n->ty->tof);
138037da2899SCharles.Forsyth 		}else
138137da2899SCharles.Forsyth 			buf = seprint(buf, end, "chan of %T", n->ty->tof);
138237da2899SCharles.Forsyth 		break;
138337da2899SCharles.Forsyth 	case Oarray:
138437da2899SCharles.Forsyth 		buf = secpy(buf, end, "array [");
138537da2899SCharles.Forsyth 		if(n->left != nil)
138637da2899SCharles.Forsyth 			buf = eprint(buf, end, n->left);
138737da2899SCharles.Forsyth 		buf = secpy(buf, end, "] of ");
138837da2899SCharles.Forsyth 		if(n->right != nil){
138937da2899SCharles.Forsyth 			buf = secpy(buf, end, "{");
139037da2899SCharles.Forsyth 			buf = eprintlist(buf, end, n->right, ", ");
139137da2899SCharles.Forsyth 			buf = secpy(buf, end, "}");
139237da2899SCharles.Forsyth 		}else{
139337da2899SCharles.Forsyth 			buf = seprint(buf, end, "%T", n->ty->tof);
139437da2899SCharles.Forsyth 		}
139537da2899SCharles.Forsyth 		break;
139637da2899SCharles.Forsyth 	case Oelem:
139737da2899SCharles.Forsyth 	case Olabel:
139837da2899SCharles.Forsyth 		if(n->left != nil){
139937da2899SCharles.Forsyth 			buf = eprintlist(buf, end, n->left, " or ");
140037da2899SCharles.Forsyth 			buf = secpy(buf, end, " =>");
140137da2899SCharles.Forsyth 		}
140237da2899SCharles.Forsyth 		buf = eprint(buf, end, n->right);
140337da2899SCharles.Forsyth 		break;
140437da2899SCharles.Forsyth 	case Orange:
140537da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
140637da2899SCharles.Forsyth 		buf = secpy(buf, end, " to ");
140737da2899SCharles.Forsyth 		buf = eprint(buf, end, n->right);
140837da2899SCharles.Forsyth 		break;
140937da2899SCharles.Forsyth 	case Ospawn:
141037da2899SCharles.Forsyth 		buf = secpy(buf, end, "spawn ");
141137da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
141237da2899SCharles.Forsyth 		break;
141337da2899SCharles.Forsyth 	case Oraise:
141437da2899SCharles.Forsyth 		buf = secpy(buf, end, "raise ");
141537da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
141637da2899SCharles.Forsyth 		break;
141737da2899SCharles.Forsyth 	case Ocall:
141837da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
141937da2899SCharles.Forsyth 		buf = secpy(buf, end, "(");
142037da2899SCharles.Forsyth 		buf = eprintlist(buf, end, n->right, ", ");
142137da2899SCharles.Forsyth 		buf = secpy(buf, end, ")");
142237da2899SCharles.Forsyth 		break;
142337da2899SCharles.Forsyth 	case Oinc:
142437da2899SCharles.Forsyth 	case Odec:
142537da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
142637da2899SCharles.Forsyth 		buf = secpy(buf, end, opname[n->op]);
142737da2899SCharles.Forsyth 		break;
142837da2899SCharles.Forsyth 	case Oindex:
142937da2899SCharles.Forsyth 	case Oindx:
143037da2899SCharles.Forsyth 	case Oinds:
143137da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
143237da2899SCharles.Forsyth 		buf = secpy(buf, end, "[");
143337da2899SCharles.Forsyth 		buf = eprint(buf, end, n->right);
143437da2899SCharles.Forsyth 		buf = secpy(buf, end, "]");
143537da2899SCharles.Forsyth 		break;
143637da2899SCharles.Forsyth 	case Oslice:
143737da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
143837da2899SCharles.Forsyth 		buf = secpy(buf, end, "[");
143937da2899SCharles.Forsyth 		buf = eprint(buf, end, n->right->left);
144037da2899SCharles.Forsyth 		buf = secpy(buf, end, ":");
144137da2899SCharles.Forsyth 		buf = eprint(buf, end, n->right->right);
144237da2899SCharles.Forsyth 		buf = secpy(buf, end, "]");
144337da2899SCharles.Forsyth 		break;
144437da2899SCharles.Forsyth 	case Oload:
144537da2899SCharles.Forsyth 		buf = seprint(buf, end, "load %T ", n->ty);
144637da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
144737da2899SCharles.Forsyth 		break;
144837da2899SCharles.Forsyth 	case Oref:
144937da2899SCharles.Forsyth 	case Olen:
145037da2899SCharles.Forsyth 	case Ohd:
145137da2899SCharles.Forsyth 	case Otl:
145237da2899SCharles.Forsyth 	case Otagof:
145337da2899SCharles.Forsyth 		buf = secpy(buf, end, opname[n->op]);
145437da2899SCharles.Forsyth 		buf = secpy(buf, end, " ");
145537da2899SCharles.Forsyth 		buf = eprint(buf, end, n->left);
145637da2899SCharles.Forsyth 		break;
145737da2899SCharles.Forsyth 	default:
145837da2899SCharles.Forsyth 		if(n->right == nil){
145937da2899SCharles.Forsyth 			buf = secpy(buf, end, opname[n->op]);
146037da2899SCharles.Forsyth 			buf = eprint(buf, end, n->left);
146137da2899SCharles.Forsyth 		}else{
146237da2899SCharles.Forsyth 			buf = eprint(buf, end, n->left);
146337da2899SCharles.Forsyth 			buf = secpy(buf, end, opname[n->op]);
146437da2899SCharles.Forsyth 			buf = eprint(buf, end, n->right);
146537da2899SCharles.Forsyth 		}
146637da2899SCharles.Forsyth 		break;
146737da2899SCharles.Forsyth 	}
146837da2899SCharles.Forsyth 	if(n->flags & PARENS)
146937da2899SCharles.Forsyth 		buf = secpy(buf, end, ")");
147037da2899SCharles.Forsyth 	return buf;
147137da2899SCharles.Forsyth }
147237da2899SCharles.Forsyth 
147337da2899SCharles.Forsyth char*
eprintlist(char * buf,char * end,Node * elist,char * sep)147437da2899SCharles.Forsyth eprintlist(char *buf, char *end, Node *elist, char *sep)
147537da2899SCharles.Forsyth {
147637da2899SCharles.Forsyth 	if(elist == nil)
147737da2899SCharles.Forsyth 		return buf;
147837da2899SCharles.Forsyth 	for(; elist->right != nil; elist = elist->right){
147937da2899SCharles.Forsyth 		if(elist->op == Onothing)
148037da2899SCharles.Forsyth 			continue;
148137da2899SCharles.Forsyth 		if(elist->left->op == Ofnptr)
148237da2899SCharles.Forsyth 			return buf;
148337da2899SCharles.Forsyth 		buf = eprint(buf, end, elist->left);
148437da2899SCharles.Forsyth 		if(elist->right->left->op != Ofnptr)
148537da2899SCharles.Forsyth 			buf = secpy(buf, end, sep);
148637da2899SCharles.Forsyth 	}
148737da2899SCharles.Forsyth 	buf = eprint(buf, end, elist->left);
148837da2899SCharles.Forsyth 	return buf;
148937da2899SCharles.Forsyth }
149037da2899SCharles.Forsyth 
149137da2899SCharles.Forsyth int
nodeconv(Fmt * f)149237da2899SCharles.Forsyth nodeconv(Fmt *f)
149337da2899SCharles.Forsyth {
149437da2899SCharles.Forsyth 	Node *n;
149537da2899SCharles.Forsyth 	char buf[4096];
149637da2899SCharles.Forsyth 
149737da2899SCharles.Forsyth 	n = va_arg(f->args, Node*);
149837da2899SCharles.Forsyth 	buf[0] = 0;
149937da2899SCharles.Forsyth 	nprint(buf, buf+sizeof(buf), n, 0);
150037da2899SCharles.Forsyth 	return fmtstrcpy(f, buf);
150137da2899SCharles.Forsyth }
150237da2899SCharles.Forsyth 
150337da2899SCharles.Forsyth char*
nprint(char * buf,char * end,Node * n,int indent)150437da2899SCharles.Forsyth nprint(char *buf, char *end, Node *n, int indent)
150537da2899SCharles.Forsyth {
150637da2899SCharles.Forsyth 	int i;
150737da2899SCharles.Forsyth 
150837da2899SCharles.Forsyth 	if(n == nil)
150937da2899SCharles.Forsyth 		return buf;
151037da2899SCharles.Forsyth 	buf = seprint(buf, end, "\n");
151137da2899SCharles.Forsyth 	for(i = 0; i < indent; i++)
151237da2899SCharles.Forsyth 		if(buf < end-1)
151337da2899SCharles.Forsyth 			*buf++ = ' ';
151437da2899SCharles.Forsyth 	switch(n->op){
151537da2899SCharles.Forsyth 	case Oname:
151637da2899SCharles.Forsyth 		if(n->decl == nil)
151737da2899SCharles.Forsyth 			buf = secpy(buf, end, "name <nil>");
151837da2899SCharles.Forsyth 		else
151937da2899SCharles.Forsyth 			buf = seprint(buf, end, "name %s", n->decl->sym->name);
152037da2899SCharles.Forsyth 		break;
152137da2899SCharles.Forsyth 	case Oconst:
152237da2899SCharles.Forsyth 		if(n->decl != nil && n->decl->sym != nil)
152337da2899SCharles.Forsyth 			buf = seprint(buf, end, "const %s", n->decl->sym->name);
152437da2899SCharles.Forsyth 		else
152537da2899SCharles.Forsyth 			buf = seprint(buf, end, "%O", n->op);
152637da2899SCharles.Forsyth 		if(n->ty == tint || n->ty == tbyte || n->ty == tbig)
152737da2899SCharles.Forsyth 			buf = seprint(buf, end, " (%ld)", (long)n->val);
152837da2899SCharles.Forsyth 		break;
152937da2899SCharles.Forsyth 	default:
153037da2899SCharles.Forsyth 		buf = seprint(buf, end, "%O", n->op);
153137da2899SCharles.Forsyth 		break;
153237da2899SCharles.Forsyth 	}
153337da2899SCharles.Forsyth 	buf = seprint(buf, end, " %T %d %d", n->ty, n->addable, n->temps);
153437da2899SCharles.Forsyth 	indent += 2;
153537da2899SCharles.Forsyth 	buf = nprint(buf, end, n->left, indent);
153637da2899SCharles.Forsyth 	buf = nprint(buf, end, n->right, indent);
153737da2899SCharles.Forsyth 	return buf;
153837da2899SCharles.Forsyth }
1539