// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "go.h" enum { PFIXME = 0, }; void exprlistfmt(Fmt *f, NodeList *l) { for(; l; l=l->next) { exprfmt(f, l->n, 0); if(l->next) fmtprint(f, ", "); } } void exprfmt(Fmt *f, Node *n, int prec) { int nprec; char *p; nprec = 0; if(n == nil) { fmtprint(f, ""); return; } if(n->implicit) { exprfmt(f, n->left, prec); return; } switch(n->op) { case OAPPEND: case ONAME: case ONONAME: case OPACK: case OLITERAL: case ODOT: case ODOTPTR: case ODOTINTER: case ODOTMETH: case ODOTTYPE: case ODOTTYPE2: case OXDOT: case OARRAYBYTESTR: case OCAP: case OCLOSE: case OCOPY: case OLEN: case OMAKE: case ONEW: case OPANIC: case OPRINT: case OPRINTN: case OCALL: case OCALLMETH: case OCALLINTER: case OCALLFUNC: case OCONV: case OCONVNOP: case OMAKESLICE: case ORUNESTR: case OADDR: case OCOM: case OIND: case OMINUS: case ONOT: case OPLUS: case ORECV: case OCONVIFACE: case OTPAREN: case OINDEX: case OINDEXMAP: nprec = 7; break; case OMUL: case ODIV: case OMOD: case OLSH: case ORSH: case OAND: case OANDNOT: nprec = 6; break; case OADD: case OSUB: case OOR: case OXOR: nprec = 5; break; case OEQ: case OLT: case OLE: case OGE: case OGT: case ONE: nprec = 4; break; case OSEND: nprec = 3; break; case OANDAND: nprec = 2; break; case OOROR: nprec = 1; break; case OTYPE: if(n->sym != S) nprec = 7; break; } if(prec > nprec) fmtprint(f, "("); switch(n->op) { default: bad: fmtprint(f, "(node %O)", n->op); break; case OREGISTER: fmtprint(f, "%R", n->val.u.reg); break; case OLITERAL: if(n->sym != S) { fmtprint(f, "%S", n->sym); break; } switch(n->val.ctype) { default: goto bad; case CTINT: fmtprint(f, "%B", n->val.u.xval); break; case CTBOOL: if(n->val.u.bval) fmtprint(f, "true"); else fmtprint(f, "false"); break; case CTCPLX: fmtprint(f, "%.17g+%.17gi", mpgetflt(&n->val.u.cval->real), mpgetflt(&n->val.u.cval->imag)); break; case CTFLT: fmtprint(f, "%.17g", mpgetflt(n->val.u.fval)); break; case CTSTR: fmtprint(f, "\"%Z\"", n->val.u.sval); break; case CTNIL: fmtprint(f, "nil"); break; } break; case ONAME: case OPACK: case ONONAME: fmtprint(f, "%S", n->sym); break; case OTYPE: if(n->type == T && n->sym != S) { fmtprint(f, "%S", n->sym); break; } fmtprint(f, "%T", n->type); break; case OTARRAY: fmtprint(f, "[]"); exprfmt(f, n->left, PFIXME); break; case OTPAREN: fmtprint(f, "("); exprfmt(f, n->left, 0); fmtprint(f, ")"); break; case OTMAP: fmtprint(f, "map["); exprfmt(f, n->left, 0); fmtprint(f, "] "); exprfmt(f, n->right, 0); break; case OTCHAN: if(n->etype == Crecv) fmtprint(f, "<-"); fmtprint(f, "chan"); if(n->etype == Csend) { fmtprint(f, "<- "); exprfmt(f, n->left, 0); } else { fmtprint(f, " "); if(n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv) { fmtprint(f, "("); exprfmt(f, n->left, 0); fmtprint(f, ")"); } else exprfmt(f, n->left, 0); } break; case OTSTRUCT: fmtprint(f, ""); break; case OTINTER: fmtprint(f, ""); break; case OTFUNC: fmtprint(f, ""); break; case OAS: exprfmt(f, n->left, 0); fmtprint(f, " = "); exprfmt(f, n->right, 0); break; case OASOP: exprfmt(f, n->left, 0); fmtprint(f, " %#O= ", n->etype); exprfmt(f, n->right, 0); break; case OAS2: case OAS2DOTTYPE: case OAS2FUNC: case OAS2MAPR: case OAS2MAPW: case OAS2RECV: exprlistfmt(f, n->list); fmtprint(f, " = "); exprlistfmt(f, n->rlist); break; case OADD: case OANDAND: case OANDNOT: case ODIV: case OEQ: case OGE: case OGT: case OLE: case OLT: case OLSH: case OMOD: case OMUL: case ONE: case OOR: case OOROR: case ORSH: case OSEND: case OSUB: case OXOR: exprfmt(f, n->left, nprec); fmtprint(f, " %#O ", n->op); exprfmt(f, n->right, nprec+1); break; case OADDR: case OCOM: case OIND: case OMINUS: case ONOT: case OPLUS: case ORECV: fmtprint(f, "%#O", n->op); if((n->op == OMINUS || n->op == OPLUS) && n->left->op == n->op) fmtprint(f, " "); exprfmt(f, n->left, 0); break; case OCLOSURE: fmtprint(f, "func literal"); break; case OCOMPLIT: fmtprint(f, "composite literal"); break; case OARRAYLIT: if(isslice(n->type)) fmtprint(f, "slice literal"); else fmtprint(f, "array literal"); break; case OMAPLIT: fmtprint(f, "map literal"); break; case OSTRUCTLIT: fmtprint(f, "struct literal"); break; case OXDOT: case ODOT: case ODOTPTR: case ODOTINTER: case ODOTMETH: exprfmt(f, n->left, 7); if(n->right == N || n->right->sym == S) fmtprint(f, "."); else { // skip leading type· in method name p = utfrrune(n->right->sym->name, 0xb7); if(p) p+=2; else p = n->right->sym->name; fmtprint(f, ".%s", p); } break; case ODOTTYPE: case ODOTTYPE2: exprfmt(f, n->left, 7); fmtprint(f, ".("); if(n->right != N) exprfmt(f, n->right, 0); else fmtprint(f, "%T", n->type); fmtprint(f, ")"); break; case OINDEX: case OINDEXMAP: exprfmt(f, n->left, 7); fmtprint(f, "["); exprfmt(f, n->right, 0); fmtprint(f, "]"); break; case OSLICE: case OSLICESTR: case OSLICEARR: exprfmt(f, n->left, 7); fmtprint(f, "["); if(n->right->left != N) exprfmt(f, n->right->left, 0); fmtprint(f, ":"); if(n->right->right != N) exprfmt(f, n->right->right, 0); fmtprint(f, "]"); break; case OCALL: case OCALLFUNC: case OCALLINTER: case OCALLMETH: exprfmt(f, n->left, 7); fmtprint(f, "("); exprlistfmt(f, n->list); if(n->isddd) fmtprint(f, "..."); fmtprint(f, ")"); break; case OCOMPLEX: fmtprint(f, "complex("); exprfmt(f, n->left, 0); fmtprint(f, ", "); exprfmt(f, n->right, 0); fmtprint(f, ")"); break; case OREAL: fmtprint(f, "real("); exprfmt(f, n->left, 0); fmtprint(f, ")"); break; case OIMAG: fmtprint(f, "imag("); exprfmt(f, n->left, 0); fmtprint(f, ")"); break; case OCONV: case OCONVIFACE: case OCONVNOP: case OARRAYBYTESTR: case ORUNESTR: if(n->type == T || n->type->sym == S) fmtprint(f, "(%T)(", n->type); else fmtprint(f, "%T(", n->type); if(n->left == N) exprlistfmt(f, n->list); else exprfmt(f, n->left, 0); fmtprint(f, ")"); break; case OAPPEND: case OCAP: case OCLOSE: case OLEN: case OCOPY: case OMAKE: case ONEW: case OPANIC: case OPRINT: case OPRINTN: fmtprint(f, "%#O(", n->op); if(n->left) exprfmt(f, n->left, 0); else exprlistfmt(f, n->list); fmtprint(f, ")"); break; case OMAKESLICE: fmtprint(f, "make(%#T, ", n->type); exprfmt(f, n->left, 0); if(count(n->list) > 2) { fmtprint(f, ", "); exprfmt(f, n->right, 0); } fmtprint(f, ")"); break; case OMAKEMAP: fmtprint(f, "make(%#T)", n->type); break; } if(prec > nprec) fmtprint(f, ")"); }