CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-stdlib-wasm-wasi

Kotlin Standard Library implementation for WebAssembly System Interface (WASI) platform providing essential I/O, time, random, UUID, and reflection capabilities.

Pending
Overview
Eval results
Files

reflection.mddocs/

Reflection Capabilities

Overview

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.

API Reference

Type Reflection Functions

/**
 * Returns the runtime representation of the given type T.
 * Uses compile-time type information to create KType instances.
 * @return KType representing the type T
 */
inline fun <reified T> typeOf(): KType

/**
 * Returns the runtime representation of the given type T with lazy initialization.
 * Optimized version that delays KType creation until first access.
 * @return KType representing the type T
 */
inline fun <reified T> typeOfLazyInit(): KType

KType Interface

/**
 * Represents a type in the Kotlin type system.
 */
interface KType {
    /**
     * The classifier of this type, typically a KClass.
     */
    val classifier: KClassifier?
    
    /**
     * Type arguments for generic types.
     */
    val arguments: List<KTypeProjection>
    
    /**
     * Whether this type is marked as nullable.
     */
    val isMarkedNullable: Boolean
}

Usage Examples

Basic Type Reflection

// Get type information for primitive types
val stringType = typeOf<String>()
val intType = typeOf<Int>()
val booleanType = typeOf<Boolean>()

println("String type: $stringType")
println("Int type: $intType")
println("Boolean type: $booleanType")

// Check type properties
println("String is nullable: ${stringType.isMarkedNullable}") // false
println("String classifier: ${stringType.classifier}")

Nullable Type Reflection

// Compare nullable and non-nullable types
val nonNullableString = typeOf<String>()
val nullableString = typeOf<String?>()

println("Non-nullable: $nonNullableString")
println("Nullable: $nullableString")
println("Nullable marked: ${nullableString.isMarkedNullable}") // true
println("Types equal: ${nonNullableString == nullableString}") // false

Generic Type Reflection

// Reflect on generic types
val listOfStrings = typeOf<List<String>>()
val mapOfStringToInt = typeOf<Map<String, Int>>()
val setOfNullableInts = typeOf<Set<Int?>>()

println("List<String>: $listOfStrings")
println("Map<String, Int>: $mapOfStringToInt")
println("Set<Int?>: $setOfNullableInts")

// Access type arguments
val listArgs = listOfStrings.arguments
println("List type arguments: $listArgs")
if (listArgs.isNotEmpty()) {
    val elementType = listArgs[0].type
    println("List element type: $elementType")
}

Collection Type Analysis

// Analyze collection types
fun analyzeCollectionType(type: KType) {
    when (type.classifier) {
        List::class -> {
            println("This is a List type")
            val elementType = type.arguments.firstOrNull()?.type
            println("Element type: $elementType")
        }
        Set::class -> {
            println("This is a Set type")
            val elementType = type.arguments.firstOrNull()?.type
            println("Element type: $elementType")
        }
        Map::class -> {
            println("This is a Map type")
            val keyType = type.arguments.getOrNull(0)?.type
            val valueType = type.arguments.getOrNull(1)?.type
            println("Key type: $keyType")
            println("Value type: $valueType")
        }
        else -> {
            println("Unknown collection type: ${type.classifier}")
        }
    }
}

// Usage
analyzeCollectionType(typeOf<List<String>>())
analyzeCollectionType(typeOf<Map<String, Int>>())
analyzeCollectionType(typeOf<Set<Double>>())

Type-Safe Configuration

// Type-safe configuration system using reflection
class ConfigurationManager {
    private val values = mutableMapOf<KType, Any?>()
    
    inline fun <reified T> set(value: T) {
        values[typeOf<T>()] = value
    }
    
    inline fun <reified T> get(): T? {
        @Suppress("UNCHECKED_CAST")
        return values[typeOf<T>()] as? T
    }
    
    inline fun <reified T> getOrDefault(defaultValue: T): T {
        return get<T>() ?: defaultValue
    }
    
    inline fun <reified T> has(): Boolean {
        return typeOf<T>() in values
    }
}

// Usage
val config = ConfigurationManager()

config.set("localhost")
config.set(8080)
config.set(true)

val host: String? = config.get<String>()
val port: Int = config.getOrDefault(3000)
val debug: Boolean = config.getOrDefault(false)

println("Host: $host")
println("Port: $port")
println("Debug: $debug")

Serialization Support

// Type-aware serialization helper
object TypedSerializer {
    private val serializers = mutableMapOf<KType, (Any?) -> String>()
    private val deserializers = mutableMapOf<KType, (String) -> Any?>()
    
    inline fun <reified T> registerSerializer(
        noinline serializer: (T?) -> String,
        noinline deserializer: (String) -> T?
    ) {
        val type = typeOf<T>()
        @Suppress("UNCHECKED_CAST")
        serializers[type] = serializer as (Any?) -> String
        @Suppress("UNCHECKED_CAST")
        deserializers[type] = deserializer as (String) -> Any?
    }
    
    inline fun <reified T> serialize(value: T?): String? {
        val type = typeOf<T>()
        return serializers[type]?.invoke(value)
    }
    
    inline fun <reified T> deserialize(data: String): T? {
        val type = typeOf<T>()
        @Suppress("UNCHECKED_CAST")
        return deserializers[type]?.invoke(data) as? T
    }
}

// Register serializers
TypedSerializer.registerSerializer<String>(
    { it ?: "null" },
    { if (it == "null") null else it }
)

TypedSerializer.registerSerializer<Int>(
    { it?.toString() ?: "null" },
    { if (it == "null") null else it.toIntOrNull() }
)

