Introduction

Kotlite is an open-sourced type-safe programming language that has a rich subset of the script variant of the Kotlin programming language. It comes with standard libraries, which are a subset of Kotlin Multiplatform/Common standard libraries and a few third-party libraries.

Kotlite Interpreter is a lightweight Kotlin Multiplatform library to interpret and execute codes written in Kotlite, and bridge the host runtime environment and the embedded runtime environment.

Major Features of Kotlite Interpreter

  • Supports a subset of Kotlin 1.9 language and standard libraries. Kotlin is a great, safe, descriptive and flexible language. Check the differences between Kotlite and Kotlin.

  • Supports writing complicated and generic code

  • Embeddable — it is a library

  • Safe

    • Classes from libraries or built-ins can be whitelisted or blacklisted

    • Extension functions from libraries or built-ins can be whitelisted or blacklisted

    • Extension properties from libraries or built-ins can be whitelisted or blacklisted

    • Global properties from libraries or built-ins can be whitelisted or blacklisted

    • No file or networking I/O or OS APIs in the standard library

  • Runs in multiplatform

  • Extensible and allows interaction with the host

    • Allows providing custom extension functions from the host

    • Allows providing custom extension properties from the host

    • Allows providing custom global properties from the host

    • Allows implementing custom libraries and delegating the calls to first-class Kotlin functions and properties

    • Allows reading values of global variables in the embedded environment from the host

    • Stdout pipe of the embedded environment is overridable

  • Lightweight — kotlinc is over 300 MB, and the sum of Kotlite with stdlib for all platforms is less than 10 MB. The JS script of the web demo is less than 800 KB.

  • Semantic analysis, e.g. variable access and type verification, before execution

  • Type inference

  • Well tested — there are more than a thousand of hand-written unit tests per platform

  • Can be written in any IDE supporting Kotlin 1.9 — Kotlite does not create new syntax

tests
To be honest, the standard library is not well tested. Only the language itself is well tested. Please kindly help to report if any issue is found.

Supported Platforms

  • JVM (Java, Kotlin/JVM, …​)

  • JS

  • Android (JVM)

  • iOS

  • macOS

  • watchOS

  • tvOS

The interpreter does not depend on any platform-specific APIs except the built-ins, so it should be easy for an experienced developer to port the library to any other platform supported by Kotlin Multiplatform.

Use Cases

Kotlite is designed for below use cases.

  • Executing user-provided simple expressions in a safe way

  • Executing user-provided script in a safe way

  • Allowing custom plugins, written as Kotlin codes, for any Kotlin or JVM applications in a safe way

  • Safely executing codes coming from servers

  • Updating mobile app UI any time without app update submissions to app store (this requires the community to contribute)

Non-goals

  • Kotlite does not replace Kotlin

  • Kotlite does not introduce new programming language features or syntax that are not provided in Kotlin, except necessaries supporting internal tools of Kotlite

Side Products

  • Rendering Kotlite codes as an AST (Abstract Syntax Tree) diagram using mermaid

  • Static analysis of Kotlite codes

  • Generating AST nodes from Kotlite codes

  • Reformatting Kotlite codes

Demo

Their source codes are under the demo folder of the GitHub repository.

Web

Android

iOS

Release Notes

Feature Requests or Reporting Issues

It is glad to have your contributions to this project by raising feature requests or reporting issues.

Please raise a ticket in the GitHub repository, if it has not been raised previously. Otherwise, vote that ticket.

For issue reporting, please include the following:

  • Minimal code that reproduces the issue

  • Platform language, OS and versions (e.g. JVM 21 on Windows)

  • Expected result

  • Actual result

Reported issues will be prioritized and addressed as soon as possible, according to importance, completeness and availability.

If you have any usage question, please visit the discussion section of the GitHub repository and search for if anyone has asked the same question previously. If there is none, please feel free to create a new discussion.

The Kotlite Interpreter

Getting Started

Include the dependencies

Firstly, include the dependencies.

Kotlite Interpreter kotlite interpreter

Kotlite Stdlib kotlite stdlib

For single platform:

dependencies {
    implementation("io.github.sunny-chung:kotlite-interpreter:<version>")
    implementation("io.github.sunny-chung:kotlite-stdlib:<version>")
    // ...
}

For multiplatform:

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                api("io.github.sunny-chung:kotlite-interpreter:<version>")
                api("io.github.sunny-chung:kotlite-stdlib:<version>")
                // ...
            }
        }
        // ...

Stages

Diagram

Developers should be familiar with most of the stages.

In the Semantic Analysis stage, it is doing lots of stuffs like checking whether a function in a class tries to override a non-existing function, returning values with a wrong data type, and inferring types, optimizing codes, etc..

Any stage can throw an exception.

The stages in different blocks do not require to be called immediately after the previous one.

Minimal Examples

After understanding the stages, we can start writing codes.

Print Hello world!
val env = ExecutionEnvironment().apply {
    install(AllStdLibModules())
}
val interpreter = KotliteInterpreter(
    filename = "Hello",
    code = """
        println("Hello world!")
    """.trimIndent(),
    executionEnvironment = env,
)
interpreter.eval()
Parsing and semantic analysis are performed in the function KotliteInterpreter(). It could be imagined as a "compilation process". If there is any error, an exception would be thrown from this function, before the eval() call.
The filename parameter is only used in error messages and stacktraces.
Retrieve global values of execution result
val env = ExecutionEnvironment().apply {
    install(AllStdLibModules())
}
val interpreter = KotliteInterpreter(
    filename = "Calculate",
    code = """
        val a = (1..10).fold(0) { acc, it ->
            acc + it
        }
    """.trimIndent(),
    executionEnvironment = env,
)
interpreter.eval()
val symbolTable = interpreter.symbolTable()
val a = (symbolTable.findPropertyByDeclaredName("a") as IntValue).value // 55
Evaluate an expression only
val env = ExecutionEnvironment().apply {
    install(AllStdLibModules())
}
val result: IntValue = evalKotliteExpression(
    filename = "Calculate",
    code = "(1..10).fold(0) { acc, it -> acc + it }",
    executionEnvironment = env,
) as IntValue
val a: Int = result.value // 55

Value and Type Classes

All the values returned by evalKotliteExpression() or SymbolTable.findPropertyByDeclaredName() or Interpreter.eval() or value arguments provided to custom functions/properties are of a subtype of RuntimeValue. Possible subtypes of RuntimeValue are:

  • IntValue

  • LongValue

  • DoubleValue

  • CharValue

  • StringValue

  • BooleanValue

  • ByteValue

  • NullValue

  • UnitValue

  • LambdaValue

  • ThrowableValue

  • ClassInstance

RuntimeValue has a member function type(), which returns the type of the underlying value. The return type is a subtype of DataType. DataType is also provided when there are type arguments provided to custom functions/properties.

Possible subtypes of DataType for consumer use are:

  • ObjectType

  • FunctionType

  • UnitType

  • NothingType

  • TypeParameterType

  • StarType

  • RepeatedType

In most of the time, ObjectType would be returned. The underlying class definition, generic type arguments and nullabilities can be accessed in the ObjectType class.

DataType has a String member property descriptiveName which returns a readable type name, for example, "MutableMap<MyPair<Int, Boolean>, List<String?>>?".

Thread Safety

The interpreter itself is not thread-safe. The code executed by the Kotlite interpreter cannot be on multiple threads.

However, Kotlite interpreter does not hold global states. Thus, it is possible to run different Interpreter instances and execute in multiple threads concurrently.

It might also work if mutex locks are enforced in provided custom functions.

Reusability

Most Kotlite classes cannot be reused, including ExecutionEnvironment, AST nodes, parsers and the interpreter. They contain states. If one wants to repeat the execution or use the same inputs of ExecutionEnvironment, they would have to duplicate the calls.

Security

Standard libraries delegations

The standard libraries are implemented as delegations to the original Kotlin / third-party APIs and classes in the host environment. For example, the implementation of the library function fun String.toRegex(): Regex would convert the StringValue to a real String in the host environment, and then invoke toRegex(), and return the Regex instance back to the embedded environment in a wrapped form. The delegation approach can be a security concern.

While most of the Kotlite built-in standard libraries should be safe to execute, delegations to some third-party libraries might be unwanted.

Filtering classes, functions and properties

So, Kotlite provides a way to remove them from the embedded execution environment.

This can be done by supplying filter functions to ExecutionEnvironment.

Built-in stuffs, e.g. Int, can be filtered out as well, but that may cause troubles during code execution and importing libraries, and has no security benefits.

Below is an example to remove the class MutableList completely without breaking the environment.

val env = ExecutionEnvironment(
    classRegistrationFilter = {
        it != "MutableList"
    },
    functionRegistrationFilter = {
        !(it.receiverType ?: "").contains("MutableList") &&
            !it.returnType.contains("MutableList")
    },
).apply {
    install(AllStdLibModules())
}

assertFailsWith<SemanticException> {
    KotliteInterpreter(
        filename = "<Test>",
        code = """
            val a = mutableListOf(1, 2, 3)
        """.trimIndent(),
        executionEnvironment = env
    )
}
Developers can still create a class with the same name, as if the class never existed. This does no harm, as it does not interact with the host.

Selectively installing libraries

It is possible to only install specific libraries to the ExecutionEnvironment.

val env = ExecutionEnvironment().apply {
    install(TextLibModule())
    install(CollectionsLibModule())
    install(ByteLibModule())
}

The order matters. If a library module depends on another one, the one being depended should be installed first.

Implicit code execution in equals(), hashCode(), toString(), compareTo()

As mentioned previously, standard libraries are just delegations to the real APIs and classes.

To enable use cases like sorting a list of custom classes or using a custom class as keys of Map, the functions equals(), hashCode(), toString(), compareTo() can be overridden by end users in Kotlite. In the host environment, calling these functions will execute the user-overridden codes and may throw exceptions. This may be an unwanted code execution and risk.

Bear in mind that doing a a == b or "Debug: $a" in your application may execute user code.

Resources Usage

There is no way to limit memory usage or computing resources of user code execution at this moment. User code can exhaust all the available memory or slow down the OS using infinite computing loops. This area might be improved in the future.

Integration with the Host

There are some APIs to allow the host provides custom executable functions and properties to the embedded script environment. These APIs are not yet stable and subject to change in the future.

Creating an integration is similar to creating a library module. It is recommended to read the details in the Creating Library Modules to have a deep understanding on this topic.

Providing functions and extension Functions

To provide an extension function, use the ExecutionEnvironment.registerFunction(CustomFunctionDefinition) API.

Below example provides an extension function with the signature fun String.size(factor: Int): Int. The function also alters a variable hostVar in the host environment before returning.

var hostVar: Int = 0

val env = ExecutionEnvironment().apply {
    registerFunction(CustomFunctionDefinition(
        receiverType = "String",
        functionName = "size",
        returnType = "Int",
        parameterTypes = listOf(CustomFunctionParameter("factor", "Int")),
        executable = { interpreter, receiver, args, typeArgs ->
            IntValue((receiver as StringValue).value.length * (args[0] as IntValue).value, interpreter.symbolTable()).also {
                hostVar = it.value
            }
        },
        position = SourcePosition("MyBridge", 1, 1),
    ))
}
The value of position is used only when there is an error or runtime exception, in attempt to provide more information about the error.

To provide a global function, simply provide a null value to the receiverType parameter.

Providing extension properties

To provide an extension property, use the ExecutionEnvironment.registerExtensionProperty(ExtensionProperty) API.

Below is an example exposing a host variable to the script environment to read and write values.

var hostScopeVariable = 0

val env = ExecutionEnvironment().apply {
    registerExtensionProperty(ExtensionProperty(
        declaredName = "f",
        receiver = "String",
        type = "Int",
        getter = { interpreter, subject, typeArgs ->
            IntValue(hostScopeVariable, interpreter.symbolTable())
        },
        setter = { interpreter, subject, value, typeArgs ->
            hostScopeVariable += (value as IntValue).value
        }
    ))
}

val interpreter = KotliteInterpreter(
    filename = "MyScript",
    code = """
        val s = "abcde"
        s.f = 10
        val a = s.f // 10
        s.f = 15
        val b = s.f // 25
    """.trimIndent(),
    executionEnvironment = env,
)
interpreter.eval()
Either getter or setter parameter can be null if there is no getter or setter.

Providing global properties

The API to provide a global property is different from that for extension properties. It is ExecutionEnvironment.registerGlobalProperty(GlobalProperty).

var property = 10

