зеркало из https://github.com/golang/tools.git
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:
Родитель
9460d02473
Коммит
40a278e5ee
|
@ -19,9 +19,9 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
|
|||
pkg.spans = make(map[types.Object]Span)
|
||||
pkg.types = make(map[ast.Expr]types.Type)
|
||||
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.
|
||||
context := types.Context{
|
||||
config := types.Config{
|
||||
Error: func(error) {},
|
||||
}
|
||||
info := &types.Info{
|
||||
|
@ -29,7 +29,7 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
|
|||
Values: pkg.values,
|
||||
Objects: pkg.idents,
|
||||
}
|
||||
_, err := context.Check(pkg.path, fs, astFiles, info)
|
||||
_, err := config.Check(pkg.path, fs, astFiles, info)
|
||||
// update spans
|
||||
for id, obj := range pkg.idents {
|
||||
pkg.growSpan(id, obj)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// Package types declares the data types and implements
|
||||
// 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:
|
||||
//
|
||||
|
@ -34,19 +34,19 @@ import (
|
|||
// 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 (".").
|
||||
//
|
||||
// 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) {
|
||||
var ctxt Context
|
||||
pkg, err := ctxt.check(path, fset, files, nil)
|
||||
var conf Config
|
||||
pkg, err := conf.check(path, fset, files, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pkg, nil
|
||||
}
|
||||
|
||||
// A Context specifies the supporting context for type checking.
|
||||
// The zero value for a Context is a ready-to-use default context.
|
||||
type Context struct {
|
||||
// A Config specifies the configuration for type checking.
|
||||
// The zero value for Config is a ready-to-use default configuration.
|
||||
type Config struct {
|
||||
// If Error != nil, it is called with each error found
|
||||
// during type checking. The error strings of errors with
|
||||
// detailed position information are formatted as follows:
|
||||
|
@ -103,7 +103,7 @@ type Info struct {
|
|||
// are not recorded.
|
||||
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:
|
||||
//
|
||||
// node obj
|
||||
|
@ -118,15 +118,15 @@ type Info struct {
|
|||
// 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
|
||||
// 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) {
|
||||
return ctxt.check(path, fset, files, info)
|
||||
func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
|
||||
return conf.check(path, fset, files, info)
|
||||
}
|
||||
|
||||
// IsAssignableTo reports whether a value of type V
|
||||
// is assignable to a variable of type T.
|
||||
func IsAssignableTo(V, T Type) bool {
|
||||
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).
|
||||
|
|
|
@ -32,7 +32,7 @@ func (check *checker) assignment(x *operand, to Type) bool {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -236,7 +236,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
|
|||
if x.mode == invalid {
|
||||
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)
|
||||
goto Error
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *Builtin) {
|
|||
|
||||
case _Alignof:
|
||||
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]
|
||||
|
||||
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)
|
||||
goto Error
|
||||
}
|
||||
offs := check.ctxt.offsetof(base, index)
|
||||
offs := check.conf.offsetof(base, index)
|
||||
x.mode = constant
|
||||
x.val = exact.MakeInt64(offs)
|
||||
x.typ = Typ[Uintptr]
|
||||
|
||||
case _Sizeof:
|
||||
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]
|
||||
|
||||
case _Assert:
|
||||
|
|
|
@ -36,7 +36,7 @@ type exprInfo struct {
|
|||
|
||||
// A checker is an instance of the type checker.
|
||||
type checker struct {
|
||||
ctxt *Context
|
||||
conf *Config
|
||||
fset *token.FileSet
|
||||
Info
|
||||
|
||||
|
@ -59,9 +59,9 @@ type checker struct {
|
|||
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{
|
||||
ctxt: ctxt,
|
||||
conf: conf,
|
||||
fset: fset,
|
||||
pkg: pkg,
|
||||
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{
|
||||
path: pkgPath,
|
||||
scope: NewScope(Universe),
|
||||
imports: make(map[string]*Package),
|
||||
}
|
||||
|
||||
check := newChecker(ctxt, fset, pkg)
|
||||
check := newChecker(conf, fset, pkg)
|
||||
defer check.handleBailout(&err)
|
||||
|
||||
// we need a reasonable path to continue
|
||||
|
@ -149,11 +149,6 @@ func (ctxt *Context) check(pkgPath string, fset *token.FileSet, files []*ast.Fil
|
|||
return
|
||||
}
|
||||
|
||||
// install optional info
|
||||
if info != nil {
|
||||
check.Info = *info
|
||||
}
|
||||
|
||||
// determine package name and files
|
||||
i := 0
|
||||
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)
|
||||
check.resolveFiles(files[:i])
|
||||
|
||||
|
|
|
@ -203,8 +203,8 @@ func checkFiles(t *testing.T, testfiles []string) {
|
|||
}
|
||||
|
||||
// typecheck and collect typechecker errors
|
||||
var ctxt Context
|
||||
ctxt.Error = func(err error) {
|
||||
var conf Config
|
||||
conf.Error = func(err error) {
|
||||
if *listErrors {
|
||||
t.Error(err)
|
||||
return
|
||||
|
@ -216,7 +216,7 @@ func checkFiles(t *testing.T, testfiles []string) {
|
|||
errlist = append(errlist, err)
|
||||
}
|
||||
}
|
||||
ctxt.Check(pkgName, fset, files, nil)
|
||||
conf.Check(pkgName, fset, files, nil)
|
||||
|
||||
if *listErrors {
|
||||
return
|
||||
|
|
|
@ -58,7 +58,7 @@ func (check *checker) conversion(x *operand, conv *ast.CallExpr, typ Type) {
|
|||
// TODO(gri) verify the remaining conversions.
|
||||
} else {
|
||||
// non-constant conversion
|
||||
if !x.isConvertible(check.ctxt, typ) {
|
||||
if !x.isConvertible(check.conf, typ) {
|
||||
goto ErrorMsg
|
||||
}
|
||||
x.mode = value
|
||||
|
@ -91,9 +91,9 @@ Error:
|
|||
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"
|
||||
if x.isAssignableTo(ctxt, T) {
|
||||
if x.isAssignableTo(conf, T) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ func (check *checker) err(err error) {
|
|||
if check.firsterr == nil {
|
||||
check.firsterr = err
|
||||
}
|
||||
f := check.ctxt.Error
|
||||
f := check.conf.Error
|
||||
if f == nil {
|
||||
panic(bailout{}) // report only first error
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
|
|||
}
|
||||
|
||||
// initialize checker
|
||||
var ctxt Context
|
||||
check := newChecker(&ctxt, fset, pkg)
|
||||
var conf Config
|
||||
check := newChecker(&conf, fset, pkg)
|
||||
check.topScope = scope
|
||||
defer check.handleBailout(&err)
|
||||
|
||||
|
@ -95,7 +95,7 @@ func EvalNode(fset *token.FileSet, node ast.Expr, pkg *Package, scope *Scope) (t
|
|||
var x operand
|
||||
check.exprOrType(&x, node)
|
||||
switch x.mode {
|
||||
case invalid, novalue, typexprn:
|
||||
case invalid, novalue:
|
||||
fallthrough
|
||||
default:
|
||||
unreachable() // or bailed out with error
|
||||
|
|
|
@ -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,
|
||||
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
|
||||
|
@ -124,7 +125,7 @@ func (check *checker) unary(x *operand, op token.Token) {
|
|||
typ := x.typ.Underlying().(*Basic)
|
||||
size := -1
|
||||
if isUnsigned(typ) {
|
||||
size = int(check.ctxt.sizeof(typ))
|
||||
size = int(check.conf.sizeof(typ))
|
||||
}
|
||||
x.val = exact.UnaryOp(op, x.val, size)
|
||||
// Typed constants must be representable in
|
||||
|
@ -154,7 +155,7 @@ func isComparison(op token.Token) bool {
|
|||
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() {
|
||||
case exact.Unknown:
|
||||
return true
|
||||
|
@ -166,7 +167,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
|
|||
if x, ok := exact.Int64Val(x); ok {
|
||||
switch as {
|
||||
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
|
||||
case Int8:
|
||||
const s = 8
|
||||
|
@ -180,7 +181,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
|
|||
case Int64:
|
||||
return true
|
||||
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
|
||||
|
@ -211,7 +212,7 @@ func isRepresentableConst(x exact.Value, ctxt *Context, as BasicKind) bool {
|
|||
n := exact.BitLen(x)
|
||||
switch as {
|
||||
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)
|
||||
case Uint64:
|
||||
return exact.Sign(x) >= 0 && n <= 64
|
||||
|
@ -270,7 +271,7 @@ func (check *checker) isRepresentable(x *operand, typ *Basic) {
|
|||
return
|
||||
}
|
||||
|
||||
if !isRepresentableConst(x.val, check.ctxt, typ.kind) {
|
||||
if !isRepresentableConst(x.val, check.conf, typ.kind) {
|
||||
var msg string
|
||||
if isNumeric(x.typ) && isNumeric(typ) {
|
||||
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
|
||||
// only updates the recorded untyped type for x and possibly its
|
||||
// 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,
|
||||
// and if x is the (formerly untyped) lhs operand of a non-constant
|
||||
// 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
|
||||
|
||||
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 {
|
||||
case token.EQL, token.NEQ:
|
||||
valid = isComparable(x.typ) ||
|
||||
|
@ -779,10 +780,6 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type) {
|
|||
case constant:
|
||||
typ = x.typ
|
||||
val = x.val
|
||||
case typexprn:
|
||||
x.mode = typexpr
|
||||
typ = x.typ
|
||||
record = false // type was already recorded
|
||||
default:
|
||||
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,
|
||||
*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)
|
||||
// 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:
|
||||
if debug {
|
||||
|
|
|
@ -46,9 +46,9 @@ var (
|
|||
return
|
||||
}
|
||||
|
||||
var ctxt Context
|
||||
var conf Config
|
||||
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 {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// 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)
|
||||
// method of a method set.
|
||||
|
|
|
@ -22,7 +22,6 @@ const (
|
|||
invalid operandMode = iota // operand is invalid
|
||||
novalue // operand represents no value (result of a function call w/o result)
|
||||
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
|
||||
variable // operand is an addressable variable
|
||||
value // operand is a computed value
|
||||
|
@ -33,7 +32,6 @@ var operandModeString = [...]string{
|
|||
invalid: "invalid",
|
||||
novalue: "no value",
|
||||
typexpr: "type",
|
||||
typexprn: "type/n",
|
||||
constant: "constant",
|
||||
variable: "variable",
|
||||
value: "value",
|
||||
|
@ -127,7 +125,7 @@ func (x *operand) isNil() bool {
|
|||
// overlapping in functionality. Need to simplify and clean up.
|
||||
|
||||
// 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] {
|
||||
return true // avoid spurious errors
|
||||
}
|
||||
|
@ -186,7 +184,7 @@ func (x *operand) isAssignableTo(ctxt *Context, T Type) bool {
|
|||
switch t := Tu.(type) {
|
||||
case *Basic:
|
||||
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,
|
||||
// but may not be a constant.
|
||||
|
@ -207,5 +205,5 @@ func (x *operand) isAssignableTo(ctxt *Context, T Type) bool {
|
|||
func (x *operand) isInteger() bool {
|
||||
return x.mode == invalid ||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -86,14 +86,14 @@ func (check *checker) arityMatch(s, init *ast.ValueSpec) {
|
|||
func (check *checker) resolveFiles(files []*ast.File) {
|
||||
pkg := check.pkg
|
||||
|
||||
// Phase 1: Pre-declare all package scope objects so that they can be found
|
||||
// when type-checking package objects.
|
||||
// Phase 1: Pre-declare all package-level objects so that they can be found
|
||||
// independent of source order.
|
||||
|
||||
var scopes []*Scope // corresponding file scope per file
|
||||
var objList []Object
|
||||
var objMap = make(map[Object]*decl)
|
||||
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) {
|
||||
assert(ident.Name == obj.Name())
|
||||
|
@ -118,7 +118,7 @@ func (check *checker) resolveFiles(files []*ast.File) {
|
|||
objMap[obj] = &decl{fileScope, typ, init}
|
||||
}
|
||||
|
||||
importer := check.ctxt.Import
|
||||
importer := check.conf.Import
|
||||
if importer == nil {
|
||||
importer = GcImport
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ func (check *checker) resolveFiles(files []*ast.File) {
|
|||
path, _ := strconv.Unquote(s.Path.Value)
|
||||
imp, err := importer(pkg.imports, path)
|
||||
if imp == nil && err == nil {
|
||||
err = errors.New("Context.Import returned nil")
|
||||
err = errors.New("Config.Import returned nil")
|
||||
}
|
||||
if err != nil {
|
||||
check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err)
|
||||
|
|
|
@ -67,9 +67,9 @@ func TestResolveIdents(t *testing.T) {
|
|||
}
|
||||
|
||||
// resolve and type-check package AST
|
||||
var ctxt Context
|
||||
var conf Config
|
||||
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 {
|
||||
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 {
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
if x, ok := n.(*ast.Ident); ok {
|
||||
|
|
|
@ -6,29 +6,29 @@
|
|||
|
||||
package types
|
||||
|
||||
func (ctxt *Context) alignof(typ Type) int64 {
|
||||
if f := ctxt.Alignof; f != nil {
|
||||
func (conf *Config) alignof(typ Type) int64 {
|
||||
if f := conf.Alignof; f != nil {
|
||||
if a := f(typ); a >= 1 {
|
||||
return a
|
||||
}
|
||||
panic("Context.Alignof returned an alignment < 1")
|
||||
panic("Config.Alignof returned an alignment < 1")
|
||||
}
|
||||
return DefaultAlignof(typ)
|
||||
}
|
||||
|
||||
func (ctxt *Context) offsetsof(s *Struct) []int64 {
|
||||
func (conf *Config) offsetsof(s *Struct) []int64 {
|
||||
offsets := s.offsets
|
||||
if offsets == nil && s.NumFields() > 0 {
|
||||
// compute offsets on demand
|
||||
if f := ctxt.Offsetsof; f != nil {
|
||||
if f := conf.Offsetsof; f != nil {
|
||||
offsets = f(s.fields)
|
||||
// sanity checks
|
||||
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 {
|
||||
if o < 0 {
|
||||
panic("Context.Offsetsof returned an offset < 0")
|
||||
panic("Config.Offsetsof returned an offset < 0")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -42,22 +42,22 @@ func (ctxt *Context) offsetsof(s *Struct) []int64 {
|
|||
// offsetof returns the offset of the field specified via
|
||||
// the index sequence relative to typ. All embedded fields
|
||||
// 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
|
||||
for _, i := range index {
|
||||
s := typ.Underlying().(*Struct)
|
||||
o += ctxt.offsetsof(s)[i]
|
||||
o += conf.offsetsof(s)[i]
|
||||
typ = s.fields[i].typ
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (ctxt *Context) sizeof(typ Type) int64 {
|
||||
if f := ctxt.Sizeof; f != nil {
|
||||
func (conf *Config) sizeof(typ Type) int64 {
|
||||
if f := conf.Sizeof; f != nil {
|
||||
if s := f(typ); s >= 0 {
|
||||
return s
|
||||
}
|
||||
panic("Context.Sizeof returned a size < 0")
|
||||
panic("Config.Sizeof returned a size < 0")
|
||||
}
|
||||
return DefaultSizeof(typ)
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ func (ctxt *Context) sizeof(typ Type) int64 {
|
|||
const DefaultMaxAlign = 8
|
||||
|
||||
// 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 {
|
||||
// For arrays and structs, alignment is defined in terms
|
||||
// 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
|
||||
// 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 {
|
||||
offsets := make([]int64, len(fields))
|
||||
var o int64
|
||||
|
@ -124,7 +124,7 @@ func DefaultOffsetsof(fields []*Field) []int64 {
|
|||
const DefaultPtrSize = 8
|
||||
|
||||
// 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 {
|
||||
switch t := typ.Underlying().(type) {
|
||||
case *Basic:
|
||||
|
|
|
@ -72,9 +72,9 @@ func typecheck(t *testing.T, path string, filenames []string) {
|
|||
}
|
||||
|
||||
// typecheck package files
|
||||
var ctxt Context
|
||||
ctxt.Error = func(err error) { t.Error(err) }
|
||||
ctxt.Check(path, fset, files, nil)
|
||||
var conf Config
|
||||
conf.Error = func(err error) { t.Error(err) }
|
||||
conf.Check(path, fset, files, nil)
|
||||
pkgCount++
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ type Context struct {
|
|||
// The Importer will override any user-supplied values for its
|
||||
// Expr, Ident, ImplicitObj and Import fields; other fields
|
||||
// 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.
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче