// TypeFromNative converts a regular Go type into a the corresponding // interpreter Type. func TypeFromNative(t reflect.Type) Type { if et, ok := evalTypes[t]; ok { return et } var nt *NamedType if t.Name() != "" { name := t.PkgPath() + "ยท" + t.Name() nt = &NamedType{token.Position{}, name, nil, true, make(map[string]Method)} evalTypes[t] = nt } var et Type switch t := t.(type) { case *reflect.BoolType: et = BoolType case *reflect.FloatType: switch t.Kind() { case reflect.Float32: et = Float32Type case reflect.Float64: et = Float64Type case reflect.Float: et = FloatType } case *reflect.IntType: switch t.Kind() { case reflect.Int16: et = Int16Type case reflect.Int32: et = Int32Type case reflect.Int64: et = Int64Type case reflect.Int8: et = Int8Type case reflect.Int: et = IntType } case *reflect.UintType: switch t.Kind() { case reflect.Uint16: et = Uint16Type case reflect.Uint32: et = Uint32Type case reflect.Uint64: et = Uint64Type case reflect.Uint8: et = Uint8Type case reflect.Uint: et = UintType case reflect.Uintptr: et = UintptrType } case *reflect.StringType: et = StringType case *reflect.ArrayType: et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem())) case *reflect.ChanType: log.Panicf("%T not implemented", t) case *reflect.FuncType: nin := t.NumIn() // Variadic functions have DotDotDotType at the end variadic := t.DotDotDot() if variadic { nin-- } in := make([]Type, nin) for i := range in { in[i] = TypeFromNative(t.In(i)) } out := make([]Type, t.NumOut()) for i := range out { out[i] = TypeFromNative(t.Out(i)) } et = NewFuncType(in, variadic, out) case *reflect.InterfaceType: log.Panicf("%T not implemented", t) case *reflect.MapType: log.Panicf("%T not implemented", t) case *reflect.PtrType: et = NewPtrType(TypeFromNative(t.Elem())) case *reflect.SliceType: et = NewSliceType(TypeFromNative(t.Elem())) case *reflect.StructType: n := t.NumField() fields := make([]StructField, n) for i := 0; i < n; i++ { sf := t.Field(i) // TODO(austin) What to do about private fields? fields[i].Name = sf.Name fields[i].Type = TypeFromNative(sf.Type) fields[i].Anonymous = sf.Anonymous } et = NewStructType(fields) case *reflect.UnsafePointerType: log.Panicf("%T not implemented", t) default: log.Panicf("unexpected reflect.Type: %T", t) } if nt != nil { if _, ok := et.(*NamedType); !ok { nt.Complete(et) et = nt } } nativeTypes[et] = t evalTypes[t] = et return et }