github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/cmd/compile/internal/types/scope.go (about)

     1  // Copyright 2017 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 types
     6  
     7  import "cmd/internal/src"
     8  
     9  // Declaration stack & operations
    10  
    11  var blockgen int32 = 1 // max block number
    12  var Block int32        // current block number
    13  
    14  // A dsym stores a symbol's shadowed declaration so that it can be
    15  // restored once the block scope ends.
    16  type dsym struct {
    17  	sym        *Sym // sym == nil indicates stack mark
    18  	def        *Node
    19  	block      int32
    20  	lastlineno src.XPos // last declaration for diagnostic
    21  }
    22  
    23  // dclstack maintains a stack of shadowed symbol declarations so that
    24  // Popdcl can restore their declarations when a block scope ends.
    25  var dclstack []dsym
    26  
    27  // Pushdcl pushes the current declaration for symbol s (if any) so that
    28  // it can be shadowed by a new declaration within a nested block scope.
    29  func Pushdcl(s *Sym) {
    30  	dclstack = append(dclstack, dsym{
    31  		sym:        s,
    32  		def:        s.Def,
    33  		block:      s.Block,
    34  		lastlineno: s.Lastlineno,
    35  	})
    36  }
    37  
    38  // Popdcl pops the innermost block scope and restores all symbol declarations
    39  // to their previous state.
    40  func Popdcl() {
    41  	for i := len(dclstack); i > 0; i-- {
    42  		d := &dclstack[i-1]
    43  		s := d.sym
    44  		if s == nil {
    45  			// pop stack mark
    46  			Block = d.block
    47  			dclstack = dclstack[:i-1]
    48  			return
    49  		}
    50  
    51  		s.Def = d.def
    52  		s.Block = d.block
    53  		s.Lastlineno = d.lastlineno
    54  
    55  		// Clear dead pointer fields.
    56  		d.sym = nil
    57  		d.def = nil
    58  	}
    59  	Fatalf("popdcl: no stack mark")
    60  }
    61  
    62  // Markdcl records the start of a new block scope for declarations.
    63  func Markdcl() {
    64  	dclstack = append(dclstack, dsym{
    65  		sym:   nil, // stack mark
    66  		block: Block,
    67  	})
    68  	blockgen++
    69  	Block = blockgen
    70  }
    71  
    72  func IsDclstackValid() bool {
    73  	for _, d := range dclstack {
    74  		if d.sym == nil {
    75  			return false
    76  		}
    77  	}
    78  	return true
    79  }