or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

callable-system.mdclass-introspection.mdcore-reflection.mdindex.mdjvm-interoperability.mdtype-system.md

callable-system.mddocs/

0

# Callable System

1

2

Function and property reflection with dynamic invocation capabilities, parameter inspection, suspend function support, and extension handling for comprehensive callable manipulation.

3

4

## Capabilities

5

6

### Property Reflection

7

8

Access and manipulate properties of different receiver types with full type safety.

9

10

```kotlin { .api }

11

/**

12

* Represents a property without any kind of receiver

13

*/

14

interface KProperty0<out V> : KProperty<V>, () -> V {

15

/** Returns the current value of the property */

16

fun get(): V

17

}

18

19

/**

20

* Represents a var-property without any kind of receiver

21

*/

22

interface KMutableProperty0<V> : KProperty0<V>, KMutableProperty<V> {

23

/** Modifies the value of the property */

24

fun set(value: V)

25

}

26

27

/**

28

* Represents a property with one receiver

29

*/

30

interface KProperty1<T, out V> : KProperty<V>, (T) -> V {

31

/** Returns the current value of the property */

32

fun get(receiver: T): V

33

}

34

35

/**

36

* Represents a var-property with one receiver

37

*/

38

interface KMutableProperty1<T, V> : KProperty1<T, V>, KMutableProperty<V> {

39

/** Modifies the value of the property */

40

fun set(receiver: T, value: V)

41

}

42

```

43

44

**Usage Examples:**

45

46

```kotlin

47

class Person(var name: String, val age: Int)

48

49

val person = Person("Alice", 30)

50

51

// Access member properties

52

val nameProperty = Person::name

53

val ageProperty = Person::age

54

55

// Get property values

56

println(nameProperty.get(person)) // "Alice"

57

println(ageProperty.get(person)) // 30

58

59

// Set mutable property value

60

if (nameProperty is KMutableProperty1<Person, String>) {

61

nameProperty.set(person, "Bob")

62

println(person.name) // "Bob"

63

}

64

65

// Top-level property access

66

var globalCounter = 0

67

val counterProperty = ::globalCounter

68

69

// Access top-level property

70

println(counterProperty.get()) // 0

71

if (counterProperty is KMutableProperty0<Int>) {

72

counterProperty.set(42)

73

println(globalCounter) // 42

74

}

75

```

76

77

### Function Invocation

78

79

Dynamic function calling with parameter mapping and suspend function support.

80

81

```kotlin { .api }

82

/**

83

* Calls this callable with the specified arguments

84

*/

85

fun <R> KCallable<R>.call(vararg args: Any?): R

86

87

/**

88

* Calls this callable with arguments provided in a map

89

*/

90

fun <R> KCallable<R>.callBy(args: Map<KParameter, Any?>): R

91

92

/**

93

* Calls a callable in the current suspend context

94

*/

95

suspend fun <R> KCallable<R>.callSuspend(vararg args: Any?): R

96

97

/**

98

* Calls a callable in the current suspend context with named arguments

99

*/

100

suspend fun <R> KCallable<R>.callSuspendBy(args: Map<KParameter, Any?>): R

101

```

102

103

**Usage Examples:**

104

105

```kotlin

106

class Calculator {

107

fun add(a: Int, b: Int): Int = a + b

108

suspend fun asyncAdd(a: Int, b: Int): Int {

109

delay(100)

110

return a + b

111

}

112

}

113

114

val calc = Calculator()

115

val addFunction = Calculator::add

116

val asyncAddFunction = Calculator::asyncAdd

117

118

// Call function with positional arguments

119

val result1 = addFunction.call(calc, 5, 3) // 8

120

121

// Call function with named arguments

122

val params = addFunction.parameters

123

val argMap = mapOf(

124

params[0] to calc, // receiver

125

params[1] to 10, // first parameter

126

params[2] to 20 // second parameter

127

)

128

val result2 = addFunction.callBy(argMap) // 30

129

130

// Call suspend function

131

runBlocking {

132

val asyncResult = asyncAddFunction.callSuspend(calc, 7, 13) // 20

133

}

134

```

135

136

### Parameter Inspection

137

138

Access detailed information about function and property parameters.

139

140

```kotlin { .api }

141

/**

142

* Represents a parameter of a function or property

143

*/

144

interface KParameter {

145

/** Name of the parameter, or null if not available */

146

val name: String?

147

/** Type of the parameter */

148

val type: KType

149

/** Kind of the parameter */

150

val kind: Kind

151

/** Whether the parameter is optional (has default value) */

152

val isOptional: Boolean

153

/** Whether the parameter is vararg */

154

val isVararg: Boolean

155

156

enum class Kind {

157

INSTANCE, // 'this' instance

158

EXTENSION_RECEIVER, // extension receiver

159

VALUE, // regular parameter

160

CONTEXT // context parameter

161

}

162

}

163

164

/** Returns a parameter representing the 'this' instance */

165

val KCallable<*>.instanceParameter: KParameter?

166

167

/** Returns a parameter representing the extension receiver */

168

val KCallable<*>.extensionReceiverParameter: KParameter?

169

170

/** Returns parameters excluding 'this' and extension receiver */

171

val KCallable<*>.valueParameters: List<KParameter>

172

173

/** Returns context parameters of this callable */

174

@ExperimentalContextParameters

175

val KCallable<*>.contextParameters: List<KParameter>

176

```

177

178

**Usage Examples:**

179

180

```kotlin

181

class Example {

182

fun method(required: String, optional: Int = 42, vararg extras: String): String {

183

return "$required-$optional-${extras.joinToString()}"

184

}

185

}

186

187

fun String.extensionFunction(param: Int): String = "$this:$param"

188

189

// Inspect regular method parameters

190

val method = Example::method

191

val parameters = method.parameters

192

193

println("Total parameters: ${parameters.size}") // 4 (including receiver)

194

195

val instanceParam = method.instanceParameter

196

println("Instance parameter: ${instanceParam?.kind}") // INSTANCE

197

198

val valueParams = method.valueParameters

199

valueParams.forEach { param ->

200

println("${param.name}: ${param.type}, optional: ${param.isOptional}, vararg: ${param.isVararg}")

201

}

202

// required: kotlin.String, optional: false, vararg: false

203

// optional: kotlin.Int, optional: true, vararg: false

204

// extras: kotlin.Array<out kotlin.String>, optional: false, vararg: true

205

206

// Inspect extension function parameters

207

val extensionFunc = String::extensionFunction

208

val extReceiver = extensionFunc.extensionReceiverParameter

209

println("Extension receiver: ${extReceiver?.type}") // kotlin.String

210

```

211

212

### Parameter Lookup

213

214

Find parameters by name and build argument mappings dynamically.

215

216

```kotlin { .api }

217

/**

218

* Returns the parameter with the given name, or null if not found

219

*/

220

fun KCallable<*>.findParameterByName(name: String): KParameter?

221

```

222

223

**Usage Examples:**

224

225

```kotlin

226

fun exampleFunction(first: String, second: Int, third: Boolean = true): String {

227

return "$first-$second-$third"

228

}

229

230

val function = ::exampleFunction

231

232

// Find parameters by name

233

val firstParam = function.findParameterByName("first")

234

val secondParam = function.findParameterByName("second")

235

val thirdParam = function.findParameterByName("third")

236

237

// Build argument map dynamically

238

val args = buildMap<KParameter, Any?> {

239

firstParam?.let { put(it, "hello") }

240

secondParam?.let { put(it, 42) }

241

// third parameter omitted - will use default value

242

}

243

244

val result = function.callBy(args) // "hello-42-true"

245

```

246

247

### Property Delegation

248

249

Access property delegates for delegated properties inspection.

250

251

```kotlin { .api }

252

/**

253

* Returns the instance of a delegated extension property, or null if not delegated

254

*/

255

fun KProperty1<*, *>.getExtensionDelegate(): Any?

256

257

/**

258

* Returns the instance of a delegated member extension property, or null if not delegated

259

*/

260

fun <D> KProperty2<D, *, *>.getExtensionDelegate(receiver: D): Any?

261

262

/**

263

* Returns the delegate of this property, or null if it is not delegated

264

*/

265

fun KProperty0<*>.getDelegate(): Any?

266

fun <T> KProperty1<T, *>.getDelegate(receiver: T): Any?

267

```

268

269

**Usage Examples:**

270

271

```kotlin

272

class MyDelegate {

273

operator fun getValue(thisRef: Any?, property: KProperty<*>): String {

274

return "delegated value"

275

}

276

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {

277

println("Setting $value")

278

}

279

}

280

281

class Example {

282

var delegatedProperty: String by MyDelegate()

283

}

284

285

val example = Example()

286

val property = Example::delegatedProperty

287

288

// Access the delegate

289

val delegate = property.getDelegate(example)

290

println(delegate::class.simpleName) // "MyDelegate"

291

292

// Check if property is delegated

293

val hasDelegate = property.getDelegate(example) != null

294

println("Is delegated: $hasDelegate") // true

295

```

296

297

### Experimental Features

298

299

Context parameters are an experimental feature that allows functions to have implicit context receivers.

300

301

```kotlin { .api }

302

/**

303

* Marks an API related to Kotlin's context parameters experimental feature

304

*/

305

@RequiresOptIn(level = RequiresOptIn.Level.ERROR)

306

@Retention(AnnotationRetention.BINARY)

307

@MustBeDocumented

308

annotation class ExperimentalContextParameters

309

```