github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/noder/posmap.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package noder 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 9 "github.com/bir3/gocompiler/src/cmd/compile/internal/syntax" 10 "github.com/bir3/gocompiler/src/cmd/internal/src" 11 ) 12 13 // A posMap handles mapping from syntax.Pos to src.XPos. 14 type posMap struct { 15 bases map[*syntax.PosBase]*src.PosBase 16 cache struct { 17 last *syntax.PosBase 18 base *src.PosBase 19 } 20 } 21 22 type poser interface{ Pos() syntax.Pos } 23 type ender interface{ End() syntax.Pos } 24 25 func (m *posMap) pos(p poser) src.XPos { return m.makeXPos(p.Pos()) } 26 func (m *posMap) end(p ender) src.XPos { return m.makeXPos(p.End()) } 27 28 func (m *posMap) makeXPos(pos syntax.Pos) src.XPos { 29 // Predeclared objects (e.g., the result parameter for error.Error) 30 // do not have a position. 31 if !pos.IsKnown() { 32 return src.NoXPos 33 } 34 35 posBase := m.makeSrcPosBase(pos.Base()) 36 return base.Ctxt.PosTable.XPos(src.MakePos(posBase, pos.Line(), pos.Col())) 37 } 38 39 // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase. 40 func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase { 41 // fast path: most likely PosBase hasn't changed 42 if m.cache.last == b0 { 43 return m.cache.base 44 } 45 46 b1, ok := m.bases[b0] 47 if !ok { 48 fn := b0.Filename() 49 absfn := trimFilename(b0) 50 51 if b0.IsFileBase() { 52 b1 = src.NewFileBase(fn, absfn) 53 } else { 54 // line directive base 55 p0 := b0.Pos() 56 p0b := p0.Base() 57 if p0b == b0 { 58 panic("infinite recursion in makeSrcPosBase") 59 } 60 p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col()) 61 b1 = src.NewLinePragmaBase(p1, fn, absfn, b0.Line(), b0.Col()) 62 } 63 if m.bases == nil { 64 m.bases = make(map[*syntax.PosBase]*src.PosBase) 65 } 66 m.bases[b0] = b1 67 } 68 69 // update cache 70 m.cache.last = b0 71 m.cache.base = b1 72 73 return b1 74 }