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

package eval

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


/*
 * Type compiler
 */

type typeCompiler struct {
	*compiler
	block *block
	// Check to be performed after a type declaration is compiled.
	//
	// TODO(austin) This will probably have to change after we
	// eliminate forward declarations.
	lateCheck func() bool
}

func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
	_, _, def := a.block.Lookup(x.Name())
	if def == nil {
		a.diagAt(x, "%s: undefined", x.Name())
		return nil
	}
	switch def := def.(type) {
	case *Constant:
		a.diagAt(x, "constant %v used as type", x.Name())
		return nil
	case *Variable:
		a.diagAt(x, "variable %v used as type", x.Name())
		return nil
	case *NamedType:
		if !allowRec && def.incomplete {
			a.diagAt(x, "illegal recursive type")
			return nil
		}
		if !def.incomplete && def.Def == nil {
			// Placeholder type from an earlier error
			return nil
		}
		return def
	case Type:
		return def
	}
	log.Crashf("name %s has unknown type %T", x.Name(), def)
	return nil
}

func (a *typeCompiler) compileArrayType(x *ast.ArrayType, allowRec bool) Type {
	// Compile element type
	elem := a.compileType(x.Elt, allowRec)

	// Compile length expression
	if x.Len == nil {
		if elem == nil {
			return nil
		}
		return NewSliceType(elem)
	}

	if _, ok := x.Len.(*ast.Ellipsis); ok {
		a.diagAt(x.Len, "... array initailizers not implemented")
		return nil
	}
	l, ok := a.compileArrayLen(a.block, x.Len)
	if !ok {
		return nil
	}
	if l < 0 {
		a.diagAt(x.Len, "array length must be non-negative")
		return nil
	}
	if elem == nil {
		return nil
	}

	return NewArrayType(l, elem)
}

func (a *typeCompiler) compileFields(fields *ast.FieldList, allowRec bool) ([]Type, []*ast.Ident, []token.Position, bool) {
	n := fields.NumFields()
	ts := make([]Type, n)
	ns := make([]*ast.Ident, n)
	ps := make([]token.Position, n)
	bad := false

	if fields != nil {
		i := 0
		for _, f := range fields.List {
			t := a.compileType(f.Type, allowRec)
			if t == nil {
				bad = true
			}
			if f.Names == nil {
				ns[i] = nil
				ts[i] = t
				ps[i] = f.Type.Pos()
				i++
				continue
			}
			for _, n := range f.Names {
				ns[i] = n
				ts[i] = t
				ps[i] = n.Pos()
				i++
			}
		}
	}

	return ts, ns, ps, bad
}

func (a *typeCompiler) compileStructType(x *ast.StructType, allowRec bool) Type {
	ts, names, poss, bad := a.compileFields(x.Fields, allowRec)

	// XXX(Spec) The spec claims that field identifiers must be
	// unique, but 6g only checks this when they are accessed.  I
	// think the spec is better in this regard: if I write two
	// fields with the same name in the same struct type, clearly
	// that's a mistake.  This definition does *not* descend into
	// anonymous fields, so it doesn't matter if those change.
	// There's separate language in the spec about checking
	// uniqueness of field names inherited from anonymous fields
	// at use time.
	fields := make([]StructField, len(ts))
	nameSet := make(map[string]token.Position, len(ts))
	for i := range fields {
		// Compute field name and check anonymous fields
		var name string
		if names[i] != nil {
			name = names[i].Name()
		} else {
			if ts[i] == nil {
				continue
			}

			var nt *NamedType
			// [For anonymous fields,] the unqualified
			// type name acts as the field identifier.
			switch t := ts[i].(type) {
			case *NamedType:
				name = t.Name
				nt = t
			case *PtrType:
				switch t := t.Elem.(type) {
				case *NamedType:
					name = t.Name
					nt = t
				}
			}
			// [An anonymous field] must be specified as a
			// type name T or as a pointer to a type name
			// *T, and T itself, may not be a pointer or
			// interface type.
			if nt == nil {
				a.diagAt(&poss[i], "embedded type must T or *T, where T is a named type")
				bad = true
				continue
			}
			// The check for embedded pointer types must
			// be deferred because of things like
			//  type T *struct { T }
			lateCheck := a.lateCheck
			a.lateCheck = func() bool {
				if _, ok := nt.lit().(*PtrType); ok {
					a.diagAt(&poss[i], "embedded type %v is a pointer type", nt)
					return false
				}
				return lateCheck()
			}
		}

		// Check name uniqueness
		if prev, ok := nameSet[name]; ok {
			a.diagAt(&poss[i], "field %s redeclared\n\tprevious declaration at %s", name, &prev)
			bad = true
			continue
		}
		nameSet[name] = poss[i]

		// Create field
		fields[i].Name = name
		fields[i].Type = ts[i]
		fields[i].Anonymous = (names[i] == nil)
	}

	if bad {
		return nil
	}

	return NewStructType(fields)
}

func (a *typeCompiler) compilePtrType(x *ast.StarExpr) Type {
	elem := a.compileType(x.X, true)
	if elem == nil {
		return nil
	}
	return NewPtrType(elem)
}

func (a *typeCompiler) compileFuncType(x *ast.FuncType, allowRec bool) *FuncDecl {
	// TODO(austin) Variadic function types

	// The types of parameters and results must be complete.
	//
	// TODO(austin) It's not clear they actually have to be complete.
	in, inNames, _, inBad := a.compileFields(x.Params, allowRec)
	out, outNames, _, outBad := a.compileFields(x.Results, allowRec)

	if inBad || outBad {
		return nil
	}
	return &FuncDecl{NewFuncType(in, false, out), nil, inNames, outNames}
}

func (a *typeCompiler) compileInterfaceType(x *ast.InterfaceType, allowRec bool) *InterfaceType {
	ts, names, poss, bad := a.compileFields(x.Methods, allowRec)

	methods := make([]IMethod, len(ts))
	nameSet := make(map[string]token.Position, len(ts))
	embeds := make([]*InterfaceType, len(ts))

	var nm, ne int
	for i := range ts {
		if ts[i] == nil {
			continue
		}

		if names[i] != nil {
			name := names[i].Name()
			methods[nm].Name = name
			methods[nm].Type = ts[i].(*FuncType)
			nm++
			if prev, ok := nameSet[name]; ok {
				a.diagAt(&poss[i], "method %s redeclared\n\tprevious declaration at %s", name, &prev)
				bad = true
				continue
			}
			nameSet[name] = poss[i]
		} else {
			// Embedded interface
			it, ok := ts[i].lit().(*InterfaceType)
			if !ok {
				a.diagAt(&poss[i], "embedded type must be an interface")
				bad = true
				continue
			}
			embeds[ne] = it
			ne++
			for _, m := range it.methods {
				if prev, ok := nameSet[m.Name]; ok {
					a.diagAt(&poss[i], "method %s redeclared\n\tprevious declaration at %s", m.Name, &prev)
					bad = true
					continue
				}
				nameSet[m.Name] = poss[i]
			}
		}
	}

	if bad {
		return nil
	}

	methods = methods[0:nm]
	embeds = embeds[0:ne]

	return NewInterfaceType(methods, embeds)
}

func (a *typeCompiler) compileMapType(x *ast.MapType) Type {
	key := a.compileType(x.Key, true)
	val := a.compileType(x.Value, true)
	if key == nil || val == nil {
		return nil
	}
	// XXX(Spec) The Map types section explicitly lists all types
	// that can be map keys except for function types.
	switch key.lit().(type) {
	case *StructType:
		a.diagAt(x, "map key cannot be a struct type")
		return nil
	case *ArrayType:
		a.diagAt(x, "map key cannot be an array type")
		return nil
	case *SliceType:
		a.diagAt(x, "map key cannot be a slice type")
		return nil
	}
	return NewMapType(key, val)
}

func (a *typeCompiler) compileType(x ast.Expr, allowRec bool) Type {
	switch x := x.(type) {
	case *ast.BadExpr:
		// Error already reported by parser
		a.silentErrors++
		return nil

	case *ast.Ident:
		return a.compileIdent(x, allowRec)

	case *ast.ArrayType:
		return a.compileArrayType(x, allowRec)

	case *ast.StructType:
		return a.compileStructType(x, allowRec)

	case *ast.StarExpr:
		return a.compilePtrType(x)

	case *ast.FuncType:
		fd := a.compileFuncType(x, allowRec)
		if fd == nil {
			return nil
		}
		return fd.Type

	case *ast.InterfaceType:
		return a.compileInterfaceType(x, allowRec)

	case *ast.MapType:
		return a.compileMapType(x)

	case *ast.ChanType:
		goto notimpl

	case *ast.ParenExpr:
		return a.compileType(x.X, allowRec)

	case *ast.Ellipsis:
		a.diagAt(x, "illegal use of ellipsis")
		return nil
	}
	a.diagAt(x, "expression used as type")
	return nil

notimpl:
	a.diagAt(x, "compileType: %T not implemented", x)
	return nil
}

/*
 * Type compiler interface
 */

func noLateCheck() bool { return true }

func (a *compiler) compileType(b *block, typ ast.Expr) Type {
	tc := &typeCompiler{a, b, noLateCheck}
	t := tc.compileType(typ, false)
	if !tc.lateCheck() {
		t = nil
	}
	return t
}

func (a *compiler) compileTypeDecl(b *block, decl *ast.GenDecl) bool {
	ok := true
	for _, spec := range decl.Specs {
		spec := spec.(*ast.TypeSpec)
		// Create incomplete type for this type
		nt := b.DefineType(spec.Name.Name(), spec.Name.Pos(), nil)
		if nt != nil {
			nt.(*NamedType).incomplete = true
		}
		// Compile type
		tc := &typeCompiler{a, b, noLateCheck}
		t := tc.compileType(spec.Type, false)
		if t == nil {
			// Create a placeholder type
			ok = false
		}
		// Fill incomplete type
		if nt != nil {
			nt.(*NamedType).Complete(t)
		}
		// Perform late type checking with complete type
		if !tc.lateCheck() {
			ok = false
			if nt != nil {
				// Make the type a placeholder
				nt.(*NamedType).Def = nil
			}
		}
	}
	return ok
}

func (a *compiler) compileFuncType(b *block, typ *ast.FuncType) *FuncDecl {
	tc := &typeCompiler{a, b, noLateCheck}
	res := tc.compileFuncType(typ, false)
	if res != nil {
		if !tc.lateCheck() {
			res = nil
		}
	}
	return res
}