val env = ExecutionEnvironment().apply {
    registerGlobalProperty(GlobalProperty(
        position = SourcePosition("MyScript", 1, 1),
        declaredName = "x",
        type = "Int",
        isMutable = true,
        getter = { interpreter -> IntValue(property, interpreter.symbolTable()) },
        setter = { interpreter, value -> property = (value as IntValue).value },
    ))
    registerGlobalProperty(GlobalProperty(
        position = SourcePosition("Math", 1, 1),
        declaredName = "myPi",
        type = "Double",
        isMutable = false,
        getter = { interpreter -> DoubleValue(3.14, interpreter.symbolTable()) },
    ))
}
As seen in examples, either getter or setter can be optional (null).

Executing other functions in executable

The APIs are less friendly, but this is possible.

Executing a lambda argument

The core stdlib has some good example.

/stdlib/src/commonMain/kotlin/com/sunnychung/lib/multiplatform/kotlite/stdlib/CoreLibModule.kt
    CustomFunctionDefinition(
        receiverType = "T",
        functionName = "also",
        returnType = "T",
        typeParameters = listOf(TypeParameter(name = "T", typeUpperBound = null)),
        parameterTypes = listOf(CustomFunctionParameter("block", "(T) -> Unit")),
        executable = { interpreter, receiver, args, typeArgs ->
            val block = args[0] as LambdaValue
            block.execute(arrayOf(receiver))
            receiver!!
        },
        position = SourcePosition(name, 1, 1),
    ),
    CustomFunctionDefinition(
        receiverType = "T",
        functionName = "apply",
        returnType = "T",
        typeParameters = listOf(TypeParameter(name = "T", typeUpperBound = null)),
        parameterTypes = listOf(CustomFunctionParameter("block", "T.() -> Unit")),
        executable = { interpreter, receiver, args, typeArgs ->
            val block = args[0] as LambdaValue
            block.execute(arguments = emptyArray(), receiver = receiver!!)
            receiver!!
        },
        position = SourcePosition(name, 1, 1),
    ),
The order matters. If A depends on B, put B before A.
Executing other declared functions

This is not easy, and not a common use case. Take a look of /interpreter/src/commonMain/kotlin/com/sunnychung/lib/multiplatform/kotlite/model/SpecialFunction.kt for an example.

Creating Library Modules

A library module is just a collection of custom classes, functions, extension functions, extension properties and global properties.

The order matters. If A depends on B, put B before A.

Kotlite Interpreter APIs

Let’s start with providing custom functions. Usually the process is like this:

Diagram

In CustomFunctionDefinition, the executable lambda argument looks like this:

{ interpreter: Interpreter, receiver: RuntimeValue?, args: List<RuntimeValue>, typeArgs: Map<String, DataType> ->
    // ...
}
The APIs and processes are similar for custom properties. This section applies to them as well.
RuntimeValue — a Kotlite value that wraps a Kotlin value

In code level, a Kotlite value is a RuntimeValue in the Kotlin host. Wrapping a Kotlin value to a RuntimeValue is tricky. Below lists out how to wrap them.

Kotlin Type Code to convert to a Kotlite value

Int

IntValue(value: Int, symbolTable: SymbolTable)

Long

LongValue(value: Long, symbolTable: SymbolTable)

Double

DoubleValue(value: Double, symbolTable: SymbolTable)

Byte

ByteValue(value: Byte, symbolTable: SymbolTable)

Boolean

BooleanValue(value: Boolean, symbolTable: SymbolTable)

String

StringValue(value: String, symbolTable: SymbolTable)

Null

NullValue

Unit

UnitValue

Non-generic object

DelegatedValue<T>(value: T, clazz: ClassDefinition, symbolTable: SymbolTable)

where T is the type of the Kotlin value, and clazz is the Kotlite class definition of the value.

Generic object

DelegatedValue<T>(value: T, clazz: ClassDefinition, symbolTable: SymbolTable, typeArguments: List<DataType>)

where T is the type of the Kotlin value, and clazz is the Kotlite class definition of the value.

Object that is supported by the standard library

Non-exhausted list:

ByteArrayValue(value: ByteArray, symbolTable: SymbolTable)

PairValue(value: Pair<RuntimeValue, RuntimeValue>, typeA: DataType, typeB: DataType, symbolTable: SymbolTable)

ListValue(value: List<RuntimeValue>, typeArgument: DataType, symbolTable: SymbolTable)

MutableMapValue(value: MutableMap<RuntimeValue, RuntimeValue>, keyType: DataType, valueType: DataType, symbolTable: SymbolTable)

Examples:

val symbolTable = interpreter.symbolTable()
val wrappedValue = ListValue(
    value = listOf(1, 2, 3, 5, 10),
    typeArgument = symbolTable.IntType,
    symbolTable = symbolTable,
)
For nested classes such as List, Map or Pair, don’t forget to wrap all the nested values. Otherwise, the things would go wrong and exceptions may be thrown during code execution.
SymbolTable

A SymbolTable can be obtained via Interpreter.symbolTable(). SymbolTable cannot be persisted, because it might be different in the context of another function call, and persisting it would lead to memory leak.

ClassDefinition and ProvidedClassDefinition

For types that are available from the standard libraries, usually it could be found by ${TypeName}Class.clazz. For example, MutableListClass.clazz for the class MutableList.

For types that are not known to Kotlite, you will have to provide a custom ClassDefinition.

ProvidedClassDefinition is a friendly API for library users to define a class. It extends ClassDefinition. An example can be found here.

DataType

If creation of generic Kotlite values is needed, for example, a List<T> value, one or more DataType are needed to specify the type arguments. It can be obtained from multiple ways.

  1. If it is available in the type arguments of the function call, use typeArgs[name].

For example, for a function signature like this:

fun <T, R : Comparable<R>> MutableList<T>.sortBy(selector: (T) -> R?)

typeArgs["T"] is the T type argument in DataType, and typeArgs["R"] is the R type argument in DataType.

  1. Primitive data types

It can be obtained from SymbolTable. For example, symbolTable.IntType. For some special types like Any, Unit and Nothing, it can be directly constructed: UnitType(isNullable: Boolean = false).

  1. For other types, it can be obtained by the String.toDataType(symbolTable: SymbolTable) convenient extension function. For example,

val symbolTable: SymbolTable = interpreter.symbolTable()

val byteArrayType: DataType = "ByteArray".toDataType(symbolTable)
val pairType: DataType = "Pair<String, Pair<Double, Int>>".toDataType(symbolTable)
val genericType: DataType = "Map<K, Int>".toDataType(symbolTable)
If there is untrusted user input, this approach is vulnerable to injection attacks.
Unwrapping Kotlite RuntimeValue to a Kotlin value

It is relatively easy. Just cast to the right type and call the member property .value.

Kotlin Type Code to convert a Kotlite value to a Kotlin value

Int

val actualValue: Int = (value as IntValue).value
val nullableActualValue: Int? = (value as? IntValue)?.value

Long

val actualValue: Long = (value as LongValue).value
val nullableActualValue: Long? = (value as? LongValue)?.value

Double

val actualValue: Double = (value as DoubleValue).value
val nullableActualValue: Double? = (value as? DoubleValue)?.value

Byte

val actualValue: Byte = (value as ByteValue).value
val nullableActualValue: Byte? = (value as? ByteValue)?.value

Boolean

val actualValue: Boolean = (value as BooleanValue).value
val nullableActualValue: Boolean? = (value as? BooleanValue)?.value

String

val actualValue: String = (value as StringValue).value
val nullableActualValue: String? = (value as? StringValue)?.value

Object

val byteArray: ByteArray = (value as DelegatedValue<ByteArray>).value
val nullableByteArray: ByteArray? = (value as? DelegatedValue<ByteArray>)?.value

val list: List<RuntimeValue> = (value as DelegatedValue<List<RuntimeValue>>).value
val listWithIntValue: List<Int> = list.map {
    (it as IntValue).value
}
For nested classes such as List, Map or Pair, don’t forget to unwrap all the nested values if necessary.

Manual approach

Create a class that extends the abstract class LibraryModule, give a name to it, include all the implementations, then this class is a Library Module that can be installed.

Taking this approach has the best performance, but requires lots of effort to write repetitive codes.

The IOLibModule in the standard library is a good example to be referenced, because it is a library module completely written by hand.

IOLibModule
/stdlib/src/commonMain/kotlin/com/sunnychung/lib/multiplatform/kotlite/stdlib/IOLibModule.kt
package com.sunnychung.lib.multiplatform.kotlite.stdlib

import com.sunnychung.lib.multiplatform.kotlite.model.CustomFunctionDefinition
import com.sunnychung.lib.multiplatform.kotlite.model.CustomFunctionParameter
import com.sunnychung.lib.multiplatform.kotlite.model.ExtensionProperty
import com.sunnychung.lib.multiplatform.kotlite.model.GlobalProperty
import com.sunnychung.lib.multiplatform.kotlite.model.LibraryModule
import com.sunnychung.lib.multiplatform.kotlite.model.ProvidedClassDefinition
import com.sunnychung.lib.multiplatform.kotlite.model.SourcePosition
import com.sunnychung.lib.multiplatform.kotlite.model.UnitValue

open class IOLibModule : LibraryModule("IO") {
    override val classes: List<ProvidedClassDefinition> = emptyList()

    override val properties: List<ExtensionProperty> = emptyList()

    override val globalProperties: List<GlobalProperty> = emptyList()

    override val functions: List<CustomFunctionDefinition> = listOf(
        CustomFunctionDefinition(
            receiverType = null,
            functionName = "println",
            returnType = "Unit",
            parameterTypes = emptyList(),
            executable = { interpreter, receiver, args, typeArgs ->
                outputToConsole("\n")
                UnitValue
            },
            position = SourcePosition(name, 1, 1),
        ),
        CustomFunctionDefinition(
            receiverType = null,
            functionName = "println",
            returnType = "Unit",
            parameterTypes = listOf(CustomFunctionParameter("message", "Any?")),
            executable = { interpreter, receiver, args, typeArgs ->
                val message = args[0]
                outputToConsole("${message.convertToString()}\n")
                UnitValue
            },
            position = SourcePosition(name, 1, 1),
        ),
        CustomFunctionDefinition(
            receiverType = null,
            functionName = "print",
            returnType = "Unit",
            parameterTypes = listOf(CustomFunctionParameter("message", "Any?")),
            executable = { interpreter, receiver, args, typeArgs ->
                val message = args[0]
                outputToConsole(message.convertToString())
                UnitValue
            },
            position = SourcePosition(name, 2, 1),
        ),
    )

    open fun outputToConsole(output: String) {
        print(output)
    }
}

Delegation approach

This approach is what the most Kotlite standard libraries take. Delegating everything to Kotlin, and generate all the delegation codes using the Kotlite Stdlib Processor Gradle plugin.

During the execution of the delegation call, Kotlite will unwrap the Kotlite RuntimeValue to a Kotlin type if needed, execute the delegated function, and then wrap the result to a Kotlite RuntimeValue. The time performance penalty is significant when the subject, argument or result is a Collection with a large size.

Below is a minimal example to generate a delegation library module. Some stuffs from the Regex and the Collection library modules are taken in the example.

/settings.gradle.kts
pluginManagement {
    repositories {
        mavenCentral()
        // ...
    }
}

Kotlite Library Preprocessor Gradle Plugin kotlite stdlib processor plugin

/your-library/build.gradle.kts
plugins {
    kotlin("multiplatform")
    id("io.github.sunny-chung.kotlite-stdlib-processor-plugin") version "<version>"
}

// ...

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                // ...
            }
            kotlin.srcDir(tasks.named("kotliteStdlibHeaderProcess").map { it.outputs })
        }

// ...

kotliteStdLibHeaderProcessor {
    inputDir = "src/kotlinheader/"
    outputDir = "build/generated/common/"
    outputPackage = "com.sunnychung.lib.multiplatform.kotlite.stdlib"
    configs = mapOf(
        "Regex" to KotliteModuleConfig(
            imports = listOf(
                "com.sunnychung.lib.multiplatform.kotlite.stdlib.regex.RegexClass",
                "com.sunnychung.lib.multiplatform.kotlite.stdlib.regex.RegexValue",
            )
        ),
    )
}

Implement the delegated class and the value factory function.

/stdlib/src/commonMain/kotlin/com/sunnychung/lib/multiplatform/kotlite/stdlib/regex/RegexValue.kt
fun RegexValue(value: Regex, symbolTable: SymbolTable) : DelegatedValue<Regex>
    = DelegatedValue<Regex>(value, "Regex", RegexClass.clazz, symbolTable = symbolTable)

object RegexClass {
     val clazz = ProvidedClassDefinition(
         fullQualifiedName = "Regex",
         typeParameters = emptyList(),
         isInstanceCreationAllowed = true,
         primaryConstructorParameters = listOf(CustomFunctionParameter("value", "String")),
         constructInstance = { interpreter, callArguments, callPosition ->
             RegexValue(Regex((callArguments[0] as StringValue).value), interpreter.symbolTable())
         },
         position = SourcePosition("Regex", 1, 1),
     )
}
The factory function name has to be ${ActualTypeName}Value. It applies to any types, regardless of primitives or interfaces. This convention is hardcoded in the code generation plugin.

