or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdhost-integration.mdindex.mdrepl-system.mdscript-annotations.mdscript-compilation.mdscript-evaluation.mdsource-code.mdtype-system.md

host-integration.mddocs/

0

# Host Integration

1

2

Host system utilities for integrating Kotlin scripting into applications with script source implementations, configuration management, and execution environments. Provides the foundation for embedding scripting capabilities in host applications.

3

4

## Capabilities

5

6

### BasicScriptingHost

7

8

Abstract base class providing fundamental scripting host functionality with coroutine support and script evaluation.

9

10

```kotlin { .api }

11

/**

12

* Abstract base class for scripting hosts

13

*/

14

abstract class BasicScriptingHost {

15

/**

16

* Execute code within a coroutine context

17

* @param body Suspend function to execute

18

*/

19

open suspend fun runInCoroutineContext(body: suspend () -> Unit) = body()

20

21

/**

22

* Evaluate a script with compilation and evaluation configurations

23

* @param script Source code to evaluate

24

* @param compilationConfiguration Configuration for compilation

25

* @param evaluationConfiguration Optional configuration for evaluation

26

* @return Result of script evaluation

27

*/

28

suspend fun eval(

29

script: SourceCode,

30

compilationConfiguration: ScriptCompilationConfiguration,

31

evaluationConfiguration: ScriptEvaluationConfiguration? = null

32

): ResultWithDiagnostics<EvaluationResult>

33

}

34

```

35

36

### ScriptingHostConfiguration

37

38

Configuration container for host-level scripting settings and services.

39

40

```kotlin { .api }

41

/**

42

* Configuration for scripting host

43

*/

44

class ScriptingHostConfiguration : PropertiesCollection {

45

companion object {

46

val Default = ScriptingHostConfiguration()

47

}

48

}

49

```

50

51

### Script Definition System

52

53

Data structures and functions for creating script definitions from templates.

54

55

```kotlin { .api }

56

/**

57

* Complete definition of a script type with compilation and evaluation configurations

58

*/

59

data class ScriptDefinition(

60

val compilationConfiguration: ScriptCompilationConfiguration,

61

val evaluationConfiguration: ScriptEvaluationConfiguration

62

)

63

64

/**

65

* Create script definition from annotated template class

66

* @param template Class annotated with @KotlinScript

67

* @param hostConfiguration Optional host configuration

68

* @return Script definition with resolved configurations

69

*/

70

fun createScriptDefinitionFromTemplate(

71

template: KClass<out Any>,

72

hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default

73

): ScriptDefinition

74

75

/**

76

* Create compilation configuration from template class

77

* @param template Class annotated with @KotlinScript

78

* @param hostConfiguration Optional host configuration

79

* @return Resolved compilation configuration

80

*/

81

fun createCompilationConfigurationFromTemplate(

82

template: KClass<out Any>,

83

hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default

84

): ScriptCompilationConfiguration

85

86

/**

87

* Create evaluation configuration from template class

88

* @param template Class annotated with @KotlinScript

89

* @param hostConfiguration Optional host configuration

90

* @return Resolved evaluation configuration

91

*/

92

fun createEvaluationConfigurationFromTemplate(

93

template: KClass<out Any>,

94

hostConfiguration: ScriptingHostConfiguration = ScriptingHostConfiguration.Default

95

): ScriptEvaluationConfiguration

96

```

97

98

### Source Code Implementations

99

100

Ready-to-use implementations for different types of script sources.

101

102

```kotlin { .api }

103

/**

104

* Abstract base class for file-based script sources

105

*/

106

abstract class FileBasedScriptSource : ExternalSourceCode {

107

/** The file containing the script source */

108

abstract val file: File

109

110

override val text: String get() = file.readText()

111

override val name: String? get() = file.name

112

override val locationId: String? get() = file.absolutePath

113

}

114

115

/**

116

* Script source backed by a file

117

*/

118

class FileScriptSource(override val file: File) : FileBasedScriptSource() {

119

override val externalLocation: String? get() = file.absolutePath

120

}

121

122

/**

123

* Script source backed by a URL

124

*/

125

class UrlScriptSource(

126

private val url: URL,

127

override val text: String

128

) : ExternalSourceCode {

129

override val name: String? get() = url.file.substringAfterLast('/')

130

override val locationId: String? get() = url.toString()

131

override val externalLocation: String? get() = url.toString()

132

}

133

134

/**

135

* Script source backed by a string

136

*/

137

class StringScriptSource(

138

override val text: String,

139

override val name: String? = null

140

) : SourceCode {

141

override val locationId: String? = name

142

}

143

```

