diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go index 3b6c79322c..cfd345d5a9 100644 --- a/usr/gri/pretty/ast.go +++ b/usr/gri/pretty/ast.go @@ -17,8 +17,7 @@ type ( Type struct; Block struct; - Lit struct; - Expr struct; + Expr interface; Stat struct; Decl struct; ) @@ -128,26 +127,6 @@ type Node struct { } -// ---------------------------------------------------------------------------- -// Literals - -type Lit struct { - Node; - - // Identifiers - Obj *Object; - - // Constant literals - - // Type literals - Len *Expr; // array length - Dir int; // channel direction - Key *Type; // receiver or map key type - Elt *Type; // array, map, channel, pointer element, or function result type - List *array.Array; End int; // struct fields, interface methods, function parameters -} - - // ---------------------------------------------------------------------------- // Scopes @@ -218,87 +197,6 @@ func (scope *Scope) Print() { } -// ---------------------------------------------------------------------------- -// Blocks -// -// Syntactic constructs of the form: -// -// "{" StatementList "}" -// ":" StatementList - -type Block struct { - Node; - List *array.Array; - End int; // position of closing "}" if present -} - - -func NewBlock(pos, tok int) *Block { - assert(tok == Scanner.LBRACE || tok == Scanner.COLON); - b := new(Block); - b.Pos, b.Tok, b.List = pos, tok, array.New(0); - return b; -} - - -// ---------------------------------------------------------------------------- -// Expressions - -type Expr struct { - Node; - X, Y *Expr; // binary (X, Y) and unary (Y) expressions - Obj *Object; // identifiers, literals - Typ *Type; -} - - -// Length of a comma-separated expression list. -func (x *Expr) Len() int { - if x == nil { - return 0; - } - n := 1; - for ; x.Tok == Scanner.COMMA; x = x.Y { - n++; - } - return n; -} - - -// The i'th expression in a comma-separated expression list. -func (x *Expr) At(i int) *Expr { - for j := 0; j < i; j++ { - assert(x.Tok == Scanner.COMMA); - x = x.Y; - } - if x.Tok == Scanner.COMMA { - x = x.X; - } - return x; -} - - -func NewExpr(pos, tok int, x, y *Expr) *Expr { - if x != nil && x.Tok == Scanner.TYPE || y != nil && y.Tok == Scanner.TYPE { - panic("no type expression allowed"); - } - e := new(Expr); - e.Pos, e.Tok, e.X, e.Y = pos, tok, x, y; - return e; -} - - -// TODO probably don't need the tok parameter eventually -func NewLit(tok int, obj *Object) *Expr { - e := new(Expr); - e.Pos, e.Tok, e.Obj, e.Typ = obj.Pos, tok, obj, obj.Typ; - return e; -} - - -var BadExpr = NewExpr(0, Scanner.ILLEGAL, nil, nil); - - // ---------------------------------------------------------------------------- // Types @@ -388,7 +286,7 @@ type Type struct { // syntactic components Pos int; // source position (< 0 if unknown position) - Expr *Expr; // type name, array length + Expr Expr; // type name, array length Mode int; // channel mode Key *Type; // receiver type or map key Elt *Type; // type name type, array, map, channel or pointer element type, function result type @@ -411,13 +309,200 @@ func NewType(pos, form int) *Type { } +func (typ* Type) String() string { + if typ != nil { + return + "Type(" + + FormStr(typ.Form) + + ")"; + } + return "nil"; +} + + +var BadType = NewType(0, Scanner.ILLEGAL); + + +// ---------------------------------------------------------------------------- +// Blocks +// +// Syntactic constructs of the form: +// +// "{" StatementList "}" +// ":" StatementList + +type Block struct { + Node; + List *array.Array; + End int; // position of closing "}" if present +} + + +func NewBlock(pos, tok int) *Block { + assert(tok == Scanner.LBRACE || tok == Scanner.COLON); + b := new(Block); + b.Pos, b.Tok, b.List = pos, tok, array.New(0); + return b; +} + + +// ---------------------------------------------------------------------------- +// Expressions + +type ( + Visitor interface; + + Expr interface { + Pos() int; + Visit(v Visitor); + }; + + BadExpr struct { + Pos_ int; + }; + + Ident struct { + Pos_ int; + Obj *Object; + }; + + BinaryExpr struct { + Pos_, Tok int; + X, Y Expr; + }; + + UnaryExpr struct { + Pos_, Tok int; + X Expr; + }; + + BasicLit struct { + Pos_, Tok int; + Val string + }; + + FunctionLit struct { + Pos_ int; // position of "func" + Typ *Type; + Body *Block; + }; + + CompositeLit struct { + Pos_ int; // position of "{" + Typ *Type; + Elts Expr; + }; + + TypeLit struct { + Typ *Type; + }; + + Selector struct { + Pos_ int; // position of "." + X Expr; + Sel *Ident; + }; + + TypeGuard struct { + Pos_ int; // position of "." + X Expr; + Typ *Type; + }; + + Index struct { + Pos_ int; // position of "[" + X, I Expr; + }; + + Call struct { + Pos_ int; // position of "(" + F, Args Expr + }; +) + + +type Visitor interface { + DoBadExpr(x *BadExpr); + DoIdent(x *Ident); + DoBinaryExpr(x *BinaryExpr); + DoUnaryExpr(x *UnaryExpr); + DoBasicLit(x *BasicLit); + DoFunctionLit(x *FunctionLit); + DoCompositeLit(x *CompositeLit); + DoTypeLit(x *TypeLit); + DoSelector(x *Selector); + DoTypeGuard(x *TypeGuard); + DoIndex(x *Index); + DoCall(x *Call); +} + + +func (x *BadExpr) Pos() int { return x.Pos_; } +func (x *Ident) Pos() int { return x.Pos_; } +func (x *BinaryExpr) Pos() int { return x.Pos_; } +func (x *UnaryExpr) Pos() int { return x.Pos_; } +func (x *BasicLit) Pos() int { return x.Pos_; } +func (x *FunctionLit) Pos() int { return x.Pos_; } +func (x *CompositeLit) Pos() int { return x.Pos_; } +func (x *TypeLit) Pos() int { return x.Typ.Pos; } +func (x *Selector) Pos() int { return x.Pos_; } +func (x *TypeGuard) Pos() int { return x.Pos_; } +func (x *Index) Pos() int { return x.Pos_; } +func (x *Call) Pos() int { return x.Pos_; } + + +func (x *BadExpr) Visit(v Visitor) { v.DoBadExpr(x); } +func (x *Ident) Visit(v Visitor) { v.DoIdent(x); } +func (x *BinaryExpr) Visit(v Visitor) { v.DoBinaryExpr(x); } +func (x *UnaryExpr) Visit(v Visitor) { v.DoUnaryExpr(x); } +func (x *BasicLit) Visit(v Visitor) { v.DoBasicLit(x); } +func (x *FunctionLit) Visit(v Visitor) { v.DoFunctionLit(x); } +func (x *CompositeLit) Visit(v Visitor) { v.DoCompositeLit(x); } +func (x *TypeLit) Visit(v Visitor) { v.DoTypeLit(x); } +func (x *Selector) Visit(v Visitor) { v.DoSelector(x); } +func (x *TypeGuard) Visit(v Visitor) { v.DoTypeGuard(x); } +func (x *Index) Visit(v Visitor) { v.DoIndex(x); } +func (x *Call) Visit(v Visitor) { v.DoCall(x); } + + + +// Length of a comma-separated expression list. +func ExprLen(x Expr) int { + if x == nil { + return 0; + } + n := 1; + for { + if p, ok := x.(*BinaryExpr); ok && p.Tok == Scanner.COMMA { + n++; + x = p.Y; + } else { + break; + } + } + return n; +} + + +func ExprAt(x Expr, i int) Expr { + for j := 0; j < i; j++ { + assert(x.(*BinaryExpr).Tok == Scanner.COMMA); + x = x.(*BinaryExpr).Y; + } + if t, is_binary := x.(*BinaryExpr); is_binary && t.Tok == Scanner.COMMA { + x = t.X; + } + return x; +} + + func (t *Type) Nfields() int { if t.List == nil { return 0; } nx, nt := 0, 0; for i, n := 0, t.List.Len(); i < n; i++ { - if t.List.At(i).(*Expr).Tok == Scanner.TYPE { + if dummy, ok := t.List.At(i).(*TypeLit); ok { nt++; } else { nx++; @@ -430,51 +515,13 @@ func (t *Type) Nfields() int { } -func (typ* Type) String() string { - if typ != nil { - return - "Type(" + - FormStr(typ.Form) + - ")"; - } - return "nil"; -} - - -// requires complete Type.Pos access -func NewTypeExpr(typ *Type) *Expr { - e := new(Expr); - e.Pos, e.Tok, e.Typ = typ.Pos, Scanner.TYPE, typ; - return e; -} - - -// requires complete Type.String access -func (x *Expr) String() string { - if x != nil { - return - "Expr(" + - Scanner.TokenString(x.Tok) + ", " + - x.X.String() + ", " + - x.Y.String() + ", " + - x.Obj.String() + ", " + - x.Typ.String() + - ")"; - } - return "nil"; -} - - -var BadType = NewType(0, Scanner.ILLEGAL); - - // ---------------------------------------------------------------------------- // Statements type Stat struct { Node; Init, Post *Stat; - Expr *Expr; + Expr Expr; Body *Block; // composite statement body Decl *Decl; // declaration statement } @@ -495,9 +542,10 @@ var BadStat = NewStat(0, Scanner.ILLEGAL); type Decl struct { Node; - Ident *Expr; // nil for ()-style declarations + Ident Expr; // nil for ()-style declarations Typ *Type; - Val *Expr; + Val Expr; + Body *Block; // list of *Decl for ()-style declarations List *array.Array; End int; } @@ -531,7 +579,7 @@ func NewComment(pos int, text string) *Comment { type Program struct { Pos int; // tok is Scanner.PACKAGE - Ident *Expr; + Ident Expr; Decls *array.Array; Comments *array.Array; } diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go index 725c6fa509..bab2977783 100644 --- a/usr/gri/pretty/compilation.go +++ b/usr/gri/pretty/compilation.go @@ -158,6 +158,8 @@ func fileExists(name string) bool { func addDeps(globalset map [string] bool, wset *array.Array, src_file string, flags *Flags) { + panic(); + /* dummy, found := globalset[src_file]; if !found { globalset[src_file] = true; @@ -198,6 +200,7 @@ func addDeps(globalset map [string] bool, wset *array.Array, src_file string, fl print("\n\n"); } } + */ } diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 8f08bcb306..ae904a6511 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -64,26 +64,22 @@ func assert(pred bool) { func (P *Parser) PrintIndent() { for i := P.indent; i > 0; i-- { - print(". "); + fmt.Printf(". "); } } func (P *Parser) Trace(msg string) { - if P.verbose { - P.PrintIndent(); - print(msg, " {\n"); - } - P.indent++; // always check proper identation + P.PrintIndent(); + fmt.Printf("%s {\n", msg); + P.indent++; } func (P *Parser) Ecart() { - P.indent--; // always check proper identation - if P.verbose { - P.PrintIndent(); - print("}\n"); - } + P.indent--; + P.PrintIndent(); + fmt.Printf("}\n"); } @@ -105,7 +101,7 @@ func (P *Parser) Next0() { case "{": s = "LBRACE"; case "}": s = "RBRACE"; } - print("[", P.pos, "] ", s, "\n"); + fmt.Printf("[%d] %s\n", P.pos, s); } } @@ -171,13 +167,12 @@ func (P *Parser) CloseScope() { } -func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int, typ *AST.Type) { +func (P *Parser) DeclareInScope(scope *AST.Scope, x AST.Expr, kind int, typ *AST.Type) { if P.scope_lev < 0 { panic("cannot declare objects in other packages"); } - if x.Tok != Scanner.ILLEGAL { // ignore bad exprs - assert(x.Tok == Scanner.IDENT); - obj := x.Obj; + if ident, ok := x.(*AST.Ident); ok { // ignore bad exprs + obj := ident.Obj; obj.Kind = kind; obj.Typ = typ; obj.Pnolev = P.scope_lev; @@ -196,47 +191,54 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int, typ *AS // Declare a comma-separated list of idents or a single ident. -func (P *Parser) Declare(p *AST.Expr, kind int, typ *AST.Type) { - for p.Tok == Scanner.COMMA { - P.DeclareInScope(P.top_scope, p.X, kind, typ); - p = p.Y; +func (P *Parser) Declare(x AST.Expr, kind int, typ *AST.Type) { + for { + p, ok := x.(*AST.BinaryExpr); + if ok && p.Tok == Scanner.COMMA { + P.DeclareInScope(P.top_scope, p.X, kind, typ); + x = p.Y; + } else { + break; + } } - P.DeclareInScope(P.top_scope, p, kind, typ); + P.DeclareInScope(P.top_scope, x, kind, typ); } // ---------------------------------------------------------------------------- // AST support -func exprType(x *AST.Expr) *AST.Type { - var t *AST.Type; - if x.Tok == Scanner.TYPE { - t = x.Typ; - } else if x.Tok == Scanner.IDENT { +func exprType(x AST.Expr) *AST.Type { + var typ *AST.Type; + if t, is_type := x.(*AST.TypeLit); is_type { + typ = t.Typ + } else if t, is_ident := x.(*AST.Ident); is_ident { // assume a type name - t = AST.NewType(x.Pos, AST.TYPENAME); - t.Expr = x; - } else if x.Tok == Scanner.PERIOD && x.Y != nil && exprType(x.X) != nil { + typ = AST.NewType(t.Pos(), AST.TYPENAME); + typ.Expr = x; + } else if t, is_selector := x.(*AST.Selector); is_selector && exprType(t.Sel) != nil { // possibly a qualified (type) identifier - t = AST.NewType(x.Pos, AST.TYPENAME); - t.Expr = x; + typ = AST.NewType(t.Pos(), AST.TYPENAME); + typ.Expr = x; } - return t; + return typ; } -func (P *Parser) NoType(x *AST.Expr) *AST.Expr { - if x != nil && x.Tok == Scanner.TYPE { - P.Error(x.Pos, "expected expression, found type"); - val := AST.NewObject(x.Pos, AST.NONE, "0"); - x = AST.NewLit(Scanner.INT, val); +func (P *Parser) NoType(x AST.Expr) AST.Expr { + if x != nil { + lit, ok := x.(*AST.TypeLit); + if ok { + P.Error(lit.Typ.Pos, "expected expression, found type"); + x = &AST.BasicLit{lit.Typ.Pos, Scanner.STRING, ""}; + } } return x; } -func (P *Parser) NewExpr(pos, tok int, x, y *AST.Expr) *AST.Expr { - return AST.NewExpr(pos, tok, P.NoType(x), P.NoType(y)); +func (P *Parser) NewBinary(pos, tok int, x, y AST.Expr) *AST.BinaryExpr { + return &AST.BinaryExpr{pos, tok, P.NoType(x), P.NoType(y)}; } @@ -244,16 +246,18 @@ func (P *Parser) NewExpr(pos, tok int, x, y *AST.Expr) *AST.Expr { // Common productions func (P *Parser) TryType() *AST.Type; -func (P *Parser) ParseExpression(prec int) *AST.Expr; +func (P *Parser) ParseExpression(prec int) AST.Expr; func (P *Parser) ParseStatement() *AST.Stat; func (P *Parser) ParseDeclaration() *AST.Decl; // If scope != nil, lookup identifier in scope. Otherwise create one. -func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr { - P.Trace("Ident"); +func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Ident { + if P.verbose { + P.Trace("Ident"); + defer P.Ecart(); + } - x := AST.BadExpr; if P.tok == Scanner.IDENT { var obj *AST.Object; if scope != nil { @@ -264,41 +268,41 @@ func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr { } else { assert(obj.Kind != AST.NONE); } - x = AST.NewLit(Scanner.IDENT, obj); - x.Pos = P.pos; // override obj.pos (incorrect if object was looked up!) + x := &AST.Ident{P.pos, obj}; if P.verbose { P.PrintIndent(); - print("Ident = \"", P.val, "\"\n"); + fmt.Printf("ident = \"%s\"\n", P.val); } P.Next(); - } else { - P.Expect(Scanner.IDENT); // use Expect() error handling + return x; } - - P.Ecart(); - return x; + + P.Expect(Scanner.IDENT); // use Expect() error handling + return &AST.Ident{P.pos, nil}; } -func (P *Parser) ParseIdentList() *AST.Expr { - P.Trace("IdentList"); +func (P *Parser) ParseIdentList() AST.Expr { + if P.verbose { + P.Trace("IdentList"); + defer P.Ecart(); + } - var last *AST.Expr; - x := P.ParseIdent(nil); + var last *AST.BinaryExpr; + var x AST.Expr = P.ParseIdent(nil); for P.tok == Scanner.COMMA { pos := P.pos; P.Next(); y := P.ParseIdent(nil); if last == nil { - x = P.NewExpr(pos, Scanner.COMMA, x, y); - last = x; + last = P.NewBinary(pos, Scanner.COMMA, x, y); + x = last; } else { - last.Y = P.NewExpr(pos, Scanner.COMMA, last.Y, y); + last.Y = P.NewBinary(pos, Scanner.COMMA, last.Y, y); last = last.Y; } } - P.Ecart(); return x; } @@ -307,7 +311,10 @@ func (P *Parser) ParseIdentList() *AST.Expr { // Types func (P *Parser) ParseType() *AST.Type { - P.Trace("Type"); + if P.verbose { + P.Trace("Type"); + defer P.Ecart(); + } t := P.TryType(); if t == nil { @@ -315,56 +322,61 @@ func (P *Parser) ParseType() *AST.Type { t = AST.BadType; } - P.Ecart(); return t; } func (P *Parser) ParseVarType() *AST.Type { - P.Trace("VarType"); + if P.verbose { + P.Trace("VarType"); + defer P.Ecart(); + } - typ := P.ParseType(); - - P.Ecart(); - return typ; + return P.ParseType(); } -func (P *Parser) ParseQualifiedIdent() *AST.Expr { - P.Trace("QualifiedIdent"); +func (P *Parser) ParseQualifiedIdent() AST.Expr { + if P.verbose { + P.Trace("QualifiedIdent"); + defer P.Ecart(); + } - x := P.ParseIdent(P.top_scope); + var x AST.Expr = P.ParseIdent(P.top_scope); for P.tok == Scanner.PERIOD { pos := P.pos; P.Next(); y := P.ParseIdent(nil); - x = P.NewExpr(pos, Scanner.PERIOD, x, y); + x = &AST.Selector{pos, x, y}; } - P.Ecart(); return x; } func (P *Parser) ParseTypeName() *AST.Type { - P.Trace("TypeName"); + if P.verbose { + P.Trace("TypeName"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.TYPENAME); t.Expr = P.ParseQualifiedIdent(); - t.Elt = t.Expr.Typ; - P.Ecart(); return t; } func (P *Parser) ParseArrayType() *AST.Type { - P.Trace("ArrayType"); + if P.verbose { + P.Trace("ArrayType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.ARRAY); P.Expect(Scanner.LBRACK); if P.tok == Scanner.ELLIPSIS { - t.Expr = P.NewExpr(P.pos, Scanner.ELLIPSIS, nil, nil); + t.Expr = P.NewBinary(P.pos, Scanner.ELLIPSIS, nil, nil); P.Next(); } else if P.tok != Scanner.RBRACK { t.Expr = P.ParseExpression(1); @@ -372,13 +384,15 @@ func (P *Parser) ParseArrayType() *AST.Type { P.Expect(Scanner.RBRACK); t.Elt = P.ParseType(); - P.Ecart(); return t; } func (P *Parser) ParseChannelType() *AST.Type { - P.Trace("ChannelType"); + if P.verbose { + P.Trace("ChannelType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.CHANNEL); t.Mode = AST.FULL; @@ -395,7 +409,6 @@ func (P *Parser) ParseChannelType() *AST.Type { } t.Elt = P.ParseVarType(); - P.Ecart(); return t; } @@ -404,7 +417,7 @@ func (P *Parser) ParseVar(expect_ident bool) *AST.Type { t := AST.BadType; if expect_ident { x := P.ParseIdent(nil); - t = AST.NewType(x.Pos, AST.TYPENAME); + t = AST.NewType(x.Pos(), AST.TYPENAME); t.Expr = x; } else if P.tok == Scanner.ELLIPSIS { t = AST.NewType(P.pos, AST.ELLIPSIS); @@ -417,7 +430,10 @@ func (P *Parser) ParseVar(expect_ident bool) *AST.Type { func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) { - P.Trace("VarList"); + if P.verbose { + P.Trace("VarList"); + defer P.Ecart(); + } // assume a list of types // (a list of identifiers looks like a list of type names) @@ -450,31 +466,34 @@ func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) { // convert the type entries into identifiers for i, n := i0, list.Len(); i < n; i++ { t := list.At(i).(*AST.Type); - if t.Form == AST.TYPENAME && t.Expr.Tok == Scanner.IDENT { - list.Set(i, t.Expr); - } else { - list.Set(i, AST.BadExpr); - P.Error(t.Pos, "identifier expected"); + if t.Form == AST.TYPENAME { + if ident, ok := t.Expr.(*AST.Ident); ok { + list.Set(i, ident); + continue; + } } + list.Set(i, &AST.BadExpr{0}); + P.Error(t.Pos, "identifier expected"); } // add type - list.Push(AST.NewTypeExpr(typ)); + list.Push(&AST.TypeLit{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).(*AST.Type); - list.Set(i, AST.NewTypeExpr(t)); + list.Set(i, &AST.TypeLit{t}); } } - - P.Ecart(); } func (P *Parser) ParseParameterList(ellipsis_ok bool) *array.Array { - P.Trace("ParameterList"); + if P.verbose { + P.Trace("ParameterList"); + defer P.Ecart(); + } list := array.New(0); P.ParseVarList(list, ellipsis_ok); @@ -483,13 +502,15 @@ func (P *Parser) ParseParameterList(ellipsis_ok bool) *array.Array { P.ParseVarList(list, ellipsis_ok); } - P.Ecart(); return list; } func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type { - P.Trace("Parameters"); + if P.verbose { + P.Trace("Parameters"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.STRUCT); P.Expect(Scanner.LPAREN); @@ -499,13 +520,15 @@ func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type { t.End = P.pos; P.Expect(Scanner.RPAREN); - P.Ecart(); return t; } func (P *Parser) ParseResultList() { - P.Trace("ResultList"); + if P.verbose { + P.Trace("ResultList"); + defer P.Ecart(); + } P.ParseType(); for P.tok == Scanner.COMMA { @@ -515,13 +538,14 @@ func (P *Parser) ParseResultList() { if P.tok != Scanner.RPAREN { P.ParseType(); } - - P.Ecart(); } func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { - P.Trace("Result"); + if P.verbose { + P.Trace("Result"); + defer P.Ecart(); + } var t *AST.Type; if P.tok == Scanner.LPAREN { @@ -531,12 +555,11 @@ func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { if typ != nil { t = AST.NewType(P.pos, AST.STRUCT); t.List = array.New(0); - t.List.Push(AST.NewTypeExpr(typ)); + t.List.Push(&AST.TypeLit{typ}); t.End = P.pos; } } - P.Ecart(); return t; } @@ -548,7 +571,10 @@ func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { // (params) (results) func (P *Parser) ParseSignature() *AST.Type { - P.Trace("Signature"); + if P.verbose { + P.Trace("Signature"); + defer P.Ecart(); + } P.OpenScope(); P.scope_lev++; @@ -562,35 +588,38 @@ func (P *Parser) ParseSignature() *AST.Type { P.scope_lev--; P.CloseScope(); - P.Ecart(); return t; } func (P *Parser) ParseFunctionType() *AST.Type { - P.Trace("FunctionType"); + if P.verbose { + P.Trace("FunctionType"); + defer P.Ecart(); + } P.Expect(Scanner.FUNC); - t := P.ParseSignature(); - - P.Ecart(); - return t; + return P.ParseSignature(); } func (P *Parser) ParseMethodSpec(list *array.Array) { - P.Trace("MethodDecl"); + if P.verbose { + P.Trace("MethodDecl"); + defer P.Ecart(); + } list.Push(P.ParseIdentList()); t := P.ParseSignature(); - list.Push(AST.NewTypeExpr(t)); - - P.Ecart(); + list.Push(&AST.TypeLit{t}); } func (P *Parser) ParseInterfaceType() *AST.Type { - P.Trace("InterfaceType"); + if P.verbose { + P.Trace("InterfaceType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.INTERFACE); P.Expect(Scanner.INTERFACE); @@ -613,13 +642,15 @@ func (P *Parser) ParseInterfaceType() *AST.Type { P.Expect(Scanner.RBRACE); } - P.Ecart(); return t; } func (P *Parser) ParseMapType() *AST.Type { - P.Trace("MapType"); + if P.verbose { + P.Trace("MapType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.MAP); P.Expect(Scanner.MAP); @@ -628,15 +659,17 @@ func (P *Parser) ParseMapType() *AST.Type { P.Expect(Scanner.RBRACK); t.Elt = P.ParseVarType(); - P.Ecart(); return t; } -func (P *Parser) ParseOperand() *AST.Expr +func (P *Parser) ParseOperand() AST.Expr func (P *Parser) ParseStructType() *AST.Type { - P.Trace("StructType"); + if P.verbose { + P.Trace("StructType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.STRUCT); P.Expect(Scanner.STRUCT); @@ -664,32 +697,35 @@ func (P *Parser) ParseStructType() *AST.Type { // enter fields into struct scope for i, n := 0, t.List.Len(); i < n; i++ { - x := t.List.At(i).(*AST.Expr); - if x.Tok == Scanner.IDENT { + if x, ok := t.List.At(i).(*AST.Ident); ok { P.DeclareInScope(t.Scope, x, AST.FIELD, nil); } } } - P.Ecart(); return t; } func (P *Parser) ParsePointerType() *AST.Type { - P.Trace("PointerType"); + if P.verbose { + P.Trace("PointerType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.POINTER); P.Expect(Scanner.MUL); t.Elt = P.ParseType(); - P.Ecart(); return t; } func (P *Parser) TryType() *AST.Type { - P.Trace("Type (try)"); + if P.verbose { + P.Trace("Type (try)"); + defer P.Ecart(); + } t := AST.BadType; switch P.tok { @@ -703,8 +739,6 @@ func (P *Parser) TryType() *AST.Type { case Scanner.MUL: t = P.ParsePointerType(); default: t = nil; // no type found } - - P.Ecart(); return t; } @@ -713,7 +747,10 @@ func (P *Parser) TryType() *AST.Type { // Blocks func (P *Parser) ParseStatementList(list *array.Array) { - P.Trace("StatementList"); + if P.verbose { + P.Trace("StatementList"); + defer P.Ecart(); + } for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { s := P.ParseStatement(); @@ -734,13 +771,14 @@ func (P *Parser) ParseStatementList(list *array.Array) { if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { P.Error(P.pos, "expected end of statement list (semicolon missing?)"); } - - P.Ecart(); } func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { - P.Trace("Block"); + if P.verbose { + P.Trace("Block"); + defer P.Ecart(); + } b := AST.NewBlock(P.pos, tok); P.Expect(tok); @@ -753,8 +791,7 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { } if ftyp.List != nil { for i, n := 0, ftyp.List.Len(); i < n; i++ { - x := ftyp.List.At(i).(*AST.Expr); - if x.Tok == Scanner.IDENT { + if x, ok := ftyp.List.At(i).(*AST.Ident); ok { P.DeclareInScope(P.top_scope, x, AST.VAR, nil); } } @@ -770,7 +807,6 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { P.opt_semi = true; } - P.Ecart(); return b; } @@ -778,8 +814,11 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { // ---------------------------------------------------------------------------- // Expressions -func (P *Parser) ParseExpressionList() *AST.Expr { - P.Trace("ExpressionList"); +func (P *Parser) ParseExpressionList() AST.Expr { + if P.verbose { + P.Trace("ExpressionList"); + defer P.Ecart(); + } x := P.ParseExpression(1); for first := true; P.tok == Scanner.COMMA; { @@ -787,111 +826,112 @@ func (P *Parser) ParseExpressionList() *AST.Expr { P.Next(); y := P.ParseExpression(1); if first { - x = P.NewExpr(pos, Scanner.COMMA, x, y); + x = P.NewBinary(pos, Scanner.COMMA, x, y); first = false; } else { - x.Y = P.NewExpr(pos, Scanner.COMMA, x.Y, y); + x.(*AST.BinaryExpr).Y = P.NewBinary(pos, Scanner.COMMA, x.(*AST.BinaryExpr).Y, y); } } - P.Ecart(); return x; } -func (P *Parser) ParseFunctionLit() *AST.Expr { - P.Trace("FunctionLit"); +func (P *Parser) ParseFunctionLit() AST.Expr { + if P.verbose { + P.Trace("FunctionLit"); + defer P.Ecart(); + } - f := AST.NewObject(P.pos, AST.FUNC, ""); + pos := P.pos; P.Expect(Scanner.FUNC); - f.Typ = P.ParseSignature(); + typ := P.ParseSignature(); P.expr_lev++; P.scope_lev++; - f.Body = P.ParseBlock(f.Typ, Scanner.LBRACE); + body := P.ParseBlock(typ, Scanner.LBRACE); P.scope_lev--; P.expr_lev--; - P.Ecart(); - return AST.NewLit(Scanner.FUNC, f); + return &AST.FunctionLit{pos, typ, body}; } -func (P *Parser) ParseOperand() *AST.Expr { - P.Trace("Operand"); +func (P *Parser) ParseOperand() AST.Expr { + if P.verbose { + P.Trace("Operand"); + defer P.Ecart(); + } - x := AST.BadExpr; switch P.tok { case Scanner.IDENT: - x = P.ParseIdent(P.top_scope); + return P.ParseIdent(P.top_scope); case Scanner.LPAREN: // TODO we could have a function type here as in: new(()) // (currently not working) P.Next(); P.expr_lev++; - x = P.ParseExpression(1); + x := P.ParseExpression(1); P.expr_lev--; P.Expect(Scanner.RPAREN); + return x; case Scanner.INT, Scanner.FLOAT, Scanner.STRING: - val := AST.NewObject(P.pos, AST.NONE, P.val); - x = AST.NewLit(P.tok, val); + x := &AST.BasicLit{P.pos, P.tok, P.val}; P.Next(); if x.Tok == Scanner.STRING { // TODO should remember the list instead of // concatenate the strings here for ; P.tok == Scanner.STRING; P.Next() { - x.Obj.Ident += P.val; + x.Val += P.val; } } + return x; case Scanner.FUNC: - x = P.ParseFunctionLit(); + return P.ParseFunctionLit(); default: t := P.TryType(); if t != nil { - x = AST.NewTypeExpr(t); + return &AST.TypeLit{t}; } else { P.Error(P.pos, "operand expected"); P.Next(); // make progress } } - P.Ecart(); - return x; + return &AST.BadExpr{P.pos}; } -func (P *Parser) ParseSelectorOrTypeGuard(x *AST.Expr) *AST.Expr { - P.Trace("SelectorOrTypeGuard"); +func (P *Parser) ParseSelectorOrTypeGuard(x AST.Expr) AST.Expr { + if P.verbose { + P.Trace("SelectorOrTypeGuard"); + defer P.Ecart(); + } - x = P.NewExpr(P.pos, Scanner.PERIOD, x, nil); + pos := P.pos; P.Expect(Scanner.PERIOD); if P.tok == Scanner.IDENT { - // TODO should always guarantee x.Typ != nil - var scope *AST.Scope; - if x.X.Typ != nil { - scope = x.X.Typ.Scope; - } - x.Y = P.ParseIdent(scope); - x.Typ = x.Y.Obj.Typ; + x = &AST.Selector{pos, x, P.ParseIdent(nil)}; } else { P.Expect(Scanner.LPAREN); - x.Y = AST.NewTypeExpr(P.ParseType()); - x.Typ = x.Y.Typ; + x = &AST.TypeGuard{pos, x, P.ParseType()}; P.Expect(Scanner.RPAREN); } - P.Ecart(); return x; } -func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr { - P.Trace("IndexOrSlice"); +func (P *Parser) ParseIndex(x AST.Expr) AST.Expr { + if P.verbose { + P.Trace("IndexOrSlice"); + defer P.Ecart(); + } pos := P.pos; P.Expect(Scanner.LBRACK); @@ -900,51 +940,51 @@ func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr { P.expr_lev--; P.Expect(Scanner.RBRACK); - P.Ecart(); - return P.NewExpr(pos, Scanner.LBRACK, x, i); + return &AST.Index{pos, x, i}; } -func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr +func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr -func (P *Parser) ParseCall(x0 *AST.Expr) *AST.Expr { - P.Trace("Call"); +func (P *Parser) ParseCall(f AST.Expr) AST.Expr { + if P.verbose { + P.Trace("Call"); + defer P.Ecart(); + } - x := P.NewExpr(P.pos, Scanner.LPAREN, x0, nil); + call := &AST.Call{P.pos, f, nil}; P.Expect(Scanner.LPAREN); if P.tok != Scanner.RPAREN { P.expr_lev++; var t *AST.Type; - if x0.Tok == Scanner.IDENT && (x0.Obj.Ident == "new" || x0.Obj.Ident == "make") { + if x0, ok := f.(*AST.Ident); ok && (x0.Obj.Ident == "new" || x0.Obj.Ident == "make") { // heuristic: assume it's a new(T) or make(T, ...) call, try to parse a type t = P.TryType(); } if t != nil { // we found a type - x.Y = AST.NewTypeExpr(t); + args := &AST.TypeLit{t}; if P.tok == Scanner.COMMA { pos := P.pos; P.Next(); y := P.ParseExpressionList(); // create list manually because NewExpr checks for type expressions - z := AST.NewExpr(pos, Scanner.COMMA, nil, y); - z.X = x.Y; - x.Y = z; + args := &AST.BinaryExpr{pos, Scanner.COMMA, args, y}; } + call.Args = args; } else { // normal argument list - x.Y = P.ParseExpressionList(); + call.Args = P.ParseExpressionList(); } P.expr_lev--; } P.Expect(Scanner.RPAREN); - P.Ecart(); - return x; + return call; } -func (P *Parser) ParseCompositeElements() *AST.Expr { +func (P *Parser) ParseCompositeElements() AST.Expr { x := P.ParseExpression(0); if P.tok == Scanner.COMMA { pos := P.pos; @@ -952,29 +992,29 @@ func (P *Parser) ParseCompositeElements() *AST.Expr { // first element determines mode singles := true; - if x.Tok == Scanner.COLON { + if t, is_binary := x.(*AST.BinaryExpr); is_binary && t.Tok == Scanner.COLON { singles = false; } - var last *AST.Expr; + var last *AST.BinaryExpr; for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { y := P.ParseExpression(0); if singles { - if y.Tok == Scanner.COLON { - P.Error(y.X.Pos, "single value expected; found pair"); + if t, is_binary := y.(*AST.BinaryExpr); is_binary && t.Tok == Scanner.COLON { + P.Error(t.X.Pos(), "single value expected; found pair"); } } else { - if y.Tok != Scanner.COLON { - P.Error(y.Pos, "key:value pair expected; found single value"); + if t, is_binary := y.(*AST.BinaryExpr); !is_binary || t.Tok != Scanner.COLON { + P.Error(y.Pos(), "key:value pair expected; found single value"); } } if last == nil { - x = P.NewExpr(pos, Scanner.COMMA, x, y); - last = x; + last = P.NewBinary(pos, Scanner.COMMA, x, y); + x = last; } else { - last.Y = P.NewExpr(pos, Scanner.COMMA, last.Y, y); + last.Y = P.NewBinary(pos, Scanner.COMMA, last.Y, y); last = last.Y; } @@ -991,25 +1031,29 @@ func (P *Parser) ParseCompositeElements() *AST.Expr { } -func (P *Parser) ParseCompositeLit(t *AST.Type) *AST.Expr { - P.Trace("CompositeLit"); +func (P *Parser) ParseCompositeLit(t *AST.Type) AST.Expr { + if P.verbose { + P.Trace("CompositeLit"); + defer P.Ecart(); + } - x := P.NewExpr(P.pos, Scanner.LBRACE, nil, nil); - x.Obj = AST.NewObject(t.Pos, AST.TYPE, ""); - x.Obj.Typ = t; + pos := P.pos; P.Expect(Scanner.LBRACE); + var elts AST.Expr; if P.tok != Scanner.RBRACE { - x.Y = P.ParseCompositeElements(); + elts = P.ParseCompositeElements(); } P.Expect(Scanner.RBRACE); - P.Ecart(); - return x; + return &AST.CompositeLit{pos, t, elts}; } -func (P *Parser) ParsePrimaryExpr() *AST.Expr { - P.Trace("PrimaryExpr"); +func (P *Parser) ParsePrimaryExpr() AST.Expr { + if P.verbose { + P.Trace("PrimaryExpr"); + defer P.Ecart(); + } x := P.ParseOperand(); for { @@ -1028,47 +1072,48 @@ func (P *Parser) ParsePrimaryExpr() *AST.Expr { if t != nil { x = P.ParseCompositeLit(t); } else { - goto exit; + return x; } - default: goto exit; + default: + return x; } } -exit: - P.Ecart(); - return x; + unreachable(); + return nil; } -func (P *Parser) ParseUnaryExpr() *AST.Expr { - P.Trace("UnaryExpr"); +func (P *Parser) ParseUnaryExpr() AST.Expr { + if P.verbose { + P.Trace("UnaryExpr"); + defer P.Ecart(); + } - x := AST.BadExpr; switch P.tok { case Scanner.ADD, Scanner.SUB, Scanner.MUL, Scanner.NOT, Scanner.XOR, Scanner.ARROW, Scanner.AND: pos, tok := P.pos, P.tok; P.Next(); y := P.ParseUnaryExpr(); - if tok == Scanner.MUL && y.Tok == Scanner.TYPE { + if lit, ok := y.(*AST.TypeLit); ok && tok == Scanner.MUL { // pointer type t := AST.NewType(pos, AST.POINTER); - t.Elt = y.Obj.Typ; - x = AST.NewTypeExpr(t); + t.Elt = lit.Typ; + return &AST.TypeLit{t}; } else { - x = P.NewExpr(pos, tok, nil, y); + return &AST.UnaryExpr{pos, tok, y}; } - - default: - x = P.ParsePrimaryExpr(); } - P.Ecart(); - return x; + return P.ParsePrimaryExpr(); } -func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr { - P.Trace("BinaryExpr"); +func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr { + if P.verbose { + P.Trace("BinaryExpr"); + defer P.Ecart(); + } x := P.ParseUnaryExpr(); for prec := Scanner.Precedence(P.tok); prec >= prec1; prec-- { @@ -1076,28 +1121,29 @@ func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr { pos, tok := P.pos, P.tok; P.Next(); y := P.ParseBinaryExpr(prec + 1); - x = P.NewExpr(pos, tok, x, y); + x = P.NewBinary(pos, tok, x, y); } } - P.Ecart(); return x; } -func (P *Parser) ParseExpression(prec int) *AST.Expr { - P.Trace("Expression"); - indent := P.indent; +func (P *Parser) ParseExpression(prec int) AST.Expr { + if P.verbose { + P.Trace("Expression"); + defer P.Ecart(); + } + indent := P.indent; if prec < 0 { panic("precedence must be >= 0"); } x := P.NoType(P.ParseBinaryExpr(prec)); - if indent != P.indent { panic("imbalanced tracing code (Expression)"); } - P.Ecart(); + return x; } @@ -1106,35 +1152,25 @@ func (P *Parser) ParseExpression(prec int) *AST.Expr { // Statements func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { - P.Trace("SimpleStat"); + if P.verbose { + P.Trace("SimpleStat"); + defer P.Ecart(); + } s := AST.BadStat; x := P.ParseExpressionList(); - is_range := false; - if range_ok && P.tok == Scanner.COLON { - pos := P.pos; - P.Next(); - y := P.ParseExpression(1); - if x.Len() == 1 { - x = P.NewExpr(pos, Scanner.COLON, x, y); - is_range = true; - } else { - P.Error(pos, "expected initialization, found ':'"); - } - } - switch P.tok { case Scanner.COLON: // label declaration s = AST.NewStat(P.pos, Scanner.COLON); s.Expr = x; - if x.Len() != 1 { - P.Error(x.Pos, "illegal label declaration"); + if AST.ExprLen(x) != 1 { + P.Error(x.Pos(), "illegal label declaration"); } P.Next(); // consume ":" P.opt_semi = true; - + case Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN, Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN, @@ -1143,34 +1179,31 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { // declaration/assignment pos, tok := P.pos, P.tok; P.Next(); - y := AST.BadExpr; + var y AST.Expr = &AST.BadExpr{pos}; if P.tok == Scanner.RANGE { range_pos := P.pos; P.Next(); y = P.ParseExpression(1); - y = P.NewExpr(range_pos, Scanner.RANGE, nil, y); + y = P.NewBinary(range_pos, Scanner.RANGE, nil, y); if tok != Scanner.DEFINE && tok != Scanner.ASSIGN { P.Error(pos, "expected '=' or ':=', found '" + Scanner.TokenString(tok) + "'"); } } else { y = P.ParseExpressionList(); - if is_range { - P.Error(y.Pos, "expected 'range', found expression"); - } - if xl, yl := x.Len(), y.Len(); xl > 1 && yl > 1 && xl != yl { - P.Error(x.Pos, "arity of lhs doesn't match rhs"); + if xl, yl := AST.ExprLen(x), AST.ExprLen(y); xl > 1 && yl > 1 && xl != yl { + P.Error(x.Pos(), "arity of lhs doesn't match rhs"); } } - s = AST.NewStat(x.Pos, Scanner.EXPRSTAT); - s.Expr = AST.NewExpr(pos, tok, x, y); - + s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); + s.Expr = P.NewBinary(pos, tok, x, y); + case Scanner.RANGE: pos := P.pos; P.Next(); y := P.ParseExpression(1); - y = P.NewExpr(pos, Scanner.RANGE, nil, y); - s = AST.NewStat(x.Pos, Scanner.EXPRSTAT); - s.Expr = AST.NewExpr(pos, Scanner.DEFINE, x, y); + y = &AST.UnaryExpr{pos, Scanner.RANGE, y}; + s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); + s.Expr = P.NewBinary(pos, Scanner.DEFINE, x, y); default: var pos, tok int; @@ -1178,34 +1211,39 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { pos, tok = P.pos, P.tok; P.Next(); } else { - pos, tok = x.Pos, Scanner.EXPRSTAT; + pos, tok = x.Pos(), Scanner.EXPRSTAT; } s = AST.NewStat(pos, tok); s.Expr = x; - if x.Len() != 1 { - P.Error(x.Pos, "only one expression allowed"); + if AST.ExprLen(x) != 1 { + P.Error(pos, "only one expression allowed"); + panic(); // fix position } } - P.Ecart(); return s; } func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { - P.Trace("InvocationStat"); + if P.verbose { + P.Trace("InvocationStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, keyword); P.Expect(keyword); s.Expr = P.ParseExpression(1); - P.Ecart(); return s; } func (P *Parser) ParseReturnStat() *AST.Stat { - P.Trace("ReturnStat"); + if P.verbose { + P.Trace("ReturnStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, Scanner.RETURN); P.Expect(Scanner.RETURN); @@ -1213,13 +1251,15 @@ func (P *Parser) ParseReturnStat() *AST.Stat { s.Expr = P.ParseExpressionList(); } - P.Ecart(); return s; } func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { - P.Trace("ControlFlowStat"); + if P.verbose { + P.Trace("ControlFlowStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, tok); P.Expect(tok); @@ -1227,13 +1267,15 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { s.Expr = P.ParseIdent(P.top_scope); } - P.Ecart(); return s; } func (P *Parser) ParseControlClause(keyword int) *AST.Stat { - P.Trace("ControlClause"); + if P.verbose { + P.Trace("ControlClause"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, keyword); P.Expect(keyword); @@ -1263,13 +1305,15 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { P.expr_lev = prev_lev; } - P.Ecart(); return s; } func (P *Parser) ParseIfStat() *AST.Stat { - P.Trace("IfStat"); + if P.verbose { + P.Trace("IfStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.IF); @@ -1297,26 +1341,30 @@ func (P *Parser) ParseIfStat() *AST.Stat { } P.CloseScope(); - P.Ecart(); return s; } func (P *Parser) ParseForStat() *AST.Stat { - P.Trace("ForStat"); + if P.verbose { + P.Trace("ForStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.FOR); s.Body = P.ParseBlock(nil, Scanner.LBRACE); P.CloseScope(); - P.Ecart(); return s; } func (P *Parser) ParseSwitchCase() *AST.Stat { - P.Trace("SwitchCase"); + if P.verbose { + P.Trace("SwitchCase"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, P.tok); if P.tok == Scanner.CASE { @@ -1326,24 +1374,28 @@ func (P *Parser) ParseSwitchCase() *AST.Stat { P.Expect(Scanner.DEFAULT); } - P.Ecart(); return s; } func (P *Parser) ParseCaseClause() *AST.Stat { - P.Trace("CaseClause"); + if P.verbose { + P.Trace("CaseClause"); + defer P.Ecart(); + } s := P.ParseSwitchCase(); s.Body = P.ParseBlock(nil, Scanner.COLON); - P.Ecart(); return s; } func (P *Parser) ParseSwitchStat() *AST.Stat { - P.Trace("SwitchStat"); + if P.verbose { + P.Trace("SwitchStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.SWITCH); @@ -1358,13 +1410,15 @@ func (P *Parser) ParseSwitchStat() *AST.Stat { P.CloseScope(); s.Body = b; - P.Ecart(); return s; } func (P *Parser) ParseCommCase() *AST.Stat { - P.Trace("CommCase"); + if P.verbose { + P.Trace("CommCase"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, P.tok); if P.tok == Scanner.CASE { @@ -1375,7 +1429,7 @@ func (P *Parser) ParseCommCase() *AST.Stat { P.Next(); if P.tok == Scanner.ARROW { y := P.ParseExpression(1); - x = AST.NewExpr(pos, tok, x, y); + x = P.NewBinary(pos, tok, x, y); } else { P.Expect(Scanner.ARROW); // use Expect() error handling } @@ -1385,24 +1439,28 @@ func (P *Parser) ParseCommCase() *AST.Stat { P.Expect(Scanner.DEFAULT); } - P.Ecart(); return s; } func (P *Parser) ParseCommClause() *AST.Stat { - P.Trace("CommClause"); + if P.verbose { + P.Trace("CommClause"); + defer P.Ecart(); + } s := P.ParseCommCase(); s.Body = P.ParseBlock(nil, Scanner.COLON); - P.Ecart(); return s; } func (P *Parser) ParseSelectStat() *AST.Stat { - P.Trace("SelectStat"); + if P.verbose { + P.Trace("SelectStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, Scanner.SELECT); P.Expect(Scanner.SELECT); @@ -1416,13 +1474,15 @@ func (P *Parser) ParseSelectStat() *AST.Stat { P.opt_semi = true; s.Body = b; - P.Ecart(); return s; } func (P *Parser) ParseStatement() *AST.Stat { - P.Trace("Statement"); + if P.verbose { + P.Trace("Statement"); + defer P.Ecart(); + } indent := P.indent; s := AST.BadStat; @@ -1465,7 +1525,6 @@ func (P *Parser) ParseStatement() *AST.Stat { if indent != P.indent { panic("imbalanced tracing code (Statement)"); } - P.Ecart(); return s; } @@ -1474,7 +1533,10 @@ func (P *Parser) ParseStatement() *AST.Stat { // Declarations func (P *Parser) ParseImportSpec(d *AST.Decl) { - P.Trace("ImportSpec"); + if P.verbose { + P.Trace("ImportSpec"); + defer P.Ecart(); + } if P.tok == Scanner.PERIOD { P.Error(P.pos, `"import ." not yet handled properly`); @@ -1485,19 +1547,19 @@ func (P *Parser) ParseImportSpec(d *AST.Decl) { if P.tok == Scanner.STRING { // TODO eventually the scanner should strip the quotes - val := AST.NewObject(P.pos, AST.NONE, P.val); - d.Val = AST.NewLit(Scanner.STRING, val); + d.Val = &AST.BasicLit{P.pos, Scanner.STRING, P.val}; P.Next(); } else { P.Expect(Scanner.STRING); // use Expect() error handling } - - P.Ecart(); } func (P *Parser) ParseConstSpec(d *AST.Decl) { - P.Trace("ConstSpec"); + if P.verbose { + P.Trace("ConstSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdentList(); d.Typ = P.TryType(); @@ -1505,24 +1567,26 @@ func (P *Parser) ParseConstSpec(d *AST.Decl) { P.Next(); d.Val = P.ParseExpressionList(); } - - P.Ecart(); } func (P *Parser) ParseTypeSpec(d *AST.Decl) { - P.Trace("TypeSpec"); + if P.verbose { + P.Trace("TypeSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdent(nil); d.Typ = P.ParseType(); P.opt_semi = true; - - P.Ecart(); } func (P *Parser) ParseVarSpec(d *AST.Decl) { - P.Trace("VarSpec"); + if P.verbose { + P.Trace("VarSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdentList(); if P.tok == Scanner.ASSIGN { @@ -1535,8 +1599,6 @@ func (P *Parser) ParseVarSpec(d *AST.Decl) { d.Val = P.ParseExpressionList(); } } - - P.Ecart(); } @@ -1560,17 +1622,17 @@ func (P *Parser) ParseSpec(d *AST.Decl) { P.Declare(d.Ident, kind, d.Typ); if d.Val != nil { // initialization/assignment - llen := d.Ident.Len(); - rlen := d.Val.Len(); + llen := AST.ExprLen(d.Ident); + rlen := AST.ExprLen(d.Val); if llen == rlen { // TODO } else if rlen == 1 { // TODO } else { if llen < rlen { - P.Error(d.Val.At(llen).Pos, "more expressions than variables"); + P.Error(AST.ExprAt(d.Val, llen).Pos(), "more expressions than variables"); } else { - P.Error(d.Ident.At(rlen).Pos, "more variables than expressions"); + P.Error(AST.ExprAt(d.Ident, rlen).Pos(), "more variables than expressions"); } } } else { @@ -1581,7 +1643,10 @@ func (P *Parser) ParseSpec(d *AST.Decl) { func (P *Parser) ParseDecl(keyword int) *AST.Decl { - P.Trace("Decl"); + if P.verbose { + P.Trace("Decl"); + defer P.Ecart(); + } d := AST.NewDecl(P.pos, keyword); P.Expect(keyword); @@ -1606,7 +1671,6 @@ func (P *Parser) ParseDecl(keyword int) *AST.Decl { P.ParseSpec(d); } - P.Ecart(); return d; } @@ -1621,7 +1685,10 @@ func (P *Parser) ParseDecl(keyword int) *AST.Decl { // func (recv) ident (params) (results) func (P *Parser) ParseFunctionDecl() *AST.Decl { - P.Trace("FunctionDecl"); + if P.verbose { + P.Trace("FunctionDecl"); + defer P.Ecart(); + } d := AST.NewDecl(P.pos, Scanner.FUNC); P.Expect(Scanner.FUNC); @@ -1635,24 +1702,24 @@ func (P *Parser) ParseFunctionDecl() *AST.Decl { } } - d.Ident = P.ParseIdent(nil); + ident := P.ParseIdent(nil); + d.Ident = ident; d.Typ = P.ParseSignature(); d.Typ.Key = recv; if P.tok == Scanner.LBRACE { - f := AST.NewObject(d.Pos, AST.FUNC, d.Ident.Obj.Ident); - f.Typ = d.Typ; - f.Body = P.ParseBlock(d.Typ, Scanner.LBRACE); - d.Val = AST.NewLit(Scanner.FUNC, f); + d.Body = P.ParseBlock(d.Typ, Scanner.LBRACE); } - P.Ecart(); return d; } func (P *Parser) ParseDeclaration() *AST.Decl { - P.Trace("Declaration"); + if P.verbose { + P.Trace("Declaration"); + defer P.Ecart(); + } indent := P.indent; d := AST.BadDecl; @@ -1670,7 +1737,6 @@ func (P *Parser) ParseDeclaration() *AST.Decl { if indent != P.indent { panic("imbalanced tracing code (Declaration)"); } - P.Ecart(); return d; } @@ -1679,7 +1745,10 @@ func (P *Parser) ParseDeclaration() *AST.Decl { // Program func (P *Parser) ParseProgram() *AST.Program { - P.Trace("Program"); + if P.verbose { + P.Trace("Program"); + defer P.Ecart(); + } P.OpenScope(); p := AST.NewProgram(P.pos); @@ -1705,6 +1774,5 @@ func (P *Parser) ParseProgram() *AST.Program { p.Comments = P.comments; P.CloseScope(); - P.Ecart(); return p; } diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 002a91a2d5..5e3f8a4b74 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -33,6 +33,26 @@ var ( ) +// ---------------------------------------------------------------------------- +// Elementary support + +func unimplemented() { + panic("unimplemented"); +} + + +func unreachable() { + panic("unreachable"); +} + + +func assert(pred bool) { + if !pred { + panic("assertion failed"); + } +} + + // ---------------------------------------------------------------------------- // Printer @@ -76,6 +96,9 @@ type Printer struct { // semantic state state int; // current semantic state laststate int; // state for last string + + // expression precedence + prec int; } @@ -104,6 +127,9 @@ func (P *Printer) Init(text io.Write, comments *array.Array) { P.NextComment(); // formatting parameters & semantic state initialized correctly by default + + // expression precedence + P.prec = Scanner.LowestPrec; } @@ -384,24 +410,21 @@ func (P *Printer) HtmlEpilogue() { } -func (P *Printer) HtmlIdentifier(x *AST.Expr) { - if x.Tok != Scanner.IDENT { - panic(); - } +func (P *Printer) HtmlIdentifier(x *AST.Ident) { obj := x.Obj; if *html && obj.Kind != AST.NONE { // depending on whether we have a declaration or use, generate different html // - no need to htmlEscape ident id := Utils.IntToString(obj.Id, 10); - if x.Pos == obj.Pos { + if x.Pos() == obj.Pos { // probably the declaration of x - P.TaggedString(x.Pos, ``, obj.Ident, ``); + P.TaggedString(x.Pos(), ``, obj.Ident, ``); } else { // probably not the declaration of x - P.TaggedString(x.Pos, ``, obj.Ident, ``); + P.TaggedString(x.Pos(), ``, obj.Ident, ``); } } else { - P.String(x.Pos, obj.Ident); + P.String(x.Pos(), obj.Ident); } } @@ -409,32 +432,58 @@ func (P *Printer) HtmlIdentifier(x *AST.Expr) { // ---------------------------------------------------------------------------- // Types -func (P *Printer) Type(t *AST.Type, full_function_type bool) int -func (P *Printer) Expr(x *AST.Expr) -func (P *Printer) Expr1(x *AST.Expr, prec1 int, full_function_type bool) +func (P *Printer) Type(t *AST.Type) int +func (P *Printer) Expr(x AST.Expr) func (P *Printer) Parameters(pos int, list *array.Array) { P.String(pos, "("); if list != nil { var prev int; for i, n := 0, list.Len(); i < n; i++ { - x := list.At(i).(*AST.Expr); + x := list.At(i).(AST.Expr); + tok := Scanner.TYPE; + if dummy, is_ident := x.(*AST.Ident); is_ident { + tok = Scanner.IDENT; + } if i > 0 { - if prev == x.Tok || prev == Scanner.TYPE { + if prev == tok || prev == Scanner.TYPE { P.separator = comma; } else { P.separator = blank; } } P.Expr(x); - prev = x.Tok; + prev = tok; } } P.String(0, ")"); } -func (P *Printer) Fields(list *array.Array, end int, full_function_type bool) { +// Returns the separator (semicolon or none) required if +// the type is terminating a declaration or statement. +func (P *Printer) Signature(t *AST.Type) int { + assert(t.Form == AST.FUNCTION); + separator := none; + P.Parameters(t.Pos, t.List); + if t.Elt != nil { + P.separator = blank; + list := t.Elt.List; + dummy, is_type := list.At(0).(*AST.TypeLit); + if list.Len() > 1 || is_type && dummy.Typ.Form == AST.FUNCTION { + // single, anonymous result types which are functions must + // be parenthesized as well + P.Parameters(0, list); + } else { + // single, anonymous result type + separator = P.Type(list.At(0).(*AST.TypeLit).Typ); + } + } + return separator; +} + + +func (P *Printer) Fields(list *array.Array, end int, in_interface bool) { P.state = opening_scope; P.String(0, "{"); @@ -442,19 +491,29 @@ func (P *Printer) Fields(list *array.Array, end int, full_function_type bool) { P.newlines = 1; var prev int; for i, n := 0, list.Len(); i < n; i++ { - x := list.At(i).(*AST.Expr); + x := list.At(i).(AST.Expr); + tok := Scanner.TYPE; + if dummy, is_ident := x.(*AST.Ident); is_ident { + tok = Scanner.IDENT; + } else if dummy, is_lit := x.(*AST.BasicLit); is_lit && dummy.Tok == Scanner.STRING { + tok = Scanner.STRING; + } if i > 0 { - if prev == Scanner.TYPE && x.Tok != Scanner.STRING || prev == Scanner.STRING { + if prev == Scanner.TYPE && tok != Scanner.STRING || prev == Scanner.STRING { P.separator = semicolon; P.newlines = 1; - } else if prev == x.Tok { + } else if prev == tok { P.separator = comma; } else { P.separator = tab; } } - P.Expr1(x, Scanner.LowestPrec, full_function_type); - prev = x.Tok; + if in_interface && tok == Scanner.TYPE { + P.Signature(x.(*AST.TypeLit).Typ); + } else { + P.Expr(x); + } + prev = tok; } P.newlines = 1; } @@ -466,7 +525,7 @@ func (P *Printer) Fields(list *array.Array, end int, full_function_type bool) { // Returns the separator (semicolon or none) required if // the type is terminating a declaration or statement. -func (P *Printer) Type(t *AST.Type, full_function_type bool) int { +func (P *Printer) Type(t *AST.Type) int { separator := semicolon; switch t.Form { @@ -479,7 +538,7 @@ func (P *Printer) Type(t *AST.Type, full_function_type bool) int { P.Expr(t.Expr); } P.String(0, "]"); - separator = P.Type(t.Elt, true); + separator = P.Type(t.Elt); case AST.STRUCT, AST.INTERFACE: switch t.Form { @@ -488,15 +547,15 @@ func (P *Printer) Type(t *AST.Type, full_function_type bool) int { } if t.List != nil { P.separator = blank; - P.Fields(t.List, t.End, t.Form == AST.STRUCT); + P.Fields(t.List, t.End, t.Form == AST.INTERFACE); } separator = none; case AST.MAP: P.String(t.Pos, "map ["); - P.Type(t.Key, true); + P.Type(t.Key); P.String(0, "]"); - separator = P.Type(t.Elt, true); + separator = P.Type(t.Elt); case AST.CHANNEL: var m string; @@ -506,29 +565,15 @@ func (P *Printer) Type(t *AST.Type, full_function_type bool) int { case AST.SEND: m = "chan <- "; } P.String(t.Pos, m); - separator = P.Type(t.Elt, true); + separator = P.Type(t.Elt); case AST.POINTER: P.String(t.Pos, "*"); - separator = P.Type(t.Elt, true); + separator = P.Type(t.Elt); case AST.FUNCTION: - if full_function_type { - P.Token(0, Scanner.FUNC); - } - P.Parameters(t.Pos, t.List); - if t.Elt != nil { - P.separator = blank; - list := t.Elt.List; - if list.Len() > 1 || list.At(0).(*AST.Expr).Typ.Form == AST.FUNCTION { - // single, anonymous result types which are functions must - // be parenthesized as well - P.Parameters(0, list); - } else { - // single, anonymous result type - P.Expr(list.At(0).(*AST.Expr)); - } - } + P.Token(0, Scanner.FUNC); + separator = P.Signature(t); case AST.ELLIPSIS: P.String(t.Pos, "..."); @@ -545,105 +590,133 @@ func (P *Printer) Type(t *AST.Type, full_function_type bool) int { // Expressions func (P *Printer) Block(b *AST.Block, indent bool); +func (P *Printer) Expr1(x AST.Expr, prec1 int); -func (P *Printer) Expr1(x *AST.Expr, prec1 int, full_function_type bool) { - if x == nil { - return; // empty expression list - } - switch x.Tok { - case Scanner.TYPE: - // type expr - P.Type(x.Typ, full_function_type); +func (P *Printer) DoBadExpr(x *AST.BadExpr) { + P.String(0, "BadExpr"); +} - case Scanner.IDENT: - P.HtmlIdentifier(x); - case Scanner.INT, Scanner.STRING, Scanner.FLOAT: - // literal - P.String(x.Pos, x.Obj.Ident); +func (P *Printer) DoIdent(x *AST.Ident) { + P.HtmlIdentifier(x); +} - case Scanner.FUNC: - // function literal - P.String(x.Pos, "func"); - P.Type(x.Obj.Typ, false); - P.Block(x.Obj.Body, true); - P.newlines = 0; - case Scanner.COMMA: - // list +func (P *Printer) DoBinaryExpr(x *AST.BinaryExpr) { + if x.Tok == Scanner.COMMA { // (don't use binary expression printing because of different spacing) P.Expr(x.X); - P.String(x.Pos, ","); + P.String(x.Pos(), ","); P.separator = blank; P.state = inside_list; P.Expr(x.Y); - - case Scanner.PERIOD: - // selector or type guard - P.Expr1(x.X, Scanner.HighestPrec, true); - P.String(x.Pos, "."); - if x.Y.Tok == Scanner.TYPE { - P.String(0, "("); - P.Expr(x.Y); - P.String(0, ")"); - } else { - P.Expr1(x.Y, Scanner.HighestPrec, true); - } - - case Scanner.LBRACK: - // index - P.Expr1(x.X, Scanner.HighestPrec, true); - P.String(x.Pos, "["); - P.Expr1(x.Y, 0, true); - P.String(0, "]"); - - case Scanner.LPAREN: - // call - P.Expr1(x.X, Scanner.HighestPrec, true); - P.String(x.Pos, "("); - P.Expr(x.Y); - P.String(0, ")"); - - case Scanner.LBRACE: - // composite literal - P.Type(x.Obj.Typ, true); - P.String(x.Pos, "{"); - P.Expr(x.Y); - P.String(0, "}"); - - default: - // unary and binary expressions including ":" for pairs - prec := Scanner.UnaryPrec; - if x.X != nil { - prec = Scanner.Precedence(x.Tok); - } - if prec < prec1 { + } else { + prec := Scanner.Precedence(x.Tok); + if prec < P.prec { P.String(0, "("); } - if x.X == nil { - // unary expression - P.Token(x.Pos, x.Tok); - if x.Tok == Scanner.RANGE { - P.separator = blank; - } - } else { - // binary expression - P.Expr1(x.X, prec, true); - P.separator = blank; - P.Token(x.Pos, x.Tok); - P.separator = blank; - } - P.Expr1(x.Y, prec, true); - if prec < prec1 { + P.Expr1(x.X, prec); + P.separator = blank; + P.Token(x.Pos(), x.Tok); + P.separator = blank; + P.Expr1(x.Y, prec); + if prec < P.prec { P.String(0, ")"); } } } -func (P *Printer) Expr(x *AST.Expr) { - P.Expr1(x, Scanner.LowestPrec, true); +func (P *Printer) DoUnaryExpr(x *AST.UnaryExpr) { + prec := Scanner.UnaryPrec; + if prec < P.prec { + P.String(0, "("); + } + P.Token(x.Pos(), x.Tok); + if x.Tok == Scanner.RANGE { + P.separator = blank; + } + P.Expr1(x.X, prec); + if prec < P.prec { + P.String(0, ")"); + } +} + + +func (P *Printer) DoBasicLit(x *AST.BasicLit) { + P.String(x.Pos(), x.Val); +} + + +func (P *Printer) DoTypeLit(x *AST.TypeLit) { + P.Type(x.Typ); +} + + +func (P *Printer) DoFunctionLit(x *AST.FunctionLit) { + P.String(x.Pos(), "func"); + P.Signature(x.Typ); + P.separator = blank; + P.Block(x.Body, true); + P.newlines = 0; +} + + +func (P *Printer) DoCompositeLit(x *AST.CompositeLit) { + P.Type(x.Typ); + P.String(x.Pos(), "{"); + P.Expr(x.Elts); + P.String(0, "}"); +} + + +func (P *Printer) DoSelector(x *AST.Selector) { + P.Expr1(x.X, Scanner.HighestPrec); + P.String(x.Pos(), "."); + P.Expr1(x.Sel, Scanner.HighestPrec); +} + + +func (P *Printer) DoTypeGuard(x *AST.TypeGuard) { + P.Expr1(x.X, Scanner.HighestPrec); + P.String(x.Pos(), "."); + P.String(0, "("); + P.Type(x.Typ); + P.String(0, ")"); +} + + +func (P *Printer) DoIndex(x *AST.Index) { + P.Expr1(x.X, Scanner.HighestPrec); + P.String(x.Pos(), "["); + P.Expr1(x.I, 0); + P.String(0, "]"); +} + + +func (P *Printer) DoCall(x *AST.Call) { + P.Expr1(x.F, Scanner.HighestPrec); + P.String(x.Pos(), "("); + P.Expr(x.Args); + P.String(0, ")"); +} + + +func (P *Printer) Expr1(x AST.Expr, prec1 int) { + if x == nil { + return; // empty expression list + } + + saved_prec := P.prec; + P.prec = prec1; + x.Visit(P); + P.prec = saved_prec; +} + + +func (P *Printer) Expr(x AST.Expr) { + P.Expr1(x, Scanner.LowestPrec); } @@ -834,7 +907,7 @@ func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) { if d.Ident != nil { P.Expr(d.Ident); } else { - P.String(d.Val.Pos, ""); // flush pending ';' separator/newlines + P.String(d.Val.Pos(), ""); // flush pending ';' separator/newlines } P.separator = tab; P.Expr(d.Val); @@ -843,13 +916,13 @@ func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) { 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, true); + 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, true); + P.separator = P.Type(d.Typ); } if d.Val != nil { P.separator = tab; @@ -866,10 +939,10 @@ func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) { P.separator = blank; } P.Expr(d.Ident); - P.separator = P.Type(d.Typ, false); - if d.Val != nil { + P.separator = P.Signature(d.Typ); + if d.Body != nil { P.separator = blank; - P.Block(d.Val.Obj.Body, true); + P.Block(d.Body, true); } default: @@ -910,7 +983,7 @@ func Print(prog *AST.Program) { P.Init(text, prog.Comments); // TODO would be better to make the name of the src file be the title - P.HtmlPrologue("package " + prog.Ident.Obj.Ident); + P.HtmlPrologue("package " + prog.Ident.(*AST.Ident).Obj.Ident); P.Program(prog); P.HtmlEpilogue();