Create a Kotlin header file by writing every global or extension functions and extension properties that would be delegated, but without body. This file should be placed in /your-library/src/kotlinheader/${LibraryName}.kt.

fun String.matches(regex: Regex): Boolean
fun String.replace(regex: Regex, replacement: String): String
fun String.replaceFirst(regex: Regex, replacement: String): String
fun String.toRegex(): Regex

val <T> List<T>.size: Int
    get()
val <T> List<T>.lastIndex: Int
    get()

Upon compilation, an abstract class Abstract${name}LibModule would be generated. Examine if the generated code is compilable and correct. It can be checked by writing unit tests.

Example of generated code
/stdlib/build/generated/common/AbstractRegexLibModule.kt
/** Generated code. DO NOT MODIFY! Changes to this file will be overwritten. **/

package com.sunnychung.lib.multiplatform.kotlite.stdlib

import com.sunnychung.lib.multiplatform.kotlite.model.AnyType
import com.sunnychung.lib.multiplatform.kotlite.model.BooleanValue
import com.sunnychung.lib.multiplatform.kotlite.model.ByteValue
import com.sunnychung.lib.multiplatform.kotlite.model.ComparableRuntimeValue
import com.sunnychung.lib.multiplatform.kotlite.model.CustomFunctionDefinition
import com.sunnychung.lib.multiplatform.kotlite.model.CustomFunctionParameter
import com.sunnychung.lib.multiplatform.kotlite.model.CharValue
import com.sunnychung.lib.multiplatform.kotlite.model.DataType
import com.sunnychung.lib.multiplatform.kotlite.model.DelegatedValue
import com.sunnychung.lib.multiplatform.kotlite.model.DoubleValue
import com.sunnychung.lib.multiplatform.kotlite.model.ExtensionProperty
import com.sunnychung.lib.multiplatform.kotlite.model.FunctionModifier
import com.sunnychung.lib.multiplatform.kotlite.model.FunctionType
import com.sunnychung.lib.multiplatform.kotlite.model.GlobalProperty
import com.sunnychung.lib.multiplatform.kotlite.model.IntValue
import com.sunnychung.lib.multiplatform.kotlite.model.IterableValue
import com.sunnychung.lib.multiplatform.kotlite.model.IteratorClass
import com.sunnychung.lib.multiplatform.kotlite.model.IteratorValue
import com.sunnychung.lib.multiplatform.kotlite.model.KotlinValueHolder
import com.sunnychung.lib.multiplatform.kotlite.model.LambdaValue
import com.sunnychung.lib.multiplatform.kotlite.model.LibraryModule
import com.sunnychung.lib.multiplatform.kotlite.model.ListClass
import com.sunnychung.lib.multiplatform.kotlite.model.ListValue
import com.sunnychung.lib.multiplatform.kotlite.model.LongValue
import com.sunnychung.lib.multiplatform.kotlite.model.NothingType
import com.sunnychung.lib.multiplatform.kotlite.model.NullValue
import com.sunnychung.lib.multiplatform.kotlite.model.ObjectType
import com.sunnychung.lib.multiplatform.kotlite.model.PairClass
import com.sunnychung.lib.multiplatform.kotlite.model.PairValue
import com.sunnychung.lib.multiplatform.kotlite.model.PrimitiveIterableValue
import com.sunnychung.lib.multiplatform.kotlite.model.PrimitiveIteratorValue
import com.sunnychung.lib.multiplatform.kotlite.model.PrimitiveType
import com.sunnychung.lib.multiplatform.kotlite.model.PrimitiveTypeName
import com.sunnychung.lib.multiplatform.kotlite.model.ProvidedClassDefinition
import com.sunnychung.lib.multiplatform.kotlite.model.SourcePosition
import com.sunnychung.lib.multiplatform.kotlite.model.StringValue
import com.sunnychung.lib.multiplatform.kotlite.model.TypeParameter
import com.sunnychung.lib.multiplatform.kotlite.model.TypeParameterType
import com.sunnychung.lib.multiplatform.kotlite.model.RuntimeValue
import com.sunnychung.lib.multiplatform.kotlite.model.UnitType
import com.sunnychung.lib.multiplatform.kotlite.model.UnitValue
import com.sunnychung.lib.multiplatform.kotlite.util.wrapPrimitiveValueAsRuntimeValue

import com.sunnychung.lib.multiplatform.kotlite.stdlib.regex.RegexClass
import com.sunnychung.lib.multiplatform.kotlite.stdlib.regex.RegexValue




abstract class AbstractRegexLibModule : LibraryModule("Regex") {
    override val classes = emptyList<ProvidedClassDefinition>()

    override val properties = listOf<ExtensionProperty>(
    )
    
    override val globalProperties = emptyList<GlobalProperty>()
    
    override val functions = listOf<CustomFunctionDefinition>(
        CustomFunctionDefinition(
            receiverType = "String",
            functionName = "matches",
            returnType = "Boolean",
            parameterTypes = listOf(
                CustomFunctionParameter(name = "regex", type = "Regex"),
            ),
            typeParameters = emptyList(),
            modifiers = setOf<FunctionModifier>(),
            executable = { interpreter, receiver, args, typeArgs ->
                val unwrappedReceiver = (receiver as StringValue).value
                val regex_ = (args[0] as KotlinValueHolder<*>).value as Regex
        
                val result = unwrappedReceiver.matches(regex_)
                result?.let { BooleanValue(it /* _t = Boolean; t.name = Boolean; t = Boolean */, symbolTable = interpreter.symbolTable()) } ?: NullValue
            },
            position = SourcePosition(filename = "Regex", lineNum = 3, col = 1),
        ),

        CustomFunctionDefinition(
            receiverType = "String",
            functionName = "replace",
            returnType = "String",
            parameterTypes = listOf(
                CustomFunctionParameter(name = "regex", type = "Regex"),
                CustomFunctionParameter(name = "replacement", type = "String"),
            ),
            typeParameters = emptyList(),
            modifiers = setOf<FunctionModifier>(),
            executable = { interpreter, receiver, args, typeArgs ->
                val unwrappedReceiver = (receiver as StringValue).value
                val regex_ = (args[0] as KotlinValueHolder<*>).value as Regex
            val replacement_ = (args[1] as StringValue).value
        
                val result = unwrappedReceiver.replace(regex_, replacement_)
                result?.let { StringValue(it /* _t = String; t.name = String; t = String */, symbolTable = interpreter.symbolTable()) } ?: NullValue
            },
            position = SourcePosition(filename = "Regex", lineNum = 4, col = 1),
        ),

        CustomFunctionDefinition(
            receiverType = "String",
            functionName = "replaceFirst",
            returnType = "String",
            parameterTypes = listOf(
                CustomFunctionParameter(name = "regex", type = "Regex"),
                CustomFunctionParameter(name = "replacement", type = "String"),
            ),
            typeParameters = emptyList(),
            modifiers = setOf<FunctionModifier>(),
            executable = { interpreter, receiver, args, typeArgs ->
                val unwrappedReceiver = (receiver as StringValue).value
                val regex_ = (args[0] as KotlinValueHolder<*>).value as Regex
            val replacement_ = (args[1] as StringValue).value
        
                val result = unwrappedReceiver.replaceFirst(regex_, replacement_)
                result?.let { StringValue(it /* _t = String; t.name = String; t = String */, symbolTable = interpreter.symbolTable()) } ?: NullValue
            },
            position = SourcePosition(filename = "Regex", lineNum = 5, col = 1),
        ),

        CustomFunctionDefinition(
            receiverType = "String",
            functionName = "toRegex",
            returnType = "Regex",
            parameterTypes = listOf(),
            typeParameters = emptyList(),
            modifiers = setOf<FunctionModifier>(),
            executable = { interpreter, receiver, args, typeArgs ->
                val unwrappedReceiver = (receiver as StringValue).value
        
                val result = unwrappedReceiver.toRegex()
                result?.let { RegexValue(it /* _t = Regex; t.name = Regex; t = Regex */, symbolTable = interpreter.symbolTable()) } ?: NullValue
            },
            position = SourcePosition(filename = "Regex", lineNum = 7, col = 1),
        ),

    )
}
The code generation plugin has lots of hardcode. You may want to fork another one and add more hardcoded stuffs.

Finally, create a class ${name}LibModule extending this abstract class, override or add anything if necessary, then it is done.

/stdlib/src/commonMain/kotlin/com/sunnychung/lib/multiplatform/kotlite/stdlib/RegexLibModule.kt
package com.sunnychung.lib.multiplatform.kotlite.stdlib

import com.sunnychung.lib.multiplatform.kotlite.model.ProvidedClassDefinition
import com.sunnychung.lib.multiplatform.kotlite.stdlib.regex.RegexClass

class RegexLibModule : AbstractRegexLibModule() {
    override val classes: List<ProvidedClassDefinition> = listOf(RegexClass.clazz)
}
Null values

In normal situations, a Kotlite null value is mapped to a NullValue before passing to the delegation calls. If the delegated function requires a real null value to function correctly, for example, setOfNotNull() or filterNotNull, it is regarded as null-aware.

In this case, add a nullaware modifier to these functions in the Kotlin header file, then the generated code would map NullValue to null. For example:

/stdlib/src/kotlinheader/Collections.kt
nullaware fun <T : Any> Iterable<T?>.filterNotNull(): List<T>
nullaware fun <T : Any> setOfNotNull(vararg elements: T?): Set<T>

Delegations to equals(), hashCode(), toString() of Kotlin values

For security reasons, they are not delegated by default. An explicit delegation declaration is required.

For manual approach, below is an example to delegate CustomClass.toString().

val env = ExecutionEnvironment().apply {
    registerClass(CustomClass.clazz)
    registerFunction(CustomFunctionDefinition(
        position = SourcePosition.NONE,
        receiverType = "CustomClass",
        functionName = "toString",
        returnType = "String",
        parameterTypes = emptyList(),
        executable = { interpreter, receiver, args, typeArgs ->
            StringValue((receiver as DelegatedValue<*>).value.toString(), interpreter.symbolTable())
        }
    ))
}

For delegation approach, declare in the Kotlin header file. Below is an example to delegate KInstant.toString().

/stdlib/src/kotlinheader/KDateTime.kt
fun KInstant.toString(): String

Distribution

Kotlite does not provide a way to distribute or host libraries. Putting the source code in GitHub and creating an awesome-kotlite repository might be an option.

Generating AST Diagrams

It is possible to generate mermaid code from Kotlite codes to render an AST diagram.

Below is an example.

val mermaidCode = kotliteAstNodeMermaidDiagram("""
    val cache = mutableMapOf<Int, Long>()
    fun fib(i: Int): Long {
        if (i < 0) throw Exception("Invalid i: ${'$'}i")
        if (i <= 1) return i.toLong()
        if (i in cache) {
            return cache[i]!!
        }
        return (fib(i - 2) + fib(i - 1)).also {
            cache[i] = it
        }
    }
    val a = fib(19) // 4181L
""".trimIndent())
println(mermaidCode, MermaidFlowchartDirection.LeftToRight)

For the above code snippet, after passing to mermaid, the generated diagram looks like this.

Diagram

Advanced Usage

Tool Structure

There are several essential tools in Kotlite. The execution directions are roughly presented in this diagram.

Diagram
Code Generator generates Kotlin codes with optionally debug information. It is mainly for debug purpose.

The data directions are as follows:

Diagram

All the tool classes are marked as open. A developer may feel free to extend the tools to create new features.

AST Nodes

The Parser generates Abstract Syntax Tree (AST) nodes. The functions of the parser correspond to each syntax defined in the Kotlin grammar. The function name is the grammar name.

For example, calling Parser.script() parses the code according to the script definition in the Kotlin grammar, and Parser.type() parses the code according to the type syntax.

Below Kotlin code parses a type written in String to AST nodes that can be used by the Semantic Analyzer and other tools.

val simpleTypeNode: ASTNode = Parser(Lexer("(anything)", "Double")).type()

val complexTypeNode: ASTNode = Parser(Lexer("(anything)", "Map<String, MutableList<Pair<Int, Double>>>")).type()

val genericTypeNode: ASTNode = Parser(Lexer("(anything)", "Map<K, V>")).type()

val functionTypeNode: ASTNode = Parser(Lexer("(anything)", "Int.(T) -> Unit")).type()

Below Kotlin code parses an expression written in String to AST nodes that can be used by the Semantic Analyzer and other tools.

