...

Source file src/cmd/compile/internal/types/scope.go

     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	
    81	// PkgDef returns the definition associated with s at package scope.
    82	func (s *Sym) PkgDef() *Node {
    83		return *s.pkgDefPtr()
    84	}
    85	
    86	// SetPkgDef sets the definition associated with s at package scope.
    87	func (s *Sym) SetPkgDef(n *Node) {
    88		*s.pkgDefPtr() = n
    89	}
    90	
    91	func (s *Sym) pkgDefPtr() **Node {
    92		// Look for outermost saved declaration, which must be the
    93		// package scope definition, if present.
    94		for _, d := range dclstack {
    95			if s == d.sym {
    96				return &d.def
    97			}
    98		}
    99	
   100		// Otherwise, the declaration hasn't been shadowed within a
   101		// function scope.
   102		return &s.Def
   103	}
   104	

View as plain text