File size: 1,754 Bytes
e36aeda | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | // 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) makeXPos(pos syntax.Pos) src.XPos {
// Predeclared objects (e.g., the result parameter for error.Error)
// do not have a position.
if !pos.IsKnown() {
return src.NoXPos
}
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()
absfn := trimFilename(b0)
if b0.IsFileBase() {
b1 = src.NewFileBase(fn, absfn)
} 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, absfn, 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
}
|