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  	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  		absfn := trimFilename(b0)
    49  
    50  		if b0.IsFileBase() {
    51  			b1 = src.NewFileBase(fn, absfn)
    52  		} else {
    53  			// line directive base
    54  			p0 := b0.Pos()
    55  			p0b := p0.Base()
    56  			if p0b == b0 {
    57  				panic("infinite recursion in makeSrcPosBase")
    58  			}
    59  			p1 := src.MakePos(m.makeSrcPosBase(p0b), p0.Line(), p0.Col())
    60  			b1 = src.NewLinePragmaBase(p1, fn, absfn, b0.Line(), b0.Col())
    61  		}
    62  		if m.bases == nil {
    63  			m.bases = make(map[*syntax.PosBase]*src.PosBase)
    64  		}
    65  		m.bases[b0] = b1
    66  	}
    67  
    68  	// update cache
    69  	m.cache.last = b0
    70  	m.cache.base = b1
    71  
    72  	return b1
    73  }
    74  
    75  func (m *posMap) join(other *posMap) {
    76  	if m.bases == nil {
    77  		m.bases = make(map[*syntax.PosBase]*src.PosBase)
    78  	}
    79  	for k, v := range other.bases {
    80  		if m.bases[k] != nil {
    81  			base.Fatalf("duplicate posmap bases")
    82  		}
    83  		m.bases[k] = v
    84  	}
    85  }
    86  

View as plain text