From 32f601bfbe3a94a16708bf3d5d9d3c9783676727 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 10 Jul 2013 18:37:52 -0400 Subject: [PATCH] go.types/ssa: unexport Package.Init; clients should use pkg.Func("init"). R=gri CC=golang-dev https://golang.org/cl/11093044 --- ssa/builder.go | 16 ++++++++-------- ssa/builder_test.go | 4 ++-- ssa/create.go | 11 ++++++----- ssa/example_test.go | 8 ++------ ssa/interp/interp.go | 2 +- ssa/source.go | 4 ++-- ssa/ssa.go | 6 +----- 7 files changed, 22 insertions(+), 29 deletions(-) diff --git a/ssa/builder.go b/ssa/builder.go index e89a1ffa..58f93f05 100644 --- a/ssa/builder.go +++ b/ssa/builder.go @@ -73,7 +73,7 @@ type builder struct { // Intra-package references are edges in the initialization dependency // graph. If the result v is a Function or Global belonging to // '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 { 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)) } -// 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 // explanation at globalValueSpec. // Precondition: g == g.Prog.Value(obj) @@ -998,7 +998,7 @@ func (b *builder) buildGlobal(g *Global, obj types.Object) { if spec == nil { 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 @@ -2055,7 +2055,7 @@ start: fn.emit(&v) case *ast.ReturnStmt: - if fn == fn.Pkg.Init { + if fn == fn.Pkg.init { // A "return" within an init block is treated // like a "goto" to the next init block. We // 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. case token.VAR: 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: for _, spec := range decl.Specs { @@ -2269,7 +2269,7 @@ func (b *builder) buildDecl(pkg *Package, decl ast.Decl) { if pkg.Prog.mode&LogSource != 0 { 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 // treated like a "goto" to the the next init @@ -2332,7 +2332,7 @@ func (p *Package) Build() { if p.Prog.mode&LogSource != 0 { defer logStack("build %s", p)() } - init := p.Init + init := p.init init.startBody() // 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. for _, typkg := range p.info.Imports() { 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.setType(types.NewTuple()) init.emit(&v) diff --git a/ssa/builder_test.go b/ssa/builder_test.go index de451c30..2344c35c 100644 --- a/ssa/builder_test.go +++ b/ssa/builder_test.go @@ -69,9 +69,9 @@ func main() { isExt := pkg != mainPkg // init() - if isExt && !isEmpty(pkg.Init) { + if isExt && !isEmpty(pkg.init) { 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) } diff --git a/ssa/create.go b/ssa/create.go index b0933f9f..f7ffa92e 100644 --- a/ssa/create.go +++ b/ssa/create.go @@ -183,9 +183,9 @@ func membersFromDecl(pkg *Package, decl ast.Decl) { case *ast.FuncDecl: id := decl.Name if decl.Recv == nil && id.Name == "init" { - if !pkg.Init.pos.IsValid() { - pkg.Init.pos = decl.Name.Pos() - pkg.Init.Synthetic = "" + if !pkg.init.pos.IsValid() { + pkg.init.pos = decl.Name.Pos() + pkg.init.Synthetic = "" } 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) } - // Add init() function (but not to Members since it can't be referenced). - p.Init = &Function{ + // Add init() function. + p.init = &Function{ name: "init", Signature: new(types.Signature), Synthetic: "package initializer", Pkg: p, Prog: prog, } + p.Members[p.init.name] = p.init // CREATE phase. // Allocate all package members: vars, funcs and consts and types. diff --git a/ssa/example_test.go b/ssa/example_test.go index 425e82dd..10b03e8a 100644 --- a/ssa/example_test.go +++ b/ssa/example_test.go @@ -67,12 +67,8 @@ func main() { mainPkg.Build() // Print out the package-level functions. - mainPkg.Init.DumpTo(os.Stdout) - for _, mem := range mainPkg.Members { - if fn, ok := mem.(*ssa.Function); ok { - fn.DumpTo(os.Stdout) - } - } + mainPkg.Func("init").DumpTo(os.Stdout) + mainPkg.Func("main").DumpTo(os.Stdout) // Output: // diff --git a/ssa/interp/interp.go b/ssa/interp/interp.go index e72d94ed..3ae36258 100644 --- a/ssa/interp/interp.go +++ b/ssa/interp/interp.go @@ -609,7 +609,7 @@ func Interpret(mainpkg *ssa.Package, mode Mode, filename string, args []string) }() // 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 { call(i, nil, token.NoPos, mainFn, nil) exitCode = 0 diff --git a/ssa/source.go b/ssa/source.go index 09daf616..9edb9acc 100644 --- a/ssa/source.go +++ b/ssa/source.go @@ -108,13 +108,13 @@ func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function case *ast.GenDecl: if decl.Tok == token.VAR && n >= 3 { // Package-level 'var' initializer. - return pkg.Init + return pkg.init } case *ast.FuncDecl: if decl.Recv == nil && decl.Name.Name == "init" { // Explicit init() function. - return pkg.Init + return pkg.init } // Declared function/method. return findNamedFunc(pkg, decl.Name.NamePos) diff --git a/ssa/ssa.go b/ssa/ssa.go index b5705426..4bf78746 100644 --- a/ssa/ssa.go +++ b/ssa/ssa.go @@ -42,7 +42,7 @@ type Package struct { Object *types.Package // the type checker's package object for this package Members map[string]Member // all package members keyed by name 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 // after building. @@ -108,10 +108,6 @@ type Type struct { // NB: a Constant is not a Value; it contains a literal Value, which // 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 { name string Value *Literal