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