ref: 4457deb19fb16af77ee0f0f8b3ea745b3fe41e1d
dir: /fmt.c/
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
static char *expoptab[] = {
[Olit] "",
[Ovar] "",
[Oasn] "=",
[Oadd] "+",
[Osub] "-",
[Omul] "*",
[Odiv] "/",
[Omod] "%",
[Oshl] "<<",
[Oshr] ">>",
[Olor] "||",
[Oland] "&&",
[Ogt] ">",
[Olt] "<",
[Oge] ">=",
[Ole] "<=",
[Oeq] "==",
[One] "!=",
[Oinc] "++",
[Odec] "--",
[Orcv] "←"
};
static char tabs[128], stars[128];
int
nodfmt(Fmt *f)
{
Nod *n;
int nt, e;
nt = f->prec;
n = va_arg(f->args, Nod*);
if(n == nil)
return 0;
if(nt && n->t != Nblk)
fmtprint(f, "%.*s", nt, tabs);
switch(n->t){
default:
return fmtprint(f, "unknown nod type %d", n->t);
case Niter:
return fmtprint(f, "FOR ( %N ← %N ) %.*N", n->iter.idx, n->iter.arg, nt+1, n->iter.body);
case Nfor:
return fmtprint(f, "FOR ( %N ; %N ; %N ) %.*N", n->nfor.init, n->nfor.cond, n->nfor.step, nt+1, n->nfor.body);
case Nif:
if(n->nif.f)
return fmtprint(f, "IF ( %N ) %.*N ELSE %.*N", n->nif.cond, nt+1, n->nif.t, nt+1, n->nif.f);
return fmtprint(f, "IF ( %N ) %.*N", n->nif.cond, nt+1, n->nif.t);
case Nsym:
return fmtprint(f, "%s", n->sym.sym);
case Nlit:
switch(n->lit.t){
case Lint:
return fmtprint(f, "%lld", n->lit.i);
case Lstr:
return fmtprint(f, "\"%s\"", n->lit.s);
default:
return fmtprint(f, "\n#error unknown literal type\n");
}
case Nexpr:
if(n->expr.op == Olit || n->expr.op == Ovar)
return fmtprint(f, "%N", n->expr.lhs);
else if(n->expr.op == Oind)
return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
else
return fmtprint(f, "EXPR(%N %s %N)", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
case Nblk:
e = nt - 1;
if(e < 0)
e = 0;
return fmtprint(f, "{\n%.*L\n%.*s}", nt, n->blk.body, e, tabs);
case Ndcl:
return fmtprint(f, "DCL %s : %s", n->dcl.name, n->dcl.type->name);
case Nfunc:
return fmtprint(f, "FN %s (\n%.*L\n) → %.*N", n->func.name, nt+1, n->func.args, nt+1, n->func.body);
case Ncall:
return fmtprint(f, "CALL %s (\n%.*L\n%.*s)", n->call.name, nt+1, n->call.args, nt, tabs);
}
}
int
nlstfmt(Fmt *f)
{
int i, nt;
Nlst n;
nt = f->prec;
n = va_arg(f->args, Nlst);
for(i = 0; i < n.nv; i++){
fmtprint(f, "%.*N", nt, n.v[i]);
if(i != n.nv-1)
fmtprint(f, "\n");
}
return 0;
}
int
cnodfmt(Fmt *f)
{
Nod *n;
char *t;
int nt, e;
Typ *ty;
nt = f->prec;
n = va_arg(f->args, Nod*);
if(n == nil)
return 0;
if(nt && n->t != Nblk)
fmtprint(f, "%.*s", nt, tabs);
switch(n->t){
default:
return fmtprint(f, "unknown nod type %d", n->t);
case Nfor:
return fmtprint(f, "for(%O; %O; %O) %.*O", n->nfor.init, n->nfor.cond, n->nfor.step, nt+1, n->nfor.body);
case Nif:
if(n->nif.f)
return fmtprint(f, "if(%O)%.*Oelse%.*O", n->nif.cond, nt+1, n->nif.t, nt+1, n->nif.f);
return fmtprint(f, "if(%O)%.*O", n->nif.cond, nt+1, n->nif.t);
case Nsym:
return fmtprint(f, "%s", n->sym.sym);
case Nlit:
switch(n->lit.t){
case Lint:
return fmtprint(f, "%lld", n->lit.i);
case Lstr:
return fmtprint(f, "\"%s\"", n->lit.s);
default:
return fmtprint(f, "\n#error unknown literal type\n");
}
case Nexpr:
if(n->expr.op == Olit || n->expr.op == Ovar)
return fmtprint(f, "%O", n->expr.lhs);
else if(n->expr.op == Oind)
return fmtprint(f, "%N[%N]", n->expr.lhs, n->expr.rhs);
else
return fmtprint(f, "%O %s %O", n->expr.lhs, expoptab[n->expr.op], n->expr.rhs);
case Nblk:
e = nt - 1;
if(e < 0)
e = 0;
return fmtprint(f, "{\n%.*P\n%.*s}", nt, n->blk.body, e, tabs);
case Ndcl:
e = 0;
for(ty = n->dcl.type; ty->t == Tslice; ty = ty->base)
e++;
return fmtprint(f, "%s %.*s%s", ty->name, e, stars, n->dcl.name);
case Nfunc:
t = n->func.type->base->name;
if(n->func.args.nv == 0)
fmtprint(f, "%s\n%s(void)", t, n->func.name);
else
fmtprint(f, "%s\n%s(%M)", t, n->func.name, n->func.args);
return fmtprint(f, "\n%.*O", nt+1, n->func.body);
case Ncall:
return fmtprint(f, "%s(%M)", n->call.name, n->call.args);
}
}
int
cnlstfmt(Fmt *f)
{
int i, nt;
Nlst n;
nt = f->prec;
n = va_arg(f->args, Nlst);
for(i = 0; i < n.nv; i++){
fmtprint(f, "%.*O", nt, n.v[i]);
if(i != n.nv-1)
fmtprint(f, ", ");
}
return 0;
}
int
cnlstfmtblk(Fmt *f)
{
int i, nt;
Nlst n;
nt = f->prec;
n = va_arg(f->args, Nlst);
for(i = 0; i < n.nv; i++){
fmtprint(f, "%.*O", nt, n.v[i]);
switch(n.v[i]->t){
case Ncall: case Ndcl: case Nexpr:
fmtprint(f, ";");
}
if(i != n.nv-1)
fmtprint(f, "\n");
}
return 0;
}
void
astfmtinstall(void)
{
memset(tabs, '\t', nelem(tabs)-1);
tabs[nelem(tabs)-1] = '\0';
memset(stars, '*', nelem(stars)-1);
tabs[nelem(stars)-1] = '\0';
fmtinstall('N', nodfmt);
fmtinstall('L', nlstfmt);
fmtinstall('O', cnodfmt);
fmtinstall('M', cnlstfmt);
fmtinstall('P', cnlstfmtblk);
}