// ----------------------------------------------------------------------------
// Types
-func (P *Printer) Type(t *AST.Type)
+func (P *Printer) Type(t *AST.Type) int
func (P *Printer) Expr(x *AST.Expr)
func (P *Printer) Parameters(pos int, list *array.Array) {
}
-func (P *Printer) Type(t *AST.Type) {
+// Returns the separator (semicolon or none) required if
+// the type is terminating a declaration or statement.
+func (P *Printer) Type(t *AST.Type) int {
+ separator := semicolon;
+
switch t.tok {
case Scanner.IDENT:
P.Expr(t.expr);
P.Expr(t.expr);
}
P.String(0, "]");
- P.Type(t.elt);
+ separator = P.Type(t.elt);
case Scanner.STRUCT, Scanner.INTERFACE:
P.Token(t.pos, t.tok);
P.separator = blank;
P.Fields(t.list, t.end);
}
+ separator = none;
case Scanner.MAP:
P.String(t.pos, "map [");
P.Type(t.key);
P.String(0, "]");
- P.Type(t.elt);
+ separator = P.Type(t.elt);
case Scanner.CHAN:
var m string;
case AST.SEND: m = "chan <- ";
}
P.String(t.pos, m);
- P.Type(t.elt);
+ separator = P.Type(t.elt);
case Scanner.MUL:
P.String(t.pos, "*");
- P.Type(t.elt);
+ separator = P.Type(t.elt);
case Scanner.LPAREN:
P.Parameters(t.pos, t.list);
default:
P.Error(t.pos, t.tok, "type");
}
+
+ return separator;
}
// ----------------------------------------------------------------------------
// Declarations
-// TODO This code is unreadable! Clean up AST and rewrite this.
-
func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) {
if !parenthesized {
if d.exported {
}
if d.tok != Scanner.FUNC && d.list != nil {
+ // group of parenthesized declarations
P.state = opening_scope;
P.String(0, "(");
if d.list.Len() > 0 {
P.String(d.end, ")");
} else {
- if d.tok == Scanner.FUNC && d.typ.key != nil {
- P.Parameters(0, d.typ.key.list);
- P.separator = blank;
- }
-
- P.Expr(d.ident);
-
- if d.typ != nil {
- if d.tok != Scanner.FUNC {
- // TODO would like to change this to a tab separator
- // but currently this causes trouble when the type is
- // a struct/interface (fields are indented wrongly)
- P.separator = blank;
+ // single declaration
+ switch d.tok {
+ case Scanner.IMPORT:
+ if d.ident != nil {
+ P.Expr(d.ident);
+ } else {
+ P.String(d.val.pos, ""); // flush pending ';' separator/newlines
}
- P.Type(d.typ);
P.separator = tab;
- }
+ P.Expr(d.val);
+ P.separator = semicolon;
+
+ case Scanner.EXPORT:
+ P.Expr(d.ident);
+ P.separator = semicolon;
- if d.val != nil {
- if d.tok != Scanner.IMPORT {
+ case Scanner.TYPE:
+ P.Expr(d.ident);
+ P.separator = blank; // TODO switch to tab? (but indentation problem with structs)
+ P.separator = P.Type(d.typ);
+
+ case Scanner.CONST, Scanner.VAR:
+ P.Expr(d.ident);
+ if d.typ != nil {
+ P.separator = blank; // TODO switch to tab? (indentation problem with structs)
+ P.separator = P.Type(d.typ);
+ }
+ if d.val != nil {
P.separator = tab;
P.String(0, "=");
P.separator = blank;
+ P.Expr(d.val);
}
- P.Expr(d.val);
- }
+ P.separator = semicolon;
- if d.list != nil {
- if d.tok != Scanner.FUNC {
- panic("must be a func declaration");
+ case Scanner.FUNC:
+ if d.typ.key != nil {
+ // method: print receiver
+ P.Parameters(0, d.typ.key.list);
+ P.separator = blank;
}
- P.separator = blank;
- P.Block(0, d.list, d.end, true);
- }
-
- if d.tok != Scanner.TYPE {
- P.separator = semicolon;
+ P.Expr(d.ident);
+ P.separator = P.Type(d.typ);
+ if d.list != nil {
+ P.separator = blank;
+ P.Block(0, d.list, d.end, true);
+ }
+
+ default:
+ P.Error(d.pos, d.tok, "decl");
}
}
P.Program(prog);
// flush
- P.String(0, "");
+ P.String(0, ""); // flush pending separator/newlines
err := P.writer.Flush();
if err != nil {
panic("print error - exiting");