func copyConstType(typ ast.Expr, pos token.Pos) ast.Expr {
	switch typ := typ.(type) {
	case *ast.Ident:
		return &ast.Ident{Name: typ.Name, NamePos: pos}
	case *ast.SelectorExpr:
		if id, ok := typ.X.(*ast.Ident); ok {
			return &ast.SelectorExpr{
				Sel: ast.NewIdent(typ.Sel.Name),
				X:   &ast.Ident{Name: id.Name, NamePos: pos},
			}
		}
	}
	return nil  
}
copyConstType returns a copy of typ with position pos.
typ must be a valid constant type.
In practice, only (possibly qualified) identifiers are possible.
package doc
import (
	"github.com/tcard/sgo/sgo/ast"
	"github.com/tcard/sgo/sgo/token"
)
func filterIdentList(list []*ast.Ident) []*ast.Ident {
	j := 0
	for _, x := range list {
		if ast.IsExported(x.Name) {
			list[j] = x
			j++
		}
	}
	return list[0:j]
}
func hasExportedName(list []*ast.Ident) bool {
	for _, x := range list {
		if x.IsExported() {
			return true
		}
	}
	return false
}
func removeErrorField(ityp *ast.InterfaceType) {
	list := ityp.Methods.List  
	j := 0
	for _, field := range list {
		keepField := true
		if n := len(field.Names); n == 0 {
			if fname, _ := baseTypeName(field.Type); fname == "error" {
				keepField = false
			}
		}
		if keepField {
			list[j] = field
			j++
		}
	}
	if j < len(list) {
		ityp.Incomplete = true
	}
	ityp.Methods.List = list[0:j]
}
func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp *ast.InterfaceType) (removedFields bool) {
	if fields == nil {
		return
	}
	list := fields.List
	j := 0
	for _, field := range list {
		keepField := false
		if n := len(field.Names); n == 0 {
			fname := r.recordAnonymousField(parent, field.Type)
			if ast.IsExported(fname) {
				keepField = true
			} else if ityp != nil && fname == "error" {
				keepField = true
				r.remember(ityp)
			}
		} else {
			field.Names = filterIdentList(field.Names)
			if len(field.Names) < n {
				removedFields = true
			}
			if len(field.Names) > 0 {
				keepField = true
			}
		}
		if keepField {
			r.filterType(nil, field.Type)
			list[j] = field
			j++
		}
	}
	if j < len(list) {
		removedFields = true
	}
	fields.List = list[0:j]
	return
}
func (r *reader) filterParamList(fields *ast.FieldList) {
	if fields != nil {
		for _, f := range fields.List {
			r.filterType(nil, f.Type)
		}
	}
}
func (r *reader) filterType(parent *namedType, typ ast.Expr) {
	switch t := typ.(type) {
	case *ast.Ident:
	case *ast.ParenExpr:
		r.filterType(nil, t.X)
	case *ast.ArrayType:
		r.filterType(nil, t.Elt)
	case *ast.StructType:
		if r.filterFieldList(parent, t.Fields, nil) {
			t.Incomplete = true
		}
	case *ast.FuncType:
		r.filterParamList(t.Params)
		r.filterParamList(t.Results)
	case *ast.InterfaceType:
		if r.filterFieldList(parent, t.Methods, t) {
			t.Incomplete = true
		}
	case *ast.MapType:
		r.filterType(nil, t.Key)
		r.filterType(nil, t.Value)
	case *ast.ChanType:
		r.filterType(nil, t.Value)
	}
}
func (r *reader) filterSpec(spec ast.Spec) bool {
	switch s := spec.(type) {
	case *ast.ImportSpec:
		return true
	case *ast.ValueSpec:
		s.Names.List = filterIdentList(s.Names.List)
		if len(s.Names.List) > 0 {
			r.filterType(nil, s.Type)
			return true
		}
	case *ast.TypeSpec:
		if name := s.Name.Name; ast.IsExported(name) {
			r.filterType(r.lookupType(s.Name.Name), s.Type)
			return true
		} else if name == "error" {
			r.errorDecl = true
		}
	}
	return false
}