go.tools/go/types: rename Context -> Config (more apt name)

Also: Various minor cleanups.

R=adonovan, r
CC=golang-dev
https://golang.org/cl/11445044
This commit is contained in:
Robert Griesemer 2013-07-18 17:07:44 -07:00
parent 9460d02473
commit 40a278e5ee
18 changed files with 88 additions and 87 deletions

View File

@ -19,9 +19,9 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
pkg.spans = make(map[types.Object]Span) pkg.spans = make(map[types.Object]Span)
pkg.types = make(map[ast.Expr]types.Type) pkg.types = make(map[ast.Expr]types.Type)
pkg.values = make(map[ast.Expr]exact.Value) pkg.values = make(map[ast.Expr]exact.Value)
// By providing the Context with our own error function, it will continue // By providing a Config with our own error function, it will continue
// past the first error. There is no need for that function to do anything. // past the first error. There is no need for that function to do anything.
context := types.Context{ config := types.Config{
Error: func(error) {}, Error: func(error) {},
} }
info := &types.Info{ info := &types.Info{
@ -29,7 +29,7 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
Values: pkg.values, Values: pkg.values,
Objects: pkg.idents, Objects: pkg.idents,
} }
_, err := context.Check(pkg.path, fs, astFiles, info) _, err := config.Check(pkg.path, fs, astFiles, info)
// update spans // update spans
for id, obj := range pkg.idents { for id, obj := range pkg.idents {
pkg.growSpan(id, obj) pkg.growSpan(id, obj)

View File

@ -4,7 +4,7 @@
// Package types declares the data types and implements // Package types declares the data types and implements
// the algorithms for type-checking of Go packages. // the algorithms for type-checking of Go packages.
// Use Check and Context.Check to invoke the type-checker. // Use Check and Config.Check to invoke the type-checker.
// //
// Type-checking consists of several interdependent phases: // Type-checking consists of several interdependent phases:
// //
@ -34,19 +34,19 @@ import (
// list of *ast.Files and corresponding file set, and the import path // list of *ast.Files and corresponding file set, and the import path
// the package is identified with. The path must not be empty or dot ("."). // the package is identified with. The path must not be empty or dot (".").
// //
// For more control over type-checking and results, use Context.Check. // For more control over type-checking and results, use Config.Check.
func Check(path string, fset *token.FileSet, files []*ast.File) (*Package, error) { func Check(path string, fset *token.FileSet, files []*ast.File) (*Package, error) {
var ctxt Context var conf Config
pkg, err := ctxt.check(path, fset, files, nil) pkg, err := conf.check(path, fset, files, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return pkg, nil return pkg, nil
} }
// A Context specifies the supporting context for type checking. // A Config specifies the configuration for type checking.
// The zero value for a Context is a ready-to-use default context. // The zero value for Config is a ready-to-use default configuration.
type Context struct { type Config struct {
// If Error != nil, it is called with each error found // If Error != nil, it is called with each error found
// during type checking. The error strings of errors with // during type checking. The error strings of errors with
// detailed position information are formatted as follows: // detailed position information are formatted as follows:
@ -103,7 +103,7 @@ type Info struct {
// are not recorded. // are not recorded.
Objects map[*ast.Ident]Object Objects map[*ast.Ident]Object
// If Implicits != nil, it records the object for each node the implicitly // If Implicits != nil, it records the object for each node that implicitly
// declares objects. The following node and object types may appear: // declares objects. The following node and object types may appear:
// //
// node obj // node obj
@ -118,15 +118,15 @@ type Info struct {
// error if any, and if info != nil, additional type information. The package is // error if any, and if info != nil, additional type information. The package is
// specified by a list of *ast.Files and corresponding file set, and the import // specified by a list of *ast.Files and corresponding file set, and the import
// path the package is identified with. The path must not be empty or dot ("."). // path the package is identified with. The path must not be empty or dot (".").
func (ctxt *Context) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) { func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
return ctxt.check(path, fset, files, info) return conf.check(path, fset, files, info)
} }
// IsAssignableTo reports whether a value of type V // IsAssignableTo reports whether a value of type V
// is assignable to a variable of type T. // is assignable to a variable of type T.
func IsAssignableTo(V, T Type) bool { func IsAssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V} x := operand{mode: value, typ: V}
return x.isAssignableTo(nil, T) // context not needed for non-constant x return x.isAssignableTo(nil, T) // config not needed for non-constant x
} }
// BUG(gri): Conversions of constants only change the type, not the value (e.g., int(1.1) is wrong). // BUG(gri): Conversions of constants only change the type, not the value (e.g., int(1.1) is wrong).

View File

@ -32,7 +32,7 @@ func (check *checker) assignment(x *operand, to Type) bool {
check.convertUntyped(x, to) check.convertUntyped(x, to)
return x.mode != invalid && x.isAssignableTo(check.ctxt, to) return x.mode != invalid && x.isAssignableTo(check.conf, to)
} }
func (check *checker) initConst(lhs *Const, x *operand) { func (check *checker) initConst(lhs *Const, x *operand) {

View File

@ -236,7 +236,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
if x.mode == invalid { if x.mode == invalid {
goto Error goto Error
} }
if !x.isAssignableTo(check.ctxt, m.key) { if !x.isAssignableTo(check.conf, m.key) {
check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key) check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
goto Error goto Error
} }
@ -327,7 +327,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
case _Alignof: case _Alignof:
x.mode = constant x.mode = constant
x.val = exact.MakeInt64(check.ctxt.alignof(x.typ)) x.val = exact.MakeInt64(check.conf.alignof(x.typ))
x.typ = Typ[Uintptr] x.typ = Typ[Uintptr]
case _Offsetof: case _Offsetof:
@ -355,14 +355,14 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base) check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base)
goto Error goto Error
} }
offs := check.ctxt.offsetof(base, index) offs := check.conf.offsetof(base, index)
x.mode = constant x.mode = constant
x.val = exact.MakeInt64(offs) x.val = exact.MakeInt64(offs)
x.typ = Typ[Uintptr] x.typ = Typ[Uintptr]
case _Sizeof: case _Sizeof:
x.mode = constant x.mode = constant
x.val = exact.MakeInt64(check.ctxt.sizeof(x.typ)) x.val = exact.MakeInt64(check.conf.sizeof(x.typ))
x.typ = Typ[Uintptr] x.typ = Typ[Uintptr]
case _Assert: case _Assert:

