]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/gc/noder.go
[dev.typeparams] merge master into dev.typeparams
[gostls13.git] / src / cmd / compile / internal / gc / noder.go
index 67d24ef0bc70672be7c579b9ee211066b34d80c6..14bacc14a8b39845683aa0baaa900d1854a28b07 100644 (file)
@@ -6,6 +6,7 @@ package gc
 
 import (
        "fmt"
+       "io"
        "os"
        "path/filepath"
        "runtime"
@@ -14,8 +15,10 @@ import (
        "unicode"
        "unicode/utf8"
 
+       "cmd/compile/internal/importer"
        "cmd/compile/internal/syntax"
        "cmd/compile/internal/types"
+       "cmd/compile/internal/types2"
        "cmd/internal/obj"
        "cmd/internal/objabi"
        "cmd/internal/src"
@@ -25,7 +28,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) uint {
+func parseFiles(filenames []string, allowGenerics bool) (lines uint) {
        noders := make([]*noder, 0, len(filenames))
        // Limit the number of simultaneously open files.
        sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
@@ -50,18 +53,61 @@ func parseFiles(filenames []string) uint {
                        }
                        defer f.Close()
 
-                       p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
+                       mode := syntax.CheckBranches
+                       if allowGenerics {
+                               mode |= syntax.AllowGenerics
+                       }
+                       p.file, _ = syntax.Parse(base, f, p.error, p.pragma, mode) // errors are tracked via p.error
                }(filename)
        }
 
-       var lines uint
+       if allowGenerics {
+               nodersmap := make(map[string]*noder)
+               var files []*syntax.File
+               for _, p := range noders {
+                       for e := range p.err {
+                               p.yyerrorpos(e.Pos, "%s", e.Msg)
+                       }
+
+                       nodersmap[p.file.Pos().RelFilename()] = p
+                       files = append(files, p.file)
+                       lines += p.file.EOF.Line()
+
+                       if nsyntaxerrors != 0 {
+                               errorexit()
+                       }
+               }
+
+               conf := types2.Config{
+                       InferFromConstraints: true,
+                       Error: func(err error) {
+                               terr := err.(types2.Error)
+                               if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
+                                       // types2 reports error clarifications via separate
+                                       // error messages which are indented with a tab.
+                                       // Ignore them to satisfy tools and tests that expect
+                                       // only one error in such cases.
+                                       // TODO(gri) Need to adjust error reporting in types2.
+                                       return
+                               }
+                               p := nodersmap[terr.Pos.RelFilename()]
+                               yyerrorl(p.makeXPos(terr.Pos), "%s", terr.Msg)
+                       },
+                       Importer: &gcimports{
+                               packages: make(map[string]*types2.Package),
+                       },
+               }
+               conf.Check(Ctxt.Pkgpath, files, nil)
+               return
+       }
+
        for _, p := range noders {
                for e := range p.err {
                        p.yyerrorpos(e.Pos, "%s", e.Msg)
                }
 
                p.node()
-               lines += p.file.Lines
+               lines += p.file.EOF.Line()
                p.file = nil // release memory
 
                if nsyntaxerrors != 0 {
@@ -72,8 +118,24 @@ func parseFiles(filenames []string) uint {
        }
 
        localpkg.Height = myheight
+       return
+}
 
-       return lines
+// Temporary import helper to get type2-based type-checking going.
+type gcimports struct {
+       packages map[string]*types2.Package
+       lookup   func(path string) (io.ReadCloser, error)
+}
+
+func (m *gcimports) Import(path string) (*types2.Package, error) {
+       return m.ImportFrom(path, "" /* no vendoring */, 0)
+}
+
+func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
+       if mode != 0 {
+               panic("mode must be 0")
+       }
+       return importer.Import(m.packages, path, srcDir, m.lookup)
 }
 
 // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.