]> Cypherpunks repositories - gostls13.git/commitdiff
- composites, receivers, various add. checks
authorRobert Griesemer <gri@golang.org>
Thu, 16 Oct 2008 19:16:50 +0000 (12:16 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 16 Oct 2008 19:16:50 +0000 (12:16 -0700)
R=r
OCL=17295
CL=17295

usr/gri/pretty/node.go
usr/gri/pretty/parser.go
usr/gri/pretty/printer.go

index 8f81af83871b904cf2fc723beb028d669ac2b792..7c4bcefc07476b147fcc45c033d3508c7e1533d9 100644 (file)
@@ -68,38 +68,8 @@ export func NewList() *List {
 }
 
 
-// ----------------------------------------------------------------------------
-// Types
-
-export const /* channel mode */ (
-       FULL = iota;
-       SEND;
-       RECV;
-)
-
-
-export type Type struct {
-       pos, tok int;
-       expr *Expr;  // type name, array length
-       mode int;  // channel mode
-       key *Type;  // map key
-       elt *Type;  // array element, map or channel value, or pointer base type
-       list *List;  // struct fields, interface methods, function parameters
-}
-
-
-export func NewType(pos, tok int) *Type {
-       t := new(Type);
-       t.pos, t.tok = pos, tok;
-       return t;
-}
-
-
 // ----------------------------------------------------------------------------
 // Expressions
-//
-// Expression pairs are represented as binary expressions with operator ":"
-// Expression lists are represented as binary expressions with operator ","
 
 export type Expr struct {
        pos, tok int;
@@ -135,9 +105,53 @@ export func NewLit(pos, tok int, s string) *Expr {
 }
 
 
-export func NewTypeExpr(pos int, t *Type) *Expr {
+// ----------------------------------------------------------------------------
+// Types
+
+export const /* channel mode */ (
+       FULL = iota;
+       SEND;
+       RECV;
+)
+
+
+export type Type struct {
+       pos, tok int;
+       expr *Expr;  // type name, array length
+       mode int;  // channel mode
+       key *Type;  // receiver type, map key
+       elt *Type;  // array element, map or channel value, or pointer base type, result type
+       list *List;  // struct fields, interface methods, function parameters
+}
+
+
+func (t *Type) nfields() int {
+       nx, nt := 0, 0;
+       for i, n := 0, t.list.len(); i < n; i++ {
+               if t.list.at(i).(*Expr).tok == Scanner.TYPE {
+                       nt++;
+               } else {
+                       nx++;
+               }
+       }
+       if nx == 0 {
+               return nt;
+       }
+       return nx;
+}
+
+
+export func NewType(pos, tok int) *Type {
+       t := new(Type);
+       t.pos, t.tok = pos, tok;
+       return t;
+}
+
+
+// requires complete Type type
+export func NewTypeExpr(t *Type) *Expr {
        e := new(Expr);
-       e.pos, e.tok, e.t = pos, Scanner.TYPE, t;
+       e.pos, e.tok, e.t = t.pos, Scanner.TYPE, t;
        return e;
 }
 
index f195a8e73da6d6b539750ce0c5ebc1d1e6a06990..53145b462bc3c5eb709c0f22d01f68c35d9a8da7 100644 (file)
@@ -131,18 +131,19 @@ func (P *Parser) ParseIdent() *Node.Expr {
 }
 
 
-func (P *Parser) ParseIdentList() *Node.List {
+func (P *Parser) ParseIdentList() *Node.Expr {
        P.Trace("IdentList");
 
-       list := Node.NewList();
-       list.Add(P.ParseIdent());
-       for P.tok == Scanner.COMMA {
+       x := P.ParseIdent();
+       if P.tok == Scanner.COMMA {
+               pos := P.pos;
                P.Next();
-               list.Add(P.ParseIdent());
+               y := P.ParseIdentList();
+               x := Node.NewExpr(pos, Scanner.COMMA, x, y);
        }
 
        P.Ecart();
-       return list;
+       return x;
 }
 
 
@@ -241,6 +242,7 @@ func (P *Parser) ParseChannelType() *Node.Type {
 func (P *Parser) ParseVarDeclList(list *Node.List) {
        P.Trace("VarDeclList");
 
+       // parse a list of types
        i0 := list.len();
        list.Add(P.ParseType());
        for P.tok == Scanner.COMMA {
@@ -250,6 +252,7 @@ func (P *Parser) ParseVarDeclList(list *Node.List) {
 
        typ := P.TryType();
 
+       // convert the list into a list of (type) expressions
        if typ != nil {
                // all list entries must be identifiers
                // convert the type entries into identifiers
@@ -263,14 +266,14 @@ func (P *Parser) ParseVarDeclList(list *Node.List) {
                        }
                }
                // add type
-               list.Add(Node.NewTypeExpr(typ.pos, typ));
+               list.Add(Node.NewTypeExpr(typ));
 
        } else {
                // all list entries are types
                // convert all type entries into type expressions
                for i, n := i0, list.len(); i < n; i++ {
                        t := list.at(i).(*Node.Type);
-                       list.set(i, Node.NewTypeExpr(t.pos, t));
+                       list.set(i, Node.NewTypeExpr(t));
                }
                
                if P.tok == Scanner.COMMA {
@@ -339,7 +342,7 @@ func (P *Parser) ParseResult() *Node.Type {
                if typ != nil {
                        t = Node.NewType(P.pos, Scanner.STRUCT);
                        t.list = Node.NewList();
-                       t.list.Add(Node.NewTypeExpr(typ.pos, typ));
+                       t.list.Add(Node.NewTypeExpr(typ));
                }
        }
 
@@ -572,7 +575,7 @@ func (P *Parser) ParseOperand() *Node.Expr {
        default:
                t := P.TryType();
                if t != nil {
-                       x = Node.NewTypeExpr(t.pos, t);
+                       x = Node.NewTypeExpr(t);
                } else {
                        P.Error(P.pos, "operand expected");
                        P.Next();  // make progress
@@ -653,31 +656,42 @@ func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr {
 }
 
 
+func (P *Parser) ParseExpressionPairList(mode int) *Node.Expr {
+       P.Trace("ExpressionPairList");
+       
+       x := P.ParseExpressionPair(mode);
+       if mode == 0 {
+               // first expression determines mode
+               if x.tok == Scanner.COLON {
+                       mode = 2;
+               } else {
+                       mode = 1;
+               }
+       }
+       if P.tok == Scanner.COMMA {
+               pos := P.pos;
+               P.Next();
+               if P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
+                       y := P.ParseExpressionPairList(mode);
+                       x = Node.NewExpr(pos, Scanner.COMMA, x, y);
+               }
+       }
+       
+       P.Ecart();
+       return x;
+}
+
+
 func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr {
        P.Trace("CompositeLit");
 
-       mode := 0;
+       pos := P.pos;
        P.Expect(Scanner.LBRACE);
-       for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
-               x := P.ParseExpressionPair(mode);
-               if mode == 0 {
-                       // first expression determines mode
-                       if x.tok == Scanner.COLON {
-                               mode = 2;
-                       } else {
-                               mode = 1;
-                       }
-               }
-               if P.tok == Scanner.COMMA {
-                       P.Next();
-               } else {
-                       break;
-               }
-       }
+       x := P.ParseExpressionPairList(0);
        P.Expect(Scanner.RBRACE);
        
        P.Ecart();
-       return Node.NewLit(P.pos, Scanner.INT, "0");  // "null" expr
+       return Node.NewExpr(pos, Scanner.LBRACE, Node.NewTypeExpr(t), x);
 }
 
 
@@ -780,16 +794,16 @@ func (P *Parser) ParseSimpleStat() *Node.Stat {
        P.Trace("SimpleStat");
        
        var s *Node.Stat;
+
        x := P.ParseExpressionList();
        
        switch P.tok {
        case Scanner.COLON:
                // label declaration
-               if x.len() == 1 {
-                       s = Node.NewStat(P.pos, Scanner.COLON);
-                       s.expr = x;
-               } else {
-                       P.Error(P.pos, "illegal label declaration");
+               s = Node.NewStat(P.pos, Scanner.COLON);
+               s.expr = x;
+               if x.len() != 1 {
+                       P.Error(x.pos, "illegal label declaration");
                }
                P.Next();  // consume ":"
                P.opt_semi = true;
@@ -803,23 +817,22 @@ func (P *Parser) ParseSimpleStat() *Node.Stat {
                P.Next();
                s.lhs = x;
                s.expr = P.ParseExpressionList();
+               if l, r := x.len(), s.expr.len(); l > 1 && r > 1 && l != r {
+                       P.Error(x.pos, "arity of lhs doesn't match rhs");
+               }
 
        default:
+               var pos, tok int;
                if P.tok == Scanner.INC || P.tok == Scanner.DEC {
-                       s = Node.NewStat(P.pos, P.tok);
-                       if x.len() == 1 {
-                               s.expr = x;
-                       } else {
-                               P.Error(P.pos, "more then one operand");
-                       }
-                       P.Next();  // consume "++" or "--"
+                       pos, tok = P.pos, P.tok;
+                       P.Next();
                } else {
-                       s = Node.NewStat(P.pos, 0);  // TODO give this a token value
-                       if x.len() == 1 {
-                               s.expr = x;
-                       } else {
-                               P.Error(P.pos, "syntax error");
-                       }
+                       pos, tok = x.pos, 0;  // TODO give this a token value
+               }
+               s = Node.NewStat(pos, tok);
+               s.expr = x;
+               if x.len() != 1 {
+                       P.Error(x.pos, "only one expression allowed");
                }
        }
        
@@ -1173,15 +1186,15 @@ func (P *Parser) ParseVarSpec(exported bool) *Node.Decl {
        P.Trace("VarSpec");
        
        d := Node.NewDecl(P.pos, Scanner.VAR, exported);
-       P.ParseIdentList();
+       d.ident = P.ParseIdentList();
        if P.tok == Scanner.ASSIGN {
                P.Next();
-               P.ParseExpressionList();
+               d.val = P.ParseExpressionList();
        } else {
-               P.ParseVarType();
+               d.typ = P.ParseVarType();
                if P.tok == Scanner.ASSIGN {
                        P.Next();
-                       P.ParseExpressionList();
+                       d.val = P.ParseExpressionList();
                }
        }
        
@@ -1246,20 +1259,20 @@ func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl {
        
        d := Node.NewDecl(P.pos, Scanner.FUNC, exported);
        P.Expect(Scanner.FUNC);
+       
+       var recv *Node.Type;
        if P.tok == Scanner.LPAREN {
                pos := P.pos;
-               recv := P.ParseParameters();
-               // TODO: fix this
-               /*
-               if recv.list.len() != 1 {
+               recv = P.ParseParameters();
+               if recv.nfields() != 1 {
                        P.Error(pos, "must have exactly one receiver");
                }
-               */
        }
        
        d.ident = P.ParseIdent();
        d.typ = P.ParseFunctionType();
-       
+       d.typ.key = recv;
+
        if P.tok == Scanner.LBRACE {
                P.scope_lev++;
                d.list = P.ParseBlock();
index 2156ae7e7d02d3421b82420d309ea2769e8de04b..72595140175bbef786d0bb46d8a4151b30ed9365 100644 (file)
@@ -70,7 +70,8 @@ func (P *Printer) CloseScope(paren string) {
 func (P *Printer) Type(t *Node.Type)
 func (P *Printer) Expr(x *Node.Expr)
 
-func (P *Printer) Parameters(list *Node.List) {
+func (P *Printer) Parameters(pos int, list *Node.List) {
+       P.String(pos, "(");
        var prev int;
        for i, n := 0, list.len(); i < n; i++ {
                x := list.at(i).(*Node.Expr);
@@ -84,6 +85,7 @@ func (P *Printer) Parameters(list *Node.List) {
                P.Expr(x);
                prev = x.tok;
        }
+       P.String(0, ")");
 }
 
 
@@ -123,7 +125,7 @@ func (P *Printer) Type(t *Node.Type) {
                if t.expr != nil {
                        P.Expr(t.expr);
                }
-               P.String(0, "] ");
+               P.String(0, "]");
                P.Type(t.elt);
 
        case Scanner.STRUCT:
@@ -137,7 +139,7 @@ func (P *Printer) Type(t *Node.Type) {
        case Scanner.MAP:
                P.String(t.pos, "[");
                P.Type(t.key);
-               P.String(0, "] ");
+               P.String(0, "]");
                P.Type(t.elt);
 
        case Scanner.CHAN:
@@ -168,13 +170,10 @@ func (P *Printer) Type(t *Node.Type) {
                P.Type(t.elt);
 
        case Scanner.LPAREN:
-               P.String(t.pos, "(");
-               P.Parameters(t.list);
-               P.String(0, ")");
+               P.Parameters(t.pos, t.list);
                if t.elt != nil {
-                       P.String(0, " (");
-                       P.Parameters(t.elt.list);
-                       P.String(0, ")");
+                       P.Blank();
+                       P.Parameters(0, t.elt.list);
                }
 
        default:
@@ -192,9 +191,6 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) {
        }
 
        switch x.tok {
-       case Scanner.VAR:
-               panic("UNIMPLEMENTED (VAR)");
-               
        case Scanner.TYPE:
                P.Type(x.t);
 
@@ -222,6 +218,12 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) {
                P.String(x.pos, "(");
                P.Expr1(x.y, 0);
                P.String(0, ")");
+
+       case Scanner.LBRACE:
+               P.Expr1(x.x, 8);
+               P.String(x.pos, "{");
+               P.Expr1(x.y, 0);
+               P.String(0, "}");
                
        default:
                if x.x == nil {
@@ -396,35 +398,6 @@ func (P *Printer) Stat(s *Node.Stat) {
 // Declarations
 
 
-/*
-func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
-       P.String("func ");
-       if x.typ.recv != nil {
-               P.String("(");
-               P.DoVarDeclList(x.typ.recv);
-               P.String(") ");
-       }
-       P.DoIdent(x.ident);
-       P.DoFunctionType(x.typ);
-       if x.body != nil {
-               P.String(" ");
-               P.DoBlock(x.body);
-       } else {
-               P.String(" ;");
-       }
-       P.NewLine();
-       P.NewLine();
-
-}
-
-
-func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
-       //P.DoIdent(x.ident);
-       //P.DoFunctionType(x.typ);
-}
-*/
-
-
 func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
        if d == nil {  // TODO remove this check
                P.String(0, "<nil decl>");
@@ -448,6 +421,11 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
                P.CloseScope(")");
 
        } else {
+               if d.tok == Scanner.FUNC && d.typ.key != nil {
+                       P.Parameters(0, d.typ.key.list);
+                       P.Blank();
+               }
+
                P.Expr(d.ident);
                
                if d.typ != nil {
@@ -471,6 +449,10 @@ func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
                        P.Blank();
                        P.Block(d.list, true);
                }
+               
+               if d.tok != Scanner.TYPE {
+                       P.semi = true;
+               }
        }
        
        P.newl = 1;