Home | History | Annotate | Download | only in types
      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 }
     80