// Use type-safe serialization
val serialized = TypedSerializer.serialize("Hello")
val deserialized: String? = TypedSerializer.deserialize(serialized ?: "")
println("Serialized: $serialized")
println("Deserialized: $deserialized")

Generic Function Utilities

// Type-safe generic utilities
object TypeUtils {
    inline fun <reified T> typeName(): String {
        return typeOf<T>().toString()
    }
    
    inline fun <reified T> isNullable(): Boolean {
        return typeOf<T>().isMarkedNullable
    }
    
    inline fun <reified T> isList(): Boolean {
        return typeOf<T>().classifier == List::class
    }
    
    inline fun <reified T> isMap(): Boolean {
        return typeOf<T>().classifier == Map::class
    }
    
    inline fun <reified Collection> getElementType(): KType? {
        val type = typeOf<Collection>()
        return type.arguments.firstOrNull()?.type
    }
}

// Usage examples
println("String name: ${TypeUtils.typeName<String>()}")
println("String? nullable: ${TypeUtils.isNullable<String?>()}")
println("List<Int> is list: ${TypeUtils.isList<List<Int>>()}")
println("Map<String, Int> is map: ${TypeUtils.isMap<Map<String, Int>>()}")

val elementType = TypeUtils.getElementType<List<String>>()
println("List<String> element type: $elementType")

Lazy Type Initialization

// Use lazy type initialization for performance
class TypeRegistry {
    private val lazyTypes = mutableMapOf<String, Lazy<KType>>()
    
    inline fun <reified T> registerLazy(name: String) {
        lazyTypes[name] = lazy { typeOfLazyInit<T>() }
    }
    
    fun getType(name: String): KType? {
        return lazyTypes[name]?.value
    }
    
    fun hasType(name: String): Boolean {
        return name in lazyTypes
    }
}

// Register types lazily
val registry = TypeRegistry()
registry.registerLazy<String>("string")
registry.registerLazy<List<Int>>("intList")
registry.registerLazy<Map<String, Any?>>("stringMap")

// Access types only when needed
val stringType = registry.getType("string")
println("Retrieved string type: $stringType")

Implementation Details

Compile-Time Type Resolution

The WASI reflection implementation uses compile-time type resolution:

  • Reified Generics: Type parameters are resolved at compile time
  • No Runtime Class Loading: No dynamic class loading or bytecode analysis
  • Static Type Information: All type information is embedded at compile time

Memory Efficiency

  • Lazy Initialization: typeOfLazyInit delays KType creation until first access
  • Type Caching: Identical types may be cached to reduce memory usage
  • Minimal Overhead: No heavy reflection infrastructure in WASI environment

Limitations

No Runtime Class Analysis

// NOT SUPPORTED: Runtime class introspection
// val methods = SomeClass::class.members // Not available
// val properties = SomeClass::class.memberProperties // Not available

// SUPPORTED: Compile-time type information only
val type = typeOf<SomeClass>()
val classifier = type.classifier

No Dynamic Method Invocation

// NOT SUPPORTED: Dynamic method calls
// val method = SomeClass::class.functions.find { it.name == "someMethod" }
// method?.call(instance, args) // Not available

// SUPPORTED: Static type checking only
fun processType(type: KType) {
    when (type.classifier) {
        String::class -> println("Processing string type")
        Int::class -> println("Processing int type")
    }
}

Performance Considerations

Type Comparison Performance

// Type comparison is efficient
val type1 = typeOf<String>()
val type2 = typeOf<String>()
val equal = type1 == type2 // Fast comparison

// Cache types for repeated use
class TypeCache {
    private val stringType = typeOf<String>()
    private val intType = typeOf<Int>()
    
    fun isString(type: KType) = type == stringType
    fun isInt(type: KType) = type == intType
}

Lazy Initialization Benefits

// Use lazy initialization for large type hierarchies
object SchemaTypes {
    val userType by lazy { typeOfLazyInit<User>() }
    val productType by lazy { typeOfLazyInit<Product>() }
    val orderType by lazy { typeOfLazyInit<Order>() }
    // Types are only created when first accessed
}

Best Practices

Type Safety

// DO: Use reified generics for type safety
inline fun <reified T> processTypedValue(value: Any?): T? {
    val expectedType = typeOf<T>()
    // Use type information for safe casting
    return value as? T
}

// DON'T: Rely on runtime class checking (not available)
// fun processValue(value: Any, clazz: Class<*>) // Not supported in WASI

Performance Optimization

// DO: Cache frequently used types
object CommonTypes {
    val STRING = typeOf<String>()
    val INT = typeOf<Int>()
    val BOOLEAN = typeOf<Boolean>()
}

// DO: Use lazy initialization for expensive type hierarchies
val complexType by lazy { typeOfLazyInit<ComplexGenericType<List<Map<String, Any?>>>>() }

// AVOID: Repeated type creation in hot paths
// Bad:
repeat(1000) {
    val type = typeOf<String>() // Creates type object each time
}

// Better:
val cachedType = typeOf<String>()
repeat(1000) {
    // Use cachedType
}

Type Registry Pattern

// Recommended pattern for managing multiple types
class ApplicationTypes {
    companion object {
        private val types = mapOf(
            "user" to typeOf<User>(),
            "product" to typeOf<Product>(),
            "order" to typeOf<Order>()
        )
        
        fun getType(name: String): KType? = types[name]
        fun hasType(name: String): Boolean = name in types
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-stdlib-wasm-wasi

docs

console-io.md

exceptions.md

index.md

random.md

reflection.md

time.md

uuid.md

tile.json