1
0
mirror of https://github.com/golang/go synced 2024-11-18 23:44:43 -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:
Alan Donovan 2013-07-10 18:37:52 -04:00
parent e783d2d666
commit 32f601bfbe
7 changed files with 22 additions and 29 deletions

View File

@ -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)

View File

@ -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)
} }

View File

@ -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.

View File

@ -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:
// //

View File

@ -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

View File

@ -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)

View File

@ -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