// Copyright 2010 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.

// DEPRECATED PACKAGE - SEE go/types INSTEAD.
// This package implements typechecking of a Go AST.
// The result of the typecheck is an augmented AST
// with object and type information for each identifier.
//
package typechecker

import (
	"fmt"
	"go/ast"
	"go/token"
	"go/scanner"
	"os"
)

// TODO(gri) don't report errors for objects/types that are marked as bad.


const debug = true // set for debugging output

// An importer takes an import path and returns the data describing the
// respective package's exported interface. The data format is TBD.
//
type Importer func(path string) ([]byte, os.Error)

// CheckPackage typechecks a package and augments the AST by setting
// *ast.Object, *ast.Type, and *ast.Scope fields accordingly. If an
// importer is provided, it is used to handle imports, otherwise they
// are ignored (likely leading to typechecking errors).
//
// If errors are reported, the AST may be incompletely augmented (fields
// may be nil) or contain incomplete object, type, or scope information.
//
func CheckPackage(fset *token.FileSet, pkg *ast.Package, importer Importer) os.Error {
	var tc typechecker
	tc.fset = fset
	tc.importer = importer
	tc.checkPackage(pkg)
	return tc.GetError(scanner.Sorted)
}

// CheckFile typechecks a single file, but otherwise behaves like
// CheckPackage. If the complete package consists of more than just
// one file, the file may not typecheck without errors.
//
func CheckFile(fset *token.FileSet, file *ast.File, importer Importer) os.Error {
	// create a single-file dummy package
	pkg := &ast.Package{file.Name.Name, nil, nil, map[string]*ast.File{fset.Position(file.Name.NamePos).Filename: file}}
	return CheckPackage(fset, pkg, importer)
}

// ----------------------------------------------------------------------------
// Typechecker state

type typechecker struct {
	fset *token.FileSet
	scanner.ErrorVector
	importer Importer
	globals  []*ast.Object        // list of global objects
	topScope *ast.Scope           // current top-most scope
	cyclemap map[*ast.Object]bool // for cycle detection
	iota     int                  // current value of iota
}

func (tc *typechecker) Errorf(pos token.Pos, format string, args ...interface{}) {
	tc.Error(tc.fset.Position(pos), fmt.Sprintf(format, args...))
}

func assert(pred bool) {
	if !pred {
		panic("internal error")
	}
}

/*
Typechecking is done in several phases:

phase 1: declare all global objects; also collect all function and method declarations
	- all objects have kind, name, decl fields; the decl field permits
	  quick lookup of an object's declaration
	- constant objects have an iota value
	- type objects have unresolved types with empty scopes, all others have nil types
	- report global double declarations

phase 2: bind methods to their receiver base types
	- receiver base types must be declared in the package, thus for
	  each method a corresponding (unresolved) type must exist
	- report method double declarations and errors with base types

phase 3: resolve all global objects
	- sequentially iterate through all objects in the global scope
	- resolve types for all unresolved types and assign types to
	  all attached methods
	- assign types to all other objects, possibly by evaluating
	  constant and initializer expressions
	- resolution may recurse; a cyclemap is used to detect cycles
	- report global typing errors

phase 4: sequentially typecheck function and method bodies
	- all global objects are declared and have types and values;
	  all methods have types
	- sequentially process statements in each body; any object
	  referred to must be fully defined at this point
	- report local typing errors
*/

func (tc *typechecker) checkPackage(pkg *ast.Package) {
	// setup package scope
	tc.topScope = Universe
	tc.openScope()
	defer tc.closeScope()

	// TODO(gri) there's no file scope at the moment since we ignore imports

	// phase 1: declare all global objects; also collect all function and method declarations
	var funcs []*ast.FuncDecl
	for _, file := range pkg.Files {
		for _, decl := range file.Decls {
			tc.declGlobal(decl)
			if f, isFunc := decl.(*ast.FuncDecl); isFunc {
				funcs = append(funcs, f)
			}
		}
	}

	// phase 2: bind methods to their receiver base types
	for _, m := range funcs {
		if m.Recv != nil {
			tc.bindMethod(m)
		}
	}

	// phase 3: resolve all global objects
	tc.cyclemap = make(map[*ast.Object]bool)
	for _, obj := range tc.globals {
		tc.resolve(obj)
	}
	assert(len(tc.cyclemap) == 0)

	// 4: sequentially typecheck function and method bodies
	for _, f := range funcs {
		ftype, _ := f.Name.Obj.Type.(*Type)
		tc.checkBlock(f.Body.List, ftype)
	}

	pkg.Scope = tc.topScope
}

func (tc *typechecker) declGlobal(global ast.Decl) {
	switch d := global.(type) {
	case *ast.BadDecl:
		// ignore

	case *ast.GenDecl:
		iota := 0
		var prev *ast.ValueSpec
		for _, spec := range d.Specs {
			switch s := spec.(type) {
			case *ast.ImportSpec:
				// TODO(gri) imports go into file scope
			case *ast.ValueSpec:
				switch d.Tok {
				case token.CONST:
					if s.Values == nil {
						// create a new spec with type and values from the previous one
						if prev != nil {
							s = &ast.ValueSpec{s.Doc, s.Names, prev.Type, prev.Values, s.Comment}
						} else {
							// TODO(gri) this should probably go into the const decl code
							tc.Errorf(s.Pos(), "missing initializer for const %s", s.Names[0].Name)
						}
					}
					for _, name := range s.Names {
						tc.globals = append(tc.globals, tc.decl(ast.Con, name, s, iota))
					}
				case token.VAR:
					for _, name := range s.Names {
						tc.globals = append(tc.globals, tc.decl(ast.Var, name, s, 0))
					}
				default:
					panic("unreachable")
				}
				prev = s
				iota++
			case *ast.TypeSpec:
				obj := tc.decl(ast.Typ, s.Name, s, 0)
				tc.globals = append(tc.globals, obj)
				// give all type objects an unresolved type so
				// that we can collect methods in the type scope
				typ := NewType(Unresolved)
				obj.Type = typ
				typ.Obj = obj
			default:
				panic("unreachable")
			}
		}

	case *ast.FuncDecl:
		if d.Recv == nil {
			tc.globals = append(tc.globals, tc.decl(ast.Fun, d.Name, d, 0))
		}

	default:
		panic("unreachable")
	}
}

// If x is of the form *T, deref returns T, otherwise it returns x.
func deref(x ast.Expr) ast.Expr {
	if p, isPtr := x.(*ast.StarExpr); isPtr {
		x = p.X
	}
	return x
}

func (tc *typechecker) bindMethod(method *ast.FuncDecl) {
	// a method is declared in the receiver base type's scope
	var scope *ast.Scope
	base := deref(method.Recv.List[0].Type)
	if name, isIdent := base.(*ast.Ident); isIdent {
		// if base is not an *ast.Ident, we had a syntax
		// error and the parser reported an error already
		obj := tc.topScope.Lookup(name.Name)
		if obj == nil {
			tc.Errorf(name.Pos(), "invalid receiver: %s is not declared in this package", name.Name)
		} else if obj.Kind != ast.Typ {
			tc.Errorf(name.Pos(), "invalid receiver: %s is not a type", name.Name)
		} else {
			typ := obj.Type.(*Type)
			assert(typ.Form == Unresolved)
			scope = typ.Scope
		}
	}
	if scope == nil {
		// no receiver type found; use a dummy scope
		// (we still want to type-check the method
		// body, so make sure there is a name object
		// and type)
		// TODO(gri) should we record the scope so
		// that we don't lose the receiver for type-
		// checking of the method body?
		scope = ast.NewScope(nil)
	}
	tc.declInScope(scope, ast.Fun, method.Name, method, 0)
}

func (tc *typechecker) resolve(obj *ast.Object) {
	// check for declaration cycles
	if tc.cyclemap[obj] {
		tc.Errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
		obj.Kind = ast.Bad
		return
	}
	tc.cyclemap[obj] = true
	defer func() {
		tc.cyclemap[obj] = false, false
	}()

	// resolve non-type objects
	typ, _ := obj.Type.(*Type)
	if typ == nil {
		switch obj.Kind {
		case ast.Bad:
			// ignore

		case ast.Con:
			tc.declConst(obj)

		case ast.Var:
			tc.declVar(obj)
			obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false)

		case ast.Fun:
			obj.Type = NewType(Function)
			t := obj.Decl.(*ast.FuncDecl).Type
			tc.declSignature(obj.Type.(*Type), nil, t.Params, t.Results)

		default:
			// type objects have non-nil types when resolve is called
			if debug {
				fmt.Printf("kind = %s\n", obj.Kind)
			}
			panic("unreachable")
		}
		return
	}

	// resolve type objects
	if typ.Form == Unresolved {
		tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false)

		// provide types for all methods
		for _, obj := range typ.Scope.Objects {
			if obj.Kind == ast.Fun {
				assert(obj.Type == nil)
				obj.Type = NewType(Method)
				f := obj.Decl.(*ast.FuncDecl)
				t := f.Type
				tc.declSignature(obj.Type.(*Type), f.Recv, t.Params, t.Results)
			}
		}
	}
}

func (tc *typechecker) checkBlock(body []ast.Stmt, ftype *Type) {
	tc.openScope()
	defer tc.closeScope()

	// inject function/method parameters into block scope, if any
	if ftype != nil {
		for _, par := range ftype.Params.Objects {
			if par.Name != "_" {
				alt := tc.topScope.Insert(par)
				assert(alt == nil) // ftype has no double declarations
			}
		}
	}

	for _, stmt := range body {
		tc.checkStmt(stmt)
	}
}

// ----------------------------------------------------------------------------
// Types

// unparen removes parentheses around x, if any.
func unparen(x ast.Expr) ast.Expr {
	if ux, hasParens := x.(*ast.ParenExpr); hasParens {
		return unparen(ux.X)
	}
	return x
}

func (tc *typechecker) declFields(scope *ast.Scope, fields *ast.FieldList, ref bool) (n uint) {
	if fields != nil {
		for _, f := range fields.List {
			typ := tc.typeFor(nil, f.Type, ref)
			for _, name := range f.Names {
				fld := tc.declInScope(scope, ast.Var, name, f, 0)
				fld.Type = typ
				n++
			}
		}
	}
	return n
}

func (tc *typechecker) declSignature(typ *Type, recv, params, results *ast.FieldList) {
	assert((typ.Form == Method) == (recv != nil))
	typ.Params = ast.NewScope(nil)
	tc.declFields(typ.Params, recv, true)
	tc.declFields(typ.Params, params, true)
	typ.N = tc.declFields(typ.Params, results, true)
}

func (tc *typechecker) typeFor(def *Type, x ast.Expr, ref bool) (typ *Type) {
	x = unparen(x)

	// type name
	if t, isIdent := x.(*ast.Ident); isIdent {
		obj := tc.find(t)

		if obj.Kind != ast.Typ {
			tc.Errorf(t.Pos(), "%s is not a type", t.Name)
			if def == nil {
				typ = NewType(BadType)
			} else {
				typ = def
				typ.Form = BadType
			}
			typ.Expr = x
			return
		}

		if !ref {
			tc.resolve(obj) // check for cycles even if type resolved
		}
		typ = obj.Type.(*Type)

		if def != nil {
			// new type declaration: copy type structure
			def.Form = typ.Form
			def.N = typ.N
			def.Key, def.Elt = typ.Key, typ.Elt
			def.Params = typ.Params
			def.Expr = x
			typ = def
		}
		return
	}

	// type literal
	typ = def
	if typ == nil {
		typ = NewType(BadType)
	}
	typ.Expr = x

	switch t := x.(type) {
	case *ast.SelectorExpr:
		if debug {
			fmt.Println("qualified identifier unimplemented")
		}
		typ.Form = BadType

	case *ast.StarExpr:
		typ.Form = Pointer
		typ.Elt = tc.typeFor(nil, t.X, true)

	case *ast.ArrayType:
		if t.Len != nil {
			typ.Form = Array
			// TODO(gri) compute the real length
			// (this may call resolve recursively)
			(*typ).N = 42
		} else {
			typ.Form = Slice
		}
		typ.Elt = tc.typeFor(nil, t.Elt, t.Len == nil)

	case *ast.StructType:
		typ.Form = Struct
		tc.declFields(typ.Scope, t.Fields, false)

	case *ast.FuncType:
		typ.Form = Function
		tc.declSignature(typ, nil, t.Params, t.Results)

	case *ast.InterfaceType:
		typ.Form = Interface
		tc.declFields(typ.Scope, t.Methods, true)

	case *ast.MapType:
		typ.Form = Map
		typ.Key = tc.typeFor(nil, t.Key, true)
		typ.Elt = tc.typeFor(nil, t.Value, true)

	case *ast.ChanType:
		typ.Form = Channel
		typ.N = uint(t.Dir)
		typ.Elt = tc.typeFor(nil, t.Value, true)

	default:
		if debug {
			fmt.Printf("x is %T\n", x)
		}
		panic("unreachable")
	}

	return
}

// ----------------------------------------------------------------------------
// TODO(gri) implement these place holders

func (tc *typechecker) declConst(*ast.Object) {
}

func (tc *typechecker) declVar(*ast.Object) {
}

func (tc *typechecker) checkStmt(ast.Stmt) {
}
