diff options
author | Robert Griesemer <gri@golang.org> | 2017-04-06 20:57:46 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2017-04-07 20:06:02 +0000 |
commit | fd44d872dea87af38228f8e50803b319017268b4 (patch) | |
tree | 214f259b3040ae2ab7f765d2469e27221ac3c19d /src/cmd/compile/internal/types/scope.go | |
parent | 3cf1ce40bde952c0ca0ac2af7737bfae5841f0c4 (diff) | |
download | go-fd44d872dea87af38228f8e50803b319017268b4.tar.gz go-fd44d872dea87af38228f8e50803b319017268b4.zip |
cmd/compile: factor out dcl stack ops into package types
Change-Id: I000bb530e00d0f0bc59e0f1366b5fb586adf4f37
Reviewed-on: https://go-review.googlesource.com/39912
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types/scope.go')
-rw-r--r-- | src/cmd/compile/internal/types/scope.go | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/types/scope.go b/src/cmd/compile/internal/types/scope.go new file mode 100644 index 0000000000..dfb63e9352 --- /dev/null +++ b/src/cmd/compile/internal/types/scope.go @@ -0,0 +1,105 @@ +// 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/internal/src" + "fmt" +) + +// Declaration stack & operations + +var blockgen int32 = 1 // max block number +var Block int32 // current block number + +// Dclstack maintains a stack of shadowed symbol declarations so that +// popdcl can restore their declarations when a block scope ends. +// The stack is maintained as a linked list, using Sym's Link field. +// +// In practice, the "stack" actually ends up forming a tree: goto and label +// statements record the current state of Dclstack so that checkgoto can +// validate that a goto statement does not jump over any declarations or +// into a new block scope. +// +// Finally, the Syms in this list are not "real" Syms as they don't actually +// represent object names. Sym is just a convenient type for saving shadowed +// Sym definitions, and only a subset of its fields are actually used. +var Dclstack *Sym + +func dcopy(a, b *Sym) { + a.Pkg = b.Pkg + a.Name = b.Name + a.Def = b.Def + a.Block = b.Block + a.Lastlineno = b.Lastlineno +} + +func push(pos src.XPos) *Sym { + d := new(Sym) + d.Lastlineno = pos + d.Link = Dclstack + Dclstack = d + return d +} + +// 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, pos src.XPos) *Sym { + d := push(pos) + dcopy(d, s) + return d +} + +// Popdcl pops the innermost block scope and restores all symbol declarations +// to their previous state. +func Popdcl() { + d := Dclstack + for ; d != nil && d.Name != ""; d = d.Link { + s := d.Pkg.Lookup(d.Name) + lno := s.Lastlineno + dcopy(s, d) + d.Lastlineno = lno + } + + if d == nil { + Fatalf("popdcl: no mark") + } + + Dclstack = d.Link // pop mark + Block = d.Block +} + +// Markdcl records the start of a new block scope for declarations. +func Markdcl(lineno src.XPos) { + d := push(lineno) + d.Name = "" // used as a mark in fifo + d.Block = Block + + blockgen++ + Block = blockgen +} + +// keep around for debugging +func DumpDclstack() { + i := 0 + for d := Dclstack; d != nil; d = d.Link { + fmt.Printf("%6d %p", i, d) + if d.Name != "" { + fmt.Printf(" '%s' %v\n", d.Name, d.Pkg.Lookup(d.Name)) + } else { + fmt.Printf(" ---\n") + } + i++ + } +} + +func IsDclstackValid() bool { + for d := Dclstack; d != nil; d = d.Link { + if d.Name == "" { + return false + } + } + return true +} |