// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package types import ( "cmd/compile/internal/base" "cmd/internal/src" ) // Declaration stack & operations var blockgen int32 = 1 // max block number var Block int32 = 1 // current block number // A dsym stores a symbol's shadowed declaration so that it can be // restored once the block scope ends. type dsym struct { sym *Sym // sym == nil indicates stack mark def Object block int32 lastlineno src.XPos // last declaration for diagnostic } // dclstack maintains a stack of shadowed symbol declarations so that // Popdcl can restore their declarations when a block scope ends. var dclstack []dsym // Pushdcl pushes the current declaration for symbol s (if any) so that // it can be shadowed by a new declaration within a nested block scope. func Pushdcl(s *Sym) { dclstack = append(dclstack, dsym{ sym: s, def: s.Def, block: s.Block, lastlineno: s.Lastlineno, }) } // Popdcl pops the innermost block scope and restores all symbol declarations // to their previous state. func Popdcl() { for i := len(dclstack); i > 0; i-- { d := &dclstack[i-1] s := d.sym if s == nil { // pop stack mark Block = d.block dclstack = dclstack[:i-1] return } s.Def = d.def s.Block = d.block s.Lastlineno = d.lastlineno // Clear dead pointer fields. d.sym = nil d.def = nil } base.Fatalf("popdcl: no stack mark") } // Markdcl records the start of a new block scope for declarations. func Markdcl() { dclstack = append(dclstack, dsym{ sym: nil, // stack mark block: Block, }) blockgen++ Block = blockgen } func isDclstackValid() bool { for _, d := range dclstack { if d.sym == nil { return false } } return true } // PkgDef returns the definition associated with s at package scope. func (s *Sym) PkgDef() Object { return *s.pkgDefPtr() } // SetPkgDef sets the definition associated with s at package scope. func (s *Sym) SetPkgDef(n Object) { *s.pkgDefPtr() = n } func (s *Sym) pkgDefPtr() *Object { // Look for outermost saved declaration, which must be the // package scope definition, if present. for i := range dclstack { d := &dclstack[i] if s == d.sym { return &d.def } } // Otherwise, the declaration hasn't been shadowed within a // function scope. return &s.Def } func CheckDclstack() { if !isDclstackValid() { base.Fatalf("mark left on the dclstack") } }