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  }