github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/internal/src/pos.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 encoding of source positions.
     6  
     7  package src
     8  
     9  import (
    10  	"github.com/shogo82148/std/io"
    11  )
    12  
    13  // A Pos encodes a source position consisting of a (line, column) number pair
    14  // and a position base. A zero Pos is a ready to use "unknown" position (nil
    15  // position base and zero line number).
    16  //
    17  // The (line, column) values refer to a position in a file independent of any
    18  // position base ("absolute" file position).
    19  //
    20  // The position base is used to determine the "relative" position, that is the
    21  // filename and line number relative to the position base. If the base refers
    22  // to the current file, there is no difference between absolute and relative
    23  // positions. If it refers to a //line directive, a relative position is relative
    24  // to that directive. A position base in turn contains the position at which it
    25  // was introduced in the current file.
    26  type Pos struct {
    27  	base *PosBase
    28  	lico
    29  }
    30  
    31  // NoPos is a valid unknown position.
    32  var NoPos Pos
    33  
    34  // MakePos creates a new Pos value with the given base, and (file-absolute)
    35  // line and column.
    36  func MakePos(base *PosBase, line, col uint) Pos
    37  
    38  // IsKnown reports whether the position p is known.
    39  // A position is known if it either has a non-nil
    40  // position base, or a non-zero line number.
    41  func (p Pos) IsKnown() bool
    42  
    43  // Before reports whether the position p comes before q in the source.
    44  // For positions in different files, ordering is by filename.
    45  func (p Pos) Before(q Pos) bool
    46  
    47  // After reports whether the position p comes after q in the source.
    48  // For positions in different files, ordering is by filename.
    49  func (p Pos) After(q Pos) bool
    50  
    51  func (p Pos) LineNumber() string
    52  
    53  func (p Pos) LineNumberHTML() string
    54  
    55  // Filename returns the name of the actual file containing this position.
    56  func (p Pos) Filename() string
    57  
    58  // Base returns the position base.
    59  func (p Pos) Base() *PosBase
    60  
    61  // SetBase sets the position base.
    62  func (p *Pos) SetBase(base *PosBase)
    63  
    64  // RelFilename returns the filename recorded with the position's base.
    65  func (p Pos) RelFilename() string
    66  
    67  // RelLine returns the line number relative to the position's base.
    68  func (p Pos) RelLine() uint
    69  
    70  // RelCol returns the column number relative to the position's base.
    71  func (p Pos) RelCol() uint
    72  
    73  // AbsFilename() returns the absolute filename recorded with the position's base.
    74  func (p Pos) AbsFilename() string
    75  
    76  // FileIndex returns the file index of the position's base's absolute
    77  // filename within the PosTable that it was registered.
    78  func (p Pos) FileIndex() int
    79  
    80  func (p Pos) String() string
    81  
    82  // Format formats a position as "filename:line" or "filename:line:column",
    83  // controlled by the showCol flag and if the column is known (!= 0).
    84  // For positions relative to line directives, the original position is
    85  // shown as well, as in "filename:line[origfile:origline:origcolumn] if
    86  // showOrig is set.
    87  func (p Pos) Format(showCol, showOrig bool) string
    88  
    89  // WriteTo a position to w, formatted as Format does.
    90  func (p Pos) WriteTo(w io.Writer, showCol, showOrig bool)
    91  
    92  // A PosBase encodes a filename and base position.
    93  // Typically, each file and line directive introduce a PosBase.
    94  type PosBase struct {
    95  	pos         Pos
    96  	filename    string
    97  	absFilename string
    98  	line, col   uint
    99  	inl         int
   100  	fileIndex   int
   101  }
   102  
   103  // NewFileBase returns a new *PosBase for a file with the given (relative and
   104  // absolute) filenames.
   105  func NewFileBase(filename, absFilename string) *PosBase
   106  
   107  // NewLinePragmaBase returns a new *PosBase for a line directive of the form
   108  //
   109  //	//line filename:line:col
   110  //	/*line filename:line:col*/
   111  //
   112  // at position pos.
   113  func NewLinePragmaBase(pos Pos, filename, absFilename string, line, col uint) *PosBase
   114  
   115  // NewInliningBase returns a copy of the orig PosBase with the given inlining
   116  // index. If orig == nil, NewInliningBase panics.
   117  func NewInliningBase(orig *PosBase, inlTreeIndex int) *PosBase
   118  
   119  // Pos returns the position at which base is located.
   120  // If b == nil, the result is the zero position.
   121  func (b *PosBase) Pos() *Pos
   122  
   123  // Filename returns the filename recorded with the base.
   124  // If b == nil, the result is the empty string.
   125  func (b *PosBase) Filename() string
   126  
   127  // AbsFilename returns the absolute filename recorded with the base.
   128  // If b == nil, the result is the empty string.
   129  func (b *PosBase) AbsFilename() string
   130  
   131  // FileSymPrefix is the linker symbol prefix that used to be used for
   132  // linker pseudo-symbols representing file names.
   133  const FileSymPrefix = "gofile.."
   134  
   135  // FileIndex returns the index of the base's absolute filename within
   136  // its PosTable's FileTable. It panics if it hasn't been registered
   137  // with a PosTable. If b == nil, the result is -1.
   138  func (b *PosBase) FileIndex() int
   139  
   140  // Line returns the line number recorded with the base.
   141  // If b == nil, the result is 0.
   142  func (b *PosBase) Line() uint
   143  
   144  // Col returns the column number recorded with the base.
   145  // If b == nil, the result is 0.
   146  func (b *PosBase) Col() uint
   147  
   148  // InliningIndex returns the index into the global inlining
   149  // tree recorded with the base. If b == nil or the base has
   150  // not been inlined, the result is < 0.
   151  func (b *PosBase) InliningIndex() int
   152  
   153  const (
   154  	// It is expected that the front end or a phase in SSA will usually generate positions tagged with
   155  	// PosDefaultStmt, but note statement boundaries with PosIsStmt.  Simple statements will have a single
   156  	// boundary; for loops with initialization may have one for their entry and one for their back edge
   157  	// (this depends on exactly how the loop is compiled; the intent is to provide a good experience to a
   158  	// user debugging a program; the goal is that a breakpoint set on the loop line fires both on entry
   159  	// and on iteration).  Proper treatment of non-gofmt input with multiple simple statements on a single
   160  	// line is TBD.
   161  	//
   162  	// Optimizing compilation will move instructions around, and some of these will become known-bad as
   163  	// step targets for debugging purposes (examples: register spills and reloads; code generated into
   164  	// the entry block; invariant code hoisted out of loops) but those instructions will still have interesting
   165  	// positions for profiling purposes. To reflect this these positions will be changed to PosNotStmt.
   166  	//
   167  	// When the optimizer removes an instruction marked PosIsStmt; it should attempt to find a nearby
   168  	// instruction with the same line marked PosDefaultStmt to be the new statement boundary.  I.e., the
   169  	// optimizer should make a best-effort to conserve statement boundary positions, and might be enhanced
   170  	// to note when a statement boundary is not conserved.
   171  	//
   172  	// Code cloning, e.g. loop unrolling or loop unswitching, is an exception to the conservation rule
   173  	// because a user running a debugger would expect to see breakpoints active in the copies of the code.
   174  	//
   175  	// In non-optimizing compilation there is still a role for PosNotStmt because of code generation
   176  	// into the entry block.  PosIsStmt statement positions should be conserved.
   177  	//
   178  	// When code generation occurs any remaining default-marked positions are replaced with not-statement
   179  	// positions.
   180  	//
   181  	PosDefaultStmt uint = iota
   182  	PosIsStmt
   183  	PosNotStmt
   184  )
   185  
   186  type PosXlogue uint
   187  
   188  const (
   189  	PosDefaultLogue PosXlogue = iota
   190  	PosPrologueEnd
   191  	PosEpilogueBegin
   192  )