mirror of https://github.com/golang/go.git
441 lines
6.8 KiB
C
441 lines
6.8 KiB
C
// 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 OARRAYBYTESTR:
|
|
case OCAP:
|
|
case OCLOSE:
|
|
case OCLOSED:
|
|
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 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 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 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 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 OCLOSED:
|
|
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, ")");
|
|
}
|