]> Cypherpunks repositories - gostls13.git/commitdiff
Steps towards tracking scopes for identifiers.
authorRobert Griesemer <gri@golang.org>
Fri, 15 Jan 2010 21:27:45 +0000 (13:27 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 15 Jan 2010 21:27:45 +0000 (13:27 -0800)
- Identifiers refer now to the language entity (Object)
  that they denote. At the moment this is at best an
  approximation.

- Initial data structures for language entities (Objects)
          and expression types (Type) independent of the actual
  type notations.

- Initial support for declaring and looking up identifiers.

- Updated various dependent files and added support functions.

- Extensively tested to avoid breakage. This is an AST change.

R=rsc
CC=golang-dev, rog
https://golang.org/cl/189080

23 files changed:
src/cmd/cgo/ast.go
src/cmd/cgo/gcc.go
src/cmd/cgo/main.go
src/cmd/cgo/out.go
src/cmd/godoc/godoc.go
src/cmd/godoc/index.go
src/cmd/godoc/snippet.go
src/cmd/gofmt/gofmt.go
src/cmd/gofmt/rewrite.go
src/pkg/exp/eval/expr.go
src/pkg/exp/eval/stmt.go
src/pkg/exp/eval/type.go
src/pkg/exp/eval/typec.go
src/pkg/exp/parser/interface.go
src/pkg/exp/parser/parser.go
src/pkg/go/ast/ast.go
src/pkg/go/ast/filter.go
src/pkg/go/ast/scope.go
src/pkg/go/doc/doc.go
src/pkg/go/parser/interface.go
src/pkg/go/parser/parser.go
src/pkg/go/printer/nodes.go
src/pkg/go/printer/printer.go

index d96a8bd9d0439ff77e2fccb4af897d398d11c075..26a59faf827fc6b598d277963d3e62516d9cd190 100644 (file)
@@ -74,7 +74,7 @@ func openProg(name string, p *Prog) {
                }
                fatal("parsing %s: %s", name, err)
        }
-       p.Package = p.AST.Name.Value
+       p.Package = p.AST.Name.Name()
 
        // Find the import "C" line and get any extra C preamble.
        // Delete the import "C" line along the way.
@@ -134,7 +134,7 @@ func walk(x interface{}, p *Prog, context string) {
                        // The parser should take care of scoping in the future,
                        // so that we will be able to distinguish a "top-level C"
                        // from a local C.
-                       if l, ok := sel.X.(*ast.Ident); ok && l.Value == "C" {
+                       if l, ok := sel.X.(*ast.Ident); ok && l.Name() == "C" {
                                i := len(p.Crefs)
                                if i >= cap(p.Crefs) {
                                        new := make([]*Cref, 2*i)
@@ -145,7 +145,7 @@ func walk(x interface{}, p *Prog, context string) {
                                }
                                p.Crefs = p.Crefs[0 : i+1]
                                p.Crefs[i] = &Cref{
-                                       Name: sel.Sel.Value,
+                                       Name: sel.Sel.Name(),
                                        Expr: n,
                                        Context: context,
                                }
index c525b492aaff3aa9b649267858a4b4671cb5cec2..07002a4c72cb820cb78230421fb7b43780a14fa3 100644 (file)
@@ -559,7 +559,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                t.Go = name // publish before recursive calls
                switch dt.Kind {
                case "union", "class":
-                       c.typedef[name.Value] = c.Opaque(t.Size)
+                       c.typedef[name.Name()] = c.Opaque(t.Size)
                        if t.C == "" {
                                t.C = fmt.Sprintf("typeof(unsigned char[%d])", t.Size)
                        }
@@ -569,7 +569,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                                t.C = csyntax
                        }
                        t.Align = align
-                       c.typedef[name.Value] = g
+                       c.typedef[name.Name()] = g
                }
 
        case *dwarf.TypedefType:
@@ -588,8 +588,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                sub := c.Type(dt.Type)
                t.Size = sub.Size
                t.Align = sub.Align
-               if _, ok := c.typedef[name.Value]; !ok {
-                       c.typedef[name.Value] = sub.Go
+               if _, ok := c.typedef[name.Name()]; !ok {
+                       c.typedef[name.Name()] = sub.Go
                }
 
        case *dwarf.UcharType:
@@ -633,7 +633,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
                        }
                        s = strings.Join(strings.Split(s, " ", 0), "") // strip spaces
                        name := c.Ident("_C_" + s)
-                       c.typedef[name.Value] = t.Go
+                       c.typedef[name.Name()] = t.Go
                        t.Go = name
                }
        }
@@ -710,7 +710,7 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
 }
 
 // Identifier
