From 6b49713df5fb89ad0946f28a559ac4c88b588a1d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 15 Oct 2008 17:06:28 -0700 Subject: [PATCH] snapshot of pretty printer: - almost there, receivers, labels, composites, comments are not yet printed - runs through 18KLOC of Go code and prints it again R=r OCL=17237 CL=17237 --- usr/gri/pretty/Makefile | 22 ++-- usr/gri/pretty/node.go | 14 ++- usr/gri/pretty/parser.go | 101 +++++++++++------ usr/gri/pretty/printer.go | 231 +++++++++++++++++++++++--------------- 4 files changed, 233 insertions(+), 135 deletions(-) diff --git a/usr/gri/pretty/Makefile b/usr/gri/pretty/Makefile index 8fd88a0ce9..ae49902ea1 100644 --- a/usr/gri/pretty/Makefile +++ b/usr/gri/pretty/Makefile @@ -36,18 +36,26 @@ test: pretty 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 diff --git a/usr/gri/pretty/node.go b/usr/gri/pretty/node.go index 51ea1e6813..8f81af8387 100644 --- a/usr/gri/pretty/node.go +++ b/usr/gri/pretty/node.go @@ -38,6 +38,11 @@ func (p *List) at(i int) Node { } +func (p *List) set(i int, x Node) { + p.a[i] = x; +} + + func (p *List) Add (x Node) { a := p.a; n := len(a); @@ -100,7 +105,7 @@ export type Expr struct { 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 } @@ -130,6 +135,13 @@ export func NewLit(pos, tok int, s string) *Expr { } +export func NewTypeExpr(pos int, t *Type) *Expr { + e := new(Expr); + e.pos, e.tok, e.t = pos, Scanner.TYPE, t; + return e; +} + + // ---------------------------------------------------------------------------- // Statements diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index a51683d678..a4b4d56854 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -238,10 +238,10 @@ func (P *Parser) ParseChannelType() *Node.Type { } -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(); @@ -251,19 +251,31 @@ func (P *Parser) ParseVarDeclList() { 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(); @@ -274,10 +286,10 @@ func (P *Parser) ParseParameterList() *Node.List { 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(); @@ -285,18 +297,18 @@ func (P *Parser) ParseParameterList() *Node.List { } -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; } @@ -316,18 +328,23 @@ func (P *Parser) ParseResultList() { } -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; } @@ -341,8 +358,8 @@ func (P *Parser) ParseFunctionType() *Node.Type { 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; @@ -405,7 +422,7 @@ func (P *Parser) ParseStructType() *Node.Type { 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); } @@ -521,7 +538,7 @@ func (P *Parser) ParseFunctionLit() *Node.Expr { P.scope_lev--; P.Ecart(); - return nil; + return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr } @@ -550,16 +567,17 @@ func (P *Parser) ParseOperand() *Node.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(); @@ -635,7 +653,7 @@ func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr { } -func (P *Parser) ParseCompositeLit() { +func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr { P.Trace("CompositeLit"); mode := 0; @@ -659,6 +677,7 @@ func (P *Parser) ParseCompositeLit() { P.Expect(Scanner.RBRACE); P.Ecart(); + return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr } @@ -673,8 +692,19 @@ func (P *Parser) ParsePrimaryExpr() *Node.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; @@ -1100,6 +1130,7 @@ func (P *Parser) ParseImportSpec() *Node.Decl { 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 @@ -1218,15 +1249,11 @@ func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl { P.Expect(Scanner.FUNC); if P.tok == Scanner.LPAREN { pos := P.pos; - P.ParseParameters(); + recv := P.ParseParameters(); + // TODO: fix this /* - if tmp.len() > 0 { - //recv = tmp.at(0); - } - */ - /* - 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"); } */ } diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 76b9dd9dce..2b5e70da17 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -16,7 +16,7 @@ export type Printer struct { } -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(";"); } @@ -31,8 +31,13 @@ func (P *Printer) String(s string) { } -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)); } @@ -44,7 +49,7 @@ func (P *Printer) NewLine() { // explicit "\n" 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; @@ -54,7 +59,7 @@ func (P *Printer) OpenScope(paren string) { 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; } @@ -63,50 +68,91 @@ func (P *Printer) CloseScope(paren string) { // ---------------------------------------------------------------------------- // 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, ""); + 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(" {"); /* @@ -119,20 +165,18 @@ func (P *Printer) Type(t *Node.Type) { } 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"); @@ -149,49 +193,55 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) { } 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, ")"); } } } @@ -231,31 +281,30 @@ func (P *Printer) Block(list *Node.List, indent bool) { 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(""); + P.String(0, ""); return; } @@ -265,66 +314,66 @@ func (P *Printer) Stat(s *Node.Stat) { 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(""); + P.String(s.pos, ""); P.semi = true; } } @@ -363,45 +412,47 @@ func (P *Printer) DoMethodDecl(x *AST.MethodDecl) { */ -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, ""); + 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); } } @@ -419,12 +470,12 @@ func (P *Printer) Declaration(d *Node.Decl) { // 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 }