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

// This file implements scope support functions.

package typechecker

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


func (tc *typechecker) openScope() *ast.Scope {
	tc.topScope = ast.NewScope(tc.topScope)
	return tc.topScope
}


func (tc *typechecker) closeScope() {
	tc.topScope = tc.topScope.Outer
}


// objPos computes the source position of the declaration of an object name.
// Only required for error reporting, so doesn't have to be fast.
func objPos(obj *ast.Object) (pos token.Position) {
	switch d := obj.Decl.(type) {
	case *ast.Field:
		for _, n := range d.Names {
			if n.Name == obj.Name {
				return n.Pos()
			}
		}
	case *ast.ValueSpec:
		for _, n := range d.Names {
			if n.Name == obj.Name {
				return n.Pos()
			}
		}
	case *ast.TypeSpec:
		return d.Name.Pos()
	case *ast.FuncDecl:
		return d.Name.Pos()
	}
	if debug {
		fmt.Printf("decl = %T\n", obj.Decl)
	}
	panic("unreachable")
}


// declInScope declares an object of a given kind and name in scope and sets the object's Decl and N fields.
// It returns the newly allocated object. If an object with the same name already exists in scope, an error
// is reported and the object is not inserted.
// (Objects with _ name are always inserted into a scope without errors, but they cannot be found.)
func (tc *typechecker) declInScope(scope *ast.Scope, kind ast.Kind, name *ast.Ident, decl interface{}, n int) *ast.Object {
	obj := ast.NewObj(kind, name.Name)
	obj.Decl = decl
	obj.N = n
	name.Obj = obj
	if alt := scope.Insert(obj); alt != obj {
		tc.Errorf(name.Pos(), "%s already declared at %s", name.Name, objPos(alt))
	}
	return obj
}


// decl is the same as declInScope(tc.topScope, ...)
func (tc *typechecker) decl(kind ast.Kind, name *ast.Ident, decl interface{}, n int) *ast.Object {
	return tc.declInScope(tc.topScope, kind, name, decl, n)
}


// find returns the object with the given name if visible in the current scope hierarchy.
// If no such object is found, an error is reported and a bad object is returned instead.
func (tc *typechecker) find(name *ast.Ident) (obj *ast.Object) {
	for s := tc.topScope; s != nil && obj == nil; s = s.Outer {
		obj = s.Lookup(name.Name)
	}
	if obj == nil {
		tc.Errorf(name.Pos(), "%s not declared", name.Name)
		obj = ast.NewObj(ast.Bad, name.Name)
	}
	name.Obj = obj
	return
}


// findField returns the object with the given name if visible in the type's scope.
// If no such object is found, an error is reported and a bad object is returned instead.
func (tc *typechecker) findField(typ *ast.Type, name *ast.Ident) (obj *ast.Object) {
	// TODO(gri) This is simplistic at the moment and ignores anonymous fields.
	obj = typ.Scope.Lookup(name.Name)
	if obj == nil {
		tc.Errorf(name.Pos(), "%s not declared", name.Name)
		obj = ast.NewObj(ast.Bad, name.Name)
	}
	return
}


// printScope prints the objects in a scope.
func printScope(scope *ast.Scope) {
	fmt.Printf("scope %p {", scope)
	if scope != nil && len(scope.Objects) > 0 {
		fmt.Println()
		for _, obj := range scope.Objects {
			form := "void"
			if obj.Type != nil {
				form = obj.Type.Form.String()
			}
			fmt.Printf("\t%s\t%s\n", obj.Name, form)
		}
	}
	fmt.Printf("}\n")
}
