1// +build gomacro_xreflect_easy 2 3/* 4 * gomacro - A Go interpreter with Lisp-like macros 5 * 6 * Copyright (C) 2017-2019 Massimiliano Ghilardi 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 11 * 12 * build_easy.go 13 * 14 * Created on May 07, 2017 15 * Author Massimiliano Ghilardi 16 */ 17 18package xreflect 19 20import ( 21 "go/types" 22 "reflect" 23) 24 25type Type interface { 26 27 // Align returns the alignment in bytes of a value of 28 // this type when allocated in memory. 29 Align() int 30 31 // FieldAlign returns the alignment in bytes of a value of 32 // this type when used as a field in a struct. 33 FieldAlign() int 34 35 // IdenticalTo reports whether the type is identical to type u. 36 IdenticalTo(u Type) bool 37 38 // AssignableTo reports whether a value of the type is assignable to type u. 39 AssignableTo(u Type) bool 40 41 // ConvertibleTo reports whether a value of the type is convertible to type u. 42 ConvertibleTo(u Type) bool 43 44 // Comparable reports whether values of this type are comparable. 45 Comparable() bool 46 47 // GoType returns the go/types.Type corresponding to the given type. 48 GoType() types.Type 49 50 // Implements reports whether the type implements the interface type u. 51 // It panics if u's Kind is not Interface 52 Implements(u Type) bool 53 54 // Name returns the type's name within its package. 55 // It returns an empty string for unnamed types. 56 Name() string 57 58 // Named returns whether the type is named. 59 // It returns false for unnamed types. 60 Named() bool 61 62 // Pkg returns a named type's package, that is, the package where it was defined. 63 // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), 64 // Pkg will return nil. 65 Pkg() *Package 66 67 // PkgName returns a named type's package name, that is, 68 // the default name that the package provides when imported. 69 // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), 70 // the package name will be the empty string. 71 PkgName() string 72 73 // PkgPath returns a named type's package path, that is, the import path 74 // that uniquely identifies the package, such as "encoding/base64". 75 // If the type was predeclared (string, error) or unnamed (*T, struct{}, []int), 76 // the package path will be the empty string. 77 PkgPath() string 78 79 // ReflectType returns a best-effort reflect.Type that approximates the type. 80 // It may be inexact for the following reasons: 81 // 1) missing reflect.NamedOf(): no way to programmatically create named types, or to access the underlying type of a named type 82 // 2) missing reflect.InterfaceOf(): interface types created at runtime will be approximated by structs 83 // 3) missing reflect.MethodOf(): method types created at runtime will be approximated by functions 84 // whose first parameter is the receiver 85 // 4) reflect.StructOf() does not support embedded or unexported fields 86 // 5) go/reflect lacks the ability to create self-referencing types: 87 // references to the type itself will be replaced by interface{}. 88 // 89 // Examples: 90 // after invoking at runtime type2.NewStruct() and type2.NewNamed() 91 // to create the following type: 92 // type List struct { Elem int; Rest *List } 93 // ReflectType will return a reflect.Type equivalent to: 94 // struct { Elem int; Rest interface{} } 95 // i.e. the type name will be missing due to limitation 1 above, 96 // and the field 'Rest' will have type interface{} instead of *List due to limitation 5. 97 ReflectType() reflect.Type 98 99 UnsafeForceReflectType(rtype reflect.Type) 100 101 // Size returns the number of bytes needed to store 102 // a value of the given type; it is analogous to unsafe.Sizeof. 103 Size() uintptr 104 105 // String returns a string representation of a type. 106 String() string 107 108 // AddMethod adds method with given name and signature to type, unless it is already in the method list. 109 // It panics if the type is unnamed, or if the signature is not a function-with-receiver type. 110 // Returns the method index, or < 0 in case of errors 111 AddMethod(name string, signature Type) int 112 113 // Bits returns the size of the type in bits. 114 // It panics if the type's Kind is not one of the 115 // sized or unsized Int, Uint, Float, or Complex kinds. 116 Bits() int 117 118 // ChanDir returns a channel type's direction. 119 // It panics if the type's Kind is not Chan. 120 ChanDir() reflect.ChanDir 121 122 // Complete marks an interface type as complete and computes wrapper methods for embedded fields. 123 // It must be called by users of InterfaceOf after the interface's embedded types are fully defined 124 // and before using the interface type in any way other than to form other types. 125 // Complete returns a canonicalized (unique) version of the receiver. 126 Complete() Type 127 // Elem returns a type's element type. 128 // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice. 129 Elem() Type 130 131 // Field returns a struct type's i-th field. 132 // It panics if the type's Kind is not Struct. 133 // It panics if i is not in the range [0, NumField()). 134 Field(i int) StructField 135 // FieldByName returns the (possibly embedded) struct field with the given name 136 // and the number of fields found at the same (shallowest) depth: 0 if not found. 137 // Private fields are returned only if they were declared in pkgpath. 138 FieldByName(name, pkgpath string) (field StructField, count int) 139 140 // IsMethod reports whether a function type's contains a receiver, i.e. is a method. 141 // If IsMethod returns true, the actual receiver type is available as the first parameter, i.e. Type.In(0) 142 // It panics if the type's Kind is not Func. 143 IsMethod() bool 144 145 // IsVariadic reports whether a function type's final input parameter is a "..." parameter. 146 // If so, t.In(t.NumIn() - 1) returns the parameter's implicit actual type []T. 147 // IsVariadic panics if the type's Kind is not Func. 148 IsVariadic() bool 149 150 // Key returns a map type's key type. 151 // It panics if the type's Kind is not Map. 152 Key() Type 153 // Kind returns the specific kind of the type. 154 Kind() reflect.Kind 155 156 // Len returns an array type's length. 157 // It panics if the type's Kind is not Array. 158 Len() int 159 160 // In returns the type of a function type's i'th input parameter. 161 // It panics if the type's Kind is not Func. 162 // It panics if i is not in the range [0, NumIn()). 163 In(i int) Type 164 165 // For interfaces, Method returns the i-th method, including methods from embedded interfaces. 166 // For all other named types, Method returns the i-th explicitly declared method, ignoring wrapper methods for embedded fields. 167 // It panics if i is outside the range 0 .. NumMethod()-1 168 Method(i int) Method 169 // MethodByName returns the method with given name (including wrapper methods for embedded fields) 170 // and the number of methods found at the same (shallowest) depth: 0 if not found. 171 // Private methods are returned only if they were declared in pkgpath. 172 MethodByName(name, pkgpath string) (method Method, count int) 173 174 // For interfaces, NumMethod returns *total* number of methods for interface t, 175 // including wrapper methods for embedded interfaces. 176 // For all other named types, NumMethod returns the number of explicitly declared methods, 177 // ignoring wrapper methods for embedded fields. 178 // Returns 0 for other unnamed types. 179 NumMethod() int 180 // NumExplicitMethod returns the number of explicitly declared methods for interface or named type t. 181 // Wrapper methods for embedded fields or embedded interfaces are not counted. 182 NumExplicitMethod() int 183 // NumMethod returns the *total* number of methods for interface or named type t, 184 // including wrapper methods for embedded fields or embedded interfaces. 185 // Note: it has slightly different semantics from go/types.(*Named).NumMethods(), 186 // since the latter returns 0 for named interfaces, and callers need to manually invoke 187 // goNamedType.Underlying().NumMethods() to retrieve the number of methods 188 // of a named interface 189 NumAllMethod() int 190 191 // NumField returns a struct type's field count. 192 // It panics if the type's Kind is not Struct. 193 NumField() int 194 195 // NumIn returns a function type's input parameter count. 196 // It panics if the type's Kind is not Func. 197 NumIn() int 198 199 // NumOut returns a function type's output parameter count. 200 // It panics if the type's Kind is not Func. 201 NumOut() int 202 203 // Out returns the type of a function type's i'th output parameter. 204 // It panics if the type's Kind is not Func. 205 // It panics if i is not in the range [0, NumOut()). 206 Out(i int) Type 207 208 // RemoveMethods removes given methods from type. 209 // It panics if the type is unnamed, or if the signature is not a function type, 210 RemoveMethods(names []string, pkgpath string) 211 212 // SetUnderlying sets the underlying type of a named type and marks it as complete. 213 // It panics if the type is unnamed, or if the underlying type is named, 214 // or if SetUnderlying() was already invoked on the named type. 215 SetUnderlying(underlying Type) 216 217 // underlying returns the underlying types.Type of a type. 218 // TODO implement Underlying() Type ? 219 // Synthetizing the underlying reflect.Type is not possible for interface types, 220 // or for struct types with embedded or unexported fields. 221 gunderlying() types.Type 222 223 elem() Type 224 225 Universe() *Universe 226 227 // GetMethods returns the pointer to the method values. 228 // It panics if the type is unnamed 229 GetMethods() *[]reflect.Value 230} 231 232func unwrap(t Type) *xtype { 233 if t == nil { 234 return nil 235 } 236 return t.(*xtype) 237} 238 239func wrap(t *xtype) Type { 240 return t 241} 242