for _, filename := range filenames {
p := &noder{
- basemap: make(map[*syntax.PosBase]*src.PosBase),
err: make(chan syntax.Error),
trackScopes: base.Flag.Dwarf,
}
return importer.Import(m.packages, path, srcDir, m.lookup)
}
-// makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
-func (p *noder) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
- // fast path: most likely PosBase hasn't changed
- if p.basecache.last == b0 {
- return p.basecache.base
- }
-
- b1, ok := p.basemap[b0]
- if !ok {
- fn := b0.Filename()
- if b0.IsFileBase() {
- b1 = src.NewFileBase(fn, absFilename(fn))
- } else {
- // line directive base
- p0 := b0.Pos()
- p0b := p0.Base()
- if p0b == b0 {
- panic("infinite recursion in makeSrcPosBase")
- }
- p1 := src.MakePos(p.makeSrcPosBase(p0b), p0.Line(), p0.Col())
- b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col())
- }
- p.basemap[b0] = b1
- }
-
- // update cache
- p.basecache.last = b0
- p.basecache.base = b1
-
- return b1
-}
-
-func (p *noder) makeXPos(pos syntax.Pos) (_ src.XPos) {
- return base.Ctxt.PosTable.XPos(src.MakePos(p.makeSrcPosBase(pos.Base()), pos.Line(), pos.Col()))
-}
-
func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
base.ErrorfAt(p.makeXPos(pos), format, args...)
}
// noder transforms package syntax's AST into a Node tree.
type noder struct {
- basemap map[*syntax.PosBase]*src.PosBase
- basecache struct {
- last *syntax.PosBase
- base *src.PosBase
- }
+ posMap
file *syntax.File
linknames []linkname
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
- n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
+ pos := base.Pos
+ if expr != syntax.ImplicitOne { // ImplicitOne doesn't have a unique position
+ pos = p.pos(expr)
+ }
+ n := ir.NewBasicLit(pos, p.basicLit(expr))
if expr.Kind == syntax.RuneLit {
n.SetType(types.UntypedRune)
}
return x
}
-func (p *noder) pos(n syntax.Node) src.XPos {
- // TODO(gri): orig.Pos() should always be known - fix package syntax
- xpos := base.Pos
- if pos := n.Pos(); pos.IsKnown() {
- xpos = p.makeXPos(pos)
- }
- return xpos
-}
-
func (p *noder) setlineno(n syntax.Node) {
- if n != nil {
+ if n != nil && n != syntax.ImplicitOne {
base.Pos = p.pos(n)
}
}
--- /dev/null
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package noder
+
+import (
+ "cmd/compile/internal/base"
+ "cmd/compile/internal/syntax"
+ "cmd/internal/src"
+)
+
+// A posMap handles mapping from syntax.Pos to src.XPos.
+type posMap struct {
+ bases map[*syntax.PosBase]*src.PosBase
+ cache struct {
+ last *syntax.PosBase
+ base *src.PosBase
+ }
+}
+
+type poser interface{ Pos() syntax.Pos }
+type ender interface{ End() syntax.Pos }
+
+func (m *posMap) pos(p poser) src.XPos { return m.makeXPos(p.Pos()) }
+func (m *posMap) end(p ender) src.XPos { return m.makeXPos(p.End()) }
+
+func (m *posMap) makeXPos(pos syntax.Pos) src.XPos {
+ if !pos.IsKnown() {
+ base.Fatalf("unknown position")
+ }
+
+ posBase := m.makeSrcPosBase(pos.Base())
+ return base.Ctxt.PosTable.XPos(src.MakePos(posBase, pos.Line(), pos.Col()))
+}
+
+// makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
+func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
+ // fast path: most likely PosBase hasn't changed
+ if m.cache.last == b0 {
+ return m.cache.base
+ }
+
+ b1, ok := m.bases[b0]
+ if !ok {
+ fn := b0.Filename()
+ if b0.IsFileBase() {
+ b1 = src.NewFileBase(fn, absFilename(fn))
+ } else {
+ // line directive base
+ p0 := b0.Pos()
+ p0b := p0.Base()
+ if p0b == b0 {
+ panic("infinite recursion in makeSrcPosBase")
+ }
+ p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col())
+ b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col())
+ }
+ if m.bases == nil {
+ m.bases = make(map[*syntax.PosBase]*src.PosBase)
+ }
+ m.bases[b0] = b1
+ }
+
+ // update cache
+ m.cache.last = b0
+ m.cache.base = b1
+
+ return b1
+}
+
+func (m *posMap) join(other *posMap) {
+ for k, v := range other.bases {
+ if m.bases[k] != nil {
+ base.Fatalf("duplicate posmap bases")
+ }
+ m.bases[k] = v
+ }
+}