val expressionNode: ASTNode = Parser(Lexer("(anything)", "(1 + 2 * 3) / 4")).expression()

Pass it to the Semantic Analyzer and Interpreter and execute manually.

val executionEnvironment = ExecutionEnvironment()
SemanticAnalyzer(
    rootNode = expressionNode,
    executionEnvironment = executionEnvironment,
).analyze()
val result = Interpreter(
    rootNode = expressionNode,
    executionEnvironment = executionEnvironment,
).eval() as IntValue
val intResult: Int = result.value // 1

The Standard Library

At this moment, the Standard Library consists of following Kotlin/Common standard library modules:

  • kotlin

  • kotlin.collections

  • kotlin.io

  • kotlin.math

  • kotlin.ranges

  • kotlin.text

and the following external libraries:

Currently, not all of their functions and properties are imported, but it is planned to support all of them, as long as the inclusion does not bring security issues.

The standard library will be expanded as well. Regex matchers, encoding, hashing and crypto libraries are on the short-term goal list.

But file I/O and networking will not be available in the standard library due to potential security issues. Users who need them can implement a delegated library module.

Redirecting the stdout pipe

It is possible to redirect the stdout stream of the embedded script environment to somewhere else, for example, a StringBuilder.

If IOLibModule is installed manually, its member function outputToConsole can be overridden.

val console = StringBuilder()
val env = ExecutionEnvironment().apply {
    install(object : IOLibModule() {
        override fun outputToConsole(output: String) {
            console.append(output)
        }
    })
}

If AllStdLibModules is installed instead, it accepts an optional constructor lambda parameter outputToConsoleFunction.

val console = StringBuilder()
val env = ExecutionEnvironment().apply {
    install(AllStdLibModules(outputToConsoleFunction = {
        console.append(it)
    }))
}

Known Issues or Limitations

There are some known issues that may not be tackled in short-term. They properly would be addressed in a later time, and might be improved bit by bit before fully addressed.

  • In a JVM with default JVM arguments, the depth of recursion calls only support up to about 140. Beyond that, "StackOverflowError" would be thrown.

  • Deep recursion calls use lots of memory and run slower

The Kotlite Language

Language

Kotlite parser implementation mostly conforms to the official Kotlin 1.9 documentation. Thus, the supported syntax and precedence resolutions are supposed to be equivalent to Kotlin 1.9.

Differences from Kotlin

Kotlin 1.9 Kotlite Script Kotlite API

Basic Data Types

Byte

✓

Short

✕

Int

✓

Long

✓

Float

✕

Double

✓

Unsigned Numbers

✕

Boolean

✓

Char

✓

String

✓

Array

Not supported except ByteArray. List is a replacement.

Pair

✓

Triple

✕

Throwable

✓

Unit

✓

Literal Constants

Decimals

✓

Long - L

✓

Hex - 0x

✕

Binary - 0b

✕

e notation (e.g. 1.2e10)

✕

_ in numbers

✕

