github.com/Rookout/GoSDK@v0.1.48/pkg/services/assembler/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.assembler file.
     4  
     5  // This file implements the encoding of source positions.
     6  
     7  package src
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"io"
    13  )
    14  
    15  
    16  
    17  
    18  
    19  
    20  
    21  
    22  
    23  
    24  
    25  
    26  
    27  
    28  type Pos struct {
    29  	base *PosBase
    30  	lico
    31  }
    32  
    33  
    34  var NoPos Pos
    35  
    36  
    37  
    38  func MakePos(base *PosBase, line, col uint) Pos {
    39  	return Pos{base, makeLico(line, col)}
    40  }
    41  
    42  
    43  
    44  
    45  func (p Pos) IsKnown() bool {
    46  	return p.base != nil || p.Line() != 0
    47  }
    48  
    49  
    50  
    51  func (p Pos) Before(q Pos) bool {
    52  	n, m := p.Filename(), q.Filename()
    53  	return n < m || n == m && p.lico < q.lico
    54  }
    55  
    56  
    57  
    58  func (p Pos) After(q Pos) bool {
    59  	n, m := p.Filename(), q.Filename()
    60  	return n > m || n == m && p.lico > q.lico
    61  }
    62  
    63  func (p Pos) LineNumber() string {
    64  	if !p.IsKnown() {
    65  		return "?"
    66  	}
    67  	return p.lico.lineNumber()
    68  }
    69  
    70  func (p Pos) LineNumberHTML() string {
    71  	if !p.IsKnown() {
    72  		return "?"
    73  	}
    74  	return p.lico.lineNumberHTML()
    75  }
    76  
    77  
    78  func (p Pos) Filename() string { return p.base.Pos().RelFilename() }
    79  
    80  
    81  func (p Pos) Base() *PosBase { return p.base }
    82  
    83  
    84  func (p *Pos) SetBase(base *PosBase) { p.base = base }
    85  
    86  
    87  func (p Pos) RelFilename() string { return p.base.Filename() }
    88  
    89  
    90  func (p Pos) RelLine() uint {
    91  	b := p.base
    92  	if b.Line() == 0 {
    93  		
    94  		return 0
    95  	}
    96  	return b.Line() + (p.Line() - b.Pos().Line())
    97  }
    98  
    99  
   100  func (p Pos) RelCol() uint {
   101  	b := p.base
   102  	if b.Col() == 0 {
   103  		
   104  		
   105  		
   106  		
   107  		return 0
   108  	}
   109  	if p.Line() == b.Pos().Line() {
   110  		
   111  		return b.Col() + (p.Col() - b.Pos().Col())
   112  	}
   113  	return p.Col()
   114  }
   115  
   116  
   117  func (p Pos) AbsFilename() string { return p.base.AbsFilename() }
   118  
   119  
   120  
   121  func (p Pos) SymFilename() string { return p.base.SymFilename() }
   122  
   123  func (p Pos) String() string {
   124  	return p.Format(true, true)
   125  }
   126  
   127  
   128  
   129  
   130  
   131  
   132  func (p Pos) Format(showCol, showOrig bool) string {
   133  	buf := new(bytes.Buffer)
   134  	p.WriteTo(buf, showCol, showOrig)
   135  	return buf.String()
   136  }
   137  
   138  
   139  func (p Pos) WriteTo(w io.Writer, showCol, showOrig bool) {
   140  	if !p.IsKnown() {
   141  		io.WriteString(w, "<unknown line number>")
   142  		return
   143  	}
   144  
   145  	if b := p.base; b == b.Pos().base {
   146  		
   147  		format(w, p.Filename(), p.Line(), p.Col(), showCol)
   148  		return
   149  	}
   150  
   151  	
   152  	
   153  	
   154  	
   155  	
   156  	
   157  	
   158  	
   159  	format(w, p.RelFilename(), p.RelLine(), p.RelCol(), showCol)
   160  	if showOrig {
   161  		io.WriteString(w, "[")
   162  		format(w, p.Filename(), p.Line(), p.Col(), showCol)
   163  		io.WriteString(w, "]")
   164  	}
   165  }
   166  
   167  
   168  
   169  func format(w io.Writer, filename string, line, col uint, showCol bool) {
   170  	io.WriteString(w, filename)
   171  	io.WriteString(w, ":")
   172  	fmt.Fprint(w, line)
   173  	
   174  	if showCol && 0 < col && col < colMax {
   175  		io.WriteString(w, ":")
   176  		fmt.Fprint(w, col)
   177  	}
   178  }
   179  
   180  
   181  func formatstr(filename string, line, col uint, showCol bool) string {
   182  	buf := new(bytes.Buffer)
   183  	format(buf, filename, line, col, showCol)
   184  	return buf.String()
   185  }
   186  
   187  
   188  
   189  
   190  
   191  
   192  type PosBase struct {
   193  	pos         Pos    
   194  	filename    string 
   195  	absFilename string 
   196  	symFilename string 
   197  	line, col   uint   
   198  	inl         int    
   199  }
   200  
   201  
   202  
   203  func NewFileBase(filename, absFilename string) *PosBase {
   204  	base := &PosBase{
   205  		filename:    filename,
   206  		absFilename: absFilename,
   207  		symFilename: FileSymPrefix + absFilename,
   208  		line:        1,
   209  		col:         1,
   210  		inl:         -1,
   211  	}
   212  	base.pos = MakePos(base, 1, 1)
   213  	return base
   214  }
   215  
   216  
   217  
   218  
   219  
   220  
   221  
   222  func NewLinePragmaBase(pos Pos, filename, absFilename string, line, col uint) *PosBase {
   223  	return &PosBase{pos, filename, absFilename, FileSymPrefix + absFilename, line, col, -1}
   224  }
   225  
   226  
   227  
   228  func NewInliningBase(old *PosBase, inlTreeIndex int) *PosBase {
   229  	if old == nil {
   230  		base := &PosBase{line: 1, col: 1, inl: inlTreeIndex}
   231  		base.pos = MakePos(base, 1, 1)
   232  		return base
   233  	}
   234  	copy := *old
   235  	base := &copy
   236  	base.inl = inlTreeIndex
   237  	if old == old.pos.base {
   238  		base.pos.base = base
   239  	}
   240  	return base
   241  }
   242  
   243  var noPos Pos
   244  
   245  
   246  
   247  func (b *PosBase) Pos() *Pos {
   248  	if b != nil {
   249  		return &b.pos
   250  	}
   251  	return &noPos
   252  }
   253  
   254  
   255  
   256  func (b *PosBase) Filename() string {
   257  	if b != nil {
   258  		return b.filename
   259  	}
   260  	return ""
   261  }
   262  
   263  
   264  
   265  func (b *PosBase) AbsFilename() string {
   266  	if b != nil {
   267  		return b.absFilename
   268  	}
   269  	return ""
   270  }
   271  
   272  const FileSymPrefix = "gofile.."
   273  
   274  
   275  
   276  
   277  func (b *PosBase) SymFilename() string {
   278  	if b != nil {
   279  		return b.symFilename
   280  	}
   281  	return FileSymPrefix + "??"
   282  }
   283  
   284  
   285  
   286  func (b *PosBase) Line() uint {
   287  	if b != nil {
   288  		return b.line
   289  	}
   290  	return 0
   291  }
   292  
   293  
   294  
   295  func (b *PosBase) Col() uint {
   296  	if b != nil {
   297  		return b.col
   298  	}
   299  	return 0
   300  }
   301  
   302  
   303  
   304  
   305  func (b *PosBase) InliningIndex() int {
   306  	if b != nil {
   307  		return b.inl
   308  	}
   309  	return -1
   310  }
   311  
   312  
   313  
   314  
   315  
   316  type lico uint32
   317  
   318  
   319  
   320  
   321  
   322  
   323  
   324  
   325  
   326  
   327  
   328  const (
   329  	lineBits, lineMax     = 20, 1<<lineBits - 2
   330  	bogusLine             = 1 
   331  	isStmtBits, isStmtMax = 2, 1<<isStmtBits - 1
   332  	xlogueBits, xlogueMax = 2, 1<<xlogueBits - 1
   333  	colBits, colMax       = 32 - lineBits - xlogueBits - isStmtBits, 1<<colBits - 1
   334  
   335  	isStmtShift = 0
   336  	isStmtMask  = isStmtMax << isStmtShift
   337  	xlogueShift = isStmtBits + isStmtShift
   338  	xlogueMask  = xlogueMax << xlogueShift
   339  	colShift    = xlogueBits + xlogueShift
   340  	lineShift   = colBits + colShift
   341  )
   342  const (
   343  	
   344  	
   345  	
   346  	
   347  	
   348  	
   349  	
   350  	
   351  	
   352  	
   353  	
   354  	
   355  	
   356  	
   357  	
   358  	
   359  	
   360  	
   361  	
   362  	
   363  	
   364  	
   365  	
   366  	
   367  	
   368  	
   369  	
   370  	PosDefaultStmt uint = iota 
   371  	PosIsStmt                  
   372  	PosNotStmt                 
   373  )
   374  
   375  type PosXlogue uint
   376  
   377  const (
   378  	PosDefaultLogue PosXlogue = iota
   379  	PosPrologueEnd
   380  	PosEpilogueBegin
   381  )
   382  
   383  func makeLicoRaw(line, col uint) lico {
   384  	return lico(line<<lineShift | col<<colShift)
   385  }
   386  
   387  
   388  
   389  func makeBogusLico() lico {
   390  	return makeLicoRaw(bogusLine, 0).withIsStmt()
   391  }
   392  
   393  func makeLico(line, col uint) lico {
   394  	if line >= lineMax {
   395  		
   396  		line = lineMax
   397  		
   398  		
   399  		col = 0
   400  	}
   401  	if col > colMax {
   402  		
   403  		col = colMax
   404  	}
   405  	
   406  	return makeLicoRaw(line, col)
   407  }
   408  
   409  func (x lico) Line() uint           { return uint(x) >> lineShift }
   410  func (x lico) SameLine(y lico) bool { return 0 == (x^y)&^lico(1<<lineShift-1) }
   411  func (x lico) Col() uint            { return uint(x) >> colShift & colMax }
   412  func (x lico) IsStmt() uint {
   413  	if x == 0 {
   414  		return PosNotStmt
   415  	}
   416  	return uint(x) >> isStmtShift & isStmtMax
   417  }
   418  func (x lico) Xlogue() PosXlogue {
   419  	return PosXlogue(uint(x) >> xlogueShift & xlogueMax)
   420  }
   421  
   422  
   423  func (x lico) withNotStmt() lico {
   424  	return x.withStmt(PosNotStmt)
   425  }
   426  
   427  
   428  func (x lico) withDefaultStmt() lico {
   429  	return x.withStmt(PosDefaultStmt)
   430  }
   431  
   432  
   433  func (x lico) withIsStmt() lico {
   434  	return x.withStmt(PosIsStmt)
   435  }
   436  
   437  
   438  func (x lico) withXlogue(xlogue PosXlogue) lico {
   439  	if x == 0 {
   440  		if xlogue == 0 {
   441  			return x
   442  		}
   443  		
   444  		x = lico(PosNotStmt << isStmtShift)
   445  	}
   446  	return lico(uint(x) & ^uint(xlogueMax<<xlogueShift) | (uint(xlogue) << xlogueShift))
   447  }
   448  
   449  
   450  func (x lico) withStmt(stmt uint) lico {
   451  	if x == 0 {
   452  		return lico(0)
   453  	}
   454  	return lico(uint(x) & ^uint(isStmtMax<<isStmtShift) | (stmt << isStmtShift))
   455  }
   456  
   457  func (x lico) lineNumber() string {
   458  	return fmt.Sprintf("%d", x.Line())
   459  }
   460  
   461  func (x lico) lineNumberHTML() string {
   462  	if x.IsStmt() == PosDefaultStmt {
   463  		return fmt.Sprintf("%d", x.Line())
   464  	}
   465  	style, pfx := "b", "+"
   466  	if x.IsStmt() == PosNotStmt {
   467  		style = "s" 
   468  		pfx = ""
   469  	}
   470  	return fmt.Sprintf("<%s>%s%d</%s>", style, pfx, x.Line(), style)
   471  }
   472  
   473  func (x lico) atColumn1() lico {
   474  	return makeLico(x.Line(), 1).withIsStmt()
   475  }