| // 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; |
| } |