");
}
func (P *Printer) DoImportDecl(d *ast.ImportDecl) {
if d.Loc.Pos > 0 {
P.Token(d.Loc, token.IMPORT);
P.separator = blank;
}
if d.Ident != nil {
P.Expr(d.Ident);
} else {
P.String(d.Path.Loc(), ""); // flush pending ';' separator/newlines
}
P.separator = tab;
if lit, is_lit := d.Path.(*ast.BasicLit); is_lit && lit.Tok == token.STRING {
P.HtmlPackageName(lit.Loc_, string(lit.Val));
} else {
// we should only reach here for strange imports
// import "foo" "bar"
P.Expr(d.Path);
}
P.newlines = 2;
}
func (P *Printer) DoConstDecl(d *ast.ConstDecl) {
if d.Loc.Pos > 0 {
P.Token(d.Loc, token.CONST);
P.separator = blank;
}
P.Idents(d.Idents);
if d.Typ != nil {
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
P.Expr(d.Typ);
}
if d.Vals != nil {
P.separator = tab;
P.Token(noloc, token.ASSIGN);
P.separator = blank;
P.Expr(d.Vals);
}
P.newlines = 2;
}
func (P *Printer) DoTypeDecl(d *ast.TypeDecl) {
if d.Loc.Pos > 0 {
P.Token(d.Loc, token.TYPE);
P.separator = blank;
}
P.Expr(d.Ident);
P.separator = blank; // TODO switch to tab? (but indentation problem with structs)
P.Expr(d.Typ);
P.newlines = 2;
}
func (P *Printer) DoVarDecl(d *ast.VarDecl) {
if d.Loc.Pos > 0 {
P.Token(d.Loc, token.VAR);
P.separator = blank;
}
P.Idents(d.Idents);
if d.Typ != nil {
P.separator = blank; // TODO switch to tab? (indentation problem with structs)
P.Expr(d.Typ);
//P.separator = P.Type(d.Typ);
}
if d.Vals != nil {
P.separator = tab;
P.Token(noloc, token.ASSIGN);
P.separator = blank;
P.Expr(d.Vals);
}
P.newlines = 2;
}
func (P *Printer) funcDecl(d *ast.FuncDecl, with_body bool) {
P.Token(d.Loc, token.FUNC);
P.separator = blank;
if recv := d.Recv; recv != nil {
// method: print receiver
P.Token(noloc, token.LPAREN);
if len(recv.Idents) > 0 {
P.Expr(recv.Idents[0]);
P.separator = blank;
}
P.Expr(recv.Typ);
P.Token(noloc, token.RPAREN);
P.separator = blank;
}
P.Expr(d.Ident);
P.Signature(d.Sig);
if with_body && d.Body != nil {
P.separator = blank;
P.Block(d.Body, true);
}
P.newlines = 2;
}
func (P *Printer) DoFuncDecl(d *ast.FuncDecl) {
P.funcDecl(d, true);
}
func (P *Printer) DoDeclList(d *ast.DeclList) {
if !*def || d.Tok == token.IMPORT || d.Tok == token.VAR {
P.Token(d.Loc, d.Tok);
} else {
P.String(d.Loc, "def");
}
P.separator = blank;
// group of parenthesized declarations
P.state = opening_scope;
P.Token(noloc, token.LPAREN);
if len(d.List) > 0 {
P.newlines = 1;
for i := 0; i < len(d.List); i++ {
if i > 0 {
P.separator = semicolon;
}
P.Decl(d.List[i]);
P.newlines = 1;
}
}
P.state = closing_scope;
P.Token(d.End, token.RPAREN);
P.opt_semi = true;
P.newlines = 2;
}
func (P *Printer) Decl(d ast.Decl) {
d.Visit(P);
}
// ----------------------------------------------------------------------------
// Package interface
// TODO this should be an AST method
func isExported(name *ast.Ident) bool {
ch, len := utf8.DecodeRuneInString(name.Str, 0);
return unicode.IsUpper(ch);
}
func (P *Printer) Interface(p *ast.Program) {
for i := 0; i < len(p.Decls); i++ {
switch d := p.Decls[i].(type) {
case *ast.FuncDecl:
if isExported(d.Ident) {
P.Printf("%s
\n", d.Ident.Str);
/*
P.Printf("");
P.funcDecl(d, false);
P.String(noloc, "");
P.Printf("
");
*/
}
}
}
}
// ----------------------------------------------------------------------------
// Program
func (P *Printer) Program(p *ast.Program) {
P.Token(p.Loc, token.PACKAGE);
P.separator = blank;
P.Expr(p.Ident);
P.newlines = 1;
for i := 0; i < len(p.Decls); i++ {
P.Decl(p.Decls[i]);
}
P.newlines = 1;
}
// ----------------------------------------------------------------------------
// External interface
var templ template.Template;
func init() {
templ.Init("template.html");
}
func Print(writer io.Write, html bool, prog *ast.Program) {
// setup
var P Printer;
padchar := byte(' ');
if *usetabs {
padchar = '\t';
}
flags := uint(0);
if html {
flags |= tabwriter.FilterHTML;
}
text := tabwriter.NewWriter(writer, *tabwidth, 1, padchar, flags);
P.Init(text, html, prog.Comments);
if P.html {
err := templ.Apply(text, "" : func() { P.Printf("%s", prog.Ident.Str); },
"INTERFACE-->" : func() { P.Interface(prog); },
"BODY-->" : func() { P.Program(prog); },
});
if err != nil {
panic("print error - exiting");
}
} else {
P.Program(prog);
}
P.String(noloc, ""); // flush pending separator/newlines
err := text.Flush();
if err != nil {
panic("print error - exiting");
}
}