Source file src/cmd/compile/internal/noder/posmap.go

     1  // Copyright 2021 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  package noder
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/syntax"
    10  	"cmd/internal/src"
    11  )
    12  
    13  // A posMap handles mapping from syntax.Pos to src.XPos.
    14  type posMap struct {
    15  	bases map[*syntax.PosBase]*src.PosBase
    16  	cache struct {
    17  		last *syntax.PosBase
    18  		base *src.PosBase
    19  	}
    20  }
    21  
    22  type poser interface{ Pos() syntax.Pos }
    23  type ender interface{ End() syntax.Pos }
    24  
    25  func (m *posMap) pos(p poser) src.XPos { return m.makeXPos(p.Pos()) }
    26  func (m *posMap) end(p ender) src.XPos { return m.makeXPos(p.End()) }
    27  
    28  func (m *posMap) makeXPos(pos syntax.Pos) src.XPos {
    29  	// Predeclared objects (e.g., the result parameter for error.Error)
    30  	// do not have a position.
    31  	if !pos.IsKnown() {
    32  		return src.NoXPos
    33  	}
    34  
    35  	posBase := m.makeSrcPosBase(pos.Base())
    36  	return base.Ctxt.PosTable.XPos(src.MakePos(posBase, pos.Line(), pos.Col()))
    37  }
    38  
    39  // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
    40  func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
    41  	// fast path: most likely PosBase hasn't changed
    42  	if m.cache.last == b0 {
    43  		return m.cache.base
    44  	}
    45  
    46  	b1, ok := m.bases[b0]
    47  	if !ok {
    48  		fn := b0.Filename()
    49  		absfn := trimFilename(b0)
    50  
    51  		if b0.IsFileBase() {
    52  			b1 = src.NewFileBase(fn, absfn)
    53  		} else {
    54  			// line directive base
    55  			p0 := b0.Pos()
    56  			p0b := p0.Base()
    57  			if p0b == b0 {
    58  				panic("infinite recursion in makeSrcPosBase")
    59  			}
    60  			p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col())
    61  			b1 = src.NewLinePragmaBase(p1, fn, absfn, b0.Line(), b0.Col())
    62  		}
    63  		if m.bases == nil {
    64  			m.bases = make(map[*syntax.PosBase]*src.PosBase)
    65  		}
    66  		m.bases[b0] = b1
    67  	}
    68  
    69  	// update cache
    70  	m.cache.last = b0
    71  	m.cache.base = b1
    72  
    73  	return b1
    74  }
    75  

View as plain text