mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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
2 changed files with 68 additions and 12 deletions
|
|
@ -229,10 +229,10 @@ func Main(archInit func(*Arch)) {
|
||||||
loadsys()
|
loadsys()
|
||||||
|
|
||||||
timings.Start("fe", "parse")
|
timings.Start("fe", "parse")
|
||||||
lines := parseFiles(flag.Args(), base.Flag.G != 0)
|
lines := parseFiles(flag.Args())
|
||||||
timings.Stop()
|
timings.Stop()
|
||||||
timings.AddEvent(int64(lines), "lines")
|
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
|
// can only parse generic code for now
|
||||||
base.ExitIfErrors()
|
base.ExitIfErrors()
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import (
|
||||||
// Each declaration in every *syntax.File is converted to a syntax tree
|
// Each declaration in every *syntax.File is converted to a syntax tree
|
||||||
// and its root represented by *Node is appended to xtop.
|
// and its root represented by *Node is appended to xtop.
|
||||||
// Returns the total count of parsed lines.
|
// 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))
|
noders := make([]*noder, 0, len(filenames))
|
||||||
// Limit the number of simultaneously open files.
|
// Limit the number of simultaneously open files.
|
||||||
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
|
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
|
||||||
|
|
@ -48,7 +48,7 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||||
sem <- struct{}{}
|
sem <- struct{}{}
|
||||||
defer func() { <-sem }()
|
defer func() { <-sem }()
|
||||||
defer close(p.err)
|
defer close(p.err)
|
||||||
base := syntax.NewFileBase(filename)
|
fbase := syntax.NewFileBase(filename)
|
||||||
|
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -58,14 +58,16 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
mode := syntax.CheckBranches
|
mode := syntax.CheckBranches
|
||||||
if allowGenerics {
|
if base.Flag.G != 0 {
|
||||||
mode |= syntax.AllowGenerics
|
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)
|
}(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowGenerics {
|
// generic noding phase (using new typechecker)
|
||||||
|
if base.Flag.G != 0 {
|
||||||
|
// setup and syntax error reporting
|
||||||
nodersmap := make(map[string]*noder)
|
nodersmap := make(map[string]*noder)
|
||||||
var files []*syntax.File
|
var files []*syntax.File
|
||||||
for _, p := range noders {
|
for _, p := range noders {
|
||||||
|
|
@ -77,11 +79,12 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||||
files = append(files, p.file)
|
files = append(files, p.file)
|
||||||
lines += p.file.EOF.Line()
|
lines += p.file.EOF.Line()
|
||||||
|
|
||||||
|
}
|
||||||
if base.SyntaxErrors() != 0 {
|
if base.SyntaxErrors() != 0 {
|
||||||
base.ErrorExit()
|
base.ErrorExit()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// typechecking
|
||||||
conf := types2.Config{
|
conf := types2.Config{
|
||||||
InferFromConstraints: true,
|
InferFromConstraints: true,
|
||||||
IgnoreBranches: true, // parser already checked via syntax.CheckBranches mode
|
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
|
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 _, p := range noders {
|
||||||
for e := range p.err {
|
for e := range p.err {
|
||||||
p.errorAt(e.Pos, "%s", e.Msg)
|
p.errorAt(e.Pos, "%s", e.Msg)
|
||||||
|
|
@ -122,10 +152,10 @@ func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
|
||||||
p.node()
|
p.node()
|
||||||
lines += p.file.EOF.Line()
|
lines += p.file.EOF.Line()
|
||||||
p.file = nil // release memory
|
p.file = nil // release memory
|
||||||
|
|
||||||
if base.SyntaxErrors() != 0 {
|
if base.SyntaxErrors() != 0 {
|
||||||
base.ErrorExit()
|
base.ErrorExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
|
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
|
||||||
testdclstack()
|
testdclstack()
|
||||||
}
|
}
|
||||||
|
|
@ -220,9 +250,35 @@ type noder struct {
|
||||||
// current function at the moment each open scope was opened.
|
// current function at the moment each open scope was opened.
|
||||||
scopeVars []int
|
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
|
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) {
|
func (p *noder) funcBody(fn ir.Node, block *syntax.BlockStmt) {
|
||||||
oldScope := p.scope
|
oldScope := p.scope
|
||||||
p.scope = 0
|
p.scope = 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue