Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / go / typechecker / typechecker.go
blob81f6bb4a4da05476f601dbeb90369e571cd7f538
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This package implements typechecking of a Go AST.
6 // The result of the typecheck is an augmented AST
7 // with object and type information for each identifier.
8 //
9 package typechecker
11 import (
12 "fmt"
13 "go/ast"
14 "go/token"
15 "go/scanner"
16 "os"
20 // TODO(gri) don't report errors for objects/types that are marked as bad.
23 const debug = true // set for debugging output
26 // An importer takes an import path and returns the data describing the
27 // respective package's exported interface. The data format is TBD.
29 type Importer func(path string) ([]byte, os.Error)
32 // CheckPackage typechecks a package and augments the AST by setting
33 // *ast.Object, *ast.Type, and *ast.Scope fields accordingly. If an
34 // importer is provided, it is used to handle imports, otherwise they
35 // are ignored (likely leading to typechecking errors).
37 // If errors are reported, the AST may be incompletely augmented (fields
38 // may be nil) or contain incomplete object, type, or scope information.
40 func CheckPackage(pkg *ast.Package, importer Importer) os.Error {
41 var tc typechecker
42 tc.importer = importer
43 tc.checkPackage(pkg)
44 return tc.GetError(scanner.Sorted)
48 // CheckFile typechecks a single file, but otherwise behaves like
49 // CheckPackage. If the complete package consists of more than just
50 // one file, the file may not typecheck without errors.
52 func CheckFile(file *ast.File, importer Importer) os.Error {
53 // create a single-file dummy package
54 pkg := &ast.Package{file.Name.Name, nil, map[string]*ast.File{file.Name.NamePos.Filename: file}}
55 return CheckPackage(pkg, importer)
59 // ----------------------------------------------------------------------------
60 // Typechecker state
62 type typechecker struct {
63 scanner.ErrorVector
64 importer Importer
65 topScope *ast.Scope // current top-most scope
66 cyclemap map[*ast.Object]bool // for cycle detection
67 iota int // current value of iota
71 func (tc *typechecker) Errorf(pos token.Position, format string, args ...interface{}) {
72 tc.Error(pos, fmt.Sprintf(format, args...))
76 func assert(pred bool) {
77 if !pred {
78 panic("internal error")
84 Typechecking is done in several phases:
86 phase 1: declare all global objects; also collect all function and method declarations
87 - all objects have kind, name, decl fields; the decl field permits
88 quick lookup of an object's declaration
89 - constant objects have an iota value
90 - type objects have unresolved types with empty scopes, all others have nil types
91 - report global double declarations
93 phase 2: bind methods to their receiver base types
94 - received base types must be declared in the package, thus for
95 each method a corresponding (unresolved) type must exist
96 - report method double declarations and errors with base types
98 phase 3: resolve all global objects
99 - sequentially iterate through all objects in the global scope
100 - resolve types for all unresolved types and assign types to
101 all attached methods
102 - assign types to all other objects, possibly by evaluating
103 constant and initializer expressions
104 - resolution may recurse; a cyclemap is used to detect cycles
105 - report global typing errors
107 phase 4: sequentially typecheck function and method bodies
108 - all global objects are declared and have types and values;
109 all methods have types
110 - sequentially process statements in each body; any object
111 referred to must be fully defined at this point
112 - report local typing errors
115 func (tc *typechecker) checkPackage(pkg *ast.Package) {
116 // setup package scope
117 tc.topScope = Universe
118 tc.openScope()
119 defer tc.closeScope()
121 // TODO(gri) there's no file scope at the moment since we ignore imports
123 // phase 1: declare all global objects; also collect all function and method declarations
124 var funcs []*ast.FuncDecl
125 for _, file := range pkg.Files {
126 for _, decl := range file.Decls {
127 tc.declGlobal(decl)
128 if f, isFunc := decl.(*ast.FuncDecl); isFunc {
129 funcs = append(funcs, f)
134 // phase 2: bind methods to their receiver base types
135 for _, m := range funcs {
136 if m.Recv != nil {
137 tc.bindMethod(m)
141 // phase 3: resolve all global objects
142 // (note that objects with _ name are also in the scope)
143 tc.cyclemap = make(map[*ast.Object]bool)
144 for _, obj := range tc.topScope.Objects {
145 tc.resolve(obj)
147 assert(len(tc.cyclemap) == 0)
149 // 4: sequentially typecheck function and method bodies
150 for _, f := range funcs {
151 tc.checkBlock(f.Body.List, f.Name.Obj.Type)
154 pkg.Scope = tc.topScope
158 func (tc *typechecker) declGlobal(global ast.Decl) {
159 switch d := global.(type) {
160 case *ast.BadDecl:
161 // ignore
163 case *ast.GenDecl:
164 iota := 0
165 var prev *ast.ValueSpec
166 for _, spec := range d.Specs {
167 switch s := spec.(type) {
168 case *ast.ImportSpec:
169 // TODO(gri) imports go into file scope
170 case *ast.ValueSpec:
171 switch d.Tok {
172 case token.CONST:
173 if s.Values == nil {
174 // create a new spec with type and values from the previous one
175 if prev != nil {
176 s = &ast.ValueSpec{s.Doc, s.Names, prev.Type, prev.Values, s.Comment}
177 } else {
178 // TODO(gri) this should probably go into the const decl code
179 tc.Errorf(s.Pos(), "missing initializer for const %s", s.Names[0].Name)
182 for _, name := range s.Names {
183 tc.decl(ast.Con, name, s, iota)
185 case token.VAR:
186 for _, name := range s.Names {
187 tc.decl(ast.Var, name, s, 0)
189 default:
190 panic("unreachable")
192 prev = s
193 iota++
194 case *ast.TypeSpec:
195 obj := tc.decl(ast.Typ, s.Name, s, 0)
196 // give all type objects an unresolved type so
197 // that we can collect methods in the type scope
198 typ := ast.NewType(ast.Unresolved)
199 obj.Type = typ
200 typ.Obj = obj
201 default:
202 panic("unreachable")
206 case *ast.FuncDecl:
207 if d.Recv == nil {
208 tc.decl(ast.Fun, d.Name, d, 0)
211 default:
212 panic("unreachable")
217 // If x is of the form *T, deref returns T, otherwise it returns x.
218 func deref(x ast.Expr) ast.Expr {
219 if p, isPtr := x.(*ast.StarExpr); isPtr {
220 x = p.X
222 return x
226 func (tc *typechecker) bindMethod(method *ast.FuncDecl) {
227 // a method is declared in the receiver base type's scope
228 var scope *ast.Scope
229 base := deref(method.Recv.List[0].Type)
230 if name, isIdent := base.(*ast.Ident); isIdent {
231 // if base is not an *ast.Ident, we had a syntax
232 // error and the parser reported an error already
233 obj := tc.topScope.Lookup(name.Name)
234 if obj == nil {
235 tc.Errorf(name.Pos(), "invalid receiver: %s is not declared in this package", name.Name)
236 } else if obj.Kind != ast.Typ {
237 tc.Errorf(name.Pos(), "invalid receiver: %s is not a type", name.Name)
238 } else {
239 typ := obj.Type
240 assert(typ.Form == ast.Unresolved)
241 scope = typ.Scope
244 if scope == nil {
245 // no receiver type found; use a dummy scope
246 // (we still want to type-check the method
247 // body, so make sure there is a name object
248 // and type)
249 // TODO(gri) should we record the scope so
250 // that we don't lose the receiver for type-
251 // checking of the method body?
252 scope = ast.NewScope(nil)
254 tc.declInScope(scope, ast.Fun, method.Name, method, 0)
258 func (tc *typechecker) resolve(obj *ast.Object) {
259 // check for declaration cycles
260 if tc.cyclemap[obj] {
261 tc.Errorf(objPos(obj), "illegal cycle in declaration of %s", obj.Name)
262 obj.Kind = ast.Bad
263 return
265 tc.cyclemap[obj] = true
266 defer func() {
267 tc.cyclemap[obj] = false, false
270 // resolve non-type objects
271 typ := obj.Type
272 if typ == nil {
273 switch obj.Kind {
274 case ast.Bad:
275 // ignore
277 case ast.Con:
278 tc.declConst(obj)
280 case ast.Var:
281 tc.declVar(obj)
282 //obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false)
284 case ast.Fun:
285 obj.Type = ast.NewType(ast.Function)
286 t := obj.Decl.(*ast.FuncDecl).Type
287 tc.declSignature(obj.Type, nil, t.Params, t.Results)
289 default:
290 // type objects have non-nil types when resolve is called
291 if debug {
292 fmt.Printf("kind = %s\n", obj.Kind)
294 panic("unreachable")
296 return
299 // resolve type objects
300 if typ.Form == ast.Unresolved {
301 tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false)
303 // provide types for all methods
304 for _, obj := range typ.Scope.Objects {
305 if obj.Kind == ast.Fun {
306 assert(obj.Type == nil)
307 obj.Type = ast.NewType(ast.Method)
308 f := obj.Decl.(*ast.FuncDecl)
309 t := f.Type
310 tc.declSignature(obj.Type, f.Recv, t.Params, t.Results)
317 func (tc *typechecker) checkBlock(body []ast.Stmt, ftype *ast.Type) {
318 tc.openScope()
319 defer tc.closeScope()
321 // inject function/method parameters into block scope, if any
322 if ftype != nil {
323 for _, par := range ftype.Params.Objects {
324 obj := tc.topScope.Insert(par)
325 assert(obj == par) // ftype has no double declarations
329 for _, stmt := range body {
330 tc.checkStmt(stmt)
335 // ----------------------------------------------------------------------------
336 // Types
338 // unparen removes parentheses around x, if any.
339 func unparen(x ast.Expr) ast.Expr {
340 if ux, hasParens := x.(*ast.ParenExpr); hasParens {
341 return unparen(ux.X)
343 return x
347 func (tc *typechecker) declFields(scope *ast.Scope, fields *ast.FieldList, ref bool) (n uint) {
348 if fields != nil {
349 for _, f := range fields.List {
350 typ := tc.typeFor(nil, f.Type, ref)
351 for _, name := range f.Names {
352 fld := tc.declInScope(scope, ast.Var, name, f, 0)
353 fld.Type = typ
358 return n
362 func (tc *typechecker) declSignature(typ *ast.Type, recv, params, results *ast.FieldList) {
363 assert((typ.Form == ast.Method) == (recv != nil))
364 typ.Params = ast.NewScope(nil)
365 tc.declFields(typ.Params, recv, true)
366 tc.declFields(typ.Params, params, true)
367 typ.N = tc.declFields(typ.Params, results, true)
371 func (tc *typechecker) typeFor(def *ast.Type, x ast.Expr, ref bool) (typ *ast.Type) {
372 x = unparen(x)
374 // type name
375 if t, isIdent := x.(*ast.Ident); isIdent {
376 obj := tc.find(t)
378 if obj.Kind != ast.Typ {
379 tc.Errorf(t.Pos(), "%s is not a type", t.Name)
380 if def == nil {
381 typ = ast.NewType(ast.BadType)
382 } else {
383 typ = def
384 typ.Form = ast.BadType
386 typ.Expr = x
387 return
390 if !ref {
391 tc.resolve(obj) // check for cycles even if type resolved
393 typ = obj.Type
395 if def != nil {
396 // new type declaration: copy type structure
397 def.Form = typ.Form
398 def.N = typ.N
399 def.Key, def.Elt = typ.Key, typ.Elt
400 def.Params = typ.Params
401 def.Expr = x
402 typ = def
404 return
407 // type literal
408 typ = def
409 if typ == nil {
410 typ = ast.NewType(ast.BadType)
412 typ.Expr = x
414 switch t := x.(type) {
415 case *ast.SelectorExpr:
416 if debug {
417 fmt.Println("qualified identifier unimplemented")
419 typ.Form = ast.BadType
421 case *ast.StarExpr:
422 typ.Form = ast.Pointer
423 typ.Elt = tc.typeFor(nil, t.X, true)
425 case *ast.ArrayType:
426 if t.Len != nil {
427 typ.Form = ast.Array
428 // TODO(gri) compute the real length
429 // (this may call resolve recursively)
430 (*typ).N = 42
431 } else {
432 typ.Form = ast.Slice
434 typ.Elt = tc.typeFor(nil, t.Elt, t.Len == nil)
436 case *ast.StructType:
437 typ.Form = ast.Struct
438 tc.declFields(typ.Scope, t.Fields, false)
440 case *ast.FuncType:
441 typ.Form = ast.Function
442 tc.declSignature(typ, nil, t.Params, t.Results)
444 case *ast.InterfaceType:
445 typ.Form = ast.Interface
446 tc.declFields(typ.Scope, t.Methods, true)
448 case *ast.MapType:
449 typ.Form = ast.Map
450 typ.Key = tc.typeFor(nil, t.Key, true)
451 typ.Elt = tc.typeFor(nil, t.Value, true)
453 case *ast.ChanType:
454 typ.Form = ast.Channel
455 typ.N = uint(t.Dir)
456 typ.Elt = tc.typeFor(nil, t.Value, true)
458 default:
459 if debug {
460 fmt.Printf("x is %T\n", x)
462 panic("unreachable")
465 return
469 // ----------------------------------------------------------------------------
470 // TODO(gri) implement these place holders
472 func (tc *typechecker) declConst(*ast.Object) {
476 func (tc *typechecker) declVar(*ast.Object) {
480 func (tc *typechecker) checkStmt(ast.Stmt) {