]> Cypherpunks repositories - gostls13.git/commitdiff
Snapshot.
authorRobert Griesemer <gri@golang.org>
Fri, 26 Sep 2008 00:20:39 +0000 (17:20 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 26 Sep 2008 00:20:39 +0000 (17:20 -0700)
Added support for function literals, composite literals.
Bug fixes.

R=r
OCL=15911
CL=15911

usr/gri/pretty/ast.go
usr/gri/pretty/parser.go
usr/gri/pretty/printer.go
usr/gri/pretty/scanner.go

index 7cbd05c5c78826e96ff260f62db32521bfb27688..b8839852a4020573eb8fafb5d5d7d40a1e87213d 100644 (file)
@@ -40,7 +40,9 @@ export type Visitor interface {
        DoIndex(x *Index);
        DoCall(x *Call);
        DoSelector(x *Selector);
-       
+       DoCompositeLit(x *CompositeLit);
+       DoFunctionLit(x *FunctionLit);
+
        // Statements
        DoLabel(x *Label);
        DoBlock(x *Block);
@@ -167,9 +169,16 @@ export type MapType struct {
 }
 
 
+export const /* chan mode */ (
+       FULL = iota;
+       RECV;
+       SEND;
+)
+
 export type ChannelType struct {
        pos int;  // position of "chan" or "<-" (if before "chan")
        elt Type;
+       mode int;
 }
 
 
@@ -324,13 +333,29 @@ export type Literal struct {
 }
 
 
-func (x *Binary)   Visit(v Visitor)  { v.DoBinary(x); }
-func (x *Unary)    Visit(v Visitor)  { v.DoUnary(x); }
-func (x *Literal)  Visit(v Visitor)  { v.DoLiteral(x); }
-func (x *Pair)     Visit(v Visitor)  { v.DoPair(x); }
-func (x *Index)    Visit(v Visitor)  { v.DoIndex(x); }
-func (x *Call)     Visit(v Visitor)  { v.DoCall(x); }
-func (x *Selector) Visit(v Visitor)  { v.DoSelector(x); }
+export type CompositeLit struct {
+       pos int;  // position of "{"
+       typ Type;
+       vals *List  // list of Expr
+}
+
+
+export type FunctionLit struct {
+       pos int;  // position of "func"
+       typ *FunctionType;
+       body *Block;
+}
+
+
+func (x *Binary)       Visit(v Visitor)  { v.DoBinary(x); }
+func (x *Unary)        Visit(v Visitor)  { v.DoUnary(x); }
+func (x *Literal)      Visit(v Visitor)  { v.DoLiteral(x); }
+func (x *Pair)         Visit(v Visitor)  { v.DoPair(x); }
+func (x *Index)        Visit(v Visitor)  { v.DoIndex(x); }
+func (x *Call)         Visit(v Visitor)  { v.DoCall(x); }
+func (x *Selector)     Visit(v Visitor)  { v.DoSelector(x); }
+func (x *CompositeLit) Visit(v Visitor)  { v.DoCompositeLit(x); }
+func (x *FunctionLit)  Visit(v Visitor)  { v.DoFunctionLit(x); }
 
 
 // ----------------------------------------------------------------------------
index c20f8f8d7cfdb232b4e1d2ffd3b529baedc57ad5..8bca136e0dcd4e1cae7ddeccab3811436f3e0767 100644 (file)
@@ -212,6 +212,7 @@ func (P *Parser) ParseArrayType() *AST.ArrayType {
        
        typ := new(AST.ArrayType);
        typ.pos = P.pos;
+       typ.len_ = AST.NIL;
        
        P.Expect(Scanner.LBRACK);
        if P.tok != Scanner.RBRACK {
@@ -231,15 +232,18 @@ func (P *Parser) ParseChannelType() *AST.ChannelType {
        
        typ := new(AST.ChannelType);
        typ.pos = P.pos;
+       typ.mode = AST.FULL;
        
        if P.tok == Scanner.CHAN {
                P.Next();
                if P.tok == Scanner.ARROW {
                        P.Next();
+                       typ.mode = AST.SEND;
                }
        } else {
                P.Expect(Scanner.ARROW);
                P.Expect(Scanner.CHAN);
+               typ.mode = AST.RECV;
        }
        typ.elt = P.ParseVarType();
 
@@ -532,91 +536,106 @@ func (P *Parser) ParseBlock() *AST.Block {
 // ----------------------------------------------------------------------------
 // Expressions
 
-func (P *Parser) ParseExpressionList() *AST.List {
+func (P *Parser) ParseExpressionList(list *AST.List) {
        P.Trace("ExpressionList");
 
-       p := AST.NewList();
-       p.Add(P.ParseExpression());
+       list.Add(P.ParseExpression());
        for P.tok == Scanner.COMMA {
                P.Next();
-               p.Add(P.ParseExpression());
+               list.Add(P.ParseExpression());
        }
        
        P.Ecart();
-       return p;
 }
 
 
-func (P *Parser) ParseFunctionLit() AST.Expr {
+func (P *Parser) ParseNewExpressionList() *AST.List {
+       list := AST.NewList();
+       P.ParseExpressionList(list);
+       return list;
+}
+
+
+func (P *Parser) ParseFunctionLit() *AST.FunctionLit {
        P.Trace("FunctionLit");
        
+       fun := new(AST.FunctionLit);
+       fun.pos = P.pos;
+       
        P.Expect(Scanner.FUNC);
-       P.ParseFunctionType();
-       P.ParseBlock();
+       fun.typ = P.ParseFunctionType();
+       fun.body = P.ParseBlock();
        
        P.Ecart();
-       var x AST.Expr;
-       return x;
+       return fun;
 }
 
 
 func (P *Parser) ParseExpressionPair() AST.Expr {
        P.Trace("ExpressionPair");
 
-       x := P.ParseExpression();
-       pos := P.pos;
+       p := new(AST.Pair);
+       p.x = P.ParseExpression();
+       p.pos = P.pos;
        P.Expect(Scanner.COLON);
-       y := P.ParseExpression();
-       
-       z := new(AST.Pair);
-       z.pos, z.x, z.y = pos, x, y;
+       p.y = P.ParseExpression();
        
        P.Ecart();
-       return z;
+       return p;
 }
 
 
-func (P *Parser) ParseExpressionPairList() *AST.List {
+func (P *Parser) ParseExpressionPairList(list *AST.List) {
        P.Trace("ExpressionPairList");
 
-       p := AST.NewList();
-       p.Add(P.ParseExpressionPair());
+       list.Add(P.ParseExpressionPair());
        for P.tok == Scanner.COMMA {
-               p.Add(P.ParseExpressionPair());
+               list.Add(P.ParseExpressionPair());
        }
        
        P.Ecart();
-       return p;
 }
 
 
-func (P *Parser) ParseCompositeLit() AST.Expr {
+func (P *Parser) ParseCompositeLit(typ AST.Type) AST.Expr {
        P.Trace("CompositeLit");
        
+       lit := new(AST.CompositeLit);
+       lit.pos = P.pos;
+       lit.typ = typ;
+       lit.vals = AST.NewList();
+       
        P.Expect(Scanner.LBRACE);
        // TODO: should allow trailing ','
        if P.tok != Scanner.RBRACE {
-               P.ParseExpression();
+               x := P.ParseExpression();
                if P.tok == Scanner.COMMA {
                        P.Next();
+                       lit.vals.Add(x);
                        if P.tok != Scanner.RBRACE {
-                               P.ParseExpressionList();
+                               P.ParseExpressionList(lit.vals);
                        }
                } else if P.tok == Scanner.COLON {
+                       p := new(AST.Pair);
+                       p.pos = P.pos;
+                       p.x = x;
                        P.Next();
-                       P.ParseExpression();
+                       p.y = P.ParseExpression();
+                       lit.vals.Add(p);
                        if P.tok == Scanner.COMMA {
                                P.Next();
                                if P.tok != Scanner.RBRACE {
-                                       P.ParseExpressionPairList();
+                                       P.ParseExpressionPairList(lit.vals);
                                }
                        }
+               } else {
+                       lit.vals.Add(x);
                }
        }
        P.Expect(Scanner.RBRACE);
 
        P.Ecart();
-       return nil;
+       return lit;
 }
 
 
@@ -645,15 +664,15 @@ func (P *Parser) ParseOperand() AST.Expr {
                
        case Scanner.HASH:
                P.Next();
-               P.ParseType();
-               P.ParseCompositeLit();
+               typ := P.ParseType();
+               P.ParseCompositeLit(typ);
                op = AST.NIL;
 
        default:
                if P.tok != Scanner.IDENT {
                        typ, ok := P.TryType();
                        if ok {
-                               op = P.ParseCompositeLit();
+                               op = P.ParseCompositeLit(typ);
                                break;
                        }
                }
@@ -712,11 +731,14 @@ func (P *Parser) ParseIndexOrSlice(x AST.Expr) AST.Expr {
 }
 
 
-func (P *Parser) ParseCall(x AST.Expr) AST.Expr {
+func (P *Parser) ParseCall(x AST.Expr) *AST.Call {
        P.Trace("Call");
 
-       pos := P.pos;
-       var args *AST.List = nil;
+       call := new(AST.Call);
+       call.pos = P.pos;
+       call.fun = x;
+       call.args = nil;
+       
        P.Expect(Scanner.LPAREN);
        if P.tok != Scanner.RPAREN {
                // first arguments could be a type if the call is to "new"
@@ -727,24 +749,24 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr {
                if P.tok != Scanner.IDENT && P.tok != Scanner.LPAREN {
                        typ, ok := P.TryType();
                        if ok {
+                               call.args = AST.NewList();
+                               call.args.Add(typ);
                                if P.tok == Scanner.COMMA {
                                        P.Next();
                                        if P.tok != Scanner.RPAREN {
-                                               args = P.ParseExpressionList();
+                                               P.ParseExpressionList(call.args);
                                        }
                                }
                        } else {
-                               args = P.ParseExpressionList();
+                               call.args = P.ParseNewExpressionList();
                        }
                } else {
-                       args = P.ParseExpressionList();
+                       call.args = P.ParseNewExpressionList();
                }
        }
        P.Expect(Scanner.RPAREN);
        
        P.Ecart();
-       call := new(AST.Call);
-       call.pos, call.fun, call.args = pos, x, args;
        return call;
 }
 
@@ -837,7 +859,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
        P.Trace("SimpleStat");
        
        var stat AST.Stat = AST.NIL;
-       x := P.ParseExpressionList();
+       x := P.ParseNewExpressionList();
        
        switch P.tok {
        case Scanner.COLON:
@@ -860,7 +882,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
                Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
                pos, tok := P.pos, P.tok;
                P.Next();
-               y := P.ParseExpressionList();
+               y := P.ParseNewExpressionList();
                a := new(AST.Assignment);
                a.pos, a.tok, a.lhs, a.rhs = pos, tok, x, y;
                stat = a;
@@ -915,7 +937,7 @@ func (P *Parser) ParseReturnStat() *AST.ReturnStat {
        
        P.Expect(Scanner.RETURN);
        if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
-               stat.res = P.ParseExpressionList();
+               stat.res = P.ParseNewExpressionList();
        }
        
        P.Ecart();
@@ -1020,7 +1042,7 @@ func (P *Parser) ParseCase() *AST.CaseClause {
        
        if P.tok == Scanner.CASE {
                P.Next();
-               clause.exprs = P.ParseExpressionList();
+               clause.exprs = P.ParseNewExpressionList();
        } else {
                P.Expect(Scanner.DEFAULT);
        }
@@ -1218,6 +1240,7 @@ func (P *Parser) ParseConstSpec(exported bool) *AST.ConstDecl {
        decl.ident = P.ParseIdent();
        var ok bool;
        decl.typ, ok = P.TryType();
+       decl.val = AST.NIL;
        
        if P.tok == Scanner.ASSIGN {
                P.Next();
@@ -1248,12 +1271,13 @@ func (P *Parser) ParseVarSpec(exported bool) *AST.VarDecl {
        decl.idents = P.ParseIdentList();
        if P.tok == Scanner.ASSIGN {
                P.Next();
-               decl.vals = P.ParseExpressionList();
+               decl.typ = AST.NIL;
+               decl.vals = P.ParseNewExpressionList();
        } else {
                decl.typ = P.ParseVarType();
                if P.tok == Scanner.ASSIGN {
                        P.Next();
-                       decl.vals = P.ParseExpressionList();
+                       decl.vals = P.ParseNewExpressionList();
                }
        }
        
index 7ab363da5b5b2e7b045b3d878008cc276aae5884..52572cedd9860fe3c3b9e4c6981648cf51f5187d 100644 (file)
@@ -107,7 +107,11 @@ func (P *Printer) DoMapType(x *AST.MapType) {
 
 
 func (P *Printer) DoChannelType(x *AST.ChannelType) {
-       P.String("chan ");
+       switch x.mode {
+       case AST.FULL: P.String("chan ");
+       case AST.RECV: P.String("<-chan ");
+       case AST.SEND: P.String("chan <- ");
+       }
        P.Print(x.elt);
 }
 
@@ -226,8 +230,8 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) {
                        if i > 0 {
                                P.NewLine(0);
                        }
-                       //print("*** i = ", i, "\n");
                        P.Print(x.decls.at(i));
+                       P.String(";");
                }
                P.NewLine(-1);
                P.String(")");
@@ -300,6 +304,22 @@ func (P *Printer) DoSelector(x *AST.Selector) {
 }
 
 
+func (P *Printer) DoCompositeLit(x *AST.CompositeLit) {
+       P.Print(x.typ);
+       P.String("{");
+       P.PrintList(x.vals);
+       P.String("}");
+}
+
+
+func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
+       P.String("func ");
+       P.Print(x.typ);
+       P.String(" ");
+       P.Print(x.body);
+}
+
+
 // ----------------------------------------------------------------------------
 // Statements
 
@@ -320,8 +340,10 @@ func (P *Printer) DoBlock(x *AST.Block) {
 
 
 func (P *Printer) DoLabel(x *AST.Label) {
+       P.NewLine(-1);
        P.Print(x.ident);
        P.String(":");
+       P.indent++;
 }
 
 
index 60dfa1c6219fdfd37ce3b1810d7cdd34be7d508d..02f5e56fe985fa37869cfd0342eef1420ceba68a 100644 (file)
@@ -794,14 +794,14 @@ export type Token struct {
 
 
 func (S *Scanner) TokenStream() *<-chan *Token {
-       ch := new(chan *Token, 100);
+       ch := new(chan *Token, 100);
        go func(S *Scanner, ch *chan <- *Token) {
                for {
                        t := new(Token);
                        t.tok, t.pos, t.val = S.Scan();
                        ch <- t;
                        if t.tok == EOF {
-                          break;
+                               break;
                        }
                }
        }(S, ch);