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 )