summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-07-29 11:51:34 -0700
committerRuss Cox <rsc@golang.org>2009-07-29 11:51:34 -0700
commit261d6437b8a7a1e7c85f9c83dd4a72446a9234a5 (patch)
treebf1bb9ec4b93a51271f20d61dbf4cf631594af88
parent6b1b84567904387148c217c483dd90778d7a98cb (diff)
downloadgolang-261d6437b8a7a1e7c85f9c83dd4a72446a9234a5.tar.gz
expression printer; %#N
R=ken OCL=32419 CL=32419
-rw-r--r--src/cmd/gc/Makefile1
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/print.c272
-rw-r--r--src/cmd/gc/subr.c66
4 files changed, 340 insertions, 0 deletions
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index 516542dbb..697cca940 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -34,6 +34,7 @@ OFILES=\
align.$O\
gen.$O\
obj.$O\
+ print.$O\
$(LIB): $(OFILES)
ar rsc $(LIB) $(OFILES)
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index e7bac2da9..5190591dc 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -816,6 +816,7 @@ int Oconv(Fmt*);
int Sconv(Fmt*);
int Tconv(Fmt*);
int Nconv(Fmt*);
+void exprfmt(Fmt*, Node*, int);
int Wconv(Fmt*);
int Zconv(Fmt*);
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
new file mode 100644
index 000000000..fc96b3a2b
--- /dev/null
+++ b/src/cmd/gc/print.c
@@ -0,0 +1,272 @@
+// 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,
+ PCHAN = 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;
+
+ nprec = 0;
+ if(n == nil) {
+ fmtprint(f, "<nil>");
+ return;
+ }
+
+ switch(n->op) {
+ case ONAME:
+ case ONONAME:
+ case OPACK:
+ case OLITERAL:
+ 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;
+ }
+
+ if(prec > nprec)
+ fmtprint(f, "(");
+
+ switch(n->op) {
+ default:
+ bad:
+ fmtprint(f, "(node %O)", n->op);
+ break;
+
+ case OLITERAL:
+ 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 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:
+ fmtprint(f, "%T", n->type);
+ break;
+
+ case OTARRAY:
+ fmtprint(f, "[]");
+ exprfmt(f, n->left, PFIXME);
+ 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, " ");
+ exprfmt(f, n->left, PCHAN);
+ }
+ break;
+
+ case OTSTRUCT:
+ fmtprint(f, "<struct>");
+ break;
+
+ case OTINTER:
+ fmtprint(f, "<inter>");
+ break;
+
+ case OTFUNC:
+ fmtprint(f, "<func>");
+ 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 OCOMPOS:
+ fmtprint(f, "<compos>");
+ break;
+
+ case ODOT:
+ case ODOTINTER:
+ case ODOTMETH:
+ exprfmt(f, n->left, 7);
+ if(n->sym == S)
+ fmtprint(f, ".<nil>");
+ else
+ fmtprint(f, ".%s", n->sym->name);
+ break;
+
+ case ODOTTYPE:
+ exprfmt(f, n->left, 7);
+ fmtprint(f, ".(");
+ exprfmt(f, n->right, 0);
+ fmtprint(f, ")");
+ break;
+
+ case OINDEX:
+ exprfmt(f, n->left, 7);
+ fmtprint(f, "[");
+ exprfmt(f, n->right, 0);
+ fmtprint(f, "]");
+ break;
+
+ case OSLICE:
+ exprfmt(f, n->left, 7);
+ fmtprint(f, "[");
+ exprfmt(f, n->right->left, 0);
+ fmtprint(f, ":");
+ exprfmt(f, n->right->right, 0);
+ fmtprint(f, "]");
+ break;
+
+ case OCALL:
+ case OCALLINTER:
+ case OCALLMETH:
+ exprfmt(f, n->left, 7);
+ fmtprint(f, "(");
+ exprlistfmt(f, n->list);
+ fmtprint(f, ")");
+ break;
+
+ case OCONV:
+ fmtprint(f, "%T(", n->type);
+ exprfmt(f, n->left, 0);
+ fmtprint(f, ")");
+ break;
+
+ case OCAP:
+ case OCLOSE:
+ case OCLOSED:
+ case OLEN:
+ case OMAKE:
+ case ONEW:
+ case OPANIC:
+ case OPANICN:
+ 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;
+ }
+
+ if(prec > nprec)
+ fmtprint(f, ")");
+}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 14a5fa7b5..264cf8a83 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -732,6 +732,65 @@ opnames[] =
[OXXX] = "XXX",
};
+static char*
+goopnames[] =
+{
+ [OADDR] = "&",
+ [OADD] = "+",
+ [OANDAND] = "&&",
+ [OANDNOT] = "&^",
+ [OAND] = "&",
+ [OAS] = "=",
+ [OAS2] = "=",
+ [OBREAK] = "break",
+ [OCAP] = "cap",
+ [OCASE] = "case",
+ [OCLOSED] = "closed",
+ [OCLOSE] = "close",
+ [OCOM] = "^",
+ [OCONTINUE] = "continue",
+ [ODEC] = "--",
+ [ODEFER] = "defer",
+ [ODIV] = "/",
+ [OEQ] = "==",
+ [OFALL] = "fallthrough",
+ [OFOR] = "for",
+ [OFUNC] = "func",
+ [OGE] = ">=",
+ [OGOTO] = "goto",
+ [OGT] = ">",
+ [OIF] = "if",
+ [OINC] = "++",
+ [OIND] = "*",
+ [OLEN] = "len",
+ [OLE] = "<=",
+ [OLSH] = "<<",
+ [OLT] = "<",
+ [OMAKE] = "make",
+ [OMINUS] = "-",
+ [OMOD] = "%",
+ [OMUL] = "*",
+ [ONEW] = "new",
+ [ONE] = "!=",
+ [ONOT] = "!",
+ [OOROR] = "||",
+ [OOR] = "|",
+ [OPANICN] = "panicln",
+ [OPANIC] = "panic",
+ [OPLUS] = "+",
+ [OPRINTN] = "println",
+ [OPRINT] = "print",
+ [ORANGE] = "range",
+ [ORECV] = "<-",
+ [ORETURN] = "return",
+ [ORSH] = ">>",
+ [OSELECT] = "select",
+ [OSEND] = "<-",
+ [OSUB] = "-",
+ [OSWITCH] = "switch",
+ [OXOR] = "^",
+};
+
int
Oconv(Fmt *fp)
{
@@ -739,6 +798,8 @@ Oconv(Fmt *fp)
int o;
o = va_arg(fp->args, int);
+ if((fp->flags & FmtSharp) && o >= 0 && o < nelem(goopnames) && goopnames[o] != nil)
+ return fmtstrcpy(fp, goopnames[o]);
if(o < 0 || o >= nelem(opnames) || opnames[o] == nil) {
snprint(buf, sizeof(buf), "O-%d", o);
return fmtstrcpy(fp, buf);
@@ -1263,6 +1324,11 @@ Nconv(Fmt *fp)
fmtprint(fp, "<N>");
goto out;
}
+
+ if(fp->flags & FmtSharp) {
+ exprfmt(fp, n, 0);
+ goto out;
+ }
switch(n->op) {
default: