mirror of
https://github.com/golang/go
synced 2024-11-17 13:54:46 -07:00
[dev.typeparams] cmd/compile: provide scaffolding to get types2 types during noding
Initial setup of types2.Info structure to provide access to types computed by generic typechecker. Use -G flag to control compiler phases with new typechecker: -G (or -G=1) parsing and typechecking ony -G -G (or -G=2) parsing, typechecking, and noding -G=3 continue after noding (currently will run old typechecker again, leading to duplicate errors Change-Id: I87dd54f7c3773228f288f7a134ac809d9481ca95 Reviewed-on: https://go-review.googlesource.com/c/go/+/274444 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
72cc2353f0
commit
6b4da14dd3
@ -229,10 +229,10 @@ func Main(archInit func(*Arch)) {
|
||||
loadsys()
|
||||
|
||||
timings.Start("fe", "parse")
|
||||
lines := parseFiles(flag.Args(), base.Flag.G != 0)
|
||||
lines := parseFiles(flag.Args())
|
||||
timings.Stop()
|
||||
timings.AddEvent(int64(lines), "lines")
|
||||
if base.Flag.G != 0 {
|
||||
if base.Flag.G != 0 && base.Flag.G < 3 {
|
||||
// can only parse generic code for now
|
||||
base.ExitIfErrors()
|
||||
return
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
// Each declaration in every *syntax.File is converted to a syntax tree
|
||||
// and its root represented by *Node is appended to xtop.
|
||||
// Returns the total count of parsed lines.
|
||||
func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
func parseFiles(filenames []string) (lines uint) {
|
||||
noders := make([]*noder, 0, len(filenames))
|
||||
// Limit the number of simultaneously open files.
|
||||
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
|
||||
@ -48,7 +48,7 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
sem <- struct{}{}
|
||||
defer func() { <-sem }()
|
||||
defer close(p.err)
|
||||
base := syntax.NewFileBase(filename)
|
||||
fbase := syntax.NewFileBase(filename)
|
||||
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
@ -58,14 +58,16 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
defer f.Close()
|
||||
|
||||
mode := syntax.CheckBranches
|
||||
if allowGenerics {
|
||||
if base.Flag.G != 0 {
|
||||
mode |= syntax.AllowGenerics
|
||||
}
|
||||
p.file, _ = syntax.Parse(base, f, p.error, p.pragma, mode) // errors are tracked via p.error
|
||||
p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
|
||||
}(filename)
|
||||
}
|
||||
|
||||
if allowGenerics {
|
||||
// generic noding phase (using new typechecker)
|
||||
if base.Flag.G != 0 {
|
||||
// setup and syntax error reporting
|
||||
nodersmap := make(map[string]*noder)
|
||||
var files []*syntax.File
|
||||
for _, p := range noders {
|
||||
@ -77,11 +79,12 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
files = append(files, p.file)
|
||||
lines += p.file.EOF.Line()
|
||||
|
||||
if base.SyntaxErrors() != 0 {
|
||||
base.ErrorExit()
|
||||
}
|
||||
}
|
||||
if base.SyntaxErrors() != 0 {
|
||||
base.ErrorExit()
|
||||
}
|
||||
|
||||
// typechecking
|
||||
conf := types2.Config{
|
||||
InferFromConstraints: true,
|
||||
IgnoreBranches: true, // parser already checked via syntax.CheckBranches mode
|
||||
@ -110,10 +113,37 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
},
|
||||
},
|
||||
}
|
||||
conf.Check(base.Ctxt.Pkgpath, files, nil)
|
||||
info := types2.Info{
|
||||
Types: make(map[syntax.Expr]types2.TypeAndValue),
|
||||
Defs: make(map[*syntax.Name]types2.Object),
|
||||
Uses: make(map[*syntax.Name]types2.Object),
|
||||
// expand as needed
|
||||
}
|
||||
conf.Check(base.Ctxt.Pkgpath, files, &info)
|
||||
base.ExitIfErrors()
|
||||
if base.Flag.G < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// noding
|
||||
for _, p := range noders {
|
||||
// errors have already been reported
|
||||
|
||||
p.typeInfo = &info
|
||||
p.node()
|
||||
lines += p.file.EOF.Line()
|
||||
p.file = nil // release memory
|
||||
base.ExitIfErrors()
|
||||
|
||||
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
|
||||
testdclstack()
|
||||
}
|
||||
|
||||
ir.LocalPkg.Height = myheight
|
||||
return
|
||||
}
|
||||
|
||||
// traditional (non-generic) noding phase
|
||||
for _, p := range noders {
|
||||
for e := range p.err {
|
||||
p.errorAt(e.Pos, "%s", e.Msg)
|
||||
@ -122,10 +152,10 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||
p.node()
|
||||
lines += p.file.EOF.Line()
|
||||
p.file = nil // release memory
|
||||
|
||||
if base.SyntaxErrors() != 0 {
|
||||
base.ErrorExit()
|
||||
}
|
||||
|
||||
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
|
||||
testdclstack()
|
||||
}
|
||||
@ -220,9 +250,35 @@ type noder struct {
|
||||
// current function at the moment each open scope was opened.
|
||||
scopeVars []int
|
||||
|
||||
// typeInfo provides access to the type information computed by the new
|
||||
// typechecker. It is only present if -G is set, and all noders point to
|
||||
// the same types.Info. For now this is a local field, if need be we can
|
||||
// make it global.
|
||||
typeInfo *types2.Info
|
||||
|
||||
lastCloseScopePos syntax.Pos
|
||||
}
|
||||
|
||||
// For now we provide these basic accessors to get to type and object
|
||||
// information of expression nodes during noding. Eventually we will
|
||||
// attach this information directly to the syntax tree which should
|
||||
// simplify access and make it more efficient as well.
|
||||
|
||||
// typ returns the type and value information for the given expression.
|
||||
func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
|
||||
return p.typeInfo.Types[x]
|
||||
}
|
||||
|
||||
// def returns the object for the given name in its declaration.
|
||||
func (p *noder) def(x *syntax.Name) types2.Object {
|
||||
return p.typeInfo.Defs[x]
|
||||
}
|
||||
|
||||
// use returns the object for the given name outside its declaration.
|
||||
func (p *noder) use(x *syntax.Name) types2.Object {
|
||||
return p.typeInfo.Uses[x]
|
||||
}
|
||||
|
||||
func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) {
|
||||
oldScope := p.scope
|
||||
p.scope = 0
|
||||
|
Loading…
Reference in New Issue
Block a user