Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/compile/internal/noder

     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  	if !pos.IsKnown() {
    30  		// TODO(mdempsky): Investigate restoring base.Fatalf.
    31  		return src.NoXPos
    32  	}
    33  
    34  	posBase := m.makeSrcPosBase(pos.Base())
    35  	return base.Ctxt.PosTable.XPos(src.MakePos(posBase, pos.Line(), pos.Col()))
    36  }
    37  
    38  // makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
    39  func (m *posMap) makeSrcPosBase(b0 *syntax.PosBase) *src.PosBase {
    40  	// fast path: most likely PosBase hasn't changed
    41  	if m.cache.last == b0 {
    42  		return m.cache.base
    43  	}
    44  
    45  	b1, ok := m.bases[b0]
    46  	if !ok {
    47  		fn := b0.Filename()
    48  		if b0.IsFileBase() {
    49  			b1 = src.NewFileBase(fn, absFilename(fn))
    50  		} else {
    51  			// line directive base
    52  			p0 := b0.Pos()
    53  			p0b := p0.Base()
    54  			if p0b == b0 {
    55  				panic("infinite recursion in makeSrcPosBase")
    56  			}
    57  			p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col())
    58  			b1 = src.NewLinePragmaBase(p1, fn, fileh(fn), b0.Line(), b0.Col())
    59  		}
    60  		if m.bases == nil {
    61  			m.bases = make(map[*syntax.PosBase]*src.PosBase)
    62  		}
    63  		m.bases[b0] = b1
    64  	}
    65  
    66  	// update cache
    67  	m.cache.last = b0
    68  	m.cache.base = b1
    69  
    70  	return b1
    71  }
    72  
    73  func (m *posMap) join(other *posMap) {
    74  	if m.bases == nil {
    75  		m.bases = make(map[*syntax.PosBase]*src.PosBase)
    76  	}
    77  	for k, v := range other.bases {
    78  		if m.bases[k] != nil {
    79  			base.Fatalf("duplicate posmap bases")
    80  		}
    81  		m.bases[k] = v
    82  	}
    83  }
    84  

View as plain text