func MustWriteGoTypes(thisPackagePath string, typi types.Type) (s string, addPkgPathList []string) { switch typ := typi.(type) { case *types.Basic: return typ.String(), nil case *types.Named: if typ.Obj().Pkg() == nil { return typ.Obj().Name(), nil } typPkgPath := typ.Obj().Pkg().Path() if thisPackagePath == typPkgPath { return typ.Obj().Name(), nil } return path.Base(typPkgPath) + "." + typ.Obj().Name(), []string{typPkgPath} case *types.Pointer: s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem()) return "*" + s, addPkgPathList case *types.Slice: s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem()) return "[]" + s, addPkgPathList case *types.Interface: return typ.String(), nil //s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem()) //return "[]" + s, addPkgPathList default: panic(fmt.Errorf("[MustWriteGoTypes] Not implement go/types [%T] [%s]", typi, typi.String())) } return "", nil }
func dump(path string, typ types.Type, st reflect.StructTag) IObj { named, _ := typ.(*types.Named) if named != nil { typ = typ.Underlying() } if strings.Split(st.Get("json"), ",")[0] == "" { if _, ok := typ.(*types.Struct); !ok { if _, ok := typ.(*types.Pointer); !ok { return nil } } } switch u := typ.(type) { case *types.Struct: return Struct(path, st, u, named) case *types.Map: return Map(path, st, u, named) case *types.Slice: return Slice(path, st, u) case *types.Pointer: return Pointer(path, st, u) case *types.Basic: return Basic(path, st, u, named) default: panic("unsupported") } }
// lockPath returns a typePath describing the location of a lock value // contained in typ. If there is no contained lock, it returns nil. func lockPath(tpkg *types.Package, typ types.Type) typePath { if typ == nil { return nil } // We're only interested in the case in which the underlying // type is a struct. (Interfaces and pointers are safe to copy.) styp, ok := typ.Underlying().(*types.Struct) if !ok { return nil } // We're looking for cases in which a reference to this type // can be locked, but a value cannot. This differentiates // embedded interfaces from embedded values. if plock := types.NewMethodSet(types.NewPointer(typ)).Lookup(tpkg, "Lock"); plock != nil { if lock := types.NewMethodSet(typ).Lookup(tpkg, "Lock"); lock == nil { return []types.Type{typ} } } nfields := styp.NumFields() for i := 0; i < nfields; i++ { ftyp := styp.Field(i).Type() subpath := lockPath(tpkg, ftyp) if subpath != nil { return append(subpath, typ) } } return nil }
func (g *goGen) genWrite(valName, seqName string, T types.Type) { if isErrorType(T) { g.Printf("if %s == nil {\n", valName) g.Printf(" %s.WriteString(\"\");\n", seqName) g.Printf("} else {\n") g.Printf(" %s.WriteString(%s.Error());\n", seqName, valName) g.Printf("}\n") return } switch T := T.(type) { case *types.Pointer: // TODO(crawshaw): test *int // TODO(crawshaw): test **Generator switch T := T.Elem().(type) { case *types.Named: obj := T.Obj() if obj.Pkg() != g.pkg { g.errorf("type %s not defined in package %s", T, g.pkg) return } g.Printf("%s.WriteGoRef(%s)\n", seqName, valName) default: g.errorf("unsupported type %s", T) } case *types.Named: switch u := T.Underlying().(type) { case *types.Interface, *types.Pointer: g.Printf("%s.WriteGoRef(%s)\n", seqName, valName) default: g.errorf("unsupported, direct named type %s: %s", T, u) } default: g.Printf("%s.Write%s(%s);\n", seqName, seqType(T), valName) } }
func sizeof(t types.Type) uint { switch t := t.(type) { case *types.Tuple: // TODO: usage of reflect most likely wrong! // uint(reflect.TypeOf(t).Elem().Size()) panic("Tuples are unsupported") case *types.Basic: return sizeBasic(t.Kind()) case *types.Pointer: return sizePtr() case *types.Slice: return sizeSlice(t) case *types.Array: return sizeArray(t) case *types.Named: if sse2, ok := sse2Info(t); ok { return sse2.size } else if info, ok := simdInfo(t); ok { return info.size } else { panic(ice(fmt.Sprintf("unknown named type \"%v\"", t.String()))) } } panic(ice(fmt.Sprintf("unknown type: %v", t))) }
func needWrapType(typ types.Type) bool { switch typ := typ.(type) { case *types.Basic: return false case *types.Struct: return true case *types.Named: switch ut := typ.Underlying().(type) { case *types.Basic: return false default: return needWrapType(ut) } case *types.Array: return true case *types.Map: return true case *types.Slice: return true case *types.Interface: wrap := true if typ.Underlying() == universe.syms["error"].GoType().Underlying() { wrap = false } return wrap case *types.Signature: return true case *types.Pointer: return needWrapType(typ.Elem()) } return false }
// MethodSet returns the method set of type T. It is thread-safe. // // If cache is nil, this function is equivalent to types.NewMethodSet(T). // Utility functions can thus expose an optional *MethodSetCache // parameter to clients that care about performance. // func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet { if cache == nil { return types.NewMethodSet(T) } cache.mu.Lock() defer cache.mu.Unlock() switch T := T.(type) { case *types.Named: return cache.lookupNamed(T).value case *types.Pointer: if N, ok := T.Elem().(*types.Named); ok { return cache.lookupNamed(N).pointer } } // all other types // (The map uses pointer equivalence, not type identity.) mset := cache.others[T] if mset == nil { mset = types.NewMethodSet(T) if cache.others == nil { cache.others = make(map[types.Type]*types.MethodSet) } cache.others[T] = mset } return mset }
func (sym *symtab) addInterfaceType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) { fn := sym.typename(t, nil) typ := t.Underlying().(*types.Interface) kind |= skInterface // special handling of 'error' if isErrorType(typ) { return } sym.syms[fn] = &symbol{ gopkg: pkg, goobj: obj, gotyp: t, kind: kind, id: id, goname: n, cgoname: "cgo_type_" + id, cpyname: "cpy_type_" + id, pyfmt: "O&", pybuf: "P", pysig: "object", c2py: "cgopy_cnv_c2py_" + id, py2c: "cgopy_cnv_py2c_" + id, pychk: fmt.Sprintf("cpy_func_%[1]s_check(%%s)", id), } }
func getStructType(t types.Type) string { ts := t.String() if ts != "time.Time" && ts != "bson.ObjectId" { return "struct" } return ts }
func (fr *frame) makeInterface(llv llvm.Value, vty types.Type, iface types.Type) *govalue { if _, ok := vty.Underlying().(*types.Pointer); !ok { ptr := fr.createTypeMalloc(vty) fr.builder.CreateStore(llv, ptr) llv = ptr } return fr.makeInterfaceFromPointer(llv, vty, iface) }
func (x array) hash(t types.Type) int { h := 0 tElt := t.Underlying().(*types.Array).Elem() for _, xi := range x { h += hash(tElt, xi) } return h }
func typefmt(typ types.Type) string { // Ugh. typename := typ.String() for _, p := range strings.Split(os.Getenv("GOPATH"), ":") { typename = strings.Replace(typename, p+"/src/", "", -1) } return typename }
// Reads the value from the given interface type, assuming that the // interface holds a value of the correct type. func (fr *frame) getInterfaceValue(v *govalue, ty types.Type) *govalue { val := fr.builder.CreateExtractValue(v.value, 1, "") if _, ok := ty.Underlying().(*types.Pointer); !ok { typedval := fr.builder.CreateBitCast(val, llvm.PointerType(fr.types.ToLLVM(ty), 0), "") val = fr.builder.CreateLoad(typedval, "") } return newValue(val, ty) }
func signed(t types.Type) bool { switch t := t.(type) { case *types.Basic: return signedBasic(t.Kind()) } panic(ice(fmt.Sprintf("unknown type: %v", t))) }
func catchReferencedTypes(et types.Type) { id := LogTypeUse(et) _, seen := catchReferencedTypesSeen[id] if seen { return } catchReferencedTypesSeen[id] = true // check that we have all the required methods? /* for t := 1; t < NextTypeID; t++ { // make sure we do this in a consistent order for _, k := range TypesEncountered.Keys() { if TypesEncountered.At(k).(int) == t { switch k.(type) { case *types.Interface: if types.Implements(et,k.(*types.Interface)) { // TODO call missing method? } } } } } */ //LogTypeUse(types.NewPointer(et)) switch et.(type) { case *types.Named: catchReferencedTypes(et.Underlying()) for m := 0; m < et.(*types.Named).NumMethods(); m++ { catchReferencedTypes(et.(*types.Named).Method(m).Type()) } case *types.Array: catchReferencedTypes(et.(*types.Array).Elem()) //catchReferencedTypes(types.NewSlice(et.(*types.Array).Elem())) case *types.Pointer: catchReferencedTypes(et.(*types.Pointer).Elem()) case *types.Slice: catchReferencedTypes(et.(*types.Slice).Elem()) case *types.Struct: for f := 0; f < et.(*types.Struct).NumFields(); f++ { if et.(*types.Struct).Field(f).IsField() { catchReferencedTypes(et.(*types.Struct).Field(f).Type()) } } case *types.Map: catchReferencedTypes(et.(*types.Map).Key()) catchReferencedTypes(et.(*types.Map).Elem()) case *types.Signature: for i := 0; i < et.(*types.Signature).Params().Len(); i++ { catchReferencedTypes(et.(*types.Signature).Params().At(i).Type()) } for o := 0; o < et.(*types.Signature).Results().Len(); o++ { catchReferencedTypes(et.(*types.Signature).Results().At(o).Type()) } case *types.Chan: catchReferencedTypes(et.(*types.Chan).Elem()) } }
// If cond is true, reads the value from the given interface type, otherwise // returns a nil value. func (fr *frame) getInterfaceValueOrNull(cond llvm.Value, v *govalue, ty types.Type) *govalue { val := fr.builder.CreateExtractValue(v.value, 1, "") if _, ok := ty.Underlying().(*types.Pointer); ok { val = fr.builder.CreateSelect(cond, val, llvm.ConstNull(val.Type()), "") } else { val = fr.loadOrNull(cond, val, ty).value } return newValue(val, ty) }
func isInt(t types.Type) bool { if t, ok := t.(*types.Basic); ok { switch t.Kind() { case types.Int, types.Int8, types.Int16, types.Int32, types.Int64: return true } } return false }
func (fr *frame) makeInterfaceFromPointer(vptr llvm.Value, vty types.Type, iface types.Type) *govalue { i8ptr := llvm.PointerType(llvm.Int8Type(), 0) llv := fr.builder.CreateBitCast(vptr, i8ptr, "") value := llvm.Undef(fr.types.ToLLVM(iface)) itab := fr.types.getItabPointer(vty, iface.Underlying().(*types.Interface)) value = fr.builder.CreateInsertValue(value, itab, 0, "") value = fr.builder.CreateInsertValue(value, llv, 1, "") return newValue(value, iface) }
func (l langType) MakeInterface(register string, regTyp types.Type, v interface{}, errorInfo string) string { ret := `new Interface(` + l.PogoComp().LogTypeUse(v.(ssa.Value).Type() /*NOT underlying()*/) + `,` + l.IndirectValue(v, errorInfo) + ")" if getHaxeClass(regTyp.String()) != "" { ret = "Force.toHaxeParam(" + ret + ")" // as interfaces are not native to haxe, so need to convert // TODO optimize when stable } return register + `=` + ret + ";" }
func (x structure) hash(t types.Type) int { tStruct := t.Underlying().(*types.Struct) h := 0 for i, n := 0, tStruct.NumFields(); i < n; i++ { if f := tStruct.Field(i); !f.Anonymous() { h += hash(f.Type(), x[i]) } } return h }
func (x array) eq(t types.Type, _y interface{}) bool { y := _y.(array) tElt := t.Underlying().(*types.Array).Elem() for i, xi := range x { if !equals(tElt, xi, y[i]) { return false } } return true }
// usesBuiltinMap returns true if the built-in hash function and // equivalence relation for type t are consistent with those of the // interpreter's representation of type t. Such types are: all basic // types (bool, numbers, string), pointers and channels. // // usesBuiltinMap returns false for types that require a custom map // implementation: interfaces, arrays and structs. // // Panic ensues if t is an invalid map key type: function, map or slice. func usesBuiltinMap(t types.Type) bool { switch t := t.(type) { case *types.Basic, *types.Chan, *types.Pointer: return true case *types.Named: return usesBuiltinMap(t.Underlying()) case *types.Interface, *types.Array, *types.Struct: return false } panic(fmt.Sprintf("invalid map key type: %T", t)) }
func makeImplementsType(T types.Type, fset *token.FileSet) serial.ImplementsType { var pos token.Pos if nt, ok := deref(T).(*types.Named); ok { // implementsResult.t may be non-named pos = nt.Obj().Pos() } return serial.ImplementsType{ Name: T.String(), Pos: fset.Position(pos).String(), Kind: typeKind(T), } }
func cgoTypeName(typ types.Type) string { switch typ := typ.(type) { case *types.Basic: kind := typ.Kind() o, ok := typedescr[kind] if ok { return o.cgotype } } return typ.String() }
func (x structure) eq(t types.Type, _y interface{}) bool { y := _y.(structure) tStruct := t.Underlying().(*types.Struct) for i, n := 0, tStruct.NumFields(); i < n; i++ { if f := tStruct.Field(i); !f.Anonymous() { if !equals(f.Type(), x[i], y[i]) { return false } } } return true }
func (fr *frame) interfaceTypeAssert(val *govalue, ty types.Type) *govalue { if _, ok := ty.Underlying().(*types.Interface); ok { return fr.changeInterface(val, ty, true) } else { valtytd := fr.types.ToRuntime(val.Type()) valtd := fr.getInterfaceTypeDescriptor(val) tytd := fr.types.ToRuntime(ty) fr.runtime.checkInterfaceType.call(fr, valtd, tytd, valtytd) return fr.getInterfaceValue(val, ty) } }
// CanHaveDynamicTypes reports whether the type T can "hold" dynamic types, // i.e. is an interface (incl. reflect.Type) or a reflect.Value. // func CanHaveDynamicTypes(T types.Type) bool { switch T := T.(type) { case *types.Named: if obj := T.Obj(); obj.Name() == "Value" && obj.Pkg().Path() == "reflect" { return true // reflect.Value } return CanHaveDynamicTypes(T.Underlying()) case *types.Interface: return true } return false }
// TypeChainString returns the full type chain as a string. func TypeChainString(t types.Type) string { out := fmt.Sprintf("%s", t) for { if t == t.Underlying() { break } else { t = t.Underlying() } out += fmt.Sprintf(" -> %s", t) } return out }
// javaType returns a string that can be used as a Java type. func (g *javaGen) javaType(T types.Type) string { switch T := T.(type) { case *types.Basic: switch T.Kind() { case types.Bool: return "boolean" case types.Int: return "long" case types.Int8: return "byte" case types.Int16: return "short" case types.Int32: return "int" case types.Int64: return "long" case types.Uint8: // TODO(crawshaw): Java bytes are signed, so this is // questionable, but vital. return "byte" // TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64: case types.Float32: return "float" case types.Float64: return "double" case types.String: return "String" default: g.errorf("unsupported return type: %s", T) return "TODO" } case *types.Slice: elem := g.javaType(T.Elem()) return elem + "[]" case *types.Pointer: if _, ok := T.Elem().(*types.Named); ok { return g.javaType(T.Elem()) } panic(fmt.Sprintf("unsupporter pointer to type: %s", T)) case *types.Named: n := T.Obj() if n.Pkg() != g.pkg { panic(fmt.Sprintf("type %s is in package %s, must be defined in package %s", n.Name(), n.Pkg().Name(), g.pkg.Name())) } // TODO(crawshaw): more checking here return n.Name() default: g.errorf("unsupported javaType: %#+v, %s\n", T, T) return "TODO" } }
func newVar(p *Package, typ types.Type, objname, name, doc string) *Var { sym := p.syms.symtype(typ) if sym == nil { panic(fmt.Errorf("could not find symbol for type [%s]!", typ.String())) } return &Var{ pkg: p, sym: sym, id: p.Name() + "_" + objname, doc: doc, name: name, } }