summaryrefslogtreecommitdiff
path: root/src/pkg/go/types/check.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/types/check.go')
-rw-r--r--src/pkg/go/types/check.go233
1 files changed, 0 insertions, 233 deletions
diff --git a/src/pkg/go/types/check.go b/src/pkg/go/types/check.go
deleted file mode 100644
index 02d662926..000000000
--- a/src/pkg/go/types/check.go
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2011 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.
-
-// This file implements the Check function, which typechecks a package.
-
-package types
-
-import (
- "fmt"
- "go/ast"
- "go/scanner"
- "go/token"
- "os"
- "strconv"
-)
-
-
-const debug = false
-
-
-type checker struct {
- fset *token.FileSet
- scanner.ErrorVector
- types map[ast.Expr]Type
-}
-
-
-func (c *checker) errorf(pos token.Pos, format string, args ...interface{}) string {
- msg := fmt.Sprintf(format, args...)
- c.Error(c.fset.Position(pos), msg)
- return msg
-}
-
-
-// collectFields collects struct fields tok = token.STRUCT), interface methods
-// (tok = token.INTERFACE), and function arguments/results (tok = token.FUNC).
-func (c *checker) collectFields(tok token.Token, list *ast.FieldList, cycleOk bool) (fields ObjList, tags []string, isVariadic bool) {
- if list != nil {
- for _, field := range list.List {
- ftype := field.Type
- if t, ok := ftype.(*ast.Ellipsis); ok {
- ftype = t.Elt
- isVariadic = true
- }
- typ := c.makeType(ftype, cycleOk)
- tag := ""
- if field.Tag != nil {
- assert(field.Tag.Kind == token.STRING)
- tag, _ = strconv.Unquote(field.Tag.Value)
- }
- if len(field.Names) > 0 {
- // named fields
- for _, name := range field.Names {
- obj := name.Obj
- obj.Type = typ
- fields = append(fields, obj)
- if tok == token.STRUCT {
- tags = append(tags, tag)
- }
- }
- } else {
- // anonymous field
- switch tok {
- case token.STRUCT:
- tags = append(tags, tag)
- fallthrough
- case token.FUNC:
- obj := ast.NewObj(ast.Var, "")
- obj.Type = typ
- fields = append(fields, obj)
- case token.INTERFACE:
- utyp := Underlying(typ)
- if typ, ok := utyp.(*Interface); ok {
- // TODO(gri) This is not good enough. Check for double declarations!
- fields = append(fields, typ.Methods...)
- } else if _, ok := utyp.(*Bad); !ok {
- // if utyp is Bad, don't complain (the root cause was reported before)
- c.errorf(ftype.Pos(), "interface contains embedded non-interface type")
- }
- default:
- panic("unreachable")
- }
- }
- }
- }
- return
-}
-
-
-// makeType makes a new type for an AST type specification x or returns
-// the type referred to by a type name x. If cycleOk is set, a type may
-// refer to itself directly or indirectly; otherwise cycles are errors.
-//
-func (c *checker) makeType(x ast.Expr, cycleOk bool) (typ Type) {
- if debug {
- fmt.Printf("makeType (cycleOk = %v)\n", cycleOk)
- ast.Print(c.fset, x)
- defer func() {
- fmt.Printf("-> %T %v\n\n", typ, typ)
- }()
- }
-
- switch t := x.(type) {
- case *ast.BadExpr:
- return &Bad{}
-
- case *ast.Ident:
- // type name
- obj := t.Obj
- if obj == nil {
- // unresolved identifier (error has been reported before)
- return &Bad{Msg: "unresolved identifier"}
- }
- if obj.Kind != ast.Typ {
- msg := c.errorf(t.Pos(), "%s is not a type", t.Name)
- return &Bad{Msg: msg}
- }
- c.checkObj(obj, cycleOk)
- if !cycleOk && obj.Type.(*Name).Underlying == nil {
- // TODO(gri) Enable this message again once its position
- // is independent of the underlying map implementation.
- // msg := c.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
- msg := "illegal cycle"
- return &Bad{Msg: msg}
- }
- return obj.Type.(Type)
-
- case *ast.ParenExpr:
- return c.makeType(t.X, cycleOk)
-
- case *ast.SelectorExpr:
- // qualified identifier
- // TODO (gri) eventually, this code belongs to expression
- // type checking - here for the time being
- if ident, ok := t.X.(*ast.Ident); ok {
- if obj := ident.Obj; obj != nil {
- if obj.Kind != ast.Pkg {
- msg := c.errorf(ident.Pos(), "%s is not a package", obj.Name)
- return &Bad{Msg: msg}
- }
- // TODO(gri) we have a package name but don't
- // have the mapping from package name to package
- // scope anymore (created in ast.NewPackage).
- return &Bad{} // for now
- }
- }
- // TODO(gri) can this really happen (the parser should have excluded this)?
- msg := c.errorf(t.Pos(), "expected qualified identifier")
- return &Bad{Msg: msg}
-
- case *ast.StarExpr:
- return &Pointer{Base: c.makeType(t.X, true)}
-
- case *ast.ArrayType:
- if t.Len != nil {
- // TODO(gri) compute length
- return &Array{Elt: c.makeType(t.Elt, cycleOk)}
- }
- return &Slice{Elt: c.makeType(t.Elt, true)}
-
- case *ast.StructType:
- fields, tags, _ := c.collectFields(token.STRUCT, t.Fields, cycleOk)
- return &Struct{Fields: fields, Tags: tags}
-
- case *ast.FuncType:
- params, _, _ := c.collectFields(token.FUNC, t.Params, true)
- results, _, isVariadic := c.collectFields(token.FUNC, t.Results, true)
- return &Func{Recv: nil, Params: params, Results: results, IsVariadic: isVariadic}
-
- case *ast.InterfaceType:
- methods, _, _ := c.collectFields(token.INTERFACE, t.Methods, cycleOk)
- methods.Sort()
- return &Interface{Methods: methods}
-
- case *ast.MapType:
- return &Map{Key: c.makeType(t.Key, true), Elt: c.makeType(t.Key, true)}
-
- case *ast.ChanType:
- return &Chan{Dir: t.Dir, Elt: c.makeType(t.Value, true)}
- }
-
- panic(fmt.Sprintf("unreachable (%T)", x))
-}
-
-
-// checkObj type checks an object.
-func (c *checker) checkObj(obj *ast.Object, ref bool) {
- if obj.Type != nil {
- // object has already been type checked
- return
- }
-
- switch obj.Kind {
- case ast.Bad:
- // ignore
-
- case ast.Con:
- // TODO(gri) complete this
-
- case ast.Typ:
- typ := &Name{Obj: obj}
- obj.Type = typ // "mark" object so recursion terminates
- typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
-
- case ast.Var:
- // TODO(gri) complete this
-
- case ast.Fun:
- // TODO(gri) complete this
-
- default:
- panic("unreachable")
- }
-}
-
-
-// Check typechecks a package.
-// It augments the AST by assigning types to all ast.Objects and returns a map
-// of types for all expression nodes in statements, and a scanner.ErrorList if
-// there are errors.
-//
-func Check(fset *token.FileSet, pkg *ast.Package) (types map[ast.Expr]Type, err os.Error) {
- var c checker
- c.fset = fset
- c.types = make(map[ast.Expr]Type)
-
- for _, obj := range pkg.Scope.Objects {
- c.checkObj(obj, false)
- }
-
- return c.types, c.GetError(scanner.NoMultiples)
-}