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