]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add comments explaining how declarations/scopes work
authorMatthew Dempsky <mdempsky@google.com>
Tue, 5 Apr 2016 19:48:49 +0000 (12:48 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 5 Apr 2016 21:04:11 +0000 (21:04 +0000)
Change-Id: I301760b015eb69ff12eee53473fdbf5e9f168413
Reviewed-on: https://go-review.googlesource.com/21542
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/go.go

index bd5a1f6f07af68ae6e238dee73b71e3e65d8dc09..8553e2f1e82203946a4e00cc316d04ecc58efbda 100644 (file)
@@ -11,6 +11,8 @@ import (
        "strings"
 )
 
+// Declaration stack & operations
+
 func dflag() bool {
        if Debug['d'] == 0 {
                return false
@@ -24,8 +26,21 @@ func dflag() bool {
        return true
 }
 
-// declaration stack & operations
-func dcopy(a *Sym, b *Sym) {
+// 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
@@ -41,6 +56,8 @@ func push() *Sym {
        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) *Sym {
        d := push()
        dcopy(d, s)
@@ -50,6 +67,8 @@ func pushdcl(s *Sym) *Sym {
        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 {
@@ -70,6 +89,7 @@ func popdcl() {
        block = d.Block
 }
 
+// markdcl records the start of a new block scope for declarations.
 func markdcl() {
        d := push()
        d.Name = "" // used as a mark in fifo
@@ -104,6 +124,7 @@ func testdclstack() {
        }
 }
 
+// redeclare emits a diagnostic about symbol s being redeclared somewhere.
 func redeclare(s *Sym, where string) {
        if s.Lastlineno == 0 {
                var tmp string
@@ -137,6 +158,8 @@ var vargen int
 
 var declare_typegen int
 
+// declare records that Node n declares symbol n.Sym in the specified
+// declaration context.
 func declare(n *Node, ctxt Class) {
        if ctxt == PDISCARD {
                return
@@ -318,8 +341,7 @@ func constiter(vl []*Node, t *Node, cl []*Node) []*Node {
        return vv
 }
 
-// this generates a new name node,
-// typically for labels or other one-off names.
+// newname returns a new ONAME Node associated with symbol s.
 func newname(s *Sym) *Node {
        if s == nil {
                Fatalf("newname nil")
@@ -364,17 +386,14 @@ func typenod(t *Type) *Node {
        return t.Nod
 }
 
-// this will return an old name
-// that has already been pushed on the
-// declaration list. a diagnostic is
-// generated if no name has been defined.
+// oldname returns the Node that declares symbol s in the current scope.
+// If no such Node currently exists, an ONONAME Node is returned instead.
 func oldname(s *Sym) *Node {
        n := s.Def
        if n == nil {
-               // maybe a top-level name will come along
-               // to give this a definition later.
-               // walkdef will check s->def again once
-               // all the input source has been processed.
+               // Maybe a top-level declaration will come along later to
+               // define s. resolve will check s.Def again once all input
+               // source has been processed.
                n = newname(s)
                n.Op = ONONAME
                n.Name.Iota = iota_ // save current iota value in const declarations
index fdea1f2fbacca209cf7ef4502405229d4a61e70a..f4b3dc9326948c7b74bcb43f92d3bebbaf147737 100644 (file)
@@ -66,6 +66,14 @@ type Pkg struct {
        Syms     map[string]*Sym
 }
 
+// Sym represents an object name. Most commonly, this is a Go identifier naming
+// an object declared within a package, but Syms are also used to name internal
+// synthesized objects.
+//
+// As a special exception, field and method names that are exported use the Sym
+// associated with localpkg instead of the package that declared them. This
+// allows using Sym pointer equality to test for Go identifier uniqueness when
+// handling selector expressions.
 type Sym struct {
        Flags     SymFlags
        Link      *Sym
@@ -111,8 +119,6 @@ const (
        SymAlgGen
 )
 
-var dclstack *Sym
-
 // Ctype describes the constant kind of an "ideal" (untyped) constant.
 type Ctype int8