View File

@ -36,7 +36,7 @@ type exprInfo struct {
// A checker is an instance of the type checker. // A checker is an instance of the type checker.
type checker struct { type checker struct {
ctxt *Context conf *Config
fset *token.FileSet fset *token.FileSet
Info Info
@ -59,9 +59,9 @@ type checker struct {
indent int // indentation for tracing indent int // indentation for tracing
} }
func newChecker(ctxt *Context, fset *token.FileSet, pkg *Package) *checker { func newChecker(conf *Config, fset *token.FileSet, pkg *Package) *checker {
return &checker{ return &checker{
ctxt: ctxt, conf: conf,
fset: fset, fset: fset,
pkg: pkg, pkg: pkg,
methods: make(map[*TypeName]*Scope), methods: make(map[*TypeName]*Scope),
@ -133,14 +133,14 @@ func (check *checker) handleBailout(err *error) {
} }
} }
func (ctxt *Context) check(pkgPath string, fset *token.FileSet, files []*ast.File, info *Info) (pkg *Package, err error) { func (conf *Config) check(pkgPath string, fset *token.FileSet, files []*ast.File, info *Info) (pkg *Package, err error) {
pkg = &Package{ pkg = &Package{
path: pkgPath, path: pkgPath,
scope: NewScope(Universe), scope: NewScope(Universe),
imports: make(map[string]*Package), imports: make(map[string]*Package),
} }
check := newChecker(ctxt, fset, pkg) check := newChecker(conf, fset, pkg)
defer check.handleBailout(&err) defer check.handleBailout(&err)
// we need a reasonable path to continue // we need a reasonable path to continue
@ -149,11 +149,6 @@ func (ctxt *Context) check(pkgPath string, fset *token.FileSet, files []*ast.Fil
return return
} }
// install optional info
if info != nil {
check.Info = *info
}
// determine package name and files // determine package name and files
i := 0 i := 0
for _, file := range files { for _, file := range files {
@ -170,6 +165,11 @@ func (ctxt *Context) check(pkgPath string, fset *token.FileSet, files []*ast.Fil
} }
} }
// install optional info
if info != nil {
check.Info = *info
}
// TODO(gri) resolveFiles needs to be split up and renamed (cleanup) // TODO(gri) resolveFiles needs to be split up and renamed (cleanup)
check.resolveFiles(files[:i]) check.resolveFiles(files[:i])

View File

@ -203,8 +203,8 @@ func checkFiles(t *testing.T, testfiles []string) {
} }
// typecheck and collect typechecker errors // typecheck and collect typechecker errors
var ctxt Context var conf Config
ctxt.Error = func(err error) { conf.Error = func(err error) {
if *listErrors { if *listErrors {
t.Error(err) t.Error(err)
return return
@ -216,7 +216,7 @@ func checkFiles(t *testing.T, testfiles []string) {
errlist = append(errlist, err) errlist = append(errlist, err)
} }
} }
ctxt.Check(pkgName, fset, files, nil) conf.Check(pkgName, fset, files, nil)
if *listErrors { if *listErrors {
return return

View File

@ -58,7 +58,7 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type) {
// TODO(gri) verify the remaining conversions. // TODO(gri) verify the remaining conversions.
} else { } else {
// non-constant conversion // non-constant conversion
if !x.isConvertible(check.ctxt, typ) { if !x.isConvertible(check.conf, typ) {
goto ErrorMsg goto ErrorMsg
} }
x.mode = value x.mode = value
@ -91,9 +91,9 @@ Error:
x.expr = conv x.expr = conv
} }
func (x *operand) isConvertible(ctxt *Context, T Type) bool { func (x *operand) isConvertible(conf *Config, T Type) bool {
// "x is assignable to T" // "x is assignable to T"
if x.isAssignableTo(ctxt, T) { if x.isAssignableTo(conf, T) {
return true return true
} }

View File

@ -58,7 +58,7 @@ func (check *checker) err(err error) {
if check.firsterr == nil { if check.firsterr == nil {
check.firsterr = err check.firsterr = err
} }
f := check.ctxt.Error f := check.conf.Error
if f == nil { if f == nil {
panic(bailout{}) // report only first error panic(bailout{}) // report only first error
} }

View File

@ -86,8 +86,8 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
} }
// initialize checker // initialize checker
var ctxt Context var conf Config
check := newChecker(&ctxt, fset, pkg) check := newChecker(&conf, fset, pkg)
check.topScope = scope check.topScope = scope
defer check.handleBailout(&err) defer check.handleBailout(&err)
@ -95,7 +95,7 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
var x operand var x operand
check.exprOrType(&x, node) check.exprOrType(&x, node)
switch x.mode { switch x.mode {
case invalid, novalue, typexprn: case invalid, novalue:
fallthrough fallthrough
default: default:
unreachable() // or bailed out with error unreachable() // or bailed out with error

View File

@ -61,7 +61,8 @@ constant lhs must be representable as an integer.
When an expression gets its final type, either on the way out from rawExpr, When an expression gets its final type, either on the way out from rawExpr,
on the way down in updateExprType, or at the end of the type checker run, on the way down in updateExprType, or at the end of the type checker run,
if present the Context.Expr method is invoked to notify a go/types client. the type (and constant value, if any) is recorded via Info.Types and Values,
if present.
*/ */
type opPredicates map[token.Token]func(Type) bool type opPredicates map[token.Token]func(Type) bool
@ -124,7 +125,7 @@ func (check *checker) unary(x *operand, op token.Token) {
typ := x.typ.Underlying().(*Basic) typ := x.typ.Underlying().(*Basic)
size := -1 size := -1
if isUnsigned(typ) { if isUnsigned(typ) {
size = int(check.ctxt.sizeof(typ)) size = int(check.conf.sizeof(typ))
} }
x.val = exact.UnaryOp(op, x.val, size) x.val = exact.UnaryOp(op, x.val, size)
// Typed constants must be representable in // Typed constants must be representable in
@ -154,7 +155,7 @@ func isComparison(op token.Token) bool {
return false return false
} }
func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool { func isRepresentableConst(x exact.Value, conf *Config, as BasicKind) bool {
switch x.Kind() { switch x.Kind() {
case exact.Unknown: case exact.Unknown:
return true return true
@ -166,7 +167,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
if x, ok := exact.Int64Val(x); ok { if x, ok := exact.Int64Val(x); ok {
switch as { switch as {
case Int: case Int:
var s = uint(ctxt.sizeof(Typ[as])) * 8 var s = uint(conf.sizeof(Typ[as])) * 8
return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1 return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
case Int8: case Int8:
const s = 8 const s = 8
@ -180,7 +181,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
case Int64: case Int64:
return true return true
case Uint, Uintptr: case Uint, Uintptr:
if s := uint(ctxt.sizeof(Typ[as])) * 8; s < 64 { if s := uint(conf.sizeof(Typ[as])) * 8; s < 64 {
return 0 <= x && x <= int64(1)<<s-1 return 0 <= x && x <= int64(1)<<s-1
} }
return 0 <= x return 0 <= x
@ -211,7 +212,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
n := exact.BitLen(x) n := exact.BitLen(x)
switch as { switch as {
case Uint, Uintptr: case Uint, Uintptr:
var s = uint(ctxt.sizeof(Typ[as])) * 8 var s = uint(conf.sizeof(Typ[as])) * 8
return exact.Sign(x) >= 0 && n <= int(s) return exact.Sign(x) >= 0 && n <= int(s)
case Uint64: case Uint64:
return exact.Sign(x) >= 0 && n <= 64 return exact.Sign(x) >= 0 && n <= 64
@ -270,7 +271,7 @@ func (check *checker) isRepresentable(x *operand, typ *Basic) {
return return
} }
if !isRepresentableConst(x.val, check.ctxt, typ.kind) { if !isRepresentableConst(x.val, check.conf, typ.kind) {
var msg string var msg string
if isNumeric(x.typ) && isNumeric(typ) { if isNumeric(x.typ) && isNumeric(typ) {
msg = "%s overflows (or cannot be accurately represented as) %s" msg = "%s overflows (or cannot be accurately represented as) %s"
@ -287,7 +288,7 @@ func (check *checker) isRepresentable(x *operand, typ *Basic) {
// If typ is still an untyped and not the final type, updateExprType // If typ is still an untyped and not the final type, updateExprType
// only updates the recorded untyped type for x and possibly its // only updates the recorded untyped type for x and possibly its
// operands. Otherwise (i.e., typ is not an untyped type anymore, // operands. Otherwise (i.e., typ is not an untyped type anymore,
// or it is the final type for x), Context.Expr is invoked, if present. // or it is the final type for x), the type and value are recorded.
// Also, if x is a constant, it must be representable as a value of typ, // Also, if x is a constant, it must be representable as a value of typ,
// and if x is the (formerly untyped) lhs operand of a non-constant // and if x is the (formerly untyped) lhs operand of a non-constant
// shift, it must be an integer value. // shift, it must be an integer value.
@ -469,7 +470,7 @@ func (check *checker) comparison(x, y *operand, op token.Token) {
// TODO(gri) deal with interface vs non-interface comparison // TODO(gri) deal with interface vs non-interface comparison
valid := false valid := false
if x.isAssignableTo(check.ctxt, y.typ) || y.isAssignableTo(check.ctxt, x.typ) { if x.isAssignableTo(check.conf, y.typ) || y.isAssignableTo(check.conf, x.typ) {
switch op { switch op {
case token.EQL, token.NEQ: case token.EQL, token.NEQ:
valid = isComparable(x.typ) || valid = isComparable(x.typ) ||
@ -779,10 +780,6 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type) {
case constant: case constant:
typ = x.typ typ = x.typ
val = x.val val = x.val
case typexprn:
x.mode = typexpr
typ = x.typ
record = false // type was already recorded
default: default:
typ = x.typ typ = x.typ
} }
@ -1220,8 +1217,13 @@ func (check *checker) expr0(x *operand, e ast.Expr, hint Type) {
case *ast.ArrayType, *ast.StructType, *ast.FuncType, case *ast.ArrayType, *ast.StructType, *ast.FuncType,
*ast.InterfaceType, *ast.MapType, *ast.ChanType: *ast.InterfaceType, *ast.MapType, *ast.ChanType:
x.mode = typexprn // not typexpr; Context.Expr callback was invoked by check.typ x.mode = typexpr
x.typ = check.typ(e, nil, false) x.typ = check.typ(e, nil, false)
// Note: rawExpr (caller of expr0) will call check.recordTypeAndValue
// even though check.typ has already called it. This is fine as both
// times the same expression and type are recorded. It is also not a
// performance issue because we only reach here for composite literal
// types, which are comparatively rare.
default: default:
if debug { if debug {

View File

@ -46,9 +46,9 @@ var (
return return
} }
var ctxt Context var conf Config
types := make(map[ast.Expr]Type) types := make(map[ast.Expr]Type)
_, err = ctxt.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types}) _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@ -14,6 +14,7 @@ import (
) )
// TODO(gri) Move Method and accessors to objects.go. // TODO(gri) Move Method and accessors to objects.go.
// TODO(gri) Method.Type() returns the wrong receiver type.
// A Method represents a concrete or abstract (interface) // A Method represents a concrete or abstract (interface)
// method of a method set. // method of a method set.

View File

@ -22,7 +22,6 @@ const (
invalid operandMode = iota // operand is invalid invalid operandMode = iota // operand is invalid
novalue // operand represents no value (result of a function call w/o result) novalue // operand represents no value (result of a function call w/o result)
typexpr // operand is a type typexpr // operand is a type
typexprn // like typexpr; only used to communicate between checker.expr0 and checker.rawExpr
constant // operand is a constant; the operand's typ is a Basic type constant // operand is a constant; the operand's typ is a Basic type
variable // operand is an addressable variable variable // operand is an addressable variable
value // operand is a computed value value // operand is a computed value
@ -33,7 +32,6 @@ var operandModeString = [...]string{
invalid: "invalid", invalid: "invalid",
novalue: "no value", novalue: "no value",
typexpr: "type", typexpr: "type",
typexprn: "type/n",
constant: "constant", constant: "constant",
variable: "variable", variable: "variable",
value: "value", value: "value",
@ -127,7 +125,7 @@ func (x *operand) isNil() bool {
// overlapping in functionality. Need to simplify and clean up. // overlapping in functionality. Need to simplify and clean up.
// isAssignableTo reports whether x is assignable to a variable of type T. // isAssignableTo reports whether x is assignable to a variable of type T.
func (x *operand) isAssignableTo(ctxt *Context, T Type) bool { func (x *operand) isAssignableTo(conf *Config, T Type) bool {
if x.mode == invalid || T == Typ[Invalid] { if x.mode == invalid || T == Typ[Invalid] {
return true // avoid spurious errors return true // avoid spurious errors
} }
@ -186,7 +184,7 @@ func (x *operand) isAssignableTo(ctxt *Context, T Type) bool {
switch t := Tu.(type) { switch t := Tu.(type) {
case *Basic: case *Basic:
if x.mode == constant { if x.mode == constant {
return isRepresentableConst(x.val, ctxt, t.kind) return isRepresentableConst(x.val, conf, t.kind)
} }
// The result of a comparison is an untyped boolean, // The result of a comparison is an untyped boolean,
// but may not be a constant. // but may not be a constant.
@ -207,5 +205,5 @@ func (x *operand) isAssignableTo(ctxt *Context, T Type) bool {
func (x *operand) isInteger() bool { func (x *operand) isInteger() bool {
return x.mode == invalid || return x.mode == invalid ||
isInteger(x.typ) || isInteger(x.typ) ||
x.mode == constant && isRepresentableConst(x.val, nil, UntypedInt) // no context required for UntypedInt x.mode == constant && isRepresentableConst(x.val, nil, UntypedInt) // no *Config required for UntypedInt
} }

View File

@ -86,14 +86,14 @@ func (check *checker) arityMatch(s, init *ast.ValueSpec) {
func (check *checker) resolveFiles(files []*ast.File) { func (check *checker) resolveFiles(files []*ast.File) {
pkg := check.pkg pkg := check.pkg
// Phase 1: Pre-declare all package scope objects so that they can be found // Phase 1: Pre-declare all package-level objects so that they can be found
// when type-checking package objects. // independent of source order.
var scopes []*Scope // corresponding file scope per file var scopes []*Scope // corresponding file scope per file
var objList []Object var objList []Object
var objMap = make(map[Object]*decl) var objMap = make(map[Object]*decl)
var methods []*mdecl var methods []*mdecl
var fileScope *Scope // current file scope, used by collect var fileScope *Scope // current file scope, used by declare
declare := func(ident *ast.Ident, obj Object, typ, init ast.Expr) { declare := func(ident *ast.Ident, obj Object, typ, init ast.Expr) {
assert(ident.Name == obj.Name()) assert(ident.Name == obj.Name())
@ -118,7 +118,7 @@ func (check *checker) resolveFiles(files []*ast.File) {
objMap[obj] = &decl{fileScope, typ, init} objMap[obj] = &decl{fileScope, typ, init}
} }
importer := check.ctxt.Import importer := check.conf.Import
if importer == nil { if importer == nil {
importer = GcImport importer = GcImport
} }
@ -146,7 +146,7 @@ func (check *checker) resolveFiles(files []*ast.File) {
path, _ := strconv.Unquote(s.Path.Value) path, _ := strconv.Unquote(s.Path.Value)
imp, err := importer(pkg.imports, path) imp, err := importer(pkg.imports, path)
if imp == nil && err == nil { if imp == nil && err == nil {
err = errors.New("Context.Import returned nil") err = errors.New("Config.Import returned nil")
} }
if err != nil { if err != nil {
check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err) check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err)

View File

@ -67,9 +67,9 @@ func TestResolveIdents(t *testing.T) {
} }
// resolve and type-check package AST // resolve and type-check package AST
var ctxt Context var conf Config
idents := make(map[*ast.Ident]Object) idents := make(map[*ast.Ident]Object)
pkg, err := ctxt.Check("testResolveIdents", fset, files, &Info{Objects: idents}) pkg, err := conf.Check("testResolveIdents", fset, files, &Info{Objects: idents})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -103,7 +103,7 @@ func TestResolveIdents(t *testing.T) {
}) })
} }
// check that each identifier in the source is enumerated by the Context.Ident callback // check that each identifier in the source is found in the idents map
for _, f := range files { for _, f := range files {
ast.Inspect(f, func(n ast.Node) bool { ast.Inspect(f, func(n ast.Node) bool {
if x, ok := n.(*ast.Ident); ok { if x, ok := n.(*ast.Ident); ok {

View File

@ -6,29 +6,29 @@
package types package types
func (ctxt *Context) alignof(typ Type) int64 { func (conf *Config) alignof(typ Type) int64 {
if f := ctxt.Alignof; f != nil { if f := conf.Alignof; f != nil {
if a := f(typ); a >= 1 { if a := f(typ); a >= 1 {
return a return a
} }
panic("Context.Alignof returned an alignment < 1") panic("Config.Alignof returned an alignment < 1")
} }
return DefaultAlignof(typ) return DefaultAlignof(typ)
} }
func (ctxt *Context) offsetsof(s *Struct) []int64 { func (conf *Config) offsetsof(s *Struct) []int64 {
offsets := s.offsets offsets := s.offsets
if offsets == nil && s.NumFields() > 0 { if offsets == nil && s.NumFields() > 0 {
// compute offsets on demand // compute offsets on demand
if f := ctxt.Offsetsof; f != nil { if f := conf.Offsetsof; f != nil {
offsets = f(s.fields) offsets = f(s.fields)
// sanity checks // sanity checks
if len(offsets) != s.NumFields() { if len(offsets) != s.NumFields() {
panic("Context.Offsetsof returned the wrong number of offsets") panic("Config.Offsetsof returned the wrong number of offsets")
} }
for _, o := range offsets { for _, o := range offsets {
if o < 0 { if o < 0 {
panic("Context.Offsetsof returned an offset < 0") panic("Config.Offsetsof returned an offset < 0")
} }
} }
} else { } else {
@ -42,22 +42,22 @@ func (ctxt *Context) offsetsof(s *Struct) []int64 {
// offsetof returns the offset of the field specified via // offsetof returns the offset of the field specified via
// the index sequence relative to typ. All embedded fields // the index sequence relative to typ. All embedded fields
// must be structs (rather than pointer to structs). // must be structs (rather than pointer to structs).
func (ctxt *Context) offsetof(typ Type, index []int) int64 { func (conf *Config) offsetof(typ Type, index []int) int64 {
var o int64 var o int64
for _, i := range index { for _, i := range index {
s := typ.Underlying().(*Struct) s := typ.Underlying().(*Struct)
o += ctxt.offsetsof(s)[i] o += conf.offsetsof(s)[i]
typ = s.fields[i].typ typ = s.fields[i].typ
} }
return o return o
} }
func (ctxt *Context) sizeof(typ Type) int64 { func (conf *Config) sizeof(typ Type) int64 {
if f := ctxt.Sizeof; f != nil { if f := conf.Sizeof; f != nil {
if s := f(typ); s >= 0 { if s := f(typ); s >= 0 {
return s return s
} }
panic("Context.Sizeof returned a size < 0") panic("Config.Sizeof returned a size < 0")
} }
return DefaultSizeof(typ) return DefaultSizeof(typ)
} }
@ -67,7 +67,7 @@ func (ctxt *Context) sizeof(typ Type) int64 {
const DefaultMaxAlign = 8 const DefaultMaxAlign = 8
// DefaultAlignof implements the default alignment computation // DefaultAlignof implements the default alignment computation
// for unsafe.Alignof. It is used if Context.Alignof == nil. // for unsafe.Alignof. It is used if Config.Alignof == nil.
func DefaultAlignof(typ Type) int64 { func DefaultAlignof(typ Type) int64 {
// For arrays and structs, alignment is defined in terms // For arrays and structs, alignment is defined in terms
// of alignment of the elements and fields, respectively. // of alignment of the elements and fields, respectively.
@ -106,7 +106,7 @@ func align(x, a int64) int64 {
} }
// DefaultOffsetsof implements the default field offset computation // DefaultOffsetsof implements the default field offset computation
// for unsafe.Offsetof. It is used if Context.Offsetsof == nil. // for unsafe.Offsetof. It is used if Config.Offsetsof == nil.
func DefaultOffsetsof(fields []*Field) []int64 { func DefaultOffsetsof(fields []*Field) []int64 {
offsets := make([]int64, len(fields)) offsets := make([]int64, len(fields))
var o int64 var o int64
@ -124,7 +124,7 @@ func DefaultOffsetsof(fields []*Field) []int64 {
const DefaultPtrSize = 8 const DefaultPtrSize = 8
// DefaultSizeof implements the default size computation // DefaultSizeof implements the default size computation
// for unsafe.Sizeof. It is used if Context.Sizeof == nil. // for unsafe.Sizeof. It is used if Config.Sizeof == nil.
func DefaultSizeof(typ Type) int64 { func DefaultSizeof(typ Type) int64 {
switch t := typ.Underlying().(type) { switch t := typ.Underlying().(type) {
case *Basic: case *Basic:

View File

@ -72,9 +72,9 @@ func typecheck(t *testing.T, path string, filenames []string) {
} }
// typecheck package files // typecheck package files
var ctxt Context var conf Config
ctxt.Error = func(err error) { t.Error(err) } conf.Error = func(err error) { t.Error(err) }
ctxt.Check(path, fset, files, nil) conf.Check(path, fset, files, nil)
pkgCount++ pkgCount++
} }

View File

@ -30,7 +30,7 @@ type Context struct {
// The Importer will override any user-supplied values for its // The Importer will override any user-supplied values for its
// Expr, Ident, ImplicitObj and Import fields; other fields // Expr, Ident, ImplicitObj and Import fields; other fields
// will be passed through to the type checker. // will be passed through to the type checker.
TypeChecker types.Context TypeChecker types.Config
// If Loader is non-nil, it is used to satisfy imports. // If Loader is non-nil, it is used to satisfy imports.
// //