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();