aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types/scope.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2017-04-06 20:57:46 -0700
committerRobert Griesemer <gri@golang.org>2017-04-07 20:06:02 +0000
commitfd44d872dea87af38228f8e50803b319017268b4 (patch)
tree214f259b3040ae2ab7f765d2469e27221ac3c19d /src/cmd/compile/internal/types/scope.go
parent3cf1ce40bde952c0ca0ac2af7737bfae5841f0c4 (diff)
downloadgo-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.go105
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
+}