-func (c *typeConv) Ident(s string) *ast.Ident { return &ast.Ident{Value: s} }
+func (c *typeConv) Ident(s string) *ast.Ident { return ast.NewIdent(s) }
 
 // Opaque type of n bytes.
 func (c *typeConv) Opaque(n int64) ast.Expr {
index e0a305c4da5eecabc77b68b23cd203d2cf603cf8..b76492cec6516e303823ede9b823500f6d00f5d1 100644 (file)
@@ -94,13 +94,13 @@ func main() {
                        switch cref.Context {
                        case "const":
                                // This came from a #define and we'll output it later.
-                               *cref.Expr = &ast.Ident{Value: cref.Name}
+                               *cref.Expr = ast.NewIdent(cref.Name)
                                break
                        case "call":
                                if !cref.TypeName {
                                        // Is an actual function call.
                                        pos := (*cref.Expr).Pos()
-                                       *cref.Expr = &ast.Ident{Position: pos, Value: "_C_" + cref.Name}
+                                       *cref.Expr = &ast.Ident{Position: pos, Obj: ast.NewObj(ast.Err, pos, "_C_"+cref.Name)}
                                        p.Funcdef[cref.Name] = cref.FuncType
                                        break
                                }
@@ -113,13 +113,13 @@ func main() {
                                // place the identifier for the value and add it to Enumdef so
                                // it will be declared as a constant in the later stage.
                                if cref.Type.EnumValues != nil {
-                                       *cref.Expr = &ast.Ident{Value: cref.Name}
+                                       *cref.Expr = ast.NewIdent(cref.Name)
                                        p.Enumdef[cref.Name] = cref.Type.EnumValues[cref.Name]
                                        break
                                }
                                // Reference to C variable.
                                // We declare a pointer and arrange to have it filled in.
-                               *cref.Expr = &ast.StarExpr{X: &ast.Ident{Value: "_C_" + cref.Name}}
+                               *cref.Expr = &ast.StarExpr{X: ast.NewIdent("_C_" + cref.Name)}
                                p.Vardef[cref.Name] = cref.Type
                        case "type":
                                if !cref.TypeName {
index d628bef452f2c671d7f2e13a3ca68a1bfa257225..e905edff3884da1d009174873e24bb8dcbfe457d 100644 (file)
@@ -69,7 +69,7 @@ func (p *Prog) writeDefs() {
        for name, def := range p.Funcdef {
                // Go func declaration.
                d := &ast.FuncDecl{
-                       Name: &ast.Ident{Value: "_C_" + name},
+                       Name: ast.NewIdent("_C_" + name),
                        Type: def.Go,
                }
                printer.Fprint(fgo2, d)
index df0f948ade91883dfbeaaf45178d14441e7f84b3..7a8a8d864c654fcf6a77a0e54d5c7f014ed09955 100644 (file)
@@ -126,7 +126,7 @@ func pkgName(filename string) string {
        if err != nil || file == nil {
                return ""
        }
-       return file.Name.Value
+       return file.Name.Name()
 }
 
 
@@ -215,7 +215,7 @@ func newDirTree(path, name string, depth, maxDepth int) *Directory {
                                        // (left-over) "documentation" package somewhere in a package
                                        // directory of different name, but this is very unlikely and
                                        // against current conventions.
-                                       (file.Name.Value == name || file.Name.Value == fakePkgName) &&
+                                       (file.Name.Name() == name || file.Name.Name() == fakePkgName) &&
                                        file.Doc != nil {
                                        // found documentation; extract a synopsys
                                        text = firstSentence(doc.CommentText(file.Doc))
@@ -439,8 +439,8 @@ func (s *Styler) BasicLit(x *ast.BasicLit) (text []byte, tag printer.HTMLTag) {
 
 
 func (s *Styler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
-       text = strings.Bytes(id.Value)
-       if s.highlight == id.Value {
+       text = strings.Bytes(id.Name())
+       if s.highlight == id.Name() {
                tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
        }
        return
index 218633b2bfaf6c9ea072cf6417831bf02f1e3e1a..b0e4da15ac6d41dca2ee0465f62d1c72b794092d 100644 (file)
@@ -452,10 +452,10 @@ func (x *Indexer) visitComment(c *ast.CommentGroup) {
 
 func (x *Indexer) visitIdent(kind SpotKind, id *ast.Ident) {
        if id != nil {
-               lists, found := x.words[id.Value]
+               lists, found := x.words[id.Name()]
                if !found {
                        lists = new(IndexResult)
-                       x.words[id.Value] = lists
+                       x.words[id.Name()] = lists
                }
 
                if kind == Use || x.decl == nil {
@@ -606,7 +606,7 @@ func (x *Indexer) VisitFile(path string, d *os.Dir) {
        }
 
        dir, _ := pathutil.Split(path)
-       pak := Pak{dir, file.Name.Value}
+       pak := Pak{dir, file.Name.Name()}
        x.file = &File{path, pak}
        ast.Walk(x, file)
 }
index 98bc9728537e47be1dce2373a484dc24289bc678..102878dc5c08ea57a7da192f7279cdb9e749e224 100755 (executable)
@@ -36,7 +36,7 @@ func (s *snippetStyler) LineTag(line int) (text []uint8, tag printer.HTMLTag) {
 
 
 func (s *snippetStyler) Ident(id *ast.Ident) (text []byte, tag printer.HTMLTag) {
-       text = strings.Bytes(id.Value)
+       text = strings.Bytes(id.Name())
        if s.highlight == id {
                tag = printer.HTMLTag{"<span class=highlight>", "</span>"}
        }
@@ -115,7 +115,7 @@ func NewSnippet(decl ast.Decl, id *ast.Ident) (s *Snippet) {
        if s == nil {
                s = &Snippet{
                        id.Pos().Line,
-                       fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Value),
+                       fmt.Sprintf(`could not generate a snippet for <span class="highlight">%s</span>`, id.Name()),
                }
        }
        return
index c26ef3dec1618128b3253e4f4e93bf2d966dec35..beca5f63d7b0b38f3ab80f303e3348832a6c5e81 100644 (file)
@@ -27,6 +27,7 @@ var (
        rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> Î±[β:]')")
 
        // debugging support
+       checks   = flag.Bool("checks", false, "do semantic checks")
        comments = flag.Bool("comments", true, "print comments")
        trace    = flag.Bool("trace", false, "print parse trace")
 
@@ -63,6 +64,9 @@ func usage() {
 
 func initParserMode() {
        parserMode = uint(0)
+       if *checks {
+               parserMode |= parser.CheckSemantics
+       }
        if *comments {
                parserMode |= parser.ParseComments
        }
index 0fade9f1c1d59d3b6157ed806b50451536f47181..32ed227a34a80abc6bc210bee8c2e66260c878e1 100644 (file)
@@ -109,7 +109,7 @@ func match(m map[string]reflect.Value, pattern, val reflect.Value) bool {
        // times in the pattern, it must match the same expression
        // each time.
        if m != nil && pattern.Type() == identType {
-               name := pattern.Interface().(*ast.Ident).Value
+               name := pattern.Interface().(*ast.Ident).Name()
                if isWildcard(name) {
                        if old, ok := m[name]; ok {
                                return match(nil, old, val)
@@ -184,7 +184,7 @@ func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value)
 
        // Wildcard gets replaced with map value.
        if m != nil && pattern.Type() == identType {
-               name := pattern.Interface().(*ast.Ident).Value
+               name := pattern.Interface().(*ast.Ident).Name()
                if isWildcard(name) {
                        if old, ok := m[name]; ok {
                                return subst(nil, old, nil)
index 8e161e522545e16b3de404082e5bf31946105183..27aea0877815440902c4d92d4ff988205245259c 100644 (file)
@@ -578,7 +578,7 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
                }
 
        case *ast.Ident:
-               return ei.compileIdent(a.block, a.constant, callCtx, x.Value)
+               return ei.compileIdent(a.block, a.constant, callCtx, x.Name())
 
        case *ast.IndexExpr:
                l, r := a.compile(x.X, false), a.compile(x.Index, false)
@@ -612,7 +612,7 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
                if v == nil {
                        return nil
                }
-               return ei.compileSelectorExpr(v, x.Sel.Value)
+               return ei.compileSelectorExpr(v, x.Sel.Name())
 
        case *ast.StarExpr:
                // We pass down our call context because this could be
index 53757f7de23dee1b9600b423c2e8dd3b4d4b5ce1..d89fde1f93db77d3adaa4181de83c897d8e58bb7 100644 (file)
@@ -210,15 +210,15 @@ func (f *flowBuf) gotosObeyScopes(a *compiler) {
  */
 
 func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
-       v, prev := a.block.DefineVar(ident.Value, ident.Pos(), t)
+       v, prev := a.block.DefineVar(ident.Name(), ident.Pos(), t)
        if prev != nil {
                // TODO(austin) It's silly that we have to capture
                // Pos() in a variable.
                pos := prev.Pos()
                if pos.IsValid() {
-                       a.diagAt(ident, "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Value, &pos)
+                       a.diagAt(ident, "variable %s redeclared in this block\n\tprevious declaration at %s", ident.Name(), &pos)
                } else {
-                       a.diagAt(ident, "variable %s redeclared in this block", ident.Value)
+                       a.diagAt(ident, "variable %s redeclared in this block", ident.Name())
                }
                return nil
        }
@@ -381,13 +381,13 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) {
                }
                // Declare and initialize v before compiling func
                // so that body can refer to itself.
-               c, prev := a.block.DefineConst(d.Name.Value, a.pos, decl.Type, decl.Type.Zero())
+               c, prev := a.block.DefineConst(d.Name.Name(), a.pos, decl.Type, decl.Type.Zero())
                if prev != nil {
                        pos := prev.Pos()
                        if pos.IsValid() {
-                               a.diagAt(d.Name, "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Value, &pos)
+                               a.diagAt(d.Name, "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Name(), &pos)
                        } else {
-                               a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Value)
+                               a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Name())
                        }
                }
                fn := a.compileFunc(a.block, decl, d.Body)
@@ -416,14 +416,14 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) {
 
 func (a *stmtCompiler) compileLabeledStmt(s *ast.LabeledStmt) {
        // Define label
-       l, ok := a.labels[s.Label.Value]
+       l, ok := a.labels[s.Label.Name()]
        if ok {
                if l.resolved.IsValid() {
-                       a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Value, &l.resolved)
+                       a.diag("label %s redeclared in this block\n\tprevious declaration at %s", s.Label.Name(), &l.resolved)
                }
        } else {
                pc := badPC
-               l = &label{name: s.Label.Value, gotoPC: &pc}
+               l = &label{name: s.Label.Name(), gotoPC: &pc}
                a.labels[l.name] = l
        }
        l.desc = "regular label"
@@ -562,7 +562,7 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
                        }
 
                        // Is this simply an assignment?
-                       if _, ok := a.block.defs[ident.Value]; ok {
+                       if _, ok := a.block.defs[ident.Name()]; ok {
                                ident = nil
                                break
                        }
@@ -861,7 +861,7 @@ func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool,
                if name == nil && pred(l) {
                        return l
                }
-               if name != nil && l.name == name.Value {
+               if name != nil && l.name == name.Name() {
                        if !pred(l) {
                                a.diag("cannot %s to %s %s", errOp, l.desc, l.name)
                                return nil
@@ -872,7 +872,7 @@ func (a *stmtCompiler) findLexicalLabel(name *ast.Ident, pred func(*label) bool,
        if name == nil {
                a.diag("%s outside %s", errOp, errCtx)
        } else {
-               a.diag("%s label %s not defined", errOp, name.Value)
+               a.diag("%s label %s not defined", errOp, name.Name())
        }
        return nil
 }
@@ -896,10 +896,10 @@ func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
                pc = l.continuePC
 
        case token.GOTO:
-               l, ok := a.labels[s.Label.Value]
+               l, ok := a.labels[s.Label.Name()]
                if !ok {
                        pc := badPC
-                       l = &label{name: s.Label.Value, desc: "unresolved label", gotoPC: &pc, used: s.Pos()}
+                       l = &label{name: s.Label.Name(), desc: "unresolved label", gotoPC: &pc, used: s.Pos()}
                        a.labels[l.name] = l
                }
 
@@ -1235,14 +1235,14 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f
        defer bodyScope.exit()
        for i, t := range decl.Type.In {
                if decl.InNames[i] != nil {
-                       bodyScope.DefineVar(decl.InNames[i].Value, decl.InNames[i].Pos(), t)
+                       bodyScope.DefineVar(decl.InNames[i].Name(), decl.InNames[i].Pos(), t)
                } else {
                        bodyScope.DefineTemp(t)
                }
        }
        for i, t := range decl.Type.Out {
                if decl.OutNames[i] != nil {
-                       bodyScope.DefineVar(decl.OutNames[i].Value, decl.OutNames[i].Pos(), t)
+                       bodyScope.DefineVar(decl.OutNames[i].Name(), decl.OutNames[i].Pos(), t)
                } else {
                        bodyScope.DefineTemp(t)
                }
index d8f00e93cd15126f42c4768a72275873ef591460..55a09603e38716c4b5206ce27dce3bef901f46c3 100644 (file)
@@ -764,7 +764,7 @@ func typeListString(ts []Type, ns []*ast.Ident) string {
                        s += ", "
                }
                if ns != nil && ns[i] != nil {
-                       s += ns[i].Value + " "
+                       s += ns[i].Name() + " "
                }
                if t == nil {
                        // Some places use nil types to represent errors
@@ -808,7 +808,7 @@ type FuncDecl struct {
 func (t *FuncDecl) String() string {
        s := "func"
        if t.Name != nil {
-               s += " " + t.Name.Value
+               s += " " + t.Name.Name()
        }
        s += funcTypeString(t.Type, t.InNames, t.OutNames)
        return s
index b4bc09a823f65d291a8f0b54bdcbf2267e41b277..0addc7dfb89e76ddd009583e09f05c05e9aaab82 100644 (file)
@@ -26,17 +26,17 @@ type typeCompiler struct {
 }
 
 func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
-       _, _, def := a.block.Lookup(x.Value)
+       _, _, def := a.block.Lookup(x.Name())
        if def == nil {
-               a.diagAt(x, "%s: undefined", x.Value)
+               a.diagAt(x, "%s: undefined", x.Name())
                return nil
        }
        switch def := def.(type) {
        case *Constant:
-               a.diagAt(x, "constant %v used as type", x.Value)
+               a.diagAt(x, "constant %v used as type", x.Name())
                return nil
        case *Variable:
-               a.diagAt(x, "variable %v used as type", x.Value)
+               a.diagAt(x, "variable %v used as type", x.Name())
                return nil
        case *NamedType:
                if !allowRec && def.incomplete {
@@ -51,7 +51,7 @@ func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
        case Type:
                return def
        }
-       log.Crashf("name %s has unknown type %T", x.Value, def)
+       log.Crashf("name %s has unknown type %T", x.Name(), def)
        return nil
 }
 
@@ -147,7 +147,7 @@ func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type
                // Compute field name and check anonymous fields
                var name string
                if names[i] != nil {
-                       name = names[i].Value
+                       name = names[i].Name()
                } else {
                        if ts[i] == nil {
                                continue
@@ -247,7 +247,7 @@ func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool)
                }
 
                if names[i] != nil {
-                       name := names[i].Value
+                       name := names[i].Name()
                        methods[nm].Name = name
                        methods[nm].Type = ts[i].(*FuncType)
                        nm++
@@ -380,7 +380,7 @@ func (a *compiler) compileTypeDecl(b *block, decl *ast.GenDecl) bool {
        for _, spec := range decl.Specs {
                spec := spec.(*ast.TypeSpec)
                // Create incomplete type for this type
-               nt := b.DefineType(spec.Name.Value, spec.Name.Pos(), nil)
+               nt := b.DefineType(spec.Name.Name(), spec.Name.Pos(), nil)
                if nt != nil {
                        nt.(*NamedType).incomplete = true
                }
index b85ad70904febee7ccefbde91a8a778201431fc6..86de026ba8b123f9bcdf1235a13a6cdd4855fcf1 100644 (file)
@@ -148,8 +148,8 @@ func ParsePkgFile(pkgname, filename string, mode uint) (*ast.File, os.Error) {
                if err != nil {
                        return nil, err
                }
-               if prog.Name.Value != pkgname {
-                       return nil, os.NewError(fmt.Sprintf("multiple packages found: %s, %s", prog.Name.Value, pkgname))
+               if prog.Name.Name() != pkgname {
+                       return nil, os.NewError(fmt.Sprintf("multiple packages found: %s, %s", prog.Name.Name(), pkgname))
                }
                if mode == PackageClauseOnly {
                        return prog, nil
@@ -189,7 +189,7 @@ func ParsePackage(path string, filter func(*os.Dir) bool, mode uint) (*ast.Packa
                        }
                        files[entry.Name] = src
                        if name == "" {
-                               name = src.Name.Value
+                               name = src.Name.Name()
                        }
                }
        }
index 70dbb6921537894758791da5d0f9a8345a6914cb..199ce172db9e7871f2f8ef6a83bf3a4491ad320f 100644 (file)
@@ -267,44 +267,18 @@ func (p *parser) expect(tok token.Token) token.Position {
 }
 
 
-// ----------------------------------------------------------------------------
-// Scope support
-
-func openScope(p *parser) *parser {
-       p.topScope = ast.NewScope(p.topScope)
-       return p
-}
-
-
-// Usage pattern: defer close(openScope(p));
-func close(p *parser) { p.topScope = p.topScope.Outer }
-
-
-func (p *parser) declare(ident *ast.Ident) {
-       if !p.topScope.Declare(ident) {
-               p.Error(p.pos, "'"+ident.Value+"' declared already")
-       }
-}
-
-
-func (p *parser) declareList(idents []*ast.Ident) {
-       for _, ident := range idents {
-               p.declare(ident)
-       }
-}
-
-
 // ----------------------------------------------------------------------------
 // Common productions
 
 func (p *parser) parseIdent() *ast.Ident {
+       obj := ast.NewObj(ast.Err, p.pos, "")
        if p.tok == token.IDENT {
-               x := &ast.Ident{p.pos, string(p.lit)}
+               obj.Name = string(p.lit)
                p.next()
-               return x
+       } else {
+               p.expect(token.IDENT) // use expect() error handling
        }
-       p.expect(token.IDENT) // use expect() error handling
-       return &ast.Ident{p.pos, ""}
+       return &ast.Ident{obj.Pos, obj}
 }
 
 
@@ -424,7 +398,7 @@ func (p *parser) makeIdentList(list *vector.Vector) []*ast.Ident {
                if !isIdent {
                        pos := list.At(i).(ast.Expr).Pos()
                        p.errorExpected(pos, "identifier")
-                       idents[i] = &ast.Ident{pos, ""}
+                       idents[i] = &ast.Ident{pos, ast.NewObj(ast.Err, pos, "")}
                }
                idents[i] = ident
        }
@@ -835,8 +809,6 @@ func (p *parser) parseBlockStmt(idents []*ast.Ident) *ast.BlockStmt {
                defer un(trace(p, "BlockStmt"))
        }
 
-       defer close(openScope(p))
-
        lbrace := p.expect(token.LBRACE)
        list := p.parseStmtList()
        rbrace := p.expect(token.RBRACE)
@@ -1421,9 +1393,6 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
                defer un(trace(p, "IfStmt"))
        }
 
-       // IfStmt block
-       defer close(openScope(p))
-
        pos := p.expect(token.IF)
        s1, s2, _ := p.parseControlClause(false)
        body := p.parseBlockStmt(nil)
@@ -1442,9 +1411,6 @@ func (p *parser) parseCaseClause() *ast.CaseClause {
                defer un(trace(p, "CaseClause"))
        }
 
-       // CaseClause block
-       defer close(openScope(p))
-
        // SwitchCase
        pos := p.pos
        var x []ast.Expr
@@ -1489,9 +1455,6 @@ func (p *parser) parseTypeCaseClause() *ast.TypeCaseClause {
                defer un(trace(p, "TypeCaseClause"))
        }
 
-       // TypeCaseClause block
-       defer close(openScope(p))
-
        // TypeSwitchCase
        pos := p.pos
        var types []ast.Expr
@@ -1528,9 +1491,6 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
                defer un(trace(p, "SwitchStmt"))
        }
 
-       // SwitchStmt block
-       defer close(openScope(p))
-
        pos := p.expect(token.SWITCH)
        s1, s2, _ := p.parseControlClause(false)
 
@@ -1565,9 +1525,6 @@ func (p *parser) parseCommClause() *ast.CommClause {
                defer un(trace(p, "CommClause"))
        }
 
-       // CommClause block
-       defer close(openScope(p))
-
        // CommCase
        pos := p.pos
        var tok token.Token
@@ -1628,9 +1585,6 @@ func (p *parser) parseForStmt() ast.Stmt {
                defer un(trace(p, "ForStmt"))
        }
 
-       // ForStmt block
-       defer close(openScope(p))
-
        pos := p.expect(token.FOR)
        s1, s2, s3 := p.parseControlClause(true)
        body := p.parseBlockStmt(nil)
@@ -1745,7 +1699,7 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.S
 
        var ident *ast.Ident
        if p.tok == token.PERIOD {
-               ident = &ast.Ident{p.pos, "."}
+               ident = &ast.Ident{p.pos, ast.NewObj(ast.Err, p.pos, ".")}
                p.next()
        } else if p.tok == token.IDENT {
                ident = p.parseIdent()
@@ -1974,9 +1928,6 @@ func (p *parser) parseFile() *ast.File {
                defer un(trace(p, "File"))
        }
 
-       // file block
-       defer close(openScope(p))
-
        // package clause
        doc := p.leadComment
        pos := p.expect(token.PACKAGE)
index 49b92fe28931d7ad05222f1d89ce31302157f568..b8a96493917d48f38b1b1348264f77e35d050fbe 100644 (file)
@@ -117,8 +117,8 @@ type (
 
        // An Ident node represents an identifier.
        Ident struct {
-               token.Position        // identifier position
-               Value          string // identifier string (e.g. foobar)
+               token.Position         // identifier position
+               Obj            *Object // denoted object
        }
 
        // An Ellipsis node stands for the "..." type in a
@@ -139,6 +139,8 @@ type (
        // A single string literal (common case) is represented by a BasicLit
        // node; StringList nodes are used only if there are two or more string
        // literals in a sequence.
+       // TODO(gri) Deprecated. StringLists are only created by exp/parser;
+       //           Remove when exp/parser is removed.
        //
        StringList struct {
                Strings []*BasicLit // list of strings, len(Strings) > 1
@@ -346,6 +348,16 @@ func (x *MapType) exprNode()       {}
 func (x *ChanType) exprNode()      {}
 
 
+// ----------------------------------------------------------------------------
+// Convenience functions for Idents
+
+// NewIdent creates a new Ident without position and minimal object
+// information. Useful for ASTs generated by code other than the Go
+// parser.
+//
+func NewIdent(name string) *Ident { return &Ident{noPos, NewObj(Err, noPos, name)} }
+
+
 // IsExported returns whether name is an exported Go symbol
 // (i.e., whether it begins with an uppercase letter).
 func IsExported(name string) bool {
@@ -353,13 +365,19 @@ func IsExported(name string) bool {
        return unicode.IsUpper(ch)
 }
 
-// IsExported returns whether name is an exported Go symbol
+
+// IsExported returns whether id is an exported Go symbol
 // (i.e., whether it begins with an uppercase letter).
-func (name *Ident) IsExported() bool { return IsExported(name.Value) }
+func (id *Ident) IsExported() bool { return id.Obj.IsExported() }
+
+
+// Name returns an identifier's name.
+func (id *Ident) Name() string { return id.Obj.Name }
+
 
-func (name *Ident) String() string {
-       if name != nil {
-               return name.Value
+func (id *Ident) String() string {
+       if id != nil && id.Obj != nil {
+               return id.Obj.Name
        }
        return "<nil>"
 }
index 697c9fcdc0de8ed39dea15f6fa2223364d70e149..3dc87696a682c8894017517bd1cbcd944183631d 100644 (file)
@@ -249,5 +249,5 @@ func MergePackageFiles(pkg *Package) *File {
        // TODO(gri) Should collect comments as well. For that the comment
        //           list should be changed back into a []*CommentGroup,
        //           otherwise need to modify the existing linked list.
-       return &File{doc, noPos, &Ident{noPos, pkg.Name}, decls, nil}
+       return &File{doc, noPos, NewIdent(pkg.Name), decls, nil}
 }
index e8ad12f97401f2c83e28c36ec0e83b17e80df767..52f44e76bcce0295087c1733b5dfe510714e7d2a 100644 (file)
@@ -4,89 +4,78 @@
 
 package ast
 
-// A Scope maintains the set of identifiers visible
-// in the scope and a link to the immediately surrounding
-// (outer) scope.
+import "go/token"
+
+type ObjKind int
+
+// The list of possible Object kinds.
+const (
+       Err ObjKind = iota // object kind unknown (forward reference or error)
+       Pkg         // package
+       Con         // constant
+       Typ         // type
+       Var         // variable
+       Fun         // function or method
+)
+
+
+// An Object describes a language entity such as a package,
+// constant, type, variable, or function (incl. methods).
 //
-//     NOTE: WORK IN PROGRESS
+type Object struct {
+       Kind  ObjKind
+       Pos   token.Position // declaration position
+       Name  string         // declared name
+       Scope *Scope         // scope in which the Object is declared
+}
+
+
+func NewObj(kind ObjKind, pos token.Position, name string) *Object {
+       return &Object{kind, pos, name, nil}
+}
+
+
+// IsExported returns whether obj is exported.
+func (obj *Object) IsExported() bool { return IsExported(obj.Name) }
+
+
+// A Scope maintains the set of named language entities visible
+// in the scope and a link to the immediately surrounding (outer)
+// scope.
 //
 type Scope struct {
-       Outer *Scope
-       Names map[string]*Ident
+       Outer   *Scope
+       Objects map[string]*Object
 }
 
 
 // NewScope creates a new scope nested in the outer scope.
-func NewScope(outer *Scope) *Scope { return &Scope{outer, make(map[string]*Ident)} }
+func NewScope(outer *Scope) *Scope { return &Scope{outer, make(map[string]*Object)} }
 
 
-// Declare inserts an identifier into the scope s. If the
-// declaration succeeds, the result is true, if the identifier
-// exists already in the scope, the result is false.
-//
-func (s *Scope) Declare(ident *Ident) bool {
-       if _, found := s.Names[ident.Value]; found {
-               return false
+// Declare attempts to insert a named object into the scope s.
+// If the scope does not contain an object with that name yet,
+// Declare inserts the object, and the result is true. Otherwise,
+// the scope remains unchanged and the result is false.
+func (s *Scope) Declare(obj *Object) bool {
+       if obj.Name != "_" {
+               if _, found := s.Objects[obj.Name]; found {
+                       return false
+               }
+               s.Objects[obj.Name] = obj
        }
-       s.Names[ident.Value] = ident
        return true
 }
 
 
-// Lookup looks up an identifier in the current scope chain.
-// If the identifier is found, it is returned; otherwise the
-// result is nil.
+// Lookup looks up an object in the current scope chain.
+// The result is nil if the object is not found.
 //
-func (s *Scope) Lookup(name string) *Ident {
+func (s *Scope) Lookup(name string) *Object {
        for ; s != nil; s = s.Outer {
-               if ident, found := s.Names[name]; found {
-                       return ident
+               if obj, found := s.Objects[name]; found {
+                       return obj
                }
        }
        return nil
 }
-
-
-// TODO(gri) Uncomment once this code is needed.
-/*
-var Universe = Scope {
-       Names: map[string]*Ident {
-               // basic types
-               "bool": nil,
-               "byte": nil,
-               "int8": nil,
-               "int16": nil,
-               "int32": nil,
-               "int64": nil,
-               "uint8": nil,
-               "uint16": nil,
-               "uint32": nil,
-               "uint64": nil,
-               "float32": nil,
-               "float64": nil,
-               "string": nil,
-
-               // convenience types
-               "int": nil,
-               "uint": nil,
-               "uintptr": nil,
-               "float": nil,
-
-               // constants
-               "false": nil,
-               "true": nil,
-               "iota": nil,
-               "nil": nil,
-
-               // functions
-               "cap": nil,
-               "len": nil,
-               "new": nil,
-               "make": nil,
-               "panic": nil,
-               "panicln": nil,
-               "print": nil,
-               "println": nil,
-       }
-}
-*/
\ No newline at end of file
index be03ddfd6b422c2a04565299dc7301c969ee821b..d97548715b363ea3909979b708c86f60f2f281aa 100644 (file)
@@ -55,7 +55,7 @@ func (doc *docReader) init(pkgName string) {
 
 func (doc *docReader) addType(decl *ast.GenDecl) {
        spec := decl.Specs[0].(*ast.TypeSpec)
-       typ := doc.lookupTypeDoc(spec.Name.Value)
+       typ := doc.lookupTypeDoc(spec.Name.Name())
        // typ should always be != nil since declared types
        // are always named - be conservative and check
        if typ != nil {
@@ -86,7 +86,7 @@ func baseTypeName(typ ast.Expr) string {
                // if the type is not exported, the effect to
                // a client is as if there were no type name
                if t.IsExported() {
-                       return string(t.Value)
+                       return string(t.Name())
                }
        case *ast.StarExpr:
                return baseTypeName(t.X)
@@ -148,7 +148,7 @@ func (doc *docReader) addValue(decl *ast.GenDecl) {
 
 
 func (doc *docReader) addFunc(fun *ast.FuncDecl) {
-       name := fun.Name.Value
+       name := fun.Name.Name()
 
        // determine if it should be associated with a type
        if fun.Recv != nil {
@@ -291,7 +291,7 @@ func (doc *docReader) addFile(src *ast.File) {
 
 func NewFileDoc(file *ast.File) *PackageDoc {
        var r docReader
-       r.init(file.Name.Value)
+       r.init(file.Name.Name())
        r.addFile(file)
        return r.newDoc("", "", nil)
 }
@@ -336,9 +336,9 @@ func declName(d *ast.GenDecl) string {
 
        switch v := d.Specs[0].(type) {
        case *ast.ValueSpec:
-               return v.Names[0].Value
+               return v.Names[0].Name()
        case *ast.TypeSpec:
-               return v.Name.Value
+               return v.Name.Name()
        }
 
        return ""
@@ -400,7 +400,7 @@ func makeFuncDocs(m map[string]*ast.FuncDecl) []*FuncDoc {
                if f.Recv != nil {
                        doc.Recv = f.Recv.Type
                }
-               doc.Name = f.Name.Value
+               doc.Name = f.Name.Name()
                doc.Decl = f
                d[i] = doc
                i++
@@ -433,7 +433,7 @@ func (p sortTypeDoc) Less(i, j int) bool {
        // sort by name
        // pull blocks (name = "") up to top
        // in original order
-       if ni, nj := p[i].Type.Name.Value, p[j].Type.Name.Value; ni != nj {
+       if ni, nj := p[i].Type.Name.Name(), p[j].Type.Name.Name(); ni != nj {
                return ni < nj
        }
        return p[i].order < p[j].order
@@ -581,12 +581,12 @@ func matchDecl(d *ast.GenDecl, names []string) bool {
                switch v := d.(type) {
                case *ast.ValueSpec:
                        for _, name := range v.Names {
-                               if match(name.Value, names) {
+                               if match(name.Name(), names) {
                                        return true
                                }
                        }
                case *ast.TypeSpec:
-                       if match(v.Name.Value, names) {
+                       if match(v.Name.Name(), names) {
                                return true
                        }
                }
index b261a4a7ee535208a24f1c5db71a3be8efeade85..a434c64e474db32a5efeda5387336177078e4c75 100644 (file)
@@ -160,7 +160,7 @@ func ParseDir(path string, filter func(*os.Dir) bool, mode uint) (map[string]*as
                        if err != nil {
                                return pkgs, err
                        }
-                       name := src.Name.Value
+                       name := src.Name.Name()
                        pkg, found := pkgs[name]
                        if !found {
                                pkg = &ast.Package{name, path, make(map[string]*ast.File)}
index e774719edb2ef5b9777fae74a9973987238a7fc2..113880918ac0079f00a688f9060f3f3f391e356b 100644 (file)
@@ -30,6 +30,7 @@ const (
        PackageClauseOnly uint = 1 << iota // parsing stops after package clause
        ImportsOnly            // parsing stops after import declarations
        ParseComments          // parse comments and add them to AST
+       CheckSemantics         // do semantic checks (only declarations for now)
        Trace                  // print a trace of parsed productions
 )
 
@@ -41,6 +42,7 @@ type parser struct {
 
        // Tracing/debugging
        mode   uint // parsing mode
+       check  bool // == (mode & CheckSemantics != 0)
        trace  bool // == (mode & Trace != 0)
        indent uint // indentation used for tracing output
 
@@ -78,7 +80,8 @@ func scannerMode(mode uint) uint {
 func (p *parser) init(filename string, src []byte, mode uint) {
        p.scanner.Init(filename, src, p, scannerMode(mode))
        p.mode = mode
-       p.trace = mode&Trace != 0 // for convenience (p.trace is used frequently)
+       p.trace = mode&Trace != 0          // for convenience (p.trace is used frequently)
+       p.check = mode&CheckSemantics != 0 // for convenience (p.check is used frequently)
        p.next()
 }
 
@@ -270,54 +273,64 @@ func (p *parser) expectSemi() {
 // ----------------------------------------------------------------------------
 // Scope support
 
+// Usage pattern: defer closeScope(openScope(p));
 func openScope(p *parser) *parser {
        p.topScope = ast.NewScope(p.topScope)
        return p
 }
 
 
-// Usage pattern: defer close(openScope(p));
-func close(p *parser) { p.topScope = p.topScope.Outer }
+func closeScope(p *parser) { p.topScope = p.topScope.Outer }
 
 
-func (p *parser) declare(ident *ast.Ident) {
-       if !p.topScope.Declare(ident) {
-               p.Error(p.pos, "'"+ident.Value+"' declared already")
-       }
-}
-
-
-func (p *parser) declareList(idents []*ast.Ident) {
-       for _, ident := range idents {
-               p.declare(ident)
+func (p *parser) parseIdent(kind ast.ObjKind) *ast.Ident {
+       obj := ast.NewObj(ast.Err, p.pos, "")
+       if p.tok == token.IDENT {
+               obj.Name = string(p.lit)
+               p.next()
+       } else {
+               p.expect(token.IDENT) // use expect() error handling
        }
+       return &ast.Ident{obj.Pos, obj}
 }
 
 
-// ----------------------------------------------------------------------------
-// Common productions
-
-func (p *parser) parseIdent() *ast.Ident {
+// TODO(gri) Separate parsing from declaration since an identifier's
+//           scope often starts only after the type has been seen.
+func (p *parser) declIdent(kind ast.ObjKind) *ast.Ident {
+       obj := ast.NewObj(kind, p.pos, "")
        if p.tok == token.IDENT {
-               x := &ast.Ident{p.pos, string(p.lit)}
+               obj.Name = string(p.lit)
+               // TODO(gri) Consider reversing the conditionals below:
+               //           always do the declaration but only report
+               //           error if enabled (may be necessary to get
+               //           search functionality in the presence of
+               //           incorrect files).
+               if p.check && !p.topScope.Declare(obj) {
+                       // TODO(gri) Declare could return already-declared
+                       //           object for a very good error message.
+                       p.Error(obj.Pos, "'"+obj.Name+"' declared already")
+               }
                p.next()
-               return x
+       } else {
+               p.expect(token.IDENT) // use expect() error handling
        }
-       p.expect(token.IDENT) // use expect() error handling
-       return &ast.Ident{p.pos, ""}
+       return &ast.Ident{obj.Pos, obj}
 }
 
 
-func (p *parser) parseIdentList() []*ast.Ident {
+// TODO(gri) Separate parsing from declaration since an identifier's
+//           scope often starts only after the type has been seen.
+func (p *parser) declIdentList(kind ast.ObjKind) []*ast.Ident {
        if p.trace {
                defer un(trace(p, "IdentList"))
        }
 
        var list vector.Vector
-       list.Push(p.parseIdent())
+       list.Push(p.declIdent(kind))
        for p.tok == token.COMMA {
                p.next()
-               list.Push(p.parseIdent())
+               list.Push(p.declIdent(kind))
        }
 
        // convert vector
@@ -330,6 +343,27 @@ func (p *parser) parseIdentList() []*ast.Ident {
 }
 
 
+func (p *parser) findIdent() *ast.Ident {
+       pos := p.pos
+       name := ""
+       var obj *ast.Object
+       if p.tok == token.IDENT {
+               name = string(p.lit)
+               obj = p.topScope.Lookup(name)
+               p.next()
+       } else {
+               p.expect(token.IDENT) // use expect() error handling
+       }
+       if obj == nil {
+               obj = ast.NewObj(ast.Err, pos, name)
+       }
+       return &ast.Ident{obj.Pos, obj}
+}
+
+
+// ----------------------------------------------------------------------------
+// Common productions
+
 func makeExprList(list *vector.Vector) []ast.Expr {
        exprs := make([]ast.Expr, len(*list))
        for i, x := range *list {
@@ -380,11 +414,11 @@ func (p *parser) parseQualifiedIdent() ast.Expr {
                defer un(trace(p, "QualifiedIdent"))
        }
 
-       var x ast.Expr = p.parseIdent()
+       var x ast.Expr = p.findIdent()
        if p.tok == token.PERIOD {
                // first identifier is a package identifier
                p.next()
-               sel := p.parseIdent()
+               sel := p.findIdent()
                x = &ast.SelectorExpr{x, sel}
        }
        return x
@@ -427,7 +461,7 @@ func (p *parser) makeIdentList(list *vector.Vector) []*ast.Ident {
                if !isIdent {
                        pos := x.(ast.Expr).Pos()
                        p.errorExpected(pos, "identifier")
-                       idents[i] = &ast.Ident{pos, ""}
+                       idents[i] = &ast.Ident{pos, ast.NewObj(ast.Err, pos, "")}
                }
                idents[i] = ident
        }
@@ -585,7 +619,7 @@ func (p *parser) parseParameterList(ellipsisOk bool) []*ast.Field {
                }
 
                for p.tok != token.RPAREN && p.tok != token.EOF {
-                       idents := p.parseIdentList()
+                       idents := p.declIdentList(ast.Var)
                        typ := p.parseParameterType(ellipsisOk)
                        list.Push(&ast.Field{nil, idents, typ, nil, nil})
                        if p.tok != token.COMMA {
@@ -619,9 +653,11 @@ func (p *parser) parseParameters(ellipsisOk bool) []*ast.Field {
 
        var params []*ast.Field
        p.expect(token.LPAREN)
+       openScope(p)
        if p.tok != token.RPAREN {
                params = p.parseParameterList(ellipsisOk)
        }
+       closeScope(p)
        p.expect(token.RPAREN)
 
        return params
@@ -823,7 +859,7 @@ func (p *parser) parseBlockStmt() *ast.BlockStmt {
                defer un(trace(p, "BlockStmt"))
        }
 
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        lbrace := p.expect(token.LBRACE)
        list := p.parseStmtList()
@@ -865,7 +901,7 @@ func (p *parser) parseOperand() ast.Expr {
 
        switch p.tok {
        case token.IDENT:
-               return p.parseIdent()
+               return p.findIdent()
 
        case token.INT, token.FLOAT, token.CHAR, token.STRING:
                x := &ast.BasicLit{p.pos, p.tok, p.lit}
@@ -905,7 +941,7 @@ func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
        p.expect(token.PERIOD)
        if p.tok == token.IDENT {
                // selector
-               sel := p.parseIdent()
+               sel := p.findIdent()
                return &ast.SelectorExpr{x, sel}
        }
 
@@ -1325,7 +1361,7 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
        s := &ast.BranchStmt{p.pos, tok, nil}
        p.expect(tok)
        if tok != token.FALLTHROUGH && p.tok == token.IDENT {
-               s.Label = p.parseIdent()
+               s.Label = p.findIdent()
        }
        p.expectSemi()
 
@@ -1382,7 +1418,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
        }
 
        // IfStmt block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        pos := p.expect(token.IF)
        s1, s2, _ := p.parseControlClause(false)
@@ -1405,7 +1441,7 @@ func (p *parser) parseCaseClause() *ast.CaseClause {
        }
 
        // CaseClause block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        // SwitchCase
        pos := p.pos
@@ -1446,7 +1482,7 @@ func (p *parser) parseTypeCaseClause() *ast.TypeCaseClause {
        }
 
        // TypeCaseClause block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        // TypeSwitchCase
        pos := p.pos
@@ -1485,7 +1521,7 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
        }
 
        // SwitchStmt block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        pos := p.expect(token.SWITCH)
        s1, s2, _ := p.parseControlClause(false)
@@ -1522,7 +1558,7 @@ func (p *parser) parseCommClause() *ast.CommClause {
        }
 
        // CommClause block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        // CommCase
        pos := p.pos
@@ -1585,7 +1621,7 @@ func (p *parser) parseForStmt() ast.Stmt {
        }
 
        // ForStmt block
-       defer close(openScope(p))
+       defer closeScope(openScope(p))
 
        pos := p.expect(token.FOR)
        s1, s2, s3 := p.parseControlClause(true)
@@ -1701,10 +1737,10 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
 
        var ident *ast.Ident
        if p.tok == token.PERIOD {
-               ident = &ast.Ident{p.pos, "."}
+               ident = &ast.Ident{p.pos, ast.NewObj(ast.Pkg, p.pos, ".")}
                p.next()
        } else if p.tok == token.IDENT {
-               ident = p.parseIdent()
+               ident = p.declIdent(ast.Pkg)
        }
 
        var path []*ast.BasicLit
@@ -1726,7 +1762,7 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
                defer un(trace(p, "ConstSpec"))
        }
 
-       idents := p.parseIdentList()
+       idents := p.declIdentList(ast.Con)
        typ := p.tryType()
        var values []ast.Expr
        if typ != nil || p.tok == token.ASSIGN {
@@ -1744,7 +1780,7 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
                defer un(trace(p, "TypeSpec"))
        }
 
-       ident := p.parseIdent()
+       ident := p.declIdent(ast.Typ)
        typ := p.parseType()
        p.expectSemi()
 
@@ -1757,7 +1793,7 @@ func parseVarSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
                defer un(trace(p, "VarSpec"))
        }
 
-       idents := p.parseIdentList()
+       idents := p.declIdentList(ast.Var)
        typ := p.tryType()
        var values []ast.Expr
        if typ == nil || p.tok == token.ASSIGN {
@@ -1843,7 +1879,7 @@ func (p *parser) parseFunctionDecl() *ast.FuncDecl {
                recv = p.parseReceiver()
        }
 
-       ident := p.parseIdent()
+       ident := p.declIdent(ast.Fun)
        params, results := p.parseSignature()
 
        var body *ast.BlockStmt
@@ -1915,15 +1951,15 @@ func (p *parser) parseFile() *ast.File {
                defer un(trace(p, "File"))
        }
 
-       // file block
-       defer close(openScope(p))
-
        // package clause
        doc := p.leadComment
        pos := p.expect(token.PACKAGE)
-       ident := p.parseIdent()
+       ident := p.parseIdent(ast.Pkg) // package name is in no scope
        p.expectSemi()
 
+       // file block
+       defer closeScope(openScope(p))
+
        var decls []ast.Decl
 
        // Don't bother parsing the rest if we had errors already.
index 226e34572ed5c5d17cba18febad74c6199c3ae56..29dc1737b6222710102cbfaf660e6eed8fbe5bd5 100644 (file)
@@ -308,7 +308,7 @@ func identListSize(list []*ast.Ident, maxSize int) (size int) {
                if i > 0 {
                        size += 2 // ", "
                }
-               size += len(x.Value)
+               size += len(x.Name())
                if size >= maxSize {
                        break
                }
index 9e82003564c735a04f74beec5ea7e4898ecc2350..4fe7bfbc37ab910234d223e8ee5e1c46fd079fa6 100644 (file)
@@ -734,7 +734,7 @@ func (p *printer) print(args ...) {
                        if p.Styler != nil {
                                data, tag = p.Styler.Ident(x)
                        } else {
-                               data = strings.Bytes(x.Value)
+                               data = strings.Bytes(x.Name())
                        }
                case *ast.BasicLit:
                        if p.Styler != nil {