or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-scripting-host.mdindex.mdjsr223-integration.mdrepl-support.mdscript-caching.mdscript-compilation.mdscript-persistence.md

script-compilation.mddocs/

0

# Script Compilation

1

2

The script compilation system provides JVM script compilation capabilities using the Kotlin compiler infrastructure with comprehensive configuration support and proxy-based compilation.

3

4

## Capabilities

5

6

### JvmScriptCompiler

7

8

JVM script compiler implementation that handles script compilation with configurable host configuration and compiler proxy.

9

10

```kotlin { .api }

11

/**

12

* JVM script compiler for compiling Kotlin scripts with proxy-based compilation

13

* @param baseHostConfiguration Base host configuration for compilation

14

* @param compilerProxy Optional custom compiler proxy, defaults to ScriptJvmCompilerIsolated

15

*/

16

open class JvmScriptCompiler(

17

baseHostConfiguration: ScriptingHostConfiguration = defaultJvmScriptingHostConfiguration,

18

compilerProxy: ScriptCompilerProxy? = null

19

) : ScriptCompiler {

20

21

/** Final host configuration with defaults applied */

22

val hostConfiguration: ScriptingHostConfiguration

23

24

/** Compiler proxy for performing actual compilation */

25

val compilerProxy: ScriptCompilerProxy

26

27

/**

28

* Compiles a script with the given configuration

29

* @param script Source code to compile

30

* @param scriptCompilationConfiguration Compilation configuration

31

* @returns Result with diagnostics containing compiled script or errors

32

*/

33

override suspend operator fun invoke(

34

script: SourceCode,

35

scriptCompilationConfiguration: ScriptCompilationConfiguration

36

): ResultWithDiagnostics<CompiledScript>

37

}

38

```

39

40

**Usage Examples:**

41

42

```kotlin

43

import kotlin.script.experimental.jvmhost.JvmScriptCompiler

44

import kotlin.script.experimental.api.*

45

import kotlin.script.experimental.jvm.*

46

47

// Basic compiler usage

48

val compiler = JvmScriptCompiler()

49

50

val script = """

51

val message = "Hello from compiled script!"

52

println(message)

53

message.length

54

""".trimIndent()

55

56

val compilationConfig = ScriptCompilationConfiguration {

57

dependencies(JvmDependency(kotlinStdlib))

58

compilerOptions.append("-opt-in=kotlin.RequiresOptIn")

59

}

60

61

val compilationResult = compiler(script.toScriptSource(), compilationConfig)

62

63

when (compilationResult) {

64

is ResultWithDiagnostics.Success -> {

65

val compiledScript = compilationResult.value

66

println("Compilation successful: ${compiledScript.sourceLocationId}")

67

68

// Get script class

69

val classResult = compiledScript.getClass()

70

when (classResult) {

71

is ResultWithDiagnostics.Success -> {

72

println("Script class: ${classResult.value.simpleName}")

73

}

74

is ResultWithDiagnostics.Failure -> {

75

println("Failed to get script class")

76

}

77

}

78

}

79

is ResultWithDiagnostics.Failure -> {

80

compilationResult.reports.forEach {

81

println("Compilation error: ${it.message}")

82

}

83

}

84

}

85

86

// Advanced compiler with custom configuration

87

val customHostConfiguration = ScriptingHostConfiguration {

88

jvm {

89

// Custom JVM configuration

90

compilationCache(FileBasedScriptCache(File("cache")))

91

}

92

}

93

94

val advancedCompiler = JvmScriptCompiler(

95

baseHostConfiguration = customHostConfiguration

96

)

97

98

val advancedCompilationConfig = ScriptCompilationConfiguration {

99

// Template-based configuration

100

baseClass(KotlinType(Any::class))

101

102

// Dependencies

103

dependencies(

104

JvmDependency(File("lib1.jar")),

105

JvmDependency(File("lib2.jar"))

106

)

107

108

// Import scripts

109

importScripts(FileBasedScriptSource(File("common.kts")))

110

111

// Compiler options

112

compilerOptions.append(

113

"-language-version", "2.0",

114

"-api-version", "2.0"

115

)

116

117

// IDE support

118

ide {

119

acceptedLocations(ScriptAcceptedLocation.Everywhere)

120

}

121

}

122

123

val advancedResult = advancedCompiler(script.toScriptSource(), advancedCompilationConfig)

124

```

125

126

### Compilation Configuration

127

