blob: a4d055fb5926167402de1d40e32b1d7454c16db2 [file] [log] [blame]
// 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 {
_bl, _index, 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 fi, 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) 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:
goto notimpl;
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;
}