summaryrefslogtreecommitdiff
path: root/src/cmd/gc/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/print.c')
-rw-r--r--src/cmd/gc/print.c480
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, ")");
+}