diff options
Diffstat (limited to 'src/cmd/gc/print.c')
-rw-r--r-- | src/cmd/gc/print.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c new file mode 100644 index 000000000..5913e848a --- /dev/null +++ b/src/cmd/gc/print.c @@ -0,0 +1,480 @@ +// 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, "<nil>"); + 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: + case OPAREN: + 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 OPAREN: + fmtprint(f, "(%#N)", n->left); + 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, "<struct>"); + break; + + case OTINTER: + fmtprint(f, "<inter>"); + break; + + case OTFUNC: + fmtprint(f, "<func>"); + 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, ".<nil>"); + 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 OSTRARRAYBYTE: + 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: + case OMAKECHAN: + fmtprint(f, "make(%#T)", n->type); + break; + + // Some statements + + case ODCL: + fmtprint(f, "var %S %#T", n->left->sym, n->left->type); + break; + + case ORETURN: + fmtprint(f, "return "); + exprlistfmt(f, n->list); + break; + + case OPROC: + fmtprint(f, "go %#N", n->left); + break; + + case ODEFER: + fmtprint(f, "defer %#N", n->left); + break; + } + + if(prec > nprec) + fmtprint(f, ")"); +} |