Home | History | Annotate | Download | only in src
      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 // After reports whether the position p comes after q in the source.
     34 // For positions with different bases, ordering is by base index.
     35 func (p XPos) After(q XPos) bool {
     36 	n, m := p.index, q.index
     37 	return n > m || n == m && p.lico > q.lico
     38 }
     39 
     40 // A PosTable tracks Pos -> XPos conversions and vice versa.
     41 // Its zero value is a ready-to-use PosTable.
     42 type PosTable struct {
     43 	baseList []*PosBase
     44 	indexMap map[*PosBase]int
     45 }
     46 
     47 // XPos returns the corresponding XPos for the given pos,
     48 // adding pos to t if necessary.
     49 func (t *PosTable) XPos(pos Pos) XPos {
     50 	m := t.indexMap
     51 	if m == nil {
     52 		// Create new list and map and populate with nil
     53 		// base so that NoPos always gets index 0.
     54 		t.baseList = append(t.baseList, nil)
     55 		m = map[*PosBase]int{nil: 0}
     56 		t.indexMap = m
     57 	}
     58 	i, ok := m[pos.base]
     59 	if !ok {
     60 		i = len(t.baseList)
     61 		t.baseList = append(t.baseList, pos.base)
     62 		t.indexMap[pos.base] = i
     63 	}
     64 	return XPos{int32(i), pos.lico}
     65 }
     66 
     67 // Pos returns the corresponding Pos for the given p.
     68 // If p cannot be translated via t, the function panics.
     69 func (t *PosTable) Pos(p XPos) Pos {
     70 	var base *PosBase
     71 	if p.index != 0 {
     72 		base = t.baseList[p.index]
     73 	}
     74 	return Pos{base, p.lico}
     75 }
     76