shithub: hammer

ref: 4457deb19fb16af77ee0f0f8b3ea745b3fe41e1d
dir: /fmt.c/

View raw version
#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);
}