144

145

### Host Configuration Keys

146

147

Configuration keys for host-level scripting settings.

148

149

```kotlin { .api }

150

/**

151

* Configuration keys for scripting host

152

*/

153

interface ScriptingHostConfigurationKeys {

154

val jvmTarget: PropertiesCollection.Key<String>

155

val getScriptingClass: PropertiesCollection.Key<GetScriptingClass>

156

val configurationDependencies: PropertiesCollection.Key<List<ScriptDependency>>

157

}

158

159

/**

160

* Interface for loading classes in the scripting environment

161

*/

162

interface GetScriptingClass {

163

/**

164

* Load a class by name

165

* @param className Fully qualified class name

166

* @return Loaded class or null if not found

167

*/

168

operator fun invoke(className: String): KClass<*>?

169

}

170

```

171

172

### Extension Functions

173

174

Utility extension functions for host integration.

175

176

```kotlin { .api }

177

/**

178

* Convert File to script source

179

*/

180

fun File.toScriptSource(): FileScriptSource

181

182

/**

183

* Convert String to script source with optional name

184

*/

185

fun String.toScriptSource(name: String? = null): StringScriptSource

186

187

/**

188

* Get scripting class loader from host configuration

189

*/

190

fun ScriptingHostConfiguration.getScriptingClass(): GetScriptingClass?

191

```

192

193

**Usage Examples:**

194

195

```kotlin

196

import kotlin.script.experimental.host.*

197

import kotlin.script.experimental.api.*

198

199

// Custom scripting host implementation

200

class MyScriptingHost : BasicScriptingHost() {

201

private val compiler: ScriptCompiler = TODO("Implementation")

202

private val evaluator: ScriptEvaluator = TODO("Implementation")

203

204

override suspend fun runInCoroutineContext(body: suspend () -> Unit) {

205

// Custom coroutine context setup

206

withContext(Dispatchers.IO) {

207

body()

208

}

209

}

210

211

suspend fun executeScript(scriptFile: File): ResultWithDiagnostics<Any?> {

212

val source = scriptFile.toScriptSource()

213

val compilationConfig = ScriptCompilationConfiguration {

214

defaultImports("kotlin.math.*")

215

}

216

val evaluationConfig = ScriptEvaluationConfiguration.Default

217

218

return eval(source, compilationConfig, evaluationConfig).map { result ->

219

when (val returnValue = result.returnValue) {

220

is ResultValue.Value -> returnValue.value

221

is ResultValue.Unit -> Unit

222

is ResultValue.Error -> throw returnValue.error

223

is ResultValue.NotEvaluated -> null

224

}

225

}

226

}

227

}

228

229

// Using the custom host

230

val host = MyScriptingHost()

231

val scriptFile = File("script.kts")

232

233

runBlocking {

234

when (val result = host.executeScript(scriptFile)) {

235

is ResultWithDiagnostics.Success -> {

236

println("Script result: ${result.value}")

237

}

238

is ResultWithDiagnostics.Failure -> {

239

result.reports.forEach { diagnostic ->

240

println("${diagnostic.severity}: ${diagnostic.message}")

241

}

242

}

243

}

244

}

245

```

246

247

### Script Definition Usage

248

249

```kotlin

250

// Define a script template

251

@KotlinScript(

252

displayName = "Data Processing Script",

253

fileExtension = "data.kts",

254

compilationConfiguration = DataScriptCompilationConfig::class,

255

evaluationConfiguration = DataScriptEvaluationConfig::class

256

)

257

abstract class DataScript

258

259

class DataScriptCompilationConfig : ScriptCompilationConfiguration({

260

defaultImports("kotlin.collections.*", "kotlin.io.*")

261

dependencies.append(JvmDependency("org.apache.commons:commons-csv:1.9.0"))

262

})

263

264

class DataScriptEvaluationConfig : ScriptEvaluationConfiguration({

265

contextVariables.put("dataDir", File("./data"))

266

})

267

268

// Create script definition from template

269

val scriptDefinition = createScriptDefinitionFromTemplate(DataScript::class)

270

271

// Use the definition

272

val host = MyScriptingHost()

273

val script = File("process-data.data.kts").toScriptSource()

274

275

val result = host.eval(

276

script,

277

scriptDefinition.compilationConfiguration,

278

scriptDefinition.evaluationConfiguration

279

)

280

```

281

282

### Advanced Host Configuration

283

284

