mirror of
https://github.com/golang/go
synced 2024-11-18 23:34:45 -07:00
go.types/ssa: unexport Package.Init; clients should use pkg.Func("init").
R=gri CC=golang-dev https://golang.org/cl/11093044
This commit is contained in:
parent
e783d2d666
commit
32f601bfbe
@ -73,7 +73,7 @@ type builder struct {
|
|||||||
// Intra-package references are edges in the initialization dependency
|
// Intra-package references are edges in the initialization dependency
|
||||||
// graph. If the result v is a Function or Global belonging to
|
// graph. If the result v is a Function or Global belonging to
|
||||||
// 'from', the package on whose behalf this lookup occurs, then lookup
|
// 'from', the package on whose behalf this lookup occurs, then lookup
|
||||||
// emits initialization code into from.Init if not already done.
|
// emits initialization code into from.init if not already done.
|
||||||
//
|
//
|
||||||
func (b *builder) lookup(from *Package, obj types.Object) Value {
|
func (b *builder) lookup(from *Package, obj types.Object) Value {
|
||||||
v := from.Prog.Value(obj)
|
v := from.Prog.Value(obj)
|
||||||
@ -988,7 +988,7 @@ func (b *builder) assignOp(fn *Function, loc lvalue, incr Value, op token.Token)
|
|||||||
loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), token.NoPos))
|
loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), token.NoPos))
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildGlobal emits code to the g.Pkg.Init function for the variable
|
// buildGlobal emits code to the g.Pkg.init function for the variable
|
||||||
// definition(s) of g. Effects occur out of lexical order; see
|
// definition(s) of g. Effects occur out of lexical order; see
|
||||||
// explanation at globalValueSpec.
|
// explanation at globalValueSpec.
|
||||||
// Precondition: g == g.Prog.Value(obj)
|
// Precondition: g == g.Prog.Value(obj)
|
||||||
@ -998,7 +998,7 @@ func (b *builder) buildGlobal(g *Global, obj types.Object) {
|
|||||||
if spec == nil {
|
if spec == nil {
|
||||||
return // already built (or in progress)
|
return // already built (or in progress)
|
||||||
}
|
}
|
||||||
b.globalValueSpec(g.Pkg.Init, spec, g, obj)
|
b.globalValueSpec(g.Pkg.init, spec, g, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// globalValueSpec emits to init code to define one or all of the vars
|
// globalValueSpec emits to init code to define one or all of the vars
|
||||||
@ -2055,7 +2055,7 @@ start:
|
|||||||
fn.emit(&v)
|
fn.emit(&v)
|
||||||
|
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
if fn == fn.Pkg.Init {
|
if fn == fn.Pkg.init {
|
||||||
// A "return" within an init block is treated
|
// A "return" within an init block is treated
|
||||||
// like a "goto" to the next init block. We
|
// like a "goto" to the next init block. We
|
||||||
// use the outermost BREAK target for this purpose.
|
// use the outermost BREAK target for this purpose.
|
||||||
@ -2241,7 +2241,7 @@ func (b *builder) buildDecl(pkg *Package, decl ast.Decl) {
|
|||||||
// Nothing to do for CONST, IMPORT.
|
// Nothing to do for CONST, IMPORT.
|
||||||
case token.VAR:
|
case token.VAR:
|
||||||
for _, spec := range decl.Specs {
|
for _, spec := range decl.Specs {
|
||||||
b.globalValueSpec(pkg.Init, spec.(*ast.ValueSpec), nil, nil)
|
b.globalValueSpec(pkg.init, spec.(*ast.ValueSpec), nil, nil)
|
||||||
}
|
}
|
||||||
case token.TYPE:
|
case token.TYPE:
|
||||||
for _, spec := range decl.Specs {
|
for _, spec := range decl.Specs {
|
||||||
@ -2269,7 +2269,7 @@ func (b *builder) buildDecl(pkg *Package, decl ast.Decl) {
|
|||||||
if pkg.Prog.mode&LogSource != 0 {
|
if pkg.Prog.mode&LogSource != 0 {
|
||||||
fmt.Fprintln(os.Stderr, "build init block @", pkg.Prog.Fset.Position(decl.Pos()))
|
fmt.Fprintln(os.Stderr, "build init block @", pkg.Prog.Fset.Position(decl.Pos()))
|
||||||
}
|
}
|
||||||
init := pkg.Init
|
init := pkg.init
|
||||||
|
|
||||||
// A return statement within an init block is
|
// A return statement within an init block is
|
||||||
// treated like a "goto" to the the next init
|
// treated like a "goto" to the the next init
|
||||||
@ -2332,7 +2332,7 @@ func (p *Package) Build() {
|
|||||||
if p.Prog.mode&LogSource != 0 {
|
if p.Prog.mode&LogSource != 0 {
|
||||||
defer logStack("build %s", p)()
|
defer logStack("build %s", p)()
|
||||||
}
|
}
|
||||||
init := p.Init
|
init := p.init
|
||||||
init.startBody()
|
init.startBody()
|
||||||
|
|
||||||
// Make init() skip if package is already initialized.
|
// Make init() skip if package is already initialized.
|
||||||
@ -2346,7 +2346,7 @@ func (p *Package) Build() {
|
|||||||
// Call the init() function of each package we import.
|
// Call the init() function of each package we import.
|
||||||
for _, typkg := range p.info.Imports() {
|
for _, typkg := range p.info.Imports() {
|
||||||
var v Call
|
var v Call
|
||||||
v.Call.Func = p.Prog.packages[typkg].Init
|
v.Call.Func = p.Prog.packages[typkg].init
|
||||||
v.Call.pos = init.pos
|
v.Call.pos = init.pos
|
||||||
v.setType(types.NewTuple())
|
v.setType(types.NewTuple())
|
||||||
init.emit(&v)
|
init.emit(&v)
|
||||||
|
@ -69,9 +69,9 @@ func main() {
|
|||||||
isExt := pkg != mainPkg
|
isExt := pkg != mainPkg
|
||||||
|
|
||||||
// init()
|
// init()
|
||||||
if isExt && !isEmpty(pkg.Init) {
|
if isExt && !isEmpty(pkg.init) {
|
||||||
t.Errorf("external package %s has non-empty init", pkg)
|
t.Errorf("external package %s has non-empty init", pkg)
|
||||||
} else if !isExt && isEmpty(pkg.Init) {
|
} else if !isExt && isEmpty(pkg.init) {
|
||||||
t.Errorf("main package %s has empty init", pkg)
|
t.Errorf("main package %s has empty init", pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,9 +183,9 @@ func membersFromDecl(pkg *Package, decl ast.Decl) {
|
|||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
id := decl.Name
|
id := decl.Name
|
||||||
if decl.Recv == nil && id.Name == "init" {
|
if decl.Recv == nil && id.Name == "init" {
|
||||||
if !pkg.Init.pos.IsValid() {
|
if !pkg.init.pos.IsValid() {
|
||||||
pkg.Init.pos = decl.Name.Pos()
|
pkg.init.pos = decl.Name.Pos()
|
||||||
pkg.Init.Synthetic = ""
|
pkg.init.Synthetic = ""
|
||||||
}
|
}
|
||||||
return // init blocks aren't functions
|
return // init blocks aren't functions
|
||||||
}
|
}
|
||||||
@ -210,14 +210,15 @@ func createPackage(prog *Program, importPath string, info *importer.PackageInfo)
|
|||||||
info: info, // transient (CREATE and BUILD phases)
|
info: info, // transient (CREATE and BUILD phases)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add init() function (but not to Members since it can't be referenced).
|
// Add init() function.
|
||||||
p.Init = &Function{
|
p.init = &Function{
|
||||||
name: "init",
|
name: "init",
|
||||||
Signature: new(types.Signature),
|
Signature: new(types.Signature),
|
||||||
Synthetic: "package initializer",
|
Synthetic: "package initializer",
|
||||||
Pkg: p,
|
Pkg: p,
|
||||||
Prog: prog,
|
Prog: prog,
|
||||||
}
|
}
|
||||||
|
p.Members[p.init.name] = p.init
|
||||||
|
|
||||||
// CREATE phase.
|
// CREATE phase.
|
||||||
// Allocate all package members: vars, funcs and consts and types.
|
// Allocate all package members: vars, funcs and consts and types.
|
||||||
|
@ -67,12 +67,8 @@ func main() {
|
|||||||
mainPkg.Build()
|
mainPkg.Build()
|
||||||
|
|
||||||
// Print out the package-level functions.
|
// Print out the package-level functions.
|
||||||
mainPkg.Init.DumpTo(os.Stdout)
|
mainPkg.Func("init").DumpTo(os.Stdout)
|
||||||
for _, mem := range mainPkg.Members {
|
mainPkg.Func("main").DumpTo(os.Stdout)
|
||||||
if fn, ok := mem.(*ssa.Function); ok {
|
|
||||||
fn.DumpTo(os.Stdout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
//
|
//
|
||||||
|
@ -609,7 +609,7 @@ func Interpret(mainpkg *ssa.Package, mode Mode, filename string, args []string)
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Run!
|
// Run!
|
||||||
call(i, nil, token.NoPos, mainpkg.Init, nil)
|
call(i, nil, token.NoPos, mainpkg.Func("init"), nil)
|
||||||
if mainFn := mainpkg.Func("main"); mainFn != nil {
|
if mainFn := mainpkg.Func("main"); mainFn != nil {
|
||||||
call(i, nil, token.NoPos, mainFn, nil)
|
call(i, nil, token.NoPos, mainFn, nil)
|
||||||
exitCode = 0
|
exitCode = 0
|
||||||
|
@ -108,13 +108,13 @@ func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function
|
|||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
if decl.Tok == token.VAR && n >= 3 {
|
if decl.Tok == token.VAR && n >= 3 {
|
||||||
// Package-level 'var' initializer.
|
// Package-level 'var' initializer.
|
||||||
return pkg.Init
|
return pkg.init
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.FuncDecl:
|
case *ast.FuncDecl:
|
||||||
if decl.Recv == nil && decl.Name.Name == "init" {
|
if decl.Recv == nil && decl.Name.Name == "init" {
|
||||||
// Explicit init() function.
|
// Explicit init() function.
|
||||||
return pkg.Init
|
return pkg.init
|
||||||
}
|
}
|
||||||
// Declared function/method.
|
// Declared function/method.
|
||||||
return findNamedFunc(pkg, decl.Name.NamePos)
|
return findNamedFunc(pkg, decl.Name.NamePos)
|
||||||
|
@ -42,7 +42,7 @@ type Package struct {
|
|||||||
Object *types.Package // the type checker's package object for this package
|
Object *types.Package // the type checker's package object for this package
|
||||||
Members map[string]Member // all package members keyed by name
|
Members map[string]Member // all package members keyed by name
|
||||||
values map[types.Object]Value // package-level vars and funcs, keyed by object
|
values map[types.Object]Value // package-level vars and funcs, keyed by object
|
||||||
Init *Function // the package's (concatenated) init function [TODO use Func("init")]
|
init *Function // Func("init"); the package's (concatenated) init function
|
||||||
|
|
||||||
// The following fields are set transiently, then cleared
|
// The following fields are set transiently, then cleared
|
||||||
// after building.
|
// after building.
|
||||||
@ -108,10 +108,6 @@ type Type struct {
|
|||||||
// NB: a Constant is not a Value; it contains a literal Value, which
|
// NB: a Constant is not a Value; it contains a literal Value, which
|
||||||
// it augments with the name and position of its 'const' declaration.
|
// it augments with the name and position of its 'const' declaration.
|
||||||
//
|
//
|
||||||
// TODO(adonovan): if we decide to add a token.Pos to literal, we
|
|
||||||
// should then add a name too, and merge Constant and Literal.
|
|
||||||
// Experiment.
|
|
||||||
//
|
|
||||||
type Constant struct {
|
type Constant struct {
|
||||||
name string
|
name string
|
||||||
Value *Literal
|
Value *Literal
|
||||||
|
Loading…
Reference in New Issue
Block a user