128

The compilation system uses `ScriptCompilationConfiguration` to control various aspects of script compilation.

129

130

#### Key Configuration Options

131

132

```kotlin { .api }

133

// Core configuration builders (imported from kotlin.script.experimental.api)

134

fun ScriptCompilationConfiguration.Builder.dependencies(vararg dependencies: ScriptDependency): ScriptCompilationConfiguration.Builder

135

fun ScriptCompilationConfiguration.Builder.importScripts(vararg scripts: SourceCode): ScriptCompilationConfiguration.Builder

136

fun ScriptCompilationConfiguration.Builder.compilerOptions(vararg options: String): ScriptCompilationConfiguration.Builder

137

fun ScriptCompilationConfiguration.Builder.baseClass(baseClass: KotlinType): ScriptCompilationConfiguration.Builder

138

fun ScriptCompilationConfiguration.Builder.hostConfiguration(configuration: ScriptingHostConfiguration): ScriptCompilationConfiguration.Builder

139

```

140

141

**Configuration Examples:**

142

143

```kotlin

144

// Dependency configuration

145

val configWithDependencies = ScriptCompilationConfiguration {

146

dependencies(

147

JvmDependency(kotlinStdlib),

148

JvmDependency(File("my-library.jar")),

149

JvmDependency("org.apache.commons:commons-lang3:3.12.0") // Maven coordinates

150

)

151

}

152

153

// Import scripts configuration

154

val configWithImports = ScriptCompilationConfiguration {

155

importScripts(

156

FileBasedScriptSource(File("utilities.kts")),

157

StringScriptSource("val commonConstant = 42", "common.kts")

158

)

159

}

160

161

// Compiler options configuration

162

val configWithOptions = ScriptCompilationConfiguration {

163

compilerOptions.append(

164

"-opt-in=kotlin.RequiresOptIn",

165

"-Xmulti-platform",

166

"-language-version", "2.0"

167

)

168

}

169

170

// Template-based configuration

171

@KotlinScript(

172

fileExtension = "custom.kts",

173

compilationConfiguration = CustomScriptConfiguration::class

174

)

175

class CustomScriptTemplate

176

177

object CustomScriptConfiguration : ScriptCompilationConfiguration({

178

baseClass(KotlinType(CustomScriptTemplate::class))

179

dependencies(JvmDependency(kotlinStdlib))

180

compilerOptions.append("-opt-in=kotlin.ExperimentalStdlibApi")

181

})

182

183

val templateConfig = ScriptCompilationConfiguration {

184

baseClass(KotlinType(CustomScriptTemplate::class))

185

refineConfiguration {

186

// Dynamic configuration refinement

187

onAnnotations(DependsOn::class, Repository::class) { context ->

188

// Process annotations to add dependencies

189

context.collectedData?.get(DependsOn::class)?.let { dependsOnList ->

190

ScriptCompilationConfiguration(context.compilationConfiguration) {

191

dependencies.append(JvmDependency(dependsOnList.flatMap { it.artifacts }))

192

}.asSuccess()

193

} ?: context.compilationConfiguration.asSuccess()

194

}

195

}

196

}

197

```

198

199

### Compiler Proxy Integration

200

201

The JVM script compiler uses a proxy pattern to delegate actual compilation to pluggable compiler implementations.

202

203

```kotlin { .api }

204

// Compiler proxy interface (from kotlin.scripting.compiler.plugin)

205

interface ScriptCompilerProxy {

206

suspend fun compile(

207

script: SourceCode,

208

scriptCompilationConfiguration: ScriptCompilationConfiguration

209

): ResultWithDiagnostics<CompiledScript>

210

}

211

```

212

213

**Custom Compiler Proxy Example:**

214

215

```kotlin

216

import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy

217

218

class CustomScriptCompilerProxy(

219

private val hostConfiguration: ScriptingHostConfiguration

220

) : ScriptCompilerProxy {

221

222

override suspend fun compile(

223

script: SourceCode,

224

scriptCompilationConfiguration: ScriptCompilationConfiguration

225

): ResultWithDiagnostics<CompiledScript> {

226

// Custom compilation logic

227

return try {

228

// Perform custom pre-processing

229

val processedScript = preprocessScript(script)

230

231

// Delegate to default compiler

232

val defaultProxy = ScriptJvmCompilerIsolated(hostConfiguration)

233

defaultProxy.compile(processedScript, scriptCompilationConfiguration)

234

} catch (e: Exception) {

235

ResultWithDiagnostics.Failure(

236

listOf(e.asErrorDiagnostics("Custom compilation failed"))

237

)

238

}

239

}

240

241

private fun preprocessScript(script: SourceCode): SourceCode {

242

// Custom preprocessing logic

243

return StringScriptSource(

244

script.text.replace("@CustomMacro", "// Expanded macro"),

245

script.name

246

)

247

}

248

}

249

250

// Use custom proxy

251

val customCompiler = JvmScriptCompiler(

252

compilerProxy = CustomScriptCompilerProxy(defaultJvmScriptingHostConfiguration)

253

)

254

```

