1
0
mirror of https://github.com/golang/go synced 2024-11-18 17:54:57 -07:00

exp/types: process ast.Fun in checkObj; fix variadic function building

Fixed creation of Func's, taking IsVariadic from parameter list rather
than results.

Updated checkObj to process ast.Fun objects.

R=gri
CC=golang-dev
https://golang.org/cl/6402046
This commit is contained in:
Andrew Wilkins 2012-07-26 11:47:46 -07:00 committed by Robert Griesemer
parent fda29b6a42
commit d399b681a4
2 changed files with 84 additions and 3 deletions

View File

@ -158,8 +158,8 @@ func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
return &Struct{Fields: fields, Tags: tags}
case *ast.FuncType:
params, _, _ := c.collectFields(token.FUNC, t.Params, true)
results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
params, _, isVariadic := c.collectFields(token.FUNC, t.Params, true)
results, _, _ := c.collectFields(token.FUNC, t.Results, true)
return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
case *ast.InterfaceType:
@ -200,7 +200,21 @@ func (c *checker) checkObj(obj *ast.Object, ref bool) {
// TODO(gri) complete this
case ast.Fun:
// TODO(gri) complete this
fdecl := obj.Decl.(*ast.FuncDecl)
ftyp := c.makeType(fdecl.Type, ref).(*Func)
obj.Type = ftyp
if fdecl.Recv != nil {
recvField := fdecl.Recv.List[0]
if len(recvField.Names) > 0 {
ftyp.Recv = recvField.Names[0].Obj
} else {
ftyp.Recv = ast.NewObj(ast.Var, "_")
ftyp.Recv.Decl = recvField
}
c.checkObj(ftyp.Recv, ref)
// TODO(axw) add method to a list in the receiver type.
}
// TODO(axw) check function body, if non-nil.
default:
panic("unreachable")

View File

@ -0,0 +1,67 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains tests verifying the types associated with an AST after
// type checking.
package types
import (
"go/ast"
"go/parser"
"testing"
)
func checkSource(t *testing.T, src string) *ast.Package {
const filename = "<src>"
file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
if err != nil {
t.Fatal(err)
}
files := map[string]*ast.File{filename: file}
pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
if err != nil {
t.Fatal(err)
}
_, err = Check(fset, pkg)
if err != nil {
t.Fatal(err)
}
return pkg
}
func TestVariadicFunctions(t *testing.T) {
pkg := checkSource(t, `
package p
func f1(arg ...int)
func f2(arg1 string, arg2 ...int)
func f3()
func f4(arg int)
`)
f1 := pkg.Scope.Lookup("f1")
f2 := pkg.Scope.Lookup("f2")
for _, f := range [...](*ast.Object){f1, f2} {
ftype := f.Type.(*Func)
if !ftype.IsVariadic {
t.Errorf("expected %s to be variadic", f.Name)
}
param := ftype.Params[len(ftype.Params)-1]
if param.Type != Int {
t.Errorf("expected last parameter of %s to have type int, found %T", f.Name, param.Type)
}
}
f3 := pkg.Scope.Lookup("f3")
f4 := pkg.Scope.Lookup("f4")
for _, f := range [...](*ast.Object){f3, f4} {
ftype := f.Type.(*Func)
if ftype.IsVariadic {
t.Fatalf("expected %s to not be variadic", f.Name)
}
}
// TODO(axw) replace this function's innards with table driven tests.
// We should have a helper function that prints a type signature. Then
// we can have a table of function declarations and expected type
// signatures which can be easily expanded.
}