1
2
3
4
5
6
7
8 package src
9
10
11 type XPos struct {
12 index int32
13 lico
14 }
15
16
17 var NoXPos XPos
18
19
20
21
22 func (p XPos) IsKnown() bool {
23 return p.index != 0 || p.Line() != 0
24 }
25
26
27
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
34 func (p XPos) SameFile(q XPos) bool {
35 return p.index == q.index
36 }
37
38
39 func (p XPos) SameFileAndLine(q XPos) bool {
40 return p.index == q.index && p.lico.SameLine(q.lico)
41 }
42
43
44
45 func (p XPos) After(q XPos) bool {
46 n, m := p.index, q.index
47 return n > m || n == m && p.lico > q.lico
48 }
49
50
51 func (p XPos) WithNotStmt() XPos {
52 p.lico = p.lico.withNotStmt()
53 return p
54 }
55
56
57 func (p XPos) WithDefaultStmt() XPos {
58 p.lico = p.lico.withDefaultStmt()
59 return p
60 }
61
62
63 func (p XPos) WithIsStmt() XPos {
64 p.lico = p.lico.withIsStmt()
65 return p
66 }
67
68
69
70
71
72
73 func (p XPos) WithBogusLine() XPos {
74 if p.index == 0 {
75
76 panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.")
77 }
78 p.lico = makeBogusLico()
79 return p
80 }
81
82
83 func (p XPos) WithXlogue(x PosXlogue) XPos {
84 p.lico = p.lico.withXlogue(x)
85 return p
86 }
87
88
89 func (p XPos) LineNumber() string {
90 if !p.IsKnown() {
91 return "?"
92 }
93 return p.lico.lineNumber()
94 }
95
96
97
98
99 func (p XPos) FileIndex() int32 {
100 return p.index
101 }
102
103 func (p XPos) LineNumberHTML() string {
104 if !p.IsKnown() {
105 return "?"
106 }
107 return p.lico.lineNumberHTML()
108 }
109
110
111 func (p XPos) AtColumn1() XPos {
112 p.lico = p.lico.atColumn1()
113 return p
114 }
115
116
117
118 type PosTable struct {
119 baseList []*PosBase
120 indexMap map[*PosBase]int
121 nameMap map[string]int
122 }
123
124
125
126 func (t *PosTable) XPos(pos Pos) XPos {
127 return XPos{t.baseIndex(pos.base), pos.lico}
128 }
129
130 func (t *PosTable) baseIndex(base *PosBase) int32 {
131 if base == nil {
132 return 0
133 }
134
135 if i, ok := t.indexMap[base]; ok {
136 return int32(i)
137 }
138
139 if base.fileIndex >= 0 {
140 panic("PosBase already registered with a PosTable")
141 }
142
143 if t.indexMap == nil {
144 t.baseList = append(t.baseList, nil)
145 t.indexMap = make(map[*PosBase]int)
146 t.nameMap = make(map[string]int)
147 }
148
149 i := len(t.baseList)
150 t.indexMap[base] = i
151 t.baseList = append(t.baseList, base)
152
153 fileIndex, ok := t.nameMap[base.absFilename]
154 if !ok {
155 fileIndex = len(t.nameMap)
156 t.nameMap[base.absFilename] = fileIndex
157 }
158 base.fileIndex = fileIndex
159
160 return int32(i)
161 }
162
163
164
165 func (t *PosTable) Pos(p XPos) Pos {
166 var base *PosBase
167 if p.index != 0 {
168 base = t.baseList[p.index]
169 }
170 return Pos{base, p.lico}
171 }
172
173
174 func (t *PosTable) FileTable() []string {
175
176
177
178 fileLUT := make([]string, len(t.nameMap))
179 for str, i := range t.nameMap {
180 fileLUT[i] = str
181 }
182 return fileLUT
183 }
184
View as plain text