0
# Reflection Capabilities
1
2
## Overview
3
4
The Reflection capabilities provide type introspection support for WASI applications. The implementation focuses on compile-time type reflection using Kotlin's reified generics, enabling applications to obtain runtime type information for generic type parameters.
5
6
## API Reference
7
8
### Type Reflection Functions
9
10
```kotlin { .api }
11
/**
12
* Returns the runtime representation of the given type T.
13
* Uses compile-time type information to create KType instances.
14
* @return KType representing the type T
15
*/
16
inline fun <reified T> typeOf(): KType
17
18
/**
19
* Returns the runtime representation of the given type T with lazy initialization.
20
* Optimized version that delays KType creation until first access.
21
* @return KType representing the type T
22
*/
23
inline fun <reified T> typeOfLazyInit(): KType
24
```
25
26
### KType Interface
27
28
```kotlin { .api }
29
/**
30
* Represents a type in the Kotlin type system.
31
*/
32
interface KType {
33
/**
34
* The classifier of this type, typically a KClass.
35
*/
36
val classifier: KClassifier?
37
38
/**
39
* Type arguments for generic types.
40
*/
41
val arguments: List<KTypeProjection>
42
43
/**
44
* Whether this type is marked as nullable.
45
*/
46
val isMarkedNullable: Boolean
47
}
48
```
49
50
## Usage Examples
51
52
### Basic Type Reflection
53
54
```kotlin
55
// Get type information for primitive types
56
val stringType = typeOf<String>()
57
val intType = typeOf<Int>()
58
val booleanType = typeOf<Boolean>()
59
60
println("String type: $stringType")
61
println("Int type: $intType")
62
println("Boolean type: $booleanType")
63
64
// Check type properties
65
println("String is nullable: ${stringType.isMarkedNullable}") // false
66
println("String classifier: ${stringType.classifier}")
67
```
68
69
### Nullable Type Reflection
70
71
```kotlin
72
// Compare nullable and non-nullable types
73
val nonNullableString = typeOf<String>()
74
val nullableString = typeOf<String?>()
75
76
println("Non-nullable: $nonNullableString")
77
println("Nullable: $nullableString")
78
println("Nullable marked: ${nullableString.isMarkedNullable}") // true
79
println("Types equal: ${nonNullableString == nullableString}") // false
80
```
81
82
### Generic Type Reflection
83
84
```kotlin
85
// Reflect on generic types
86
val listOfStrings = typeOf<List<String>>()
87
val mapOfStringToInt = typeOf<Map<String, Int>>()
88
val setOfNullableInts = typeOf<Set<Int?>>()
89
90
println("List<String>: $listOfStrings")
91
println("Map<String, Int>: $mapOfStringToInt")
92
println("Set<Int?>: $setOfNullableInts")
93
94
// Access type arguments
95
val listArgs = listOfStrings.arguments
96
println("List type arguments: $listArgs")
97
if (listArgs.isNotEmpty()) {
98
val elementType = listArgs[0].type
99
println("List element type: $elementType")
100
}
101
```
102
103
### Collection Type Analysis
104
105
```kotlin
106
// Analyze collection types
107
fun analyzeCollectionType(type: KType) {
108
when (type.classifier) {
109
List::class -> {
110
println("This is a List type")
111
val elementType = type.arguments.firstOrNull()?.type
112
println("Element type: $elementType")
113
}
114
Set::class -> {
115
println("This is a Set type")
116
val elementType = type.arguments.firstOrNull()?.type
117
println("Element type: $elementType")
118
}
119
Map::class -> {
120
println("This is a Map type")
121
val keyType = type.arguments.getOrNull(0)?.type
122
val valueType = type.arguments.getOrNull(1)?.type
123
println("Key type: $keyType")
124
println("Value type: $valueType")
125
}
126
else -> {
127
println("Unknown collection type: ${type.classifier}")
128
}
129
}
130
}
131
132
// Usage
133
analyzeCollectionType(typeOf<List<String>>())
134
analyzeCollectionType(typeOf<Map<String, Int>>())
135
analyzeCollectionType(typeOf<Set<Double>>())
136
```
137
138
### Type-Safe Configuration
139
140
```kotlin
141
// Type-safe configuration system using reflection
142
class ConfigurationManager {
143
private val values = mutableMapOf<KType, Any?>()
144
145
inline fun <reified T> set(value: T) {
146
values[typeOf<T>()] = value
147
}
148
149
inline fun <reified T> get(): T? {
150
@Suppress("UNCHECKED_CAST")
151
return values[typeOf<T>()] as? T
152
}
153
154
inline fun <reified T> getOrDefault(defaultValue: T): T {
155
return get<T>() ?: defaultValue
156
}
157
158
inline fun <reified T> has(): Boolean {
159
return typeOf<T>() in values
160
}
161
}
162
163
// Usage
164
val config = ConfigurationManager()
165
166
config.set("localhost")
167
config.set(8080)
168
config.set(true)
169
170
val host: String? = config.get<String>()
171
val port: Int = config.getOrDefault(3000)
172
val debug: Boolean = config.getOrDefault(false)
173
174
println("Host: $host")
175
println("Port: $port")
176
println("Debug: $debug")
177
```
178
179
### Serialization Support
180
181
```kotlin
182
// Type-aware serialization helper
183
object TypedSerializer {
184
private val serializers = mutableMapOf<KType, (Any?) -> String>()
185
private val deserializers = mutableMapOf<KType, (String) -> Any?>()
186
187
inline fun <reified T> registerSerializer(
188
noinline serializer: (T?) -> String,
189
noinline deserializer: (String) -> T?
190
) {
191
val type = typeOf<T>()
192
@Suppress("UNCHECKED_CAST")
193
serializers[type] = serializer as (Any?) -> String
194
@Suppress("UNCHECKED_CAST")
195
deserializers[type] = deserializer as (String) -> Any?
196
}
197
198
inline fun <reified T> serialize(value: T?): String? {
199
val type = typeOf<T>()
200
return serializers[type]?.invoke(value)
201
}
202
203
inline fun <reified T> deserialize(data: String): T? {
204
val type = typeOf<T>()
205
@Suppress("UNCHECKED_CAST")
206
return deserializers[type]?.invoke(data) as? T
207
}
208
}
209
210
// Register serializers
211
TypedSerializer.registerSerializer<String>(
212
{ it ?: "null" },
213
{ if (it == "null") null else it }
214
)
215
216
TypedSerializer.registerSerializer<Int>(
217
{ it?.toString() ?: "null" },
218
{ if (it == "null") null else it.toIntOrNull() }
219
)
220
221
// Use type-safe serialization
222
val serialized = TypedSerializer.serialize("Hello")
223
val deserialized: String? = TypedSerializer.deserialize(serialized ?: "")
224
println("Serialized: $serialized")
225
println("Deserialized: $deserialized")
226
```
227
228
### Generic Function Utilities
229
230
```kotlin
231
// Type-safe generic utilities
232
object TypeUtils {
233
inline fun <reified T> typeName(): String {
234
return typeOf<T>().toString()
235
}
236
237
inline fun <reified T> isNullable(): Boolean {
238
return typeOf<T>().isMarkedNullable
239
}
240
241
inline fun <reified T> isList(): Boolean {
242
return typeOf<T>().classifier == List::class
243
}
244
245
inline fun <reified T> isMap(): Boolean {
246
return typeOf<T>().classifier == Map::class
247
}
248
249
inline fun <reified Collection> getElementType(): KType? {
250
val type = typeOf<Collection>()
251
return type.arguments.firstOrNull()?.type
252
}
253
}
254
255
// Usage examples
256
println("String name: ${TypeUtils.typeName<String>()}")
257
println("String? nullable: ${TypeUtils.isNullable<String?>()}")
258
println("List<Int> is list: ${TypeUtils.isList<List<Int>>()}")
259
println("Map<String, Int> is map: ${TypeUtils.isMap<Map<String, Int>>()}")
260
261
val elementType = TypeUtils.getElementType<List<String>>()
262
println("List<String> element type: $elementType")
263
```
264
265
### Lazy Type Initialization
266
267
```kotlin
268
// Use lazy type initialization for performance
269
class TypeRegistry {
270
private val lazyTypes = mutableMapOf<String, Lazy<KType>>()
271
272
inline fun <reified T> registerLazy(name: String) {
273
lazyTypes[name] = lazy { typeOfLazyInit<T>() }
274
}
275
276
fun getType(name: String): KType? {
277
return lazyTypes[name]?.value
278
}
279
280
fun hasType(name: String): Boolean {
281
return name in lazyTypes
282
}
283
}
284
285
// Register types lazily
286
val registry = TypeRegistry()
287
registry.registerLazy<String>("string")
288
registry.registerLazy<List<Int>>("intList")
289
registry.registerLazy<Map<String, Any?>>("stringMap")
290
291
// Access types only when needed
292
val stringType = registry.getType("string")
293
println("Retrieved string type: $stringType")
294
```
295
296
## Implementation Details
297
298
### Compile-Time Type Resolution
299
300
The WASI reflection implementation uses compile-time type resolution:
301
302
- **Reified Generics**: Type parameters are resolved at compile time
303
- **No Runtime Class Loading**: No dynamic class loading or bytecode analysis
304
- **Static Type Information**: All type information is embedded at compile time
305
306
### Memory Efficiency
307
308
- **Lazy Initialization**: `typeOfLazyInit` delays KType creation until first access
309
- **Type Caching**: Identical types may be cached to reduce memory usage
310
- **Minimal Overhead**: No heavy reflection infrastructure in WASI environment
311
312
### Limitations
313
314
#### No Runtime Class Analysis
315
316
```kotlin
317
// NOT SUPPORTED: Runtime class introspection
318
// val methods = SomeClass::class.members // Not available
319
// val properties = SomeClass::class.memberProperties // Not available
320
321
// SUPPORTED: Compile-time type information only
322
val type = typeOf<SomeClass>()
323
val classifier = type.classifier
324
```
325
326
#### No Dynamic Method Invocation
327
328
```kotlin
329
// NOT SUPPORTED: Dynamic method calls
330
// val method = SomeClass::class.functions.find { it.name == "someMethod" }
331
// method?.call(instance, args) // Not available
332
333
// SUPPORTED: Static type checking only
334
fun processType(type: KType) {
335
when (type.classifier) {
336
String::class -> println("Processing string type")
337
Int::class -> println("Processing int type")
338
}
339
}
340
```
341
342
## Performance Considerations
343
344
### Type Comparison Performance
345
346
```kotlin
347
// Type comparison is efficient
348
val type1 = typeOf<String>()
349
val type2 = typeOf<String>()
350
val equal = type1 == type2 // Fast comparison
351
352
// Cache types for repeated use
353
class TypeCache {
354
private val stringType = typeOf<String>()
355
private val intType = typeOf<Int>()
356
357
fun isString(type: KType) = type == stringType
358
fun isInt(type: KType) = type == intType
359
}
360
```
361
362
### Lazy Initialization Benefits
363
364
```kotlin
365
// Use lazy initialization for large type hierarchies
366
object SchemaTypes {
367
val userType by lazy { typeOfLazyInit<User>() }
368
val productType by lazy { typeOfLazyInit<Product>() }
369
val orderType by lazy { typeOfLazyInit<Order>() }
370
// Types are only created when first accessed
371
}
372
```
373
374
## Best Practices
375
376
### Type Safety
377
378
```kotlin
379
// DO: Use reified generics for type safety
380
inline fun <reified T> processTypedValue(value: Any?): T? {
381
val expectedType = typeOf<T>()
382
// Use type information for safe casting
383
return value as? T
384
}
385
386
// DON'T: Rely on runtime class checking (not available)
387
// fun processValue(value: Any, clazz: Class<*>) // Not supported in WASI
388
```
389
390
### Performance Optimization
391
392
```kotlin
393
// DO: Cache frequently used types
394
object CommonTypes {
395
val STRING = typeOf<String>()
396
val INT = typeOf<Int>()
397
val BOOLEAN = typeOf<Boolean>()
398
}
399
400
// DO: Use lazy initialization for expensive type hierarchies
401
val complexType by lazy { typeOfLazyInit<ComplexGenericType<List<Map<String, Any?>>>>() }
402
403
// AVOID: Repeated type creation in hot paths
404
// Bad:
405
repeat(1000) {
406
val type = typeOf<String>() // Creates type object each time
407
}
408
409
// Better:
410
val cachedType = typeOf<String>()
411
repeat(1000) {
412
// Use cachedType
413
}
414
```
415
416
### Type Registry Pattern
417
418
```kotlin
419
// Recommended pattern for managing multiple types
420
class ApplicationTypes {
421
companion object {
422
private val types = mapOf(
423
"user" to typeOf<User>(),
424
"product" to typeOf<Product>(),
425
"order" to typeOf<Order>()
426
)
427
428
fun getType(name: String): KType? = types[name]
429
fun hasType(name: String): Boolean = name in types
430
}
431
}
432
```