blob: af69202838c2f6327d55770fbeecef821a92add2 [file] [log] [blame]
// 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;
nprec = 0;
if(n == nil) {
fmtprint(f, "<nil>");
return;
}
switch(n->op) {
case ONAME:
case ONONAME:
case OPACK:
case OLITERAL:
case ODOT:
case ODOTPTR:
case ODOTINTER:
case ODOTMETH:
case OARRAYBYTESTR:
case OCAP:
case OCLOSE:
case OCLOSED:
case OCOPY:
case OLEN:
case OMAKE:
case ONEW:
case OPANIC:
case OPANICN:
case OPRINT:
case OPRINTN:
case OCALL:
case OCONV:
case OCONVNOP:
case OCONVSLICE:
case OCONVIFACE:
case OMAKESLICE:
case ORUNESTR:
case OADDR:
case OCOM:
case OIND:
case OMINUS:
case ONOT:
case OPLUS:
case ORECV:
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 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:
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, " ");
if(n->left->op == OTCHAN && 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 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 OCOMPLIT:
fmtprint(f, "composite literal");
break;
case OARRAYLIT:
fmtprint(f, "slice literal");
break;
case OMAPLIT:
fmtprint(f, "map literal");
break;
case OSTRUCTLIT:
fmtprint(f, "struct literal");
break;
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
fmtprint(f, ".%s", n->right->sym->name);
break;
case ODOTTYPE:
exprfmt(f, n->left, 7);
fmtprint(f, ".(");
exprfmt(f, n->right, 0);
fmtprint(f, ")");
break;
case OINDEX:
case OINDEXMAP:
case OINDEXSTR:
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 OCALLFUNC:
case OCALLINTER:
case OCALLMETH:
exprfmt(f, n->left, 7);
fmtprint(f, "(");
exprlistfmt(f, n->list);
fmtprint(f, ")");
break;
case OCMPLX:
fmtprint(f, "cmplx(");
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 OCONVNOP:
case OCONVSLICE:
case OCONVIFACE:
case OARRAYBYTESTR:
case ORUNESTR:
if(n->type == T || n->type->sym == S)
fmtprint(f, "(%T)(", n->type);
else
fmtprint(f, "%T(", n->type);
exprfmt(f, n->left, 0);
fmtprint(f, ")");
break;
case OCAP:
case OCLOSE:
case OCLOSED:
case OLEN:
case OCOPY:
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;
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, ")");
}