testnoisy: pretty
pretty *.go
pretty ../gosrc/*.go
+ #pretty $(GOROOT)/test/*.go # contains incorrect programs
pretty $(GOROOT)/test/235.go
pretty $(GOROOT)/test/args.go
pretty $(GOROOT)/test/bufiolib.go
pretty $(GOROOT)/test/char_lit.go
- pretty $(GOROOT)/test/sieve.go
+ pretty $(GOROOT)/test/complit.go
+ pretty $(GOROOT)/test/const.go
+ pretty $(GOROOT)/test/dialgoogle.go
+ pretty $(GOROOT)/test/empty.go
+ pretty $(GOROOT)/test/env.go
+ pretty $(GOROOT)/test/float_lit.go
+ pretty $(GOROOT)/test/fmt_test.go
+ pretty $(GOROOT)/test/for.go
+ pretty $(GOROOT)/test/func.go
+ pretty $(GOROOT)/test/func1.go
+ pretty $(GOROOT)/test/func2.go
pretty $(GOROOT)/src/pkg/*.go
- pretty $(GOROOT)/src/lib/flag.go
- pretty $(GOROOT)/src/lib/fmt.go
- pretty $(GOROOT)/src/lib/rand.go
- pretty $(GOROOT)/src/lib/math/*.go
- pretty $(GOROOT)/src/lib/container/*.go
- pretty $(GOROOT)/src/lib/syscall/*.go
+ pretty $(GOROOT)/src/lib/*.go
+ pretty $(GOROOT)/src/lib/*/*.go
+ pretty $(GOROOT)/usr/r/*/*.go
echo "DONE"
# These tests don't work yet
}
+func (p *List) set(i int, x Node) {
+ p.a[i] = x;
+}
+
+
func (p *List) Add (x Node) {
a := p.a;
n := len(a);
pos, tok int;
x, y *Expr; // binary (x, y) and unary (y) expressions
s string; // identifiers and literals
- t *Type; // declarations and composite literals
+ t *Type; // operands that are types
}
}
+export func NewTypeExpr(pos int, t *Type) *Expr {
+ e := new(Expr);
+ e.pos, e.tok, e.t = pos, Scanner.TYPE, t;
+ return e;
+}
+
+
// ----------------------------------------------------------------------------
// Statements
}
-func (P *Parser) ParseVarDeclList() {
+func (P *Parser) ParseVarDeclList(list *Node.List) {
P.Trace("VarDeclList");
- list := Node.NewList();
+ i0 := list.len();
list.Add(P.ParseType());
for P.tok == Scanner.COMMA {
P.Next();
typ := P.TryType();
if typ != nil {
- // all list entries must be identifiers;
- // convert the list into an expression list of identifiers
- for i, n := 0, list.len(); i < n; i++ {
+ // all list entries must be identifiers
+ // convert the type entries into identifiers
+ for i, n := i0, list.len(); i < n; i++ {
t := list.at(i).(*Node.Type);
if t.tok == Scanner.IDENT && t.expr.tok == Scanner.IDENT {
- x := t.expr;
+ list.set(i, t.expr);
} else {
+ list.set(i, Node.NewLit(t.pos, Scanner.IDENT, "bad"));
P.Error(t.pos, "identifier expected");
}
}
+ // add type
+ list.Add(Node.NewTypeExpr(typ.pos, typ));
+
} else {
// all list entries are types
+ // convert all type entries into type expressions
+ for i, n := i0, list.len(); i < n; i++ {
+ t := list.at(i).(*Node.Type);
+ list.set(i, Node.NewTypeExpr(t.pos, t));
+ }
+ if P.tok == Scanner.COMMA {
+ panic("internal parser error");
+ }
}
P.Ecart();
P.Trace("ParameterList");
list := Node.NewList();
- P.ParseVarDeclList();
+ P.ParseVarDeclList(list);
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseVarDeclList();
+ P.ParseVarDeclList(list);
}
P.Ecart();
}
-func (P *Parser) ParseParameters() *Node.List {
+func (P *Parser) ParseParameters() *Node.Type {
P.Trace("Parameters");
- var list *Node.List;
+ t := Node.NewType(P.pos, Scanner.STRUCT);
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
- list = P.ParseParameterList();
+ t.list = P.ParseParameterList();
}
P.Expect(Scanner.RPAREN);
P.Ecart();
- return list;
+ return t;
}
}
-func (P *Parser) ParseResult() *Node.List {
+func (P *Parser) ParseResult() *Node.Type {
P.Trace("Result");
- var list *Node.List;
+ var t *Node.Type;
if P.tok == Scanner.LPAREN {
- list = P.ParseParameters();
+ t = P.ParseParameters();
} else {
typ := P.TryType();
+ if typ != nil {
+ t = Node.NewType(P.pos, Scanner.STRUCT);
+ t.list = Node.NewList();
+ t.list.Add(Node.NewTypeExpr(typ.pos, typ));
+ }
}
P.Ecart();
- return list;
+ return t;
}
P.Trace("FunctionType");
t := Node.NewType(P.pos, Scanner.LPAREN);
- t.list = P.ParseParameters();
- P.ParseResult();
+ t.list = P.ParseParameters().list; // TODO find better solution
+ t.elt = P.ParseResult();
P.Ecart();
return t;
P.Next();
t.list = Node.NewList();
for P.tok == Scanner.IDENT {
- P.ParseVarDeclList();
+ P.ParseVarDeclList(t.list);
if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON);
}
P.scope_lev--;
P.Ecart();
- return nil;
+ return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
}
case Scanner.FUNC:
- P.ParseFunctionLit();
+ x = P.ParseFunctionLit();
default:
- typ := P.TryType();
- if typ != nil {
- break;
+ t := P.TryType();
+ if t != nil {
+ x = Node.NewTypeExpr(t.pos, t);
+ } else {
+ P.Error(P.pos, "operand expected");
+ P.Next(); // make progress
+ x = Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
-
- P.Error(P.pos, "operand expected");
- P.Next(); // make progress
}
P.Ecart();
}
-func (P *Parser) ParseCompositeLit() {
+func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr {
P.Trace("CompositeLit");
mode := 0;
P.Expect(Scanner.RBRACE);
P.Ecart();
+ return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
case Scanner.LPAREN: x = P.ParseCall(x);
case Scanner.LBRACE:
if P.expr_lev > 0 {
- P.ParseCompositeLit();
+ var t *Node.Type;
+ if x.tok == Scanner.TYPE {
+ t = x.t;
+ } else if x.tok == Scanner.IDENT {
+ // assume a type name
+ t = Node.NewType(x.pos, Scanner.IDENT);
+ t.expr = x;
+ } else {
+ P.Error(x.pos, "type expected for composite literal");
+ }
+ x = P.ParseCompositeLit(t);
} else {
+ // composites inside control clauses must be parenthesized
goto exit;
}
default: goto exit;
if P.tok == Scanner.STRING {
// TODO eventually the scanner should strip the quotes
+ d.val = Node.NewLit(P.pos, Scanner.STRING, P.val);
P.Next();
} else {
P.Expect(Scanner.STRING); // use Expect() error handling
P.Expect(Scanner.FUNC);
if P.tok == Scanner.LPAREN {
pos := P.pos;
- P.ParseParameters();
- /*
- if tmp.len() > 0 {
- //recv = tmp.at(0);
- }
- */
+ recv := P.ParseParameters();
+ // TODO: fix this
/*
- if recv.idents.len() != 1 {
- //P.Error(pos, "must have exactly one receiver");
+ if recv.list.len() != 1 {
+ P.Error(pos, "must have exactly one receiver");
}
*/
}
}
-func (P *Printer) String(s string) {
+func (P *Printer) String(pos int, s string) {
if P.semi && P.level > 0 { // no semicolons at level 0
print(";");
}
}
-func (P *Printer) Token(tok int) {
- P.String(Scanner.TokenString(tok));
+func (P *Printer) Blank() {
+ P.String(0, " ");
+}
+
+
+func (P *Printer) Token(pos int, tok int) {
+ P.String(pos, Scanner.TokenString(tok));
}
func (P *Printer) OpenScope(paren string) {
P.semi, P.newl = false, false;
- P.String(paren);
+ P.String(0, paren);
P.level++;
P.indent++;
P.newl = true;
func (P *Printer) CloseScope(paren string) {
P.indent--;
P.semi = false;
- P.String(paren);
+ P.String(0, paren);
P.level--;
P.semi, P.newl = false, true;
}
// ----------------------------------------------------------------------------
// Types
+func (P *Printer) Type(t *Node.Type)
func (P *Printer) Expr(x *Node.Expr)
+func (P *Printer) Parameters(list *Node.List) {
+ var prev int;
+ for i, n := 0, list.len(); i < n; i++ {
+ x := list.at(i).(*Node.Expr);
+ if i > 0 {
+ if prev == x.tok || prev == Scanner.TYPE {
+ P.String(0, ", ");
+ } else {
+ P.Blank();
+ }
+ }
+ P.Expr(x);
+ prev = x.tok;
+ }
+}
+
+
+func (P *Printer) Fields(list *Node.List) {
+ var prev int;
+ for i, n := 0, list.len(); i < n; i++ {
+ x := list.at(i).(*Node.Expr);
+ if i > 0 {
+ if prev == Scanner.TYPE {
+ P.String(0, ";");
+ P.newl = true;
+ } else if prev == x.tok {
+ P.String(0, ", ");
+ } else {
+ P.Blank();
+ }
+ }
+ P.Expr(x);
+ prev = x.tok;
+ }
+ P.newl = true;
+}
+
+
func (P *Printer) Type(t *Node.Type) {
+ if t == nil { // TODO remove this check
+ P.String(0, "<nil type>");
+ return;
+ }
+
switch t.tok {
case Scanner.IDENT:
P.Expr(t.expr);
case Scanner.LBRACK:
- P.String("[");
+ P.String(t.pos, "[");
if t.expr != nil {
P.Expr(t.expr);
}
- P.String("] ");
+ P.String(0, "] ");
P.Type(t.elt);
case Scanner.STRUCT:
- P.String("struct");
+ P.String(t.pos, "struct");
if t.list != nil {
P.OpenScope(" {");
- /*
- for i := 0; i < x.fields.len(); i++ {
- P.Print(x.fields.at(i));
- P.newl, P.semi = true, true;
- }
- */
+ P.Fields(t.list);
P.CloseScope("}");
}
case Scanner.MAP:
- P.String("[");
+ P.String(t.pos, "[");
P.Type(t.key);
- P.String("] ");
+ P.String(0, "] ");
P.Type(t.elt);
case Scanner.CHAN:
+ var m string;
switch t.mode {
- case Node.FULL: P.String("chan ");
- case Node.RECV: P.String("<-chan ");
- case Node.SEND: P.String("chan <- ");
+ case Node.FULL: m = "chan ";
+ case Node.RECV: m = "<-chan ";
+ case Node.SEND: m = "chan <- ";
}
+ P.String(t.pos, m);
P.Type(t.elt);
case Scanner.INTERFACE:
- P.String("interface");
+ P.String(t.pos, "interface");
if t.list != nil {
P.OpenScope(" {");
/*
}
case Scanner.MUL:
- P.String("*");
+ P.String(t.pos, "*");
P.Type(t.elt);
case Scanner.LPAREN:
- P.String("(");
- //P.PrintList(x.params);
- P.String(")");
- /*
- if x.result != nil {
- P.String(" (");
- P.PrintList(x.result);
- P.String(")");
+ P.String(t.pos, "(");
+ P.Parameters(t.list);
+ P.String(0, ")");
+ if t.elt != nil {
+ P.String(0, " (");
+ P.Parameters(t.elt.list);
+ P.String(0, ")");
}
- */
default:
panic("UNREACHABLE");
}
switch x.tok {
+ case Scanner.VAR:
+ panic("UNIMPLEMENTED (VAR)");
+
+ case Scanner.TYPE:
+ P.Type(x.t);
+
case Scanner.IDENT, Scanner.INT, Scanner.STRING, Scanner.FLOAT:
- P.String(x.s);
+ P.String(x.pos, x.s);
case Scanner.COMMA:
P.Expr1(x.x, 0);
- P.String(", ");
+ P.String(x.pos, ", ");
P.Expr1(x.y, 0);
case Scanner.PERIOD:
- P.Expr1(x.x, 8);
- P.String(".");
+ P.Expr1(x.x, 8); // 8 == highest precedence
+ P.String(x.pos, ".");
P.Expr1(x.y, 8);
case Scanner.LBRACK:
P.Expr1(x.x, 8);
- P.String("[");
+ P.String(x.pos, "[");
P.Expr1(x.y, 0);
- P.String("]");
+ P.String(0, "]");
case Scanner.LPAREN:
P.Expr1(x.x, 8);
- P.String("(");
+ P.String(x.pos, "(");
P.Expr1(x.y, 0);
- P.String(")");
+ P.String(0, ")");
default:
if x.x == nil {
// unary expression
- P.Token(x.tok);
- P.Expr1(x.y, 7);
+ P.Token(x.pos, x.tok);
+ P.Expr1(x.y, 7); // 7 == unary operator precedence
} else {
// binary expression: print ()'s if necessary
prec := Scanner.Precedence(x.tok);
if prec < prec1 {
- print("(");
+ P.String(0, "(");
}
P.Expr1(x.x, prec);
- P.String(" ");
- P.Token(x.tok);
- P.String(" ");
+ P.Blank();
+ P.Token(x.pos, x.tok);
+ P.Blank();
P.Expr1(x.y, prec);
if prec < prec1 {
- print(")");
+ P.String(0, ")");
}
}
}
func (P *Printer) ControlClause(s *Node.Stat) {
if s.init != nil {
- P.String(" ");
+ P.Blank();
P.Stat(s.init);
P.semi = true;
- P.String("");
}
if s.expr != nil {
- P.String(" ");
+ P.Blank();
P.Expr(s.expr);
P.semi = false;
}
if s.tok == Scanner.FOR && s.post != nil {
P.semi = true;
- P.String(" ");
+ P.Blank();
P.Stat(s.post);
P.semi = false;
}
- P.String(" ");
+ P.Blank();
}
-func (P *Printer) Declaration(d *Node.Decl);
+func (P *Printer) Declaration(d *Node.Decl, parenthesized bool);
func (P *Printer) Stat(s *Node.Stat) {
if s == nil { // TODO remove this check
- P.String("<nil stat>");
+ P.String(0, "<nil stat>");
return;
}
P.semi = true;
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
- P.Declaration(s.decl);
+ P.Declaration(s.decl, false);
case Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN,
Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN,
Scanner.REM_ASSIGN, Scanner.AND_ASSIGN, Scanner.OR_ASSIGN,
Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
P.Expr(s.lhs);
- P.String(" ");
- P.Token(s.tok);
- P.String(" ");
+ P.Blank();
+ P.Token(s.pos, s.tok);
+ P.Blank();
P.Expr(s.expr);
P.semi = true;
case Scanner.INC, Scanner.DEC:
P.Expr(s.expr);
- P.Token(s.tok);
+ P.Token(s.pos, s.tok);
P.semi = true;
case Scanner.LBRACE:
P.Block(s.block, true);
case Scanner.IF:
- P.String("if");
+ P.String(s.pos, "if");
P.ControlClause(s);
P.Block(s.block, true);
if s.post != nil {
P.newl = false;
- P.String(" else ");
+ P.String(0, " else ");
P.Stat(s.post);
}
case Scanner.FOR:
- P.String("for");
+ P.String(s.pos, "for");
P.ControlClause(s);
P.Block(s.block, true);
case Scanner.SWITCH, Scanner.SELECT:
- P.Token(s.tok);
+ P.Token(s.pos, s.tok);
P.ControlClause(s);
P.Block(s.block, false);
case Scanner.CASE, Scanner.DEFAULT:
- P.Token(s.tok);
+ P.Token(s.pos, s.tok);
if s.expr != nil {
- P.String(" ");
+ P.Blank();
P.Expr(s.expr);
}
- P.String(":");
+ P.String(0, ":");
P.OpenScope("");
P.StatementList(s.block);
P.CloseScope("");
case Scanner.GO, Scanner.RETURN, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
- P.Token(s.tok);
- P.String(" ");
+ P.Token(s.pos, s.tok);
+ P.Blank();
P.Expr(s.expr);
P.semi = true;
default:
- P.String("<stat>");
+ P.String(s.pos, "<stat>");
P.semi = true;
}
}
*/
-func (P *Printer) Declaration(d *Node.Decl) {
- if d.tok == Scanner.FUNC || d.ident == nil {
+func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
+ if d == nil { // TODO remove this check
+ P.String(0, "<nil decl>");
+ return;
+ }
+
+ if !parenthesized {
if d.exported {
- P.String("export ");
+ P.String(0, "export ");
}
- P.Token(d.tok);
- P.String(" ");
+ P.Token(d.pos, d.tok);
+ P.Blank();
}
if d.ident == nil {
- switch d.list.len() {
- case 0:
- P.String("()");
- case 1:
- P.Declaration(d.list.at(0).(*Node.Decl));
- default:
- P.OpenScope("(");
- for i := 0; i < d.list.len(); i++ {
- P.Declaration(d.list.at(i).(*Node.Decl));
- P.newl, P.semi = true, true;
- }
- P.CloseScope(")");
+ P.OpenScope("(");
+ for i := 0; i < d.list.len(); i++ {
+ P.Declaration(d.list.at(i).(*Node.Decl), true);
+ P.newl, P.semi = true, true;
}
+ P.CloseScope(")");
} else {
P.Expr(d.ident);
if d.typ != nil {
- P.String(" ");
+ P.Blank();
P.Type(d.typ);
}
if d.val != nil {
- P.String(" = ");
+ if d.tok == Scanner.IMPORT {
+ P.Blank();
+ } else {
+ P.String(0, " = ");
+ }
P.Expr(d.val);
}
if d.list != nil {
if d.tok != Scanner.FUNC {
panic("must be a func declaration");
}
- P.String(" ");
+ P.Blank();
P.Block(d.list, true);
}
}
// Program
func (P *Printer) Program(p *Node.Program) {
- P.String("package ");
+ P.String(p.pos, "package ");
P.Expr(p.ident);
P.NewLine();
for i := 0; i < p.decls.len(); i++ {
- P.Declaration(p.decls.at(i));
+ P.Declaration(p.decls.at(i), false);
}
P.newl = true;
- P.String("");
+ P.String(0, ""); // flush
}