go/*: remove ast.TypeParamList in favor of ast.FieldList

This commit is contained in:
Robert Griesemer 2019-05-15 14:29:37 -07:00
parent e3b54c8023
commit 66b509a402
5 changed files with 66 additions and 79 deletions

View File

@ -191,8 +191,8 @@ func isDirective(c string) bool {
//
type Field struct {
Doc *CommentGroup // associated documentation; or nil
Names []*Ident // field/method/parameter names; or nil
Type Expr // field/method/parameter type
Names []*Ident // field/method/(type) parameter names; or nil
Type Expr // field/method/parameter type or contract
Tag *BasicLit // field tag; or nil
Comment *CommentGroup // line comments; or nil
}
@ -242,7 +242,7 @@ func (f *FieldList) End() token.Pos {
return token.NoPos
}
// NumFields returns the number of parameters or struct fields represented by a FieldList.
// NumFields returns the number of (type) parameters or struct fields represented by a FieldList.
func (f *FieldList) NumFields() int {
n := 0
if f != nil {
@ -257,17 +257,6 @@ func (f *FieldList) NumFields() int {
return n
}
// A TypeParamList represents a list of type parameters with contract, enclosed by parentheses.
type TypeParamList struct {
Lparen token.Pos // position of "("
Names []*Ident // type parameter names; or nil
Contract Expr // contract; or nil
Rparen token.Pos // position of ")"
}
func (t *TypeParamList) Pos() token.Pos { return t.Lparen }
func (t *TypeParamList) End() token.Pos { return t.Rparen }
// An expression is represented by a tree consisting of one
// or more of the following concrete expression nodes.
//
@ -465,18 +454,18 @@ type (
// A ContractType node represents a contract.
ContractType struct {
Contract token.Pos // position of "contract" pseudo keyword
Params *TypeParamList // list of type parameters; non-nil
Lbrace token.Pos // position of "{"
Constraints []*Constraint // list of constraints
Rbrace token.Pos // position of "}"
Contract token.Pos // position of "contract" pseudo keyword
TParams []*Ident // list of type parameters; or nil
Lbrace token.Pos // position of "{"
Constraints []*Constraint // list of constraints
Rbrace token.Pos // position of "}"
}
)
type Constraint struct {
Param *Ident // constrained type parameter; or nil (for embedded constraints)
MName *Ident // method name, "==" or "!="; or nil
Type Expr // embedded constraint (CallExpr), constraint type, BasicLit (0, 0.0, 0i), method type (*FuncType); or nil
MName *Ident // method name; or nil
Type Expr // embedded constraint (CallExpr), constraint type, method type (*FuncType); or nil
}
// Pos and End implementations for expression/type nodes.
@ -914,12 +903,12 @@ type (
// A TypeSpec node represents a type declaration (TypeSpec production).
TypeSpec struct {
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
TPar *TypeParamList // type parameters; or nil
Assign token.Pos // position of '=', if any
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
Comment *CommentGroup // line comments; or nil
Doc *CommentGroup // associated documentation; or nil
Name *Ident // type name
TParams *FieldList // type parameters; or nil
Assign token.Pos // position of '=', if any
Type Expr // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
Comment *CommentGroup // line comments; or nil
}
)
@ -992,12 +981,12 @@ type (
// A FuncDecl node represents a function declaration.
FuncDecl struct {
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
TPar *TypeParamList // type parameters; or nil
Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil for external (non-Go) function
Doc *CommentGroup // associated documentation; or nil
Recv *FieldList // receiver (methods); or nil (functions)
Name *Ident // function/method name
TParams *FieldList // type parameters; or nil
Type *FuncType // function signature: parameters, results, and position of "func" keyword
Body *BlockStmt // function body; or nil for external (non-Go) function
}
)

View File

@ -26,6 +26,9 @@ import (
"unicode"
)
// Enable parsing of type parameters in [] rather than () parentheses.
// This code was an experiment which we eventually decided against due
// to various unpleasant ambiguities. Leave around for now, just in case.
const useBrackets = false
// The parser structure holds the parser's internal state.
@ -1081,7 +1084,7 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
return
}
func (p *parser) parseTypeParams(scope *ast.Scope) *ast.TypeParamList {
func (p *parser) parseTypeParams(scope *ast.Scope) *ast.FieldList {
if p.trace {
defer un(trace(p, "TypeParams"))
}
@ -1095,26 +1098,24 @@ func (p *parser) parseTypeParams(scope *ast.Scope) *ast.TypeParamList {
p.expect(token.TYPE)
}
var names []*ast.Ident
var contract ast.Expr
f := new(ast.Field)
if p.tok != token.RBRACK && p.tok != token.RPAREN {
names = p.parseIdentList()
f.Names = p.parseIdentList()
}
if p.tok == token.IDENT {
// contract
contract = p.parseTypeName(nil)
f.Type = p.parseTypeName(nil)
}
p.declare(f, nil, scope, ast.Typ, f.Names...)
if lbrack.IsValid() {
rbrack = p.expect(token.RBRACK)
}
tparams := &ast.TypeParamList{Lparen: lbrack, Names: names, Contract: contract, Rparen: rbrack}
p.declare(tparams, nil, scope, ast.Typ, names...)
return tparams
return &ast.FieldList{Opening: lbrack, List: []*ast.Field{f}, Closing: rbrack}
}
func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool) (tparams *ast.TypeParamList, params *ast.FieldList) {
func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool) (tparams, params *ast.FieldList) {
if p.trace {
defer un(trace(p, "Parameters"))
}
@ -1132,9 +1133,9 @@ func (p *parser) parseParameters(scope *ast.Scope, typeParamsOk, ellipsisOk bool
tparams = p.parseTypeParams(scope)
rparen := p.expect(token.RPAREN)
// fix tparams
tparams.Lparen = lparen
tparams.Rparen = rparen
// fix parentheses positions
tparams.Opening = lparen
tparams.Closing = rparen
lparen = p.expect(token.LPAREN)
}
@ -1283,19 +1284,18 @@ func (p *parser) parseContractType() *ast.ContractType {
defer un(trace(p, "ContractType"))
}
var names []*ast.Ident
lparen := p.expect(token.LPAREN)
var params []*ast.Ident
p.expect(token.LPAREN)
scope := ast.NewScope(nil) // contract scope
for p.tok != token.RPAREN && p.tok != token.EOF {
names = append(names, p.parseIdent())
params = append(params, p.parseIdent())
if !p.atComma("contract parameter list", token.RPAREN) {
break
}
p.next()
}
p.declare(nil, nil, scope, ast.Typ, names...)
rparen := p.expect(token.RPAREN)
params := &ast.TypeParamList{Lparen: lparen, Names: names, Rparen: rparen}
p.declare(nil, nil, scope, ast.Typ, params...)
p.expect(token.RPAREN)
var constraints []*ast.Constraint
lbrace := p.expect(token.LBRACE)
@ -1305,7 +1305,7 @@ func (p *parser) parseContractType() *ast.ContractType {
}
rbrace := p.expect(token.RBRACE)
return &ast.ContractType{Params: params, Lbrace: lbrace, Constraints: constraints, Rbrace: rbrace}
return &ast.ContractType{TParams: params, Lbrace: lbrace, Constraints: constraints, Rbrace: rbrace}
}
// Constraint = TypeParam Type | TypeParam MethodName Signature | ContractTypeName "(" [ TypeList [ "," ] ] ")" .
@ -2755,9 +2755,9 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.
p.next()
p.openScope()
tparams := p.parseTypeParams(p.topScope)
tparams.Lparen = lbrack
tparams.Rparen = p.expect(token.RBRACK)
spec.TPar = tparams
tparams.Opening = lbrack
tparams.Closing = p.expect(token.RBRACK)
spec.TParams = tparams
if p.tok == token.ASSIGN {
// type alias
spec.Assign = p.pos
@ -2781,9 +2781,9 @@ func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.
p.next()
p.openScope()
tparams := p.parseTypeParams(p.topScope)
tparams.Lparen = lparen
tparams.Rparen = p.expect(token.RPAREN)
spec.TPar = tparams
tparams.Opening = lparen
tparams.Closing = p.expect(token.RPAREN)
spec.TParams = tparams
if p.tok == token.ASSIGN {
// type alias
spec.Assign = p.pos
@ -2898,10 +2898,10 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
}
decl := &ast.FuncDecl{
Doc: doc,
Recv: recv,
Name: ident,
TPar: tparams,
Doc: doc,
Recv: recv,
Name: ident,
TParams: tparams,
Type: &ast.FuncType{
Func: pos,
Params: params,

View File

@ -1773,14 +1773,8 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
p.print(blank)
}
p.expr(d.Name)
// TODO(gri) decide if we should print empty type parameter lists "(type)" at all
if tparams := d.TPar; tparams != nil {
p.print(tparams.Lparen, token.LPAREN, token.TYPE)
if len(tparams.Names) > 0 {
p.print(blank)
p.identList(tparams.Names, true)
}
p.print(tparams.Rparen, token.RPAREN)
if d.TParams.NumFields() != 0 {
p.parameters(d.TParams)
}
p.signature(d.Type.Params, d.Type.Results)
p.funcBody(p.distanceFrom(d.Pos(), startCol), vtab, d.Body)

View File

@ -649,7 +649,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
sig := new(Signature)
obj.typ = sig // guard against cycles
fdecl := decl.fdecl
check.funcType(sig, fdecl.Recv, fdecl.TPar, fdecl.Type)
check.funcType(sig, fdecl.Recv, fdecl.TParams, fdecl.Type)
if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
// ok to continue

View File

@ -143,10 +143,10 @@ func (check *Checker) definedType(e ast.Expr, def *Named) (T Type) {
}
// funcType type-checks a function or method type.
func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, tpar *ast.TypeParamList, ftyp *ast.FuncType) {
func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, tpar *ast.FieldList, ftyp *ast.FuncType) {
// type parameters are in a scope enclosing the function scope
// TODO(gri) should we always have this extra scope?
if tpar != nil && len(tpar.Names) > 0 {
if tpar.NumFields() != 0 {
check.scope = NewScope(check.scope, token.NoPos, token.NoPos, "function type parameters") // TODO(gri) replace with check.openScope call
defer check.closeScope()
}
@ -406,16 +406,20 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
return -1
}
func (check *Checker) collectTypeParams(scope *Scope, list *ast.TypeParamList) (tparams []*TypeName) {
func (check *Checker) collectTypeParams(scope *Scope, list *ast.FieldList) (tparams []*TypeName) {
if list == nil {
return
}
for i, name := range list.Names {
tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
NewTypeParam(tpar, i) // assigns type to tpar as a side-effect
check.declare(scope, name, tpar, scope.pos)
tparams = append(tparams, tpar)
index := 0
for _, f := range list.List {
for _, name := range f.Names {
tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil)
NewTypeParam(tpar, index) // assigns type to tpar as a side-effect
check.declare(scope, name, tpar, scope.pos)
tparams = append(tparams, tpar)
index++
}
}
return