]> Cypherpunks repositories - gostls13.git/commitdiff
support for ...T parameters (go/* packages)
authorRobert Griesemer <gri@golang.org>
Thu, 28 Jan 2010 21:24:48 +0000 (13:24 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 28 Jan 2010 21:24:48 +0000 (13:24 -0800)
R=rsc
CC=golang-dev
https://golang.org/cl/194126

src/pkg/exp/parser/parser.go
src/pkg/go/ast/ast.go
src/pkg/go/parser/interface.go
src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go
src/pkg/go/printer/nodes.go
src/pkg/go/printer/testdata/declarations.golden
src/pkg/go/printer/testdata/declarations.input

index 199ce172db9e7871f2f8ef6a83bf3a4491ad320f..8336bdb08fa87165b5e9900de8d5cc384cd6ba28 100644 (file)
@@ -379,7 +379,7 @@ func (p *parser) parseArrayType(ellipsisOk bool) ast.Expr {
        lbrack := p.expect(token.LBRACK)
        var len ast.Expr
        if ellipsisOk && p.tok == token.ELLIPSIS {
-               len = &ast.Ellipsis{p.pos}
+               len = &ast.Ellipsis{p.pos, nil}
                p.next()
        } else if p.tok != token.RBRACK {
                len = p.parseExpr()
@@ -499,11 +499,11 @@ func (p *parser) tryParameterType(ellipsisOk bool) ast.Expr {
        if ellipsisOk && p.tok == token.ELLIPSIS {
                pos := p.pos
                p.next()
+               typ := p.tryType()
                if p.tok != token.RPAREN {
-                       // "..." always must be at the very end of a parameter list
-                       p.Error(pos, "expected type, found '...'")
+                       p.Error(pos, "can use '...' for last parameter only")
                }
-               return &ast.Ellipsis{pos}
+               return &ast.Ellipsis{pos, typ}
        }
        return p.tryType()
 }
index d29dee63e3d8a4d25fade5284349371914b4d6b4..ed87039a7e59400584d6f618895e60372ceb4c61 100644 (file)
@@ -125,7 +125,8 @@ type (
        // parameter list or the "..." length in an array type.
        //
        Ellipsis struct {
-               token.Position // position of "..."
+               token.Position      // position of "..."
+               Elt            Expr // ellipsis element type (parameter lists only)
        }
 
        // A BasicLit node represents a literal of basic type.
index c940e4702936e8cec9db84fc678b461cac52631f..1bd63dd49d67c42c25ca233961e40eebc53a28ad 100644 (file)
@@ -164,7 +164,7 @@ func ParseDir(path string, filter func(*os.Dir) bool, mode uint) (map[string]*as
                return nil, err
        }
 
-       scope := ast.NewScope(nil)
+       var scope *ast.Scope = nil // for now tracking of declarations is disabled
        pkgs := make(map[string]*ast.Package)
        for i := 0; i < len(list); i++ {
                entry := &list[i]
index 76e9783637faca976e2a246afceb587fb2b5edbb..140b954f9bc827562bac77440501fa9fbe2b39c9 100644 (file)
@@ -81,10 +81,7 @@ func (p *parser) init(filename string, src []byte, scope *ast.Scope, mode uint)
        p.mode = mode
        p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
        if scope != nil {
-               // Disabled for now.  Causes error with "godoc http":
-               //    parser.parseDir: src/pkg/http/server.go:159:16: 'Write' declared already at src/pkg/http/request.go:140:21 (and 4 more errors)
-
-               // p.checkDecl = true
+               p.checkDecl = true
        } else {
                scope = ast.NewScope(nil) // provide a dummy scope
        }
@@ -480,7 +477,7 @@ func (p *parser) parseArrayType(ellipsisOk bool) ast.Expr {
        lbrack := p.expect(token.LBRACK)
        var len ast.Expr
        if ellipsisOk && p.tok == token.ELLIPSIS {
-               len = &ast.Ellipsis{p.pos}
+               len = &ast.Ellipsis{p.pos, nil}
                p.next()
        } else if p.tok != token.RBRACK {
                len = p.parseExpr()
@@ -600,11 +597,11 @@ func (p *parser) tryParameterType(ellipsisOk bool) ast.Expr {
        if ellipsisOk && p.tok == token.ELLIPSIS {
                pos := p.pos
                p.next()
+               typ := p.tryType()
                if p.tok != token.RPAREN {
-                       // "..." always must be at the very end of a parameter list
-                       p.Error(pos, "expected type, found '...'")
+                       p.Error(pos, "can use '...' for last parameter only")
                }
-               return &ast.Ellipsis{pos}
+               return &ast.Ellipsis{pos, typ}
        }
        return p.tryType()
 }
@@ -1824,6 +1821,9 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
                p.next()
        } else if p.tok == token.IDENT {
                ident = p.parseIdent(ast.Pkg)
+               // TODO(gri) Make sure the ident is not already declared in the
+               //           package scope. Also, cannot add the same name to
+               //           the package scope later.
                p.declIdent(p.fileScope, ident)
        }
 
index 0d43d2ca701e4081beed2caaf4b679bc2bd31fc5..9db695bd4e06cef95c20a952a9514f9263e23556 100644 (file)
@@ -36,6 +36,8 @@ var validPrograms = []interface{}{
        `package main; func main() { _ = (<-chan int)(x) }` + "\n",
        `package main; func main() { _ = (<-chan <-chan int)(x) }` + "\n",
        `package main; func f(func() func() func())` + "\n",
+       `package main; func f(...)` + "\n",
+       `package main; func f(float, ...int)` + "\n",
 }
 
 
index 29dc1737b6222710102cbfaf660e6eed8fbe5bd5..65b19e9f5d4c8ecfb31fdee68953e33948e2bebb 100644 (file)
@@ -759,6 +759,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
 
        case *ast.Ellipsis:
                p.print(token.ELLIPSIS)
+               if x.Elt != nil {
+                       p.expr(x.Elt, multiLine)
+               }
 
        case *ast.ArrayType:
                p.print(token.LBRACK)
index 17d8bfaff02ec8e07e55ee65fc9646b6738e74a5..d21316969f0e17a9d71961b00d1197ced5ed10ff 100644 (file)
@@ -547,3 +547,27 @@ func _() { // opening "{" must move up
 
        var _ = x       // comment
 }
+
+
+// ellipsis parameters
+func _(...)
+func _(...int)
+func _(...*int)
+func _(...[]int)
+func _(...struct{})
+func _(bool, ...interface{})
+func _(bool, ...func())
+func _(bool, ...func(...))
+func _(bool, ...map[string]int)
+func _(bool, ...chan int)
+
+func _(b bool, x ...)
+func _(b bool, x ...int)
+func _(b bool, x ...*int)
+func _(b bool, x ...[]int)
+func _(b bool, x ...struct{})
+func _(x ...interface{})
+func _(x ...func())
+func _(x ...func(...))
+func _(x ...map[string]int)
+func _(x ...chan int)
index c54a1c0467a233b4841b08f1f6410dbce03a73b4..948755a9a67d0ed1b82de9aa845b35a796b55751 100644 (file)
@@ -551,3 +551,27 @@ func _()  // opening "{" must move up
        var _  // comment
        = x;
 }
+
+
+// ellipsis parameters
+func _(...)
+func _(...int)
+func _(...*int)
+func _(...[]int)
+func _(...struct{})
+func _(bool, ...interface{})
+func _(bool, ...func())
+func _(bool, ...func(...))
+func _(bool, ...map[string]int)
+func _(bool, ...chan int)
+
+func _(b bool, x ...)
+func _(b bool, x ...int)
+func _(b bool, x ...*int)
+func _(b bool, x ...[]int)
+func _(b bool, x ...struct{})
+func _(x ...interface{})
+func _(x ...func())
+func _(x ...func(...))
+func _(x ...map[string]int)
+func _(x ...chan int)