github.com/gernest/nezuko@v0.1.2/internal/src/xpos.go (about) 1 // Copyright 2016 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 // This file implements the compressed encoding of source 6 // positions using a lookup table. 7 8 package src 9 10 // XPos is a more compact representation of Pos. 11 type XPos struct { 12 index int32 13 lico 14 } 15 16 // NoXPos is a valid unknown position. 17 var NoXPos XPos 18 19 // IsKnown reports whether the position p is known. 20 // XPos.IsKnown() matches Pos.IsKnown() for corresponding 21 // positions. 22 func (p XPos) IsKnown() bool { 23 return p.index != 0 || p.Line() != 0 24 } 25 26 // Before reports whether the position p comes before q in the source. 27 // For positions with different bases, ordering is by base index. 28 func (p XPos) Before(q XPos) bool { 29 n, m := p.index, q.index 30 return n < m || n == m && p.lico < q.lico 31 } 32 33 // SameFile reports whether p and q are positions in the same file. 34 func (p XPos) SameFile(q XPos) bool { 35 return p.index == q.index 36 } 37 38 // After reports whether the position p comes after q in the source. 39 // For positions with different bases, ordering is by base index. 40 func (p XPos) After(q XPos) bool { 41 n, m := p.index, q.index 42 return n > m || n == m && p.lico > q.lico 43 } 44 45 // WithNotStmt returns the same location to be marked with DWARF is_stmt=0 46 func (p XPos) WithNotStmt() XPos { 47 p.lico = p.lico.withNotStmt() 48 return p 49 } 50 51 // WithDefaultStmt returns the same location with undetermined is_stmt 52 func (p XPos) WithDefaultStmt() XPos { 53 p.lico = p.lico.withDefaultStmt() 54 return p 55 } 56 57 // WithIsStmt returns the same location to be marked with DWARF is_stmt=1 58 func (p XPos) WithIsStmt() XPos { 59 p.lico = p.lico.withIsStmt() 60 return p 61 } 62 63 // WithXlogue returns the same location but marked with DWARF function prologue/epilogue 64 func (p XPos) WithXlogue(x PosXlogue) XPos { 65 p.lico = p.lico.withXlogue(x) 66 return p 67 } 68 69 func (p XPos) LineNumber() string { 70 if !p.IsKnown() { 71 return "?" 72 } 73 return p.lico.lineNumber() 74 } 75 76 func (p XPos) LineNumberHTML() string { 77 if !p.IsKnown() { 78 return "?" 79 } 80 return p.lico.lineNumberHTML() 81 } 82 83 // A PosTable tracks Pos -> XPos conversions and vice versa. 84 // Its zero value is a ready-to-use PosTable. 85 type PosTable struct { 86 baseList []*PosBase 87 indexMap map[*PosBase]int 88 } 89 90 // XPos returns the corresponding XPos for the given pos, 91 // adding pos to t if necessary. 92 func (t *PosTable) XPos(pos Pos) XPos { 93 m := t.indexMap 94 if m == nil { 95 // Create new list and map and populate with nil 96 // base so that NoPos always gets index 0. 97 t.baseList = append(t.baseList, nil) 98 m = map[*PosBase]int{nil: 0} 99 t.indexMap = m 100 } 101 i, ok := m[pos.base] 102 if !ok { 103 i = len(t.baseList) 104 t.baseList = append(t.baseList, pos.base) 105 t.indexMap[pos.base] = i 106 } 107 return XPos{int32(i), pos.lico} 108 } 109 110 // Pos returns the corresponding Pos for the given p. 111 // If p cannot be translated via t, the function panics. 112 func (t *PosTable) Pos(p XPos) Pos { 113 var base *PosBase 114 if p.index != 0 { 115 base = t.baseList[p.index] 116 } 117 return Pos{base, p.lico} 118 }