255

256

## Compilation Results

257

258

The compilation process returns `CompiledScript` instances that encapsulate the compiled script artifacts.

259

260

### CompiledScript Interface

261

262

```kotlin { .api }

263

interface CompiledScript {

264

/** Compilation configuration used to compile this script */

265

val compilationConfiguration: ScriptCompilationConfiguration

266

267

/** Source location identifier for error reporting */

268

val sourceLocationId: String?

269

270

/** Other scripts that were compiled together with this script */

271

val otherScripts: List<CompiledScript>

272

273

/** Result field information if script has a result expression */

274

val resultField: Pair<String, KotlinType>?

275

276

/**

277

* Gets the compiled script class

278

* @param scriptEvaluationConfiguration Optional evaluation configuration

279

* @returns Result containing the script class or compilation errors

280

*/

281

suspend fun getClass(scriptEvaluationConfiguration: ScriptEvaluationConfiguration? = null): ResultWithDiagnostics<KClass<*>>

282

}

283

```

284

285

**Working with Compiled Scripts:**

286

287

```kotlin

288

val compilationResult = compiler(script.toScriptSource(), compilationConfig)

289

290

when (compilationResult) {

291

is ResultWithDiagnostics.Success -> {

292

val compiledScript = compilationResult.value

293

294

// Access compilation metadata

295

println("Source: ${compiledScript.sourceLocationId}")

296

println("Has result field: ${compiledScript.resultField != null}")

297

println("Other scripts: ${compiledScript.otherScripts.size}")

298

299

// Get script class for evaluation

300

val classResult = compiledScript.getClass()

301

when (classResult) {

302

is ResultWithDiagnostics.Success -> {

303

val scriptClass = classResult.value

304

305

// Create script instance

306

val constructor = scriptClass.constructors.first()

307

val scriptInstance = constructor.call()

308

309

// Access result field if available

310

compiledScript.resultField?.let { (fieldName, fieldType) ->

311

val field = scriptClass.java.getDeclaredField(fieldName)

312

field.isAccessible = true

313

val result = field.get(scriptInstance)

314

println("Script result: $result (${fieldType.typeName})")

315

}

316

}

317

is ResultWithDiagnostics.Failure -> {

318

println("Failed to get script class")

319

}

320

}

321

}

322

is ResultWithDiagnostics.Failure -> {

323

println("Compilation failed")

324

}

325

}

326

```

327

328

## Error Handling

329

330

Compilation errors are reported through the diagnostic system with detailed location information and error categories.

331

332

### Common Compilation Errors

333

334

- **Syntax Errors**: Invalid Kotlin syntax in script code

335

- **Type Errors**: Type mismatches, unresolved references

336

- **Dependency Errors**: Missing or invalid dependencies

337

- **Import Errors**: Failed to import or resolve imported scripts

338

- **Configuration Errors**: Invalid compilation configuration

339

340

**Detailed Error Handling:**

341

342

```kotlin

343

val result = compiler(script.toScriptSource(), compilationConfig)

344

345

when (result) {

346

is ResultWithDiagnostics.Failure -> {

347

result.reports.groupBy { it.severity }.forEach { (severity, reports) ->

348

println("$severity errors:")

349

reports.forEach { diagnostic ->

350

val location = diagnostic.location?.let { loc ->

351

" at line ${loc.start.line}, column ${loc.start.col}"

352

} ?: ""

353

354

println(" ${diagnostic.message}$location")

355

356

// Show exception details if available

357

diagnostic.exception?.let { ex ->

358

println(" Caused by: ${ex.javaClass.simpleName}: ${ex.message}")

359

ex.stackTrace.take(3).forEach { frame ->

360

println(" at $frame")

361

}

362

}

363

}

364

}

365

}

366

}

367

```