#include "limbo.h" static Node* putinline(Node*);static void fpcall(Src*, int, Node*, Node*); voidoptabinit(void){ int i; for(i = 0; setisbyteinst[i] >= 0; i++) isbyteinst[setisbyteinst[i]] = 1; for(i = 0; setisused[i] >= 0; i++) isused[setisused[i]] = 1; for(i = 0; setsideeffect[i] >= 0; i++) sideeffect[setsideeffect[i]] = 1; opind[Tbyte] = 1; opind[Tint] = 2; opind[Tbig] = 3; opind[Treal] = 4; opind[Tstring] = 5; opind[Tfix] = 6; opcommute[Oeq] = Oeq; opcommute[Oneq] = Oneq; opcommute[Olt] = Ogt; opcommute[Ogt] = Olt; opcommute[Ogeq] = Oleq; opcommute[Oleq] = Ogeq; opcommute[Oadd] = Oadd; opcommute[Omul] = Omul; opcommute[Oxor] = Oxor; opcommute[Oor] = Oor; opcommute[Oand] = Oand; oprelinvert[Oeq] = Oneq; oprelinvert[Oneq] = Oeq; oprelinvert[Olt] = Ogeq; oprelinvert[Ogt] = Oleq; oprelinvert[Ogeq] = Olt; oprelinvert[Oleq] = Ogt; isrelop[Oeq] = 1; isrelop[Oneq] = 1; isrelop[Olt] = 1; isrelop[Oleq] = 1; isrelop[Ogt] = 1; isrelop[Ogeq] = 1; isrelop[Oandand] = 1; isrelop[Ooror] = 1; isrelop[Onot] = 1; precasttab[Tstring][Tbyte] = tint; precasttab[Tbyte][Tstring] = tint; precasttab[Treal][Tbyte] = tint; precasttab[Tbyte][Treal] = tint; precasttab[Tbig][Tbyte] = tint; precasttab[Tbyte][Tbig] = tint; precasttab[Tfix][Tbyte] = tint; precasttab[Tbyte][Tfix] = tint; precasttab[Tbig][Tfix] = treal; precasttab[Tfix][Tbig] = treal; precasttab[Tstring][Tfix] = treal; precasttab[Tfix][Tstring] = treal; casttab[Tint][Tint] = IMOVW; casttab[Tbig][Tbig] = IMOVL; casttab[Treal][Treal] = IMOVF; casttab[Tbyte][Tbyte] = IMOVB; casttab[Tstring][Tstring] = IMOVP; casttab[Tfix][Tfix] = ICVTXX; /* never same type */ casttab[Tint][Tbyte] = ICVTWB; casttab[Tint][Treal] = ICVTWF; casttab[Tint][Tstring] = ICVTWC; casttab[Tint][Tfix] = ICVTXX; casttab[Tbyte][Tint] = ICVTBW; casttab[Treal][Tint] = ICVTFW; casttab[Tstring][Tint] = ICVTCW; casttab[Tfix][Tint] = ICVTXX; casttab[Tint][Tbig] = ICVTWL; casttab[Treal][Tbig] = ICVTFL; casttab[Tstring][Tbig] = ICVTCL; casttab[Tbig][Tint] = ICVTLW; casttab[Tbig][Treal] = ICVTLF; casttab[Tbig][Tstring] = ICVTLC; casttab[Treal][Tstring] = ICVTFC; casttab[Tstring][Treal] = ICVTCF; casttab[Treal][Tfix] = ICVTFX; casttab[Tfix][Treal] = ICVTXF; casttab[Tstring][Tarray] = ICVTCA; casttab[Tarray][Tstring] = ICVTAC; /* * placeholders; fixed in precasttab */ casttab[Tbyte][Tstring] = 0xff; casttab[Tstring][Tbyte] = 0xff; casttab[Tbyte][Treal] = 0xff; casttab[Treal][Tbyte] = 0xff; casttab[Tbyte][Tbig] = 0xff; casttab[Tbig][Tbyte] = 0xff; casttab[Tfix][Tbyte] = 0xff; casttab[Tbyte][Tfix] = 0xff; casttab[Tfix][Tbig] = 0xff; casttab[Tbig][Tfix] = 0xff; casttab[Tfix][Tstring] = 0xff; casttab[Tstring][Tfix] = 0xff;} /* * global variable and constant initialization checking */intvcom(Decl *ids){ Decl *v; int ok; ok = 1; for(v = ids; v != nil; v = v->next) ok &= varcom(v); for(v = ids; v != nil; v = v->next) v->init = simplify(v->init); return ok;} Node*simplify(Node *n){ if(n == nil) return nil; if(debug['F']) print("simplify %n\n", n); n = efold(rewrite(n)); if(debug['F']) print("simplified %n\n", n); return n;} static intisfix(Node *n){ if(n->ty->kind == Tint || n->ty->kind == Tfix){ if(n->op == Ocast) return n->left->ty->kind == Tint || n->left->ty->kind == Tfix; return 1; } return 0;} /* * rewrite an expression to make it easiser to compile, * or give the correct results */Node*rewrite(Node *n){ Long v; Type *t; Decl *d; Node *nn, *left, *right; if(n == nil) return nil; left = n->left; right = n->right; /* * rewrites */ switch(n->op){ case Oname: d = n->decl; if(d->importid != nil){ left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid)); left->ty = n->ty; return rewrite(left); } if((t = n->ty)->kind == Texception){ if(t->cons) fatal("cons in rewrite Oname"); n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD)); n = mkunary(Oind, n); n->ty = t; n->left->ty = n->left->left->ty = tint; return rewrite(n); } break; case Odas: n->op = Oas; return rewrite(n); case Oneg: n->left = rewrite(left); if(n->ty == treal) break; left = n->left; n->right = left; n->left = mkconst(&n->src, 0); n->left->ty = n->ty; n->op = Osub; break; case Ocomp: v = 0; v = ~v; n->right = mkconst(&n->src, v); n->right->ty = n->ty; n->left = rewrite(left); n->op = Oxor; break; case Oinc: case Odec: case Opreinc: case Opredec: n->left = rewrite(left); switch(n->ty->kind){ case Treal: n->right = mkrconst(&n->src, 1.0); break; case Tint: case Tbig: case Tbyte: case Tfix: n->right = mkconst(&n->src, 1); n->right->ty = n->ty; break; default: fatal("can't rewrite inc/dec %n", n); break; } if(n->op == Opreinc) n->op = Oaddas; else if(n->op == Opredec) n->op = Osubas; break; case Oslice: if(right->left->op == Onothing) right->left = mkconst(&right->left->src, 0); n->left = rewrite(left); n->right = rewrite(right); break; case Oindex: n->op = Oindx; n->left = rewrite(left); n->right = rewrite(right); n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; break; case Oload: n->right = mkn(Oname, nil, nil); n->right->src = n->left->src; n->right->decl = n->ty->tof->decl; n->right->ty = n->ty; n->left = rewrite(left); break; case Ocast: if(left->ty->kind == Texception){ n = rewrite(left); break; } n->op = Ocast; t = precasttab[left->ty->kind][n->ty->kind]; if(t != nil){ n->left = mkunary(Ocast, left); n->left->ty = t; return rewrite(n); } n->left = rewrite(left); break; case Oraise: if(left->ty == tstring) {} else if(!left->ty->cons) break; else if(left->op != Ocall || left->left->ty->kind == Tfn){ left = mkunary(Ocall, left); left->ty = left->left->ty; } n->left = rewrite(left); break; case Ocall: t = left->ty; if(t->kind == Tref) t = t->tof; if(t->kind == Tfn){if(debug['U']) print("call %n\n", left); if(left->ty->kind == Tref){ /* call by function reference */ n->left = mkunary(Oind, left); n->left->ty = t; return rewrite(n); } d = nil; if(left->op == Oname) d = left->decl; else if(left->op == Omdot && left->right->op == Odot) d = left->right->right->decl; else if(left->op == Omdot || left->op == Odot) d = left->right->decl; else if(left->op != Oind) fatal("cannot deal with call %n in rewrite", n); if(ispoly(d)) addfnptrs(d, 0); n->left = rewrite(left); if(right != nil) n->right = rewrite(right); if(d != nil && d->caninline == 1) n = simplify(putinline(n)); break; } switch(n->ty->kind){ case Tref: n = mkunary(Oref, n); n->ty = n->left->ty; n->left->ty = n->left->ty->tof; n->left->left->ty = n->left->ty; return rewrite(n); case Tadt: n->op = Otuple; n->right = nil; if(n->ty->tags != nil){ n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag)); if(right != nil){ nn->right = right; nn->src.stop = right->src.stop; } n->ty = left->right->decl->ty->tof; }else n->left = right; return rewrite(n); case Tadtpick: n->op = Otuple; n->right = nil; n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag)); if(right != nil){ nn->right = right; nn->src.stop = right->src.stop; } n->ty = left->right->decl->ty->tof; return rewrite(n); case Texception: if(!n->ty->cons) return n->left; if(left->op == Omdot){ left->right->ty = left->ty; left = left->right; } n->op = Otuple; n->right = nil; n->left = nn = mkunary(Oseq, left->decl->init); nn->right = mkunary(Oseq, mkconst(&n->src, 0)); nn->right->right = right; n->ty = mkexbasetype(n->ty); n = mkunary(Oref, n); n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil)); return rewrite(n); default: fatal("can't deal with %n in rewrite/Ocall", n); break; } break; case Omdot: /* * what about side effects from left? */ d = right->decl; switch(d->store){ case Dfn: n->left = rewrite(left); if(right->op == Odot){ n->right = dupn(1, &left->src, right->right); n->right->ty = d->ty; } break; case Dconst: case Dtag: case Dtype: /* handled by fold */ return n; case Dglobal: right->op = Oconst; right->val = d->offset; right->ty = tint; n->left = left = mkunary(Oind, left); left->ty = tint; n->op = Oadd; n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; n->left = rewrite(n->left); return n; case Darg: return n; default: fatal("can't deal with %n in rewrite/Omdot", n); break; } break; case Odot: /* * what about side effects from left? */ d = right->decl; switch(d->store){ case Dfn: if(right->left != nil){ n = mkbin(Omdot, dupn(1, &left->src, right->left), right); right->left = nil; n->ty = d->ty; return rewrite(n); } if(left->ty->kind == Tpoly){ n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next)); n->ty = d->ty; return rewrite(n); } n->op = Oname; n->decl = d; n->right = nil; n->left = nil; return n; case Dconst: case Dtag: case Dtype: /* handled by fold */ return n; } if(istuple(left)) return n; /* handled by fold */ right->op = Oconst; right->val = d->offset; right->ty = tint; if(left->ty->kind != Tref){ n->left = mkunary(Oadr, left); n->left->ty = tint; } n->op = Oadd; n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; n->left = rewrite(n->left); return n; case Oadr: left = rewrite(left); n->left = left; if(left->op == Oind) return left->left; break; case Otagof: if(n->decl == nil){ n->op = Oind; return rewrite(n); } return n; case Omul: case Odiv: left = n->left = rewrite(left); right = n->right = rewrite(right); if(n->ty->kind == Tfix && isfix(left) && isfix(right)){ if(left->op == Ocast && tequal(left->ty, n->ty)) n->left = left->left; if(right->op == Ocast && tequal(right->ty, n->ty)) n->right = right->left; } break; case Oself: if(newfnptr) return n; if(selfdecl == nil){ d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil); installids(Dglobal, d); d->refs++; } nn = mkn(Oload, nil, nil); nn->src = n->src; nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5)); nn->ty = impdecl->ty; usetype(nn->ty); usetype(nn->ty->tof); nn = rewrite(nn); nn->op = Oself; return nn; case Ofnptr: if(n->flags == 0){ /* module */ if(left == nil) left = mkn(Oself, nil, nil); return rewrite(left); } right->flags = n->flags;Lines 1–500 of 2558. Load more
#include "limbo.h" static Node* putinline(Node*); static void fpcall(Src*, int, Node*, Node*); void optabinit(void) { int i; for(i = 0; setisbyteinst[i] >= 0; i++) isbyteinst[setisbyteinst[i]] = 1; for(i = 0; setisused[i] >= 0; i++) isused[setisused[i]] = 1; for(i = 0; setsideeffect[i] >= 0; i++) sideeffect[setsideeffect[i]] = 1; opind[Tbyte] = 1; opind[Tint] = 2; opind[Tbig] = 3; opind[Treal] = 4; opind[Tstring] = 5; opind[Tfix] = 6; opcommute[Oeq] = Oeq; opcommute[Oneq] = Oneq; opcommute[Olt] = Ogt; opcommute[Ogt] = Olt; opcommute[Ogeq] = Oleq; opcommute[Oleq] = Ogeq; opcommute[Oadd] = Oadd; opcommute[Omul] = Omul; opcommute[Oxor] = Oxor; opcommute[Oor] = Oor; opcommute[Oand] = Oand; oprelinvert[Oeq] = Oneq; oprelinvert[Oneq] = Oeq; oprelinvert[Olt] = Ogeq; oprelinvert[Ogt] = Oleq; oprelinvert[Ogeq] = Olt; oprelinvert[Oleq] = Ogt; isrelop[Oeq] = 1; isrelop[Oneq] = 1; isrelop[Olt] = 1; isrelop[Oleq] = 1; isrelop[Ogt] = 1; isrelop[Ogeq] = 1; isrelop[Oandand] = 1; isrelop[Ooror] = 1; isrelop[Onot] = 1; precasttab[Tstring][Tbyte] = tint; precasttab[Tbyte][Tstring] = tint; precasttab[Treal][Tbyte] = tint; precasttab[Tbyte][Treal] = tint; precasttab[Tbig][Tbyte] = tint; precasttab[Tbyte][Tbig] = tint; precasttab[Tfix][Tbyte] = tint; precasttab[Tbyte][Tfix] = tint; precasttab[Tbig][Tfix] = treal; precasttab[Tfix][Tbig] = treal; precasttab[Tstring][Tfix] = treal; precasttab[Tfix][Tstring] = treal; casttab[Tint][Tint] = IMOVW; casttab[Tbig][Tbig] = IMOVL; casttab[Treal][Treal] = IMOVF; casttab[Tbyte][Tbyte] = IMOVB; casttab[Tstring][Tstring] = IMOVP; casttab[Tfix][Tfix] = ICVTXX; /* never same type */ casttab[Tint][Tbyte] = ICVTWB; casttab[Tint][Treal] = ICVTWF; casttab[Tint][Tstring] = ICVTWC; casttab[Tint][Tfix] = ICVTXX; casttab[Tbyte][Tint] = ICVTBW; casttab[Treal][Tint] = ICVTFW; casttab[Tstring][Tint] = ICVTCW; casttab[Tfix][Tint] = ICVTXX; casttab[Tint][Tbig] = ICVTWL; casttab[Treal][Tbig] = ICVTFL; casttab[Tstring][Tbig] = ICVTCL; casttab[Tbig][Tint] = ICVTLW; casttab[Tbig][Treal] = ICVTLF; casttab[Tbig][Tstring] = ICVTLC; casttab[Treal][Tstring] = ICVTFC; casttab[Tstring][Treal] = ICVTCF; casttab[Treal][Tfix] = ICVTFX; casttab[Tfix][Treal] = ICVTXF; casttab[Tstring][Tarray] = ICVTCA; casttab[Tarray][Tstring] = ICVTAC; /* * placeholders; fixed in precasttab */ casttab[Tbyte][Tstring] = 0xff; casttab[Tstring][Tbyte] = 0xff; casttab[Tbyte][Treal] = 0xff; casttab[Treal][Tbyte] = 0xff; casttab[Tbyte][Tbig] = 0xff; casttab[Tbig][Tbyte] = 0xff; casttab[Tfix][Tbyte] = 0xff; casttab[Tbyte][Tfix] = 0xff; casttab[Tfix][Tbig] = 0xff; casttab[Tbig][Tfix] = 0xff; casttab[Tfix][Tstring] = 0xff; casttab[Tstring][Tfix] = 0xff; } /* * global variable and constant initialization checking */ int vcom(Decl *ids) { Decl *v; int ok; ok = 1; for(v = ids; v != nil; v = v->next) ok &= varcom(v); for(v = ids; v != nil; v = v->next) v->init = simplify(v->init); return ok; } Node* simplify(Node *n) { if(n == nil) return nil; if(debug['F']) print("simplify %n\n", n); n = efold(rewrite(n)); if(debug['F']) print("simplified %n\n", n); return n; } static int isfix(Node *n) { if(n->ty->kind == Tint || n->ty->kind == Tfix){ if(n->op == Ocast) return n->left->ty->kind == Tint || n->left->ty->kind == Tfix; return 1; } return 0; } /* * rewrite an expression to make it easiser to compile, * or give the correct results */ Node* rewrite(Node *n) { Long v; Type *t; Decl *d; Node *nn, *left, *right; if(n == nil) return nil; left = n->left; right = n->right; /* * rewrites */ switch(n->op){ case Oname: d = n->decl; if(d->importid != nil){ left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid)); left->ty = n->ty; return rewrite(left); } if((t = n->ty)->kind == Texception){ if(t->cons) fatal("cons in rewrite Oname"); n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD)); n = mkunary(Oind, n); n->ty = t; n->left->ty = n->left->left->ty = tint; return rewrite(n); } break; case Odas: n->op = Oas; return rewrite(n); case Oneg: n->left = rewrite(left); if(n->ty == treal) break; left = n->left; n->right = left; n->left = mkconst(&n->src, 0); n->left->ty = n->ty; n->op = Osub; break; case Ocomp: v = 0; v = ~v; n->right = mkconst(&n->src, v); n->right->ty = n->ty; n->left = rewrite(left); n->op = Oxor; break; case Oinc: case Odec: case Opreinc: case Opredec: n->left = rewrite(left); switch(n->ty->kind){ case Treal: n->right = mkrconst(&n->src, 1.0); break; case Tint: case Tbig: case Tbyte: case Tfix: n->right = mkconst(&n->src, 1); n->right->ty = n->ty; break; default: fatal("can't rewrite inc/dec %n", n); break; } if(n->op == Opreinc) n->op = Oaddas; else if(n->op == Opredec) n->op = Osubas; break; case Oslice: if(right->left->op == Onothing) right->left = mkconst(&right->left->src, 0); n->left = rewrite(left); n->right = rewrite(right); break; case Oindex: n->op = Oindx; n->left = rewrite(left); n->right = rewrite(right); n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; break; case Oload: n->right = mkn(Oname, nil, nil); n->right->src = n->left->src; n->right->decl = n->ty->tof->decl; n->right->ty = n->ty; n->left = rewrite(left); break; case Ocast: if(left->ty->kind == Texception){ n = rewrite(left); break; } n->op = Ocast; t = precasttab[left->ty->kind][n->ty->kind]; if(t != nil){ n->left = mkunary(Ocast, left); n->left->ty = t; return rewrite(n); } n->left = rewrite(left); break; case Oraise: if(left->ty == tstring) {} else if(!left->ty->cons) break; else if(left->op != Ocall || left->left->ty->kind == Tfn){ left = mkunary(Ocall, left); left->ty = left->left->ty; } n->left = rewrite(left); break; case Ocall: t = left->ty; if(t->kind == Tref) t = t->tof; if(t->kind == Tfn){ if(debug['U']) print("call %n\n", left); if(left->ty->kind == Tref){ /* call by function reference */ n->left = mkunary(Oind, left); n->left->ty = t; return rewrite(n); } d = nil; if(left->op == Oname) d = left->decl; else if(left->op == Omdot && left->right->op == Odot) d = left->right->right->decl; else if(left->op == Omdot || left->op == Odot) d = left->right->decl; else if(left->op != Oind) fatal("cannot deal with call %n in rewrite", n); if(ispoly(d)) addfnptrs(d, 0); n->left = rewrite(left); if(right != nil) n->right = rewrite(right); if(d != nil && d->caninline == 1) n = simplify(putinline(n)); break; } switch(n->ty->kind){ case Tref: n = mkunary(Oref, n); n->ty = n->left->ty; n->left->ty = n->left->ty->tof; n->left->left->ty = n->left->ty; return rewrite(n); case Tadt: n->op = Otuple; n->right = nil; if(n->ty->tags != nil){ n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag)); if(right != nil){ nn->right = right; nn->src.stop = right->src.stop; } n->ty = left->right->decl->ty->tof; }else n->left = right; return rewrite(n); case Tadtpick: n->op = Otuple; n->right = nil; n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag)); if(right != nil){ nn->right = right; nn->src.stop = right->src.stop; } n->ty = left->right->decl->ty->tof; return rewrite(n); case Texception: if(!n->ty->cons) return n->left; if(left->op == Omdot){ left->right->ty = left->ty; left = left->right; } n->op = Otuple; n->right = nil; n->left = nn = mkunary(Oseq, left->decl->init); nn->right = mkunary(Oseq, mkconst(&n->src, 0)); nn->right->right = right; n->ty = mkexbasetype(n->ty); n = mkunary(Oref, n); n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil)); return rewrite(n); default: fatal("can't deal with %n in rewrite/Ocall", n); break; } break; case Omdot: /* * what about side effects from left? */ d = right->decl; switch(d->store){ case Dfn: n->left = rewrite(left); if(right->op == Odot){ n->right = dupn(1, &left->src, right->right); n->right->ty = d->ty; } break; case Dconst: case Dtag: case Dtype: /* handled by fold */ return n; case Dglobal: right->op = Oconst; right->val = d->offset; right->ty = tint; n->left = left = mkunary(Oind, left); left->ty = tint; n->op = Oadd; n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; n->left = rewrite(n->left); return n; case Darg: return n; default: fatal("can't deal with %n in rewrite/Omdot", n); break; } break; case Odot: /* * what about side effects from left? */ d = right->decl; switch(d->store){ case Dfn: if(right->left != nil){ n = mkbin(Omdot, dupn(1, &left->src, right->left), right); right->left = nil; n->ty = d->ty; return rewrite(n); } if(left->ty->kind == Tpoly){ n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next)); n->ty = d->ty; return rewrite(n); } n->op = Oname; n->decl = d; n->right = nil; n->left = nil; return n; case Dconst: case Dtag: case Dtype: /* handled by fold */ return n; } if(istuple(left)) return n; /* handled by fold */ right->op = Oconst; right->val = d->offset; right->ty = tint; if(left->ty->kind != Tref){ n->left = mkunary(Oadr, left); n->left->ty = tint; } n->op = Oadd; n = mkunary(Oind, n); n->ty = n->left->ty; n->left->ty = tint; n->left = rewrite(n->left); return n; case Oadr: left = rewrite(left); n->left = left; if(left->op == Oind) return left->left; break; case Otagof: if(n->decl == nil){ n->op = Oind; return rewrite(n); } return n; case Omul: case Odiv: left = n->left = rewrite(left); right = n->right = rewrite(right); if(n->ty->kind == Tfix && isfix(left) && isfix(right)){ if(left->op == Ocast && tequal(left->ty, n->ty)) n->left = left->left; if(right->op == Ocast && tequal(right->ty, n->ty)) n->right = right->left; } break; case Oself: if(newfnptr) return n; if(selfdecl == nil){ d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil); installids(Dglobal, d); d->refs++; } nn = mkn(Oload, nil, nil); nn->src = n->src; nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5)); nn->ty = impdecl->ty; usetype(nn->ty); usetype(nn->ty->tof); nn = rewrite(nn); nn->op = Oself; return nn; case Ofnptr: if(n->flags == 0){ /* module */ if(left == nil) left = mkn(Oself, nil, nil); return rewrite(left); } right->flags = n->flags;