Character escapes (\t, \b, \n, \r, \', \", \\, \$)

✓

Unicode literal (e.g. \u0000)

✓

UTF-16 surrogate pair characters in String literals

✓

Multiline Strings (""")

✓

String Templates ($)

✓

Nested String Templates (e.g. "is ${if (isEnabled) "at ${location.describe()}" else "N/A"}"}")

✓

Syntax

Using spaces and symbols in identifiers (e.g. variable/function names)

✕

Single-line comment (//)

✓

Block comments (/* …​ */)

✓

Nested block comments

✕

Extra new line characters within an expression

✓

Operators

Bitwise Operations (shl, shr, ushr, and, or, xor, inv)

✕

Boolean Logic (&&, ||, !)

✓

Arithmetics (+, -, *, /, %)

✓

Comparisons (<, >, ⇐, >=)

✓

Equality (==, !=)

✓

Reference Equality (===, !==)

✕

Type Checks (is, !is)

✓ (with difference)

Besides the root type, Kotlite checks whether all the type arguments are assignable to the subject’s one as well.

Kotlin does not check.

Type Casts (as, as?)

In operators (in, !in)

✓

To operator (to)

✓

Spread operator (*)

✕

Control Flow

If expressions

✓

When expressions with optional val and condition variances

✓ (with difference)

Kotlite always requires an else block.

Kotlin does not require when it is not necessary.

For loops

✓

While loops

✓

Do-while loops

✓

Break and Continue

✓

Normal Returns

✓

Labelling loops

✕

Automatic Labels for loops

✕

Automatic Labels for lambdas

✕

Manually labelling lambdas

✓

Break and Continue Labels

✕

Return to Labels

✓

Return to functions outside enclosing inline functions

✕

Throw exceptions

✓

Try expressions

✓

Try-catch-finally

✓

Catch exceptions which are thrown outside interpreter scope

✓

Properties

val/var with optional initial values

✓

Shadow variables

✓

Custom getters and setters

✕

✓

Backing fields for custom getters and setters

✕

const, lateinit modifiers

✕

Delegation (by keyword)

✕

Destructuring declarations

✕

Functions, Infix and Operator Functions

Normal functions

✓

Local functions

✓

Value parameters with default expression

✓

Named arguments

✓

Single-expression functions (e.g. fun f() = 10)

✓

Variable number of arguments (vararg modifier)

✓ (with difference)

In Kotlin, vararg argument is provided as a type of Array<T>.

In Kotlite, it is provided as List<T>.

Overloading functions

✓

Infix functions

✓

Infix calls

✓

Tail recursive functions (tailrec fun)

✕

Inline functions

✕

Overloading unary operators (, -, !, +, --)

✕

Overloading arithmetic binary operators (+, -, *, /, %)

✓

Overloading range operators (.., ..<)

✓

Overloading "in" operators (in, !in)

✓

Overloading indexed access operators ([], []=)

✓

Overloading invoke operators (())

✕

Overloading augmented assignments (+=, -=, *=, /=, %=)

✓

Overloading equality operators (==, !=)

✓

Overloading comparison operators (>, <, >=, ⇐)

✓

Suspending functions

✕

Packages and Imports

✕

Class Foundations

Primary constructor with optional val/var declarations

✓

Secondary constructors

✕

(Multiple) init blocks

✓

Member properties

✓

Member properties with custom getters and setters

✓

Backing fields of member properties with custom getters and setters

✕

Member functions

✓

Overloading member functions

✓

Visibility modifiers (public/private/protected/internal)

✕

Reference to other classes that are declared after this class

✕

Store companion object references into a field

✕

Class Inheritance

Passing values and type arguments to super class constructors

✓

Inheriting members from super classes and interfaces

✓

open modifier

✓

final modifier

✕

Overriding functions

✓ (with difference)

In Kotlin, default values and names of parameters of open functions cannot be overridden.

In Kotlite, it is possible.

In the future, Kotlite may follow Kotlin.

Overriding properties

✓

Implicit this

✓

super keyword

✓

Calling super functions

✓

Calling super properties

✓

Abstract functions

✓

Abstract properties

✕

Delegations

✕

Overriding functions from the "Any" class

✓

this expression with diamond

✕

super expression with diamond

✕

Class Variations

Nested classes

✕

Inner classes

✕

Abstract classes

✓

Sealed classes

✕

Enum classes

Partial

In Kotlite, only optional primary constructor with property declarations is supported. Other form of member declarations is not supported.

For example, the following is supported:

enum class MyEnum(val value: Int, val label: String) {
    A(3, "aaa"), B(5, "bb")
}

enum class Enum2 {
    A, B, C
}

Data classes

✕

Value classes

✕

Object classes

✕

Companion objects

Only available for extension functions and properties

Annotation classes

✕

Anonymous classes

✕

Interfaces

Abstract functions

✓

Functions with body

✕

Abstract properties

✕

(Multiple) interfaces inheritance

✓

Functional interfaces (fun interface)

✕

Sealed interfaces

✕

Extensions

Extension functions

✓

Extension operator functions

✓

Extension properties

✕

✓

Nullable receiver extensions

✓

Companion object extensions

✓

Generic type parameter as the receiver of extension functions (e.g. fun <T: Any> T.f())

✓

Extension functions as class members

✓

Resolving calls to extension functions of super classes/interfaces

✓

Generics

Type parameters in classes

✓

Type parameters in interfaces

✓

Type parameters in non-class functions

✓

Type parameters in (generic) class member functions

✓

Type parameters in extension functions

✓

Nested generic types

✓

Use type parameter as receiver of extension functions

✕

in, out type projections

✕

Star projection (<*>)

✓

Upper bounds of type parameters (e.g. T : Base)

✓

Recursive upper bounds of type parameters (e.g. T : Comparable<T>)

✓

Definitely non-nullable types (e.g. T & Any)

✕

where generic constraints

✕

Type erasure

Different

In Kotlin, type argument is not preserved.

In Kotlite, it is behaved as if type argument is erased, but it is preserved in runtime.

Unchecked casts

✓

Underscore as type arguments

✕

Reified type parameters

No as there is no type erasure

Type Alias

✕

Null Safety

Nullable types (e.g. String?)

✓

Non-nullable types (e.g. String)

✓

Safe call operator (?.)

✓

Elvis operator (?:)

✓

NPE operator (!!)

✓

Safe casts (as?)

✓

Lambdas and Higher-order Functions

Lambda expressions

✓

Anonymous functions

✕

Returning and storing lambda literals

✓

Passing trailing lambdas to functions

✓

Implicit single parameter it

✓

Underscore as unused variable names

✓

Destructuring value arguments in lambdas

✕

Accessing variables and functions declared in the enclosing closures

✓

Nested lambdas

✓

Labelling lambdas

✓

Function types with receiver in function value parameters (e.g. fun f(g: Int.() → Unit))

✓

Function literials with receiver (e.g. val f: Int.() → Unit)

✕

Function reference (::)

✕

Checking Before Execution

Type checking

✓

Checking of non-exist variables, functions or classes

✓

Checking of illegal writes to read-only properties

✓

Checking of ambiguous function calls

✓

Checking of type arguments not conforming to upper bound conditions

✓

Detect incompatible types on is and as operators

✕

Type Inference

Types of property declarations (val/var)

✓

Return types of if and when expressions

✓

Return types of single-expression functions

✓

Infer lambda vaule parameter types

✓

Infer lambda return types

✓

Type arguments of generic function calls

✓

Type arguments of generic class constructors

✓

Receiver of generic extension functions

✓

Infer nested types recursively

✓

Cyclic type inference error detection

✓

Identify a nullable type is non-nullable after asserting it is non-null

✕

Identify a super type is a subtype after asserting it is a subtype

✕

Unwrap types of unnecessary safe call operator (?.)

✕

Annotations

✕

Reflection

✕

Coroutines

✕

Asynchronous Programming

✕

Interoperability with Java and other languages

✕

Runtime Behaviour Differences

Code Kotlin 1.9 Kotlite
Generics with as? operator
open class A<T> {
    fun <X> cast(value: X): T? = value as? T
}
class B : A<String>()
class C : A<Int>()
val x = B()
val y = C()
val a = x.cast("abc")
val b = x.cast(123)
val c = y.cast("abc")
val d = y.cast(123)
val e = y.cast(null)
println("$a $b $c $d $e")

Throws exception:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

Output:

abc null null 123 null
Generics with as? operator
open class A<T> {
    fun <X> cast(value: X): X? = value as? T as? X
}
class B : A<String>()
class C : A<Int>()
val x = B()
val y = C()
val a = x.cast("abc")
val b = x.cast(123)
val c = y.cast("abc")
val d = y.cast(123)
val e = y.cast(null)
println("$a $b $c $d $e")

Output:

abc 123 abc 123 null

Output:

abc null null 123 null
Property resolutions in local classes
fun main() {
    var a: Int = -10
    class MyCls {
        var a: Int = 1
        var b: Int
            get() = a
            set(value) {
                a = value
            }
    }
    val o: MyCls = MyCls()
    val x: Int = o.a
    o.b = 20
    val y: Int = o.a
    o.b = 6
    val z: Int = o.a
    println("a = $a; z = $z")
}

main()

Output:

a = 6; z = 1

Output:

a = -10; z = 6

Intended Differences

In Kotlin, member functions always have a higher priority than extension functions.

Currently, since the only way to provide custom class functions in Kotlite is to provide extension functions, extension functions with below signatures are treated as special functions and have a higher priority than member functions. Return types are not in consideration in the process of identifying special functions.

fun equals(Any?)
fun hashCode()
fun toString()

Built-in and Standard Library APIs

Built-in

Types

Any

open class Any

Comparable

interface Comparable<T>

Throwable

open class Throwable constructor(message: String? = null, cause: Throwable? = null)

Int

class Int : Comparable<Int>

Double

class Double : Comparable<Double>

Long

class Long : Comparable<Long>

Boolean

class Boolean : Comparable<Boolean>

String

class String : Comparable<String>

Char

class Char : Comparable<Char>

Byte

class Byte

Unit

class Unit

Nothing

class Nothing

Function

class Function

Class

class Class<T : Any>

Pair

class Pair<A, B> constructor(first: A, second: B)

Exception

open class Exception constructor(message: String? = null, cause: Throwable? = null)

NullPointerException

class NullPointerException constructor(message: String? = null, cause: Throwable? = null)

TypeCastException

class TypeCastException constructor(valueType: String, targetType: String)

Iterator

interface Iterator<T>

Iterable

interface Iterable<T>

PrimitiveIterator

interface PrimitiveIterator<T> : Iterator<T>

PrimitiveIterable

interface PrimitiveIterable<T> : Iterable<T>

Collection

interface Collection<T> : Iterable<T>

List

class List<T> : Collection<T>
Extension Properties
val <A, B> Pair<A, B>.first: A get()
val <A, B> Pair<A, B>.second: B get()
val Throwable.message: String? get()
val Throwable.cause: Throwable? get()
val Throwable.name: String get()
Extension Functions
fun Throwable.stackTraceToString(): String
operator fun <T> Iterator<T>.hasNext(): Boolean
operator fun <T> Iterator<T>.next(): T
fun <T> Iterable<T>.iterator(): Iterator<T>
operator fun <T> PrimitiveIterator<T>.hasNext(): Boolean
operator fun <T> PrimitiveIterator<T>.next(): T
fun <T> PrimitiveIterable<T>.iterator(): PrimitiveIterator<T>

Core

Global Functions
fun <R> run(block: () -> R): R
fun <T, R> with(receiver: T, block: T.() -> R): R
fun repeat(times: Int, action: (Int) -> Unit): Unit
fun TODO(): Nothing
fun check(value: Boolean): Unit
fun check(value: Boolean, lazyMessage: () -> Any): Unit
fun <T : Any> checkNotNull(value: T?): T
fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any): T
fun require(value: Boolean): Unit
fun require(value: Boolean, lazyMessage: () -> Any): Unit
fun <T : Any> requireNotNull(value: T?): T
fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any): T
Extension Functions
fun <T> T.also(block: (T) -> Unit): T
fun <T> T.apply(block: T.() -> Unit): T
fun <T, R> T.let(block: (T) -> R): R
fun <T, R> T.run(block: T.() -> R): R
fun Double.isFinite(): Boolean
fun Double.isInfinite(): Boolean
fun Double.isNaN(): Boolean
fun Int.toLong(): Long
fun Int.toDouble(): Double
fun Long.toInt(): Int
fun Long.toDouble(): Double
fun Double.toInt(): Int
fun Double.toLong(): Long
fun <T> Pair<T, T>.toList(): List<T>
fun <T> T.takeIf(predicate: (T) -> Boolean): T?
fun <T> T.takeUnless(predicate: (T) -> Boolean): T?

IO

Global Functions
fun println(): Unit
fun println(message: Any?): Unit
fun print(message: Any?): Unit

Collections

Types

MutableCollection

interface MutableCollection<T> : Collection<T>

MutableList

class MutableList<T> : MutableCollection<T>

Map

class Map<K, V>

MutableMap

class MutableMap<K, V>

MapEntry

class MapEntry<K, V>

Set

class Set<T> : Collection<T>

MutableSet

class MutableSet<T> : MutableCollection<T>
Extension Properties
val <T> List<T>.size: Int get()
val <T> List<T>.lastIndex: Int get()
val <K, V> Map<K, V>.size: Int get()
val <K, V> Map<K, V>.keys: Collection<K> get()
val <K, V> Map<K, V>.values: Collection<V> get()
val <K, V> MapEntry<K, V>.key: K get()
val <K, V> MapEntry<K, V>.value: V get()
val <T> Set<T>.size: Int get()
Global Functions
fun <T> listOf(vararg elements: T): List<T>
fun <T> mutableListOf(vararg elements: T): MutableList<T>
fun <T : Any> listOfNotNull(vararg elements: T?): List<T>
fun <T> List(size: Int, init: (Int) -> T): List<T>
fun <T> MutableList(size: Int, init: (Int) -> T): MutableList<T>
fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V>
fun <K, V> mutableMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V>
fun <T> mutableSetOf(vararg elements: T): MutableSet<T>
fun <T> setOf(vararg elements: T): Set<T>
fun <T : Any> setOfNotNull(vararg elements: T?): Set<T>
Extension Functions
fun <T> MutableCollection<T>.add(element: T): Boolean
fun <T> MutableCollection<T>.addAll(elements: Iterable<T>): Boolean
fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean
fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean
fun <T> List<T>.asReversed(): List<T>
fun <T : Comparable<T>> List<T?>.binarySearch(element: T?, fromIndex: Int = 0, toIndex: Int = size): Int
fun <T> List<T>.binarySearch(fromIndex: Int = 0, toIndex: Int = size, comparison: (T) -> Int): Int
fun <T, K : Comparable<K>> List<T>.binarySearchBy(key: K?, fromIndex: Int = 0, toIndex: Int = size, selector: (T) -> K?): Int
fun <T, R> Iterable<T>.chunked(size: Int, transform: (List<T>) -> R): List<R>
operator fun <T> Iterable<T>.contains(element: T): Boolean
fun <T> List<T>.containsAll(elements: List<T>): Boolean
fun <T> MutableCollection<T>.clear(): Unit
fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int
fun <T> Iterable<T>.count(): Int
fun <T> Iterable<T>.distinct(): List<T>
fun <T, K> Iterable<T>.distinctBy(selector: (T) -> K): List<T>
fun <T> Iterable<T>.drop(n: Int): List<T>
fun <T> List<T>.dropLast(n: Int): List<T>
fun <T> List<T>.dropLastWhile(predicate: (T) -> Boolean): List<T>
fun <T> Iterable<T>.dropWhile(predicate: (T) -> Boolean): List<T>
fun <T> Iterable<T>.elementAt(index: Int): T
fun <T> Iterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T
fun <T> Iterable<T>.elementAtOrNull(index: Int): T?
fun <T> MutableList<T>.fill(value: T): Unit
fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T>
fun <T> Iterable<T>.filterIndexed(predicate: (Int, T) -> Boolean): List<T>
fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T>
fun <T : Any> Iterable<T?>.filterNotNull(): List<T>
fun <T> Iterable<T>.find(predicate: (T) -> Boolean): T?
fun <T> Iterable<T>.findLast(predicate: (T) -> Boolean): T?
fun <T> Iterable<T>.first(): T
fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T
fun <T, R : Any> Iterable<T>.firstNotNullOf(transform: (T) -> R?): R
fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R?
fun <T> Iterable<T>.firstOrNull(): T?
fun <T> Iterable<T>.firstOrNull(predicate: (T) -> Boolean): T?
fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
fun <T, R> Iterable<T>.flatMapIndexed(transform: (Int, T) -> Iterable<R>): List<R>
fun <T, R> Iterable<T>.fold(initial: R, operation: (R, T) -> R): R
fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (Int, R, T) -> R): R
fun <T, R> List<T>.foldRight(initial: R, operation: (T, R) -> R): R
fun <T, R> List<T>.foldRightIndexed(initial: R, operation: (Int, T, R) -> R): R
fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit
fun <T> Iterable<T>.forEachIndexed(action: (Int, T) -> Unit): Unit
operator fun <T> List<T>.get(index: Int): T
fun <T> List<T>.getOrElse(index: Int, defaultValue: (Int) -> T): T
fun <T> List<T>.getOrNull(index: Int): T?
fun <T> Iterable<T>.indexOf(element: T): Int
fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int
fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int
fun <T> List<T>.isEmpty(): Boolean
fun <T> List<T>.isNotEmpty(): Boolean
fun <T> List<T>?.isNullOrEmpty(): Boolean
fun <T> Iterable<T>.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -(1), truncated: String = "...", transform: (T) -> String = null): String
fun <T> Iterable<T>.last(): T
fun <T> Iterable<T>.last(predicate: (T) -> Boolean): T
fun <T> Iterable<T>.lastIndexOf(element: T): Int
fun <T> Iterable<T>.lastOrNull(): T?
fun <T> Iterable<T>.lastOrNull(predicate: (T) -> Boolean): T?
fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R>
fun <T, R> Iterable<T>.mapIndexed(transform: (Int, T) -> R): List<R>
fun <T, R : Any> Iterable<T>.mapIndexedNotNull(transform: (Int, T) -> R?): List<R>
fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R>
fun <T : Comparable<T>> Iterable<T>.max(): T
fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T
fun <T, R : Comparable<R>> Iterable<T>.maxByOrNull(selector: (T) -> R): T?
fun <T, R : Comparable<R>> Iterable<T>.maxOf(selector: (T) -> R): R
fun <T, R : Comparable<R>> Iterable<T>.maxOfOrNull(selector: (T) -> R): R?
fun <T : Comparable<T>> Iterable<T>.maxOrNull(): T?
fun <T : Comparable<T>> Iterable<T>.min(): T
fun <T, R : Comparable<R>> Iterable<T>.minBy(selector: (T) -> R): T
fun <T, R : Comparable<R>> Iterable<T>.minByOrNull(selector: (T) -> R): T?
fun <T, R : Comparable<R>> Iterable<T>.minOf(selector: (T) -> R): R
fun <T, R : Comparable<R>> Iterable<T>.minOfOrNull(selector: (T) -> R): R?
fun <T : Comparable<T>> Iterable<T>.minOrNull(): T?
operator fun <T> Iterable<T>.minus(element: T): List<T>
operator fun <T> Iterable<T>.minus(elements: Iterable<T>): List<T>
operator fun <T> MutableCollection<T>.minusAssign(element: T): Unit
operator fun <T> MutableCollection<T>.minusAssign(elements: Iterable<T>): Unit
fun <T> Iterable<T>.minusElement(element: T): List<T>
fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean
fun <T> Iterable<T>.none(): Boolean
fun <T, C : Iterable<T>> C.onEach(action: (T) -> Unit): C
fun <T> List<T>.onEachIndexed(action: (Int, T) -> Unit): List<T>
fun <T> List<T>?.orEmpty(): List<T>
fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>>
operator fun <T> Iterable<T>.plus(element: T): List<T>
operator fun <T> Iterable<T>.plus(elements: List<T>): List<T>
operator fun <T> MutableCollection<T>.plusAssign(element: T): Unit
operator fun <T> MutableCollection<T>.plusAssign(elements: Iterable<T>): Unit
fun <T> Iterable<T>.plusElement(element: T): List<T>
fun <T> List<T>.random(): T
fun <T> List<T>.randomOrNull(): T?
fun <T> MutableCollection<T>.remove(element: T): Boolean
fun <T> MutableCollection<T>.removeAll(elements: Collection<T>): Boolean
fun <T> MutableList<T>.removeAll(predicate: (T) -> Boolean): Boolean
fun <T> MutableList<T>.removeAt(index: Int): T
fun <T> MutableList<T>.removeFirst(): T
fun <T> MutableList<T>.removeFirstOrNull(): T?
fun <T> MutableList<T>.removeLast(): T
fun <T> MutableList<T>.removeLastOrNull(): T?
fun <T> MutableCollection<T>.retainAll(elements: Collection<T>): Boolean
fun <T> MutableList<T>.retainAll(predicate: (T) -> Boolean): Boolean
fun <T> Iterable<T>.reversed(): List<T>
fun <T, R> Iterable<T>.scan(initial: R, operation: (R, T) -> R): List<R>
fun <T, R> Iterable<T>.scanIndexed(initial: R, operation: (Int, R, T) -> R): List<R>
operator fun <T> MutableList<T>.set(index: Int, element: T): T
fun <T> MutableList<T>.shuffle(): Unit
fun <T> Iterable<T>.shuffled(): List<T>
fun <T> Iterable<T>.single(): T
fun <T> Iterable<T>.single(predicate: (T) -> Boolean): T
fun <T> Iterable<T>.singleOrNull(): T?
fun <T> Iterable<T>.singleOrNull(predicate: (T) -> Boolean): T?
fun <T : Comparable<T>> MutableList<T>.sort(): Unit
fun <T, R : Comparable<R>> MutableList<T>.sortBy(selector: (T) -> R?): Unit
fun <T, R : Comparable<R>> MutableList<T>.sortByDescending(selector: (T) -> R?): Unit
fun <T : Comparable<T>> MutableList<T>.sortDescending(): Unit
fun <T : Comparable<T>> Iterable<T>.sorted(): List<T>
fun <T, R : Comparable<R>> Iterable<T>.sortedBy(selector: (T) -> R?): List<T>
fun <T, R : Comparable<R>> Iterable<T>.sortedByDescending(selector: (T) -> R?): List<T>
fun <T : Comparable<T>> Iterable<T>.sortedDescending(): List<T>
fun <T> List<T>.subList(fromIndex: Int, toIndex: Int): List<T>
fun <T> Iterable<T>.take(n: Int): List<T>
fun <T> List<T>.takeLast(n: Int): List<T>
fun <T> List<T>.takeLastWhile(predicate: (T) -> Boolean): List<T>
fun <T> Iterable<T>.takeWhile(predicate: (T) -> Boolean): List<T>
fun <T> Iterable<T>.toList(): List<T>
fun <T> Iterable<T>.toMutableList(): MutableList<T>
fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>>
fun <T, R> Iterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List<T>) -> R): List<R>
infix fun <T, R> Iterable<T>.zip(other: Iterable<R>): List<Pair<T, R>>
fun <T, R, V> Iterable<T>.zip(other: Iterable<R>, transform: (T, R) -> V): List<V>
operator fun <K, V> Map<K, V>.contains(key: K): Boolean
fun <K> Map<K, *>.containsKey(key: K): Boolean
fun <K, V> Map<K, V>.containsValue(value: V): Boolean
operator fun <K, V> Map<K, V>.iterator(): Iterator<MapEntry<K, V>>
fun <K, V> Map<K, V>.all(predicate: (MapEntry<K, V>) -> Boolean): Boolean
fun <K, V> Map<K, V>.any(): Boolean
fun <K, V> Map<K, V>.any(predicate: (MapEntry<K, V>) -> Boolean): Boolean
fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>
fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K): Map<K, T>
fun <K, V> Iterable<K>.associateBy(valueSelector: (K) -> V): Map<K, V>
fun <K, V> Iterable<K>.associateWith(valueSelector: (K) -> V): Map<K, V>
fun <K, V> MutableMap<K, V>.clear(): Unit
fun <K, V> Map<K, V>.count(): Int
fun <K, V> Map<K, V>.count(predicate: (MapEntry<K, V>) -> Boolean): Int
fun <K, V> Map<K, V>.filter(predicate: (MapEntry<K, V>) -> Boolean): Map<K, V>
fun <K, V> Map<K, V>.filterKeys(predicate: (K) -> Boolean): Map<K, V>
fun <K, V> Map<K, V>.filterNot(predicate: (MapEntry<K, V>) -> Boolean): Map<K, V>
fun <K, V> Map<K, V>.filterValues(predicate: (V) -> Boolean): Map<K, V>
fun <K, V, R : Any> Map<K, V>.firstNotNullOf(transform: (MapEntry<K, V>) -> R?): R
fun <K, V, R : Any> Map<K, V>.firstNotNullOfOrNull(transform: (MapEntry<K, V>) -> R?): R?
fun <K, V, R> Map<K, V>.flatMap(transform: (MapEntry<K, V>) -> Iterable<R>): List<R>
fun <K, V> Map<K, V>.forEach(action: (MapEntry<K, V>) -> Unit): Unit
operator fun <K, V> Map<K, V>.get(key: K): V?
fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V
fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V
fun <K, V> Map<K, V>.getValue(key: K): V
fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>
fun <T, K, V> Iterable<T>.groupBy(keySelector: (T) -> K, valueSelector: (T) -> V): Map<K, List<V>>
fun <K, V> Map<K, V>.isNotEmpty(): Boolean
fun <K, V> Map<K, V>?.isNullOrEmpty(): Boolean
fun <K, V, R> Map<K, V>.map(transform: (MapEntry<K, V>) -> R): List<R>
fun <K, V, R> Map<K, V>.mapKeys(transform: (MapEntry<K, V>) -> R): Map<R, V>
fun <K, V, R : Any> Map<K, V>.mapNotNull(transform: (MapEntry<K, V>) -> R?): List<R>
fun <K, V, R> Map<K, V>.mapValues(transform: (MapEntry<K, V>) -> R): Map<K, R>
fun <K, V, R : Comparable<R>> Map<K, V>.maxBy(selector: (MapEntry<K, V>) -> R): MapEntry<K, V>
fun <K, V, R : Comparable<R>> Map<K, V>.maxByOrNull(selector: (MapEntry<K, V>) -> R): MapEntry<K, V>?
fun <K, V, R : Comparable<R>> Map<K, V>.maxOf(selector: (MapEntry<K, V>) -> R): R
fun <K, V, R : Comparable<R>> Map<K, V>.maxOfOrNull(selector: (MapEntry<K, V>) -> R): R?
fun <K, V, R : Comparable<R>> Map<K, V>.minBy(selector: (MapEntry<K, V>) -> R): MapEntry<K, V>
fun <K, V, R : Comparable<R>> Map<K, V>.minByOrNull(selector: (MapEntry<K, V>) -> R): MapEntry<K, V>?
fun <K, V, R : Comparable<R>> Map<K, V>.minOf(selector: (MapEntry<K, V>) -> R): R
fun <K, V, R : Comparable<R>> Map<K, V>.minOfOrNull(selector: (MapEntry<K, V>) -> R): R?
operator fun <K, V> Map<K, V>.minus(key: K): Map<K, V>
operator fun <K, V> Map<K, V>.minus(keys: List<K>): Map<K, V>
operator fun <K, V> MutableMap<K, V>.minusAssign(key: K): Unit
operator fun <K, V> MutableMap<K, V>.minusAssign(keys: List<K>): Unit
fun <K, V> Map<K, V>.none(): Boolean
fun <K, V> Map<K, V>.none(predicate: (MapEntry<K, V>) -> Boolean): Boolean
fun <K, V, M : Map<K, V>> M.onEach(action: (MapEntry<K, V>) -> Unit): M
fun <K, V> Map<K, V>.onEachIndexed(action: (Int, MapEntry<K, V>) -> Unit): Map<K, V>
fun <K, V> MutableMap<K, V>.onEachIndexed(action: (Int, MapEntry<K, V>) -> Unit): MutableMap<K, V>
fun <K, V> Map<K, V>?.orEmpty(): Map<K, V>
operator fun <K, V> Map<K, V>.plus(pair: Pair<K, V>): Map<K, V>
operator fun <K, V> Map<K, V>.plus(pairs: List<Pair<K, V>>): Map<K, V>
operator fun <K, V> MutableMap<K, V>.plusAssign(pair: Pair<K, V>): Unit
operator fun <K, V> MutableMap<K, V>.plusAssign(pairs: List<Pair<K, V>>): Unit
fun <K, V> MutableMap<K, V>.put(key: K, value: V): V?
fun <K, V> MutableMap<K, V>.putAll(pairs: List<Pair<K, V>>): Unit
fun <K, V> MutableMap<K, V>.remove(key: K): V?
operator fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit
fun <K, V> Map<K, V>.toList(): List<Pair<K, V>>
fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V>
fun <K, V> Map<K, V>.toMap(): Map<K, V>
fun <K, V> Map<K, V>.toMutableMap(): MutableMap<K, V>
fun <K, V> Map<K, V>.withDefault(defaultValue: (K) -> V): Map<K, V>
fun <K, V> MutableMap<K, V>.withDefault(defaultValue: (K) -> V): MutableMap<K, V>
operator fun <T> Set<T>.contains(element: T): Boolean
fun <T> Set<T>.containsAll(elements: Collection<T>): Boolean
fun <T> Set<T>.isEmpty(): Boolean
operator fun <T> Set<T>.iterator(): Iterator<T>
infix fun <T> Iterable<T>.intersect(other: Iterable<T>): Set<T>
operator fun <T> Set<T>.minus(element: T): Set<T>
operator fun <T> Set<T>.minus(elements: Iterable<T>): Set<T>
fun <T> Set<T>.minusElement(element: T): Set<T>
fun <T> Set<T>?.orEmpty(): Set<T>
operator fun <T> Set<T>.plus(element: T): Set<T>
operator fun <T> Set<T>.plus(elements: Iterable<T>): Set<T>
fun <T> Set<T>.plusElement(element: T): Set<T>
infix fun <T> Iterable<T>.subtract(other: Iterable<T>): Set<T>
fun <T> Iterable<T>.toMutableSet(): MutableSet<T>
fun <T> Iterable<T>.toSet(): Set<T>
infix fun <T> Iterable<T>.union(other: Iterable<T>): Set<T>
fun <T> MutableSet<T>.add(element: T): Boolean
fun <T> MutableSet<T>.addAll(elements: Collection<T>): Boolean
fun <T> MutableSet<T>.clear(): Unit
fun <T> MutableSet<T>.remove(element: T): Boolean
fun <T> MutableSet<T>.removeAll(elements: Collection<T>): Boolean
fun <T> MutableSet<T>.retainAll(elements: Collection<T>): Boolean
fun <T> PrimitiveIterable<T>.all(predicate: (T) -> Boolean): Boolean
fun <T> PrimitiveIterable<T>.any(predicate: (T) -> Boolean): Boolean
fun <T, R> PrimitiveIterable<T>.chunked(size: Int, transform: (List<T>) -> R): List<R>
operator fun <T> PrimitiveIterable<T>.contains(element: T): Boolean
fun <T> PrimitiveIterable<T>.count(predicate: (T) -> Boolean): Int
fun <T> PrimitiveIterable<T>.count(): Int
fun <T> PrimitiveIterable<T>.distinct(): List<T>
fun <T, K> PrimitiveIterable<T>.distinctBy(selector: (T) -> K): List<T>
fun <T> PrimitiveIterable<T>.drop(n: Int): List<T>
fun <T> PrimitiveIterable<T>.dropWhile(predicate: (T) -> Boolean): List<T>
fun <T> PrimitiveIterable<T>.elementAt(index: Int): T
fun <T> PrimitiveIterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T
fun <T> PrimitiveIterable<T>.elementAtOrNull(index: Int): T?
fun <T> PrimitiveIterable<T>.filter(predicate: (T) -> Boolean): List<T>
fun <T> PrimitiveIterable<T>.filterIndexed(predicate: (Int, T) -> Boolean): List<T>
fun <T> PrimitiveIterable<T>.filterNot(predicate: (T) -> Boolean): List<T>
fun <T> PrimitiveIterable<T>.find(predicate: (T) -> Boolean): T?
fun <T> PrimitiveIterable<T>.findLast(predicate: (T) -> Boolean): T?
fun <T> PrimitiveIterable<T>.first(): T
fun <T> PrimitiveIterable<T>.first(predicate: (T) -> Boolean): T
fun <T, R : Any> PrimitiveIterable<T>.firstNotNullOf(transform: (T) -> R?): R
fun <T, R : Any> PrimitiveIterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R?
fun <T> PrimitiveIterable<T>.firstOrNull(): T?
fun <T> PrimitiveIterable<T>.firstOrNull(predicate: (T) -> Boolean): T?
fun <T, R> PrimitiveIterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>
fun <T, R> PrimitiveIterable<T>.flatMapIndexed(transform: (Int, T) -> Iterable<R>): List<R>
fun <T, R> PrimitiveIterable<T>.fold(initial: R, operation: (R, T) -> R): R
fun <T, R> PrimitiveIterable<T>.foldIndexed(initial: R, operation: (Int, R, T) -> R): R
fun <T> PrimitiveIterable<T>.forEach(action: (T) -> Unit): Unit
fun <T> PrimitiveIterable<T>.forEachIndexed(action: (Int, T) -> Unit): Unit
fun <T> PrimitiveIterable<T>.indexOf(element: T): Int
fun <T> PrimitiveIterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int
fun <T> PrimitiveIterable<T>.indexOfLast(predicate: (T) -> Boolean): Int
fun <T> PrimitiveIterable<T>.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -(1), truncated: String = "...", transform: (T) -> String = null): String
fun <T> PrimitiveIterable<T>.last(): T
fun <T> PrimitiveIterable<T>.last(predicate: (T) -> Boolean): T
fun <T> PrimitiveIterable<T>.lastIndexOf(element: T): Int
fun <T> PrimitiveIterable<T>.lastOrNull(): T?
fun <T> PrimitiveIterable<T>.lastOrNull(predicate: (T) -> Boolean): T?
fun <T, R> PrimitiveIterable<T>.map(transform: (T) -> R): List<R>
fun <T, R> PrimitiveIterable<T>.mapIndexed(transform: (Int, T) -> R): List<R>
fun <T, R : Any> PrimitiveIterable<T>.mapIndexedNotNull(transform: (Int, T) -> R?): List<R>
fun <T, R : Any> PrimitiveIterable<T>.mapNotNull(transform: (T) -> R?): List<R>
fun <T : Comparable<T>> PrimitiveIterable<T>.max(): T
fun <T, R : Comparable<R>> PrimitiveIterable<T>.maxBy(selector: (T) -> R): T
fun <T, R : Comparable<R>> PrimitiveIterable<T>.maxByOrNull(selector: (T) -> R): T?
fun <T, R : Comparable<R>> PrimitiveIterable<T>.maxOf(selector: (T) -> R): R
fun <T, R : Comparable<R>> PrimitiveIterable<T>.maxOfOrNull(selector: (T) -> R): R?
fun <T : Comparable<T>> PrimitiveIterable<T>.maxOrNull(): T?
fun <T : Comparable<T>> PrimitiveIterable<T>.min(): T
fun <T, R : Comparable<R>> PrimitiveIterable<T>.minBy(selector: (T) -> R): T
fun <T, R : Comparable<R>> PrimitiveIterable<T>.minByOrNull(selector: (T) -> R): T?
fun <T, R : Comparable<R>> PrimitiveIterable<T>.minOf(selector: (T) -> R): R
fun <T, R : Comparable<R>> PrimitiveIterable<T>.minOfOrNull(selector: (T) -> R): R?
fun <T : Comparable<T>> PrimitiveIterable<T>.minOrNull(): T?
operator fun <T> PrimitiveIterable<T>.minus(element: T): List<T>
operator fun <T> PrimitiveIterable<T>.minus(elements: PrimitiveIterable<T>): List<T>
fun <T> PrimitiveIterable<T>.minusElement(element: T): List<T>
fun <T> PrimitiveIterable<T>.none(predicate: (T) -> Boolean): Boolean
fun <T> PrimitiveIterable<T>.none(): Boolean
fun <T> PrimitiveIterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>>
operator fun <T> PrimitiveIterable<T>.plus(element: T): List<T>
operator fun <T> PrimitiveIterable<T>.plus(elements: List<T>): List<T>
fun <T> PrimitiveIterable<T>.plusElement(element: T): List<T>
fun <T> PrimitiveIterable<T>.reversed(): List<T>
fun <T, R> PrimitiveIterable<T>.scan(initial: R, operation: (R, T) -> R): List<R>
fun <T, R> PrimitiveIterable<T>.scanIndexed(initial: R, operation: (Int, R, T) -> R): List<R>
fun <T> PrimitiveIterable<T>.shuffled(): List<T>
fun <T> PrimitiveIterable<T>.single(): T
fun <T> PrimitiveIterable<T>.single(predicate: (T) -> Boolean): T
fun <T> PrimitiveIterable<T>.singleOrNull(): T?
fun <T> PrimitiveIterable<T>.singleOrNull(predicate: (T) -> Boolean): T?
fun <T : Comparable<T>> PrimitiveIterable<T>.sorted(): List<T>
fun <T, R : Comparable<R>> PrimitiveIterable<T>.sortedBy(selector: (T) -> R?): List<T>
fun <T, R : Comparable<R>> PrimitiveIterable<T>.sortedByDescending(selector: (T) -> R?): List<T>
fun <T : Comparable<T>> PrimitiveIterable<T>.sortedDescending(): List<T>
fun <T> PrimitiveIterable<T>.take(n: Int): List<T>
fun <T> PrimitiveIterable<T>.takeWhile(predicate: (T) -> Boolean): List<T>
fun <T> PrimitiveIterable<T>.toList(): List<T>
fun <T> PrimitiveIterable<T>.toMutableList(): MutableList<T>
fun <T, R> PrimitiveIterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List<T>) -> R): List<R>
infix fun <T, R> PrimitiveIterable<T>.zip(other: PrimitiveIterable<R>): List<Pair<T, R>>
fun <T, R, V> PrimitiveIterable<T>.zip(other: PrimitiveIterable<R>, transform: (T, R) -> V): List<V>
fun <T, K, V> PrimitiveIterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>
fun <T, K> PrimitiveIterable<T>.associateBy(keySelector: (T) -> K): Map<K, T>
fun <K, V> PrimitiveIterable<K>.associateBy(valueSelector: (K) -> V): Map<K, V>
fun <K, V> PrimitiveIterable<K>.associateWith(valueSelector: (K) -> V): Map<K, V>
fun <T, K> PrimitiveIterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>>
fun <T, K, V> PrimitiveIterable<T>.groupBy(keySelector: (T) -> K, valueSelector: (T) -> V): Map<K, List<V>>
infix fun <T> PrimitiveIterable<T>.intersect(other: PrimitiveIterable<T>): Set<T>
infix fun <T> PrimitiveIterable<T>.subtract(other: PrimitiveIterable<T>): Set<T>
fun <T> PrimitiveIterable<T>.toMutableSet(): MutableSet<T>
fun <T> PrimitiveIterable<T>.toSet(): Set<T>
infix fun <T> PrimitiveIterable<T>.union(other: PrimitiveIterable<T>): Set<T>

Text

Extension Properties
val String.length: Int get()
val String.lastIndex: Int get()
Extension Functions
fun String.all(predicate: (Char) -> Boolean): Boolean
fun String.any(predicate: (Char) -> Boolean): Boolean
fun String.commonPrefixWith(other: String, ignoreCase: Boolean = false): String
fun String.commonSuffixWith(other: String, ignoreCase: Boolean = false): String
fun String.compareTo(other: String, ignoreCase: Boolean = false): Int
fun String.contains(other: String, ignoreCase: Boolean = false): Boolean
fun String.contains(other: Char, ignoreCase: Boolean = false): Boolean
fun String.count(): Int
fun String.drop(n: Int): String
fun String.dropLast(n: Int): String
fun String.dropLastWhile(predicate: (Char) -> Boolean): String
fun String.dropWhile(predicate: (Char) -> Boolean): String
fun String.endsWith(suffix: String, ignoreCase: Boolean = false): Boolean
fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean
fun String.filter(predicate: (Char) -> Boolean): String
fun String.filterIndexed(predicate: (Int, Char) -> Boolean): String
fun String.filterNot(predicate: (Char) -> Boolean): String
fun String.first(): Char
fun String.firstOrNull(): Char?
fun String.forEach(action: (Char) -> Unit): Unit
fun String.forEachIndexed(action: (Int, Char) -> Unit): Unit
fun String.getOrElse(index: Int, defaultValue: (Int) -> Char): Char
fun String.getOrNull(index: Int): Char?
fun String.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int
fun String.indexOfFirst(predicate: (Char) -> Boolean): Int
fun String.indexOfLast(predicate: (Char) -> Boolean): Int
fun String.isBlank(): Boolean
fun String.isEmpty(): Boolean
fun String.isNotBlank(): Boolean
fun String.isNotEmpty(): Boolean
fun String?.isNullOrBlank(): Boolean
fun String?.isNullOrEmpty(): Boolean
fun String.last(): Char
fun String.lastIndexOf(string: String, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int
fun String.lastOrNull(): Char?
fun String.lowercase(): String
fun String.none(predicate: (Char) -> Boolean): Boolean
fun String?.orEmpty(): String
fun String.padEnd(length: Int, padChar: Char = ' '): String
fun String.padStart(length: Int, padChar: Char = ' '): String
fun String.prependIndent(indent: String = " "): String
fun String.random(): Char
fun String.randomOrNull(): Char?
fun String.removePrefix(prefix: String): String
fun String.removeRange(startIndex: Int, endIndex: Int): String
fun String.removeSuffix(suffix: String): String
fun String.removeSurrounding(prefix: String, suffix: String): String
fun String.repeat(n: Int): String
fun String.replace(oldValue: Char, newValue: Char, ignoreCase: Boolean = false): String
fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String
fun String.replaceAfter(delimiter: String, replacement: String, missingDelimiterValue: String = this): String
fun String.replaceAfterLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String
fun String.replaceBefore(delimiter: String, replacement: String, missingDelimiterValue: String = this): String
fun String.replaceBeforeLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String
fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean = false): String
fun String.replaceRange(startIndex: Int, endIndex: Int, replacement: String): String
fun String.reversed(): String
fun String.single(): Char
fun String.singleOrNull(): Char?
fun String.startsWith(prefix: String, ignoreCase: Boolean = false): Boolean
fun String.substring(startIndex: Int, endIndex: Int = length): String
fun String.substringAfter(delimiter: String, missingDelimiterValue: String = this): String
fun String.substringAfterLast(delimiter: String, missingDelimiterValue: String = this): String
fun String.substringBefore(delimiter: String, missingDelimiterValue: String = this): String
fun String.substringBeforeLast(delimiter: String, missingDelimiterValue: String = this): String
fun String.take(n: Int): String
fun String.takeLast(n: Int): String
fun String.takeLastWhile(predicate: (Char) -> Boolean): String
fun String.takeWhile(predicate: (Char) -> Boolean): String
fun String?.toBoolean(): Boolean
fun String.toBooleanStrictOrNull(): Boolean?
fun String.toDouble(): Double
fun String.toDoubleOrNull(): Double?
fun String.toInt(): Int
fun String.toInt(radix: Int): Int
fun String.toIntOrNull(): Int?
fun String.toIntOrNull(radix: Int): Int?
fun String.trim(): String
fun String.trimEnd(): String
fun String.trimStart(): String
fun String.uppercase(): String
fun Char.isDefined(): Boolean
fun Char.isDigit(): Boolean
fun Char.isHighSurrogate(): Boolean
fun Char.isISOControl(): Boolean
fun Char.isLetter(): Boolean
fun Char.isLetterOrDigit(): Boolean
fun Char.isLowerCase(): Boolean
fun Char.isLowSurrogate(): Boolean
fun Char.isSurrogate(): Boolean
fun Char.isUpperCase(): Boolean
fun Char.isWhitespace(): Boolean
fun Char.lowercase(): String
fun Char.lowercaseChar(): Char
fun Char.uppercase(): String
fun Char.uppercaseChar(): Char

Regex

Types

Regex

class Regex constructor(value: String)
Extension Functions
fun String.matches(regex: Regex): Boolean
fun String.replace(regex: Regex, replacement: String): String
fun String.replaceFirst(regex: Regex, replacement: String): String
fun String.toRegex(): Regex

Math

Global Properties
val E: Double
val PI: Double
Extension Properties
val Double.absoluteValue: Double get()
val Int.absoluteValue: Int get()
val Long.absoluteValue: Long get()
val Double.sign: Double get()
val Int.sign: Int get()
val Long.sign: Int get()
Global Functions
fun abs(x: Double): Double
fun abs(x: Int): Int
fun abs(x: Long): Long
fun acos(x: Double): Double
fun acosh(x: Double): Double
fun asin(x: Double): Double
fun asinh(x: Double): Double
fun atan(x: Double): Double
fun atan2(y: Double, x: Double): Double
fun atanh(x: Double): Double
fun cbrt(x: Double): Double
fun ceil(x: Double): Double
fun cos(x: Double): Double
fun cosh(x: Double): Double
fun exp(x: Double): Double
fun expm1(x: Double): Double
fun floor(x: Double): Double
fun hypot(x: Double, y: Double): Double
fun ln(x: Double): Double
fun ln1p(x: Double): Double
fun log(x: Double, base: Double): Double
fun log10(x: Double): Double
fun log2(x: Double): Double
fun max(a: Double, b: Double): Double
fun max(a: Int, b: Int): Int
fun max(a: Long, b: Long): Long
fun min(a: Double, b: Double): Double
fun min(a: Int, b: Int): Int
fun min(a: Long, b: Long): Long
fun round(x: Double): Double
fun sign(x: Double): Double
fun sin(x: Double): Double
fun sinh(x: Double): Double
fun sqrt(x: Double): Double
fun tan(x: Double): Double
fun tanh(x: Double): Double
fun truncate(x: Double): Double
Extension Functions
fun Double.nextDown(): Double
fun Double.nextTowards(to: Double): Double
fun Double.nextUp(): Double
fun Double.pow(x: Double): Double
fun Double.pow(n: Int): Double
fun Double.roundToInt(): Int
fun Double.roundToLong(): Long
fun Double.withSign(sign: Double): Double
fun Double.withSign(sign: Int): Double

Byte

Types

ByteArray

class ByteArray
Extension Properties
val ByteArray.lastIndex: Int get()
val ByteArray.size: Int get()
Global Functions
fun byteArrayOf(vararg elements: Byte): ByteArray
Extension Functions
fun Int.toByte(): Byte
fun Long.toByte(): Byte
fun Byte.toInt(): Int
fun Byte.toLong(): Long
fun Byte.toDouble(): Double
fun Byte.toChar(): Char
fun ByteArray.asList(): List<Byte>
fun ByteArray.average(): Double
infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean
fun ByteArray?.contentToString(): String
fun ByteArray.firstOrNull(predicate: (Byte) -> Boolean): Byte?
fun ByteArray?.contentHashCode(): Int
fun ByteArray.copyOf(): ByteArray
fun ByteArray.copyOf(newSize: Int): ByteArray
fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray
fun ByteArray.count(): Int
fun ByteArray.drop(n: Int): List<Byte>
fun ByteArray.dropLast(n: Int): List<Byte>
fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size): Unit
fun ByteArray.forEach(action: (Byte) -> Unit): Unit
fun ByteArray.forEachIndexed(action: (Int, Byte) -> Unit): Unit
fun ByteArray.first(): Byte
operator fun ByteArray.get(index: Int): Byte
operator fun ByteArray.iterator(): Iterator<Byte>
fun ByteArray.getOrElse(index: Int, defaultValue: (Int) -> Byte): Byte
fun ByteArray.getOrNull(index: Int): Byte?
fun ByteArray.indexOf(element: Byte): Int
fun ByteArray.indexOfFirst(predicate: (Byte) -> Boolean): Int
fun ByteArray.indexOfLast(predicate: (Byte) -> Boolean): Int
fun ByteArray.joinToString(separator: String = ", ", prefix: String = "", postfix: String = "", limit: Int = -(1), truncated: String = "...", transform: (Byte) -> String = null): String
fun ByteArray.last(): Byte
fun <R> ByteArray.map(transform: (Byte) -> R): List<R>
fun <R> ByteArray.mapIndexed(transform: (Int, Byte) -> R): List<R>
fun ByteArray.max(): Byte
fun ByteArray.min(): Byte
fun ByteArray.none(): Boolean
fun ByteArray.onEach(action: (Byte) -> Unit): ByteArray
fun ByteArray.onEachIndexed(action: (Int, Byte) -> Unit): ByteArray
operator fun ByteArray.plus(element: Byte): ByteArray
operator fun ByteArray.plus(elements: ByteArray): ByteArray
fun ByteArray.random(): Byte
fun ByteArray.randomOrNull(): Byte?
fun ByteArray.reverse(): Unit
fun ByteArray.reversed(): List<Byte>
fun ByteArray.reversedArray(): ByteArray
operator fun ByteArray.set(index: Int, value: Byte): Unit
fun ByteArray.single(): Byte
fun ByteArray.singleOrNull(): Byte?
fun ByteArray.sort(): Unit
fun ByteArray.sortDescending(): Unit
fun ByteArray.sorted(): List<Byte>
fun ByteArray.sortedArray(): ByteArray
fun ByteArray.sortedArrayDescending(): ByteArray
fun ByteArray.sortedDescending(): List<Byte>
fun ByteArray.sum(): Int
fun ByteArray.take(n: Int): List<Byte>
fun ByteArray.takeLast(n: Int): List<Byte>
fun Collection<Byte>.toByteArray(): ByteArray
fun ByteArray.toList(): List<Byte>
fun ByteArray.toSet(): Set<Byte>
fun ByteArray.decodeToString(startIndex: Int = 0, endIndex: Int = this.size, throwOnInvalidSequence: Boolean = false): String
fun String.encodeToByteArray(startIndex: Int = 0, endIndex: Int = this.length, throwOnInvalidSequence: Boolean = false): ByteArray

Range

Types

ClosedRange

interface ClosedRange<T : Comparable<T>>

OpenEndRange

interface OpenEndRange<T : Comparable<T>>

IntProgression

open class IntProgression : PrimitiveIterable<Int>

IntRange

class IntRange : ClosedRange<Int>, OpenEndRange<Int>

LongProgression

open class LongProgression : PrimitiveIterable<Long>

LongRange

class LongRange : ClosedRange<Long>, OpenEndRange<Long>
Extension Properties
val <T : Comparable<T>> ClosedRange<T>.start: T get()
val <T : Comparable<T>> ClosedRange<T>.endInclusive: T get()
val <T : Comparable<T>> OpenEndRange<T>.start: T get()
val <T : Comparable<T>> OpenEndRange<T>.endExclusive: T get()
val IntProgression.first: Int get()
val IntProgression.last: Int get()
val IntProgression.step: Int get()
val LongProgression.first: Long get()
val LongProgression.last: Long get()
val LongProgression.step: Long get()
Extension Functions
operator fun <T : Comparable<T>> ClosedRange<T>.contains(value: T): Boolean
fun <T : Comparable<T>> ClosedRange<T>.isEmpty(): Boolean
operator fun <T : Comparable<T>> OpenEndRange<T>.contains(value: T): Boolean
fun <T : Comparable<T>> OpenEndRange<T>.isEmpty(): Boolean
operator fun <T : Comparable<T>> T.rangeTo(that: T): ClosedRange<T>
operator fun <T : Comparable<T>> T.rangeUntil(that: T): OpenEndRange<T>
fun IntProgression.isEmpty(): Boolean
fun IntProgression.reversed(): IntProgression
infix fun IntProgression.step(step: Int): IntProgression
operator fun IntRange.contains(element: Int?): Boolean
fun IntRange.random(): Int
fun IntRange.randomOrNull(): Int?
infix fun Int.downTo(to: Byte): IntProgression
infix fun Int.downTo(to: Int): IntProgression
infix fun Int.downTo(to: Long): LongProgression
infix fun Int.until(to: Byte): IntRange
infix fun Int.until(to: Int): IntRange
infix fun Int.until(to: Long): LongRange
operator fun Int.rangeTo(that: Int): IntRange
operator fun Int.rangeUntil(that: Int): IntRange
fun LongProgression.isEmpty(): Boolean
fun LongProgression.reversed(): LongProgression
infix fun LongProgression.step(step: Long): LongProgression
operator fun LongRange.contains(element: Long?): Boolean
fun LongRange.random(): Long
fun LongRange.randomOrNull(): Long?
infix fun Long.downTo(to: Byte): LongProgression
infix fun Long.downTo(to: Int): LongProgression
infix fun Long.downTo(to: Long): LongProgression
infix fun Long.until(to: Byte): LongRange
infix fun Long.until(to: Int): LongRange
infix fun Long.until(to: Long): LongRange
operator fun Long.rangeTo(that: Long): LongRange
operator fun Long.rangeUntil(that: Long): LongRange

KDateTime

Types

KDateTimeFormattable

interface KDateTimeFormattable

KPointOfTime

class KPointOfTime : KDateTimeFormattable, Comparable<KPointOfTime>

KDateTimeFormat

class KDateTimeFormat constructor(pattern: String)

KDate

class KDate constructor(year: Int, month: Int, day: Int)

KDuration

class KDuration : KDateTimeFormattable, Comparable<KDuration>

KInstant

class KInstant constructor(timestampMs: Long) : KDateTimeFormattable

KZonedDateTime

class KZonedDateTime constructor(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int, millisecond: Int = 0, zoneOffset: KZoneOffset)

KZonedInstant

class KZonedInstant constructor(timestampMs: Long, zoneOffset: KZoneOffset) : KDateTimeFormattable

KZoneOffset

class KZoneOffset constructor(hours: Int, minutes: Int)
Extension Properties
val KZonedInstant.zoneOffset: KZoneOffset get()
val KZoneOffset.Companion.UTC: KZoneOffset get()
val KDuration.Companion.ZERO: KDuration get()
val KZonedDateTime.year: Int get()
val KZonedDateTime.month: Int get()
val KZonedDateTime.day: Int get()
val KZonedDateTime.hour: Int get()
val KZonedDateTime.minute: Int get()
val KZonedDateTime.second: Int get()
val KZonedDateTime.millisecond: Int get()
val KZonedDateTime.zoneOffset: KZoneOffset get()
val KDateTimeFormat.pattern: String get()
var KDateTimeFormat.weekDayNames: List<String> get() set()
val KDateTimeFormat.Companion.ISO8601_DATETIME: KDateTimeFormat get()
val KDateTimeFormat.Companion.FULL: KDateTimeFormat get()
val KDateTimeFormat.Companion.ISO8601_FORMATS: List<KDateTimeFormat> get()
val KDateTimeFormat.Companion.IOS_DATE_FORMATS: List<KDateTimeFormat> get()
val KDateTimeFormat.Companion.WEEKDAY_NAMES: List<String> get()
Extension Functions
operator fun KInstant.plus(duration: KDuration): KInstant
operator fun KInstant.minus(duration: KDuration): KInstant
infix fun KInstant.at(zoneOffset: KZoneOffset): KZonedInstant
fun KInstant.atZoneOffset(zoneOffset: KZoneOffset): KZonedInstant
fun KInstant.atLocalZoneOffset(): KZonedInstant
fun KInstant.Companion.now(): KInstant
fun KInstant.Companion.parseFrom(input: String, formats: List<KDateTimeFormat>): KInstant
fun KDateTimeFormattable.toMilliseconds(): Long
fun KDateTimeFormattable.hourPart(): Int
fun KDateTimeFormattable.minutePart(): Int
fun KDateTimeFormattable.secondPart(): Int
fun KDateTimeFormattable.millisecondPart(): Int
fun KDateTimeFormattable.format(pattern: String): String
fun KPointOfTime.toEpochMilliseconds(): Long
operator fun KPointOfTime.minus(other: KPointOfTime): KDuration
fun KPointOfTime.toIso8601String(): String
fun KPointOfTime.toIso8601StringWithMilliseconds(): String
operator fun KPointOfTime.compareTo(other: KPointOfTime): Int
operator fun KZonedInstant.plus(duration: KDuration): KZonedInstant
operator fun KZonedInstant.minus(duration: KDuration): KZonedInstant
fun KZonedInstant.startOfDay(): KZonedInstant
fun KZonedInstant.dropZoneOffset(): KInstant
fun KZonedInstant.Companion.nowAtLocalZoneOffset(): KZonedInstant
fun KZonedInstant.Companion.nowAtZoneOffset(zoneOffset: KZoneOffset): KZonedInstant
fun KZonedInstant.Companion.parseFrom(input: String, formats: List<KDateTimeFormat>): KZonedInstant
fun KZonedInstant.Companion.parseFromIso8601String(input: String): KZonedInstant
fun KZonedInstant.toKZonedDateTime(): KZonedDateTime
fun KZoneOffset.toMilliseconds(): Long
fun KZoneOffset.toDisplayString(): String
fun KZoneOffset.Companion.parseFrom(string: String): KZoneOffset
fun KZoneOffset.Companion.fromMilliseconds(millis: Long): KZoneOffset
fun KZoneOffset.Companion.local(): KZoneOffset
operator fun KDuration.plus(other: KDuration): KDuration
operator fun KDuration.minus(other: KDuration): KDuration
operator fun KDuration.compareTo(other: KDuration): Int
fun KDuration.toSeconds(): Long
fun KDuration.toMinutes(): Long
fun KDuration.toHours(): Long
fun KDuration.toDays(): Long
fun KDuration.toWeeks(): Long
fun KZonedDateTime.toKZonedInstant(): KZonedInstant
fun KZonedDateTime.startOfDay(): KZonedDateTime
fun KZonedDateTime.copy(year: Int? = null, month: Int? = null, day: Int? = null, hour: Int? = null, minute: Int? = null, second: Int? = null, millisecond: Int? = null, zoneOffset: KZoneOffset? = null): KZonedDateTime
fun KZonedDateTime.format(pattern: String): String
fun KZonedDateTime.toIso8601String(): String
fun KZonedDateTime.toIso8601StringWithMilliseconds(): String
operator fun KZonedDateTime.plus(duration: KDuration): KZonedDateTime
operator fun KZonedDateTime.minus(duration: KDuration): KZonedDateTime
operator fun KZonedDateTime.minus(dateTime: KZonedDateTime): KDuration
fun KDateTimeFormat.format(datetime: KDateTimeFormattable): String
fun KDateTimeFormat.parseToKZonedDateTime(input: String): KZonedDateTime
fun Int.milliseconds(): KDuration
fun Long.milliseconds(): KDuration
fun Int.seconds(): KDuration
fun Long.seconds(): KDuration
fun Int.minutes(): KDuration
fun Int.hours(): KDuration
fun Int.days(): KDuration
fun Int.weeks(): KDuration
fun KInstant.toString(): String
fun KZonedInstant.toString(): String
fun KZonedDateTime.toString(): String
fun KZoneOffset.toString(): String
fun KDuration.toString(): String

Uuid

Types

Uuid

class Uuid
Extension Properties
val Uuid.mostSignificantBits: Long get()
val Uuid.leastSignificantBits: Long get()
val Uuid.bytes: ByteArray get()
val Uuid.variant: Int get()
val Uuid.version: Int get()
Global Functions
fun uuid4(): Uuid
fun uuidFrom(string: String): Uuid
fun uuidOf(bytes: ByteArray): Uuid
fun uuidString(): String
Extension Functions
fun Uuid.toString(): String