// 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.Value);
	if def == nil {
		a.diagAt(x, "%s: undefined", x.Value);
		return nil;
	}
	switch def := def.(type) {
	case *Constant:
		a.diagAt(x, "constant %v used as type", x.Value);
		return nil;
	case *Variable:
		a.diagAt(x, "variable %v used as type", x.Value);
		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.Value, 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 countFields(fs []*ast.Field) int {
	n := 0;
	for _, f := range fs {
		if f.Names == nil {
			n++;
		} else {
			n += len(f.Names);
		}
	}
	return n;
}

func (a *typeCompiler) compileFields(fs []*ast.Field, allowRec bool) ([]Type, []*ast.Ident, []token.Position, bool) {
	n := countFields(fs);
	ts := make([]Type, n);
	ns := make([]*ast.Ident, n);
	ps := make([]token.Position, n);

	bad := false;
	i := 0;
	for _, f := range fs {
		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].Value;
		} 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].Value;
			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.Value, 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;
}