```kotlin

285

// Custom class loader for scripting

286

class CustomScriptingClassLoader : GetScriptingClass {

287

private val additionalClassPath = mutableListOf<URL>()

288

289

fun addToClassPath(url: URL) {

290

additionalClassPath.add(url)

291

}

292

293

override fun invoke(className: String): KClass<*>? {

294

return try {

295

val classLoader = URLClassLoader(additionalClassPath.toTypedArray())

296

Class.forName(className, false, classLoader).kotlin

297

} catch (e: ClassNotFoundException) {

298

null

299

}

300

}

301

}

302

303

// Host configuration with custom class loader

304

val customClassLoader = CustomScriptingClassLoader().apply {

305

addToClassPath(File("lib/custom.jar").toURI().toURL())

306

}

307

308

val hostConfig = ScriptingHostConfiguration {

309

getScriptingClass(customClassLoader)

310

jvmTarget("1.8")

311

configurationDependencies(listOf(

312

JvmDependency("org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.0")

313

))

314

}

315

316

// Create configurations with custom host config

317

val compilationConfig = createCompilationConfigurationFromTemplate(

318

DataScript::class,

319

hostConfig

320

)

321

322

val evaluationConfig = createEvaluationConfigurationFromTemplate(

323

DataScript::class,

324

hostConfig

325

)

326

```

327

328

### Script Source Utilities

329

330

```kotlin

331

// Various ways to create script sources

332

val fileSource = File("script.kts").toScriptSource()

333

val stringSource = "println(\"Hello World\")".toScriptSource("hello.kts")

334

335

// URL-based script source

336

val url = URL("https://example.com/script.kts")

337

val urlText = url.readText()

338

val urlSource = UrlScriptSource(url, urlText)

339

340

// Custom script source with caching

341

class CachedFileScriptSource(override val file: File) : FileBasedScriptSource() {

342

private var cachedText: String? = null

343

private var lastModified: Long = 0

344

345

override val text: String

346

get() {

347

val currentModified = file.lastModified()

348

if (cachedText == null || currentModified > lastModified) {

349

cachedText = file.readText()

350

lastModified = currentModified

351

}

352

return cachedText!!

353

}

354

355

override val externalLocation: String? get() = file.absolutePath

356

}

357

358

// Database-backed script source

359

class DatabaseScriptSource(

360

private val scriptId: String,

361

private val database: ScriptDatabase

362

) : ExternalSourceCode {

363

override val text: String by lazy { database.getScriptContent(scriptId) }

364

override val name: String? = "script_$scriptId"

365

override val locationId: String? = "db:$scriptId"

366

override val externalLocation: String? = "database://scripts/$scriptId"

367

}

368

```

369

370

### Host Integration Patterns

371

372

```kotlin

373

// Plugin-based scripting system

374

class PluginScriptingHost : BasicScriptingHost() {

375

private val plugins = mutableMapOf<String, ScriptPlugin>()

376

377

fun registerPlugin(name: String, plugin: ScriptPlugin) {

378

plugins[name] = plugin

379

}

380

381

suspend fun executeWithPlugins(script: SourceCode): ResultWithDiagnostics<Any?> {

382

// Pre-execution plugin hooks

383

plugins.values.forEach { it.beforeExecution(script) }

384

385

val result = eval(script, getCompilationConfig(), getEvaluationConfig())

386

387

// Post-execution plugin hooks

388

plugins.values.forEach { it.afterExecution(script, result) }

389

390

return result.map { evaluationResult ->

391

when (val returnValue = evaluationResult.returnValue) {

392

is ResultValue.Value -> returnValue.value

393

else -> null

394

}

395

}

396

}

397

}

398

399

interface ScriptPlugin {

400

suspend fun beforeExecution(script: SourceCode)

401

suspend fun afterExecution(script: SourceCode, result: ResultWithDiagnostics<EvaluationResult>)

402

}

403

404

// Service-based scripting host

405

class ServiceBasedScriptingHost(

406

private val compiler: ScriptCompiler,

407

private val evaluator: ScriptEvaluator,

408

private val logger: Logger

409

) : BasicScriptingHost() {

410

411

override suspend fun runInCoroutineContext(body: suspend () -> Unit) {

412

logger.info("Starting script execution")

413

try {

414

withTimeout(30000) { // 30 second timeout

415

body()

416

}

417

} catch (e: TimeoutCancellationException) {

418

logger.error("Script execution timed out")

419

throw e

420

} finally {

421

logger.info("Script execution completed")

422

}

423

}

424

}

425

```