>_KOTLINRS REFERENCE
A compiled Kotlin runtime written in Rust. Source is lexed and parsed to an AST, lowered to fusevm bytecode, and executed on the same language-agnostic VM + three-tier Cranelift JIT that hosts zshrs, stryke, awkrs, elisprs, rubylang, phplang, pythonrs, and node-js. No JVM, no kotlinc, no .class files. In active development.
What it is
kotlinrs runs Kotlin programs as ordinary compiled bytecode: it lexes and parses the source, lowers it to fusevm instructions, and lets the shared engine execute and JIT-compile them. There is no bespoke VM or tree-walker — arithmetic, comparison, control flow, locals, and calls lower to native fusevm ops so the Cranelift JIT can trace hot loops. A small runtime host (src/host.rs) supplies only the three Kotlin behaviours the universal ops cannot express: the Boolean/Double display form (true/false, 1.0) and truncating integer / and % with an ArithmeticException on a zero divisor.
It is another language hosted on fusevm, the shared bytecode VM and Cranelift JIT. kotlinrs carries no VM or JIT of its own.
Architecture
Kotlin source → lexer → parser (AST) → lower to fusevm bytecode → fusevm VM + Cranelift JIT
│
KtHost extension handler (toString / idiv / imod)
fusevm-hosted
No local vm.rs / jit.rs. Kotlin is lowered to fusevm bytecode and executed on the shared three-tier Cranelift JIT.
Native ops
Arithmetic, comparison, if/while/for, locals, and calls compile to native fusevm ops (Add, NumLt, Call, …) — so the JIT can trace hot loops, not a bespoke interpreter.
Thin host
Only Kotlin display form and truncating integer //% are handled by the extension handler; everything else is language-agnostic bytecode.
Editor tooling
An LSP server (--lsp), a DAP debugger (--dap), inline Rust FFI (rust { … }), and bytecode disassembly (--disasm) ship in-tree.
Example
fun fib(n: Int): Int {
if (n < 2) return n
return fib(n - 1) + fib(n - 2)
}
fun main() {
for (i in 0..10) {
println("fib($i) = ${fib(i)}")
}
var total = 0
for (x in 1..4) total += x
println(total) // => 10
val half = 7 / 2 // truncating Int division => 3
println(half)
}
Toolchain
--lsp
A Language Server Protocol server on stdio: parser-driven diagnostics, plus completion and hover over the whole 273-entry reference corpus — keywords, operators, types, builtins, throwables and every stdlib member — each with a signature, a description and an example (src/lsp.rs).
--dap
A Debug Adapter Protocol server on stdio: source-line breakpoints, step in/over/out, a stack frame, and live local values, with the debuggee's stdout streamed as output events (src/dap.rs).
rust { … } FFI
An inline rust { pub extern "C" fn … } block compiles to a cached cdylib whose exported functions are callable by name from Kotlin (src/rust_ffi.rs, fusevm::ffi).
Introspection
--dump-tokens, --dump-ast, and --disasm (a fusevm bytecode disassembly listing) print each stage and exit.
Status & roadmap
| Component | State | Notes |
|---|---|---|
| Lexer / parser → AST | Implemented | Kotlin subset: fun, val/var, if/while/for, ranges, string interpolation (src/lexer.rs, src/parser.rs). |
| AST → fusevm bytecode lowering | Implemented | Native arithmetic / comparison / control flow; no local VM (src/compiler.rs). |
| Kotlin runtime host | Implemented | toString() display form, truncating integer //%, zero-divisor ArithmeticException, plus the object heap behind classes / collections / lambdas / throwables (src/host.rs). |
Exceptions (try/catch/finally/throw) | Implemented | try as an expression; the JVM throwable hierarchy in catch; host faults (/ 0, !!, bad index) catchable. fusevm has no unwind opcode, so an in-flight exception is a host pending slot plus per-statement unwind checks — emitted only in programs that use exceptions. |
Standalone kotlin binary | Implemented | Run .kt files and -e one-liners (src/main.rs). |
LSP server (--lsp) | Implemented | Parser diagnostics, keyword/type/builtin completion and hover (src/lsp.rs). |
DAP adapter (--dap) | Implemented | Line breakpoints, step in/over/out, stack + live locals, streamed stdout (src/dap.rs). |
Inline Rust FFI (rust { … }) | Implemented | Cached cdylib, exported functions callable by name (src/rust_ffi.rs, fusevm::ffi). |
Bytecode disassembly (--disasm) | Implemented | Shared fusevm::Chunk::disassemble listing. |
Classes, data class, collections, lambdas | Implemented | Constructor and body properties, companion object, inheritance (open/abstract/sealed/interface, virtual dispatch), generated toString/equals/copy/componentN, List/Map/Set/Pair/Triple, arrays, ranges, first-class lambdas and the higher-order collection functions. |
| Extensions, scope functions, parameters | Implemented | Extension functions dispatched by the receiver's static type; both scope-function families (let/also/takeIf/takeUnless and run/apply/with); default, named and vararg arguments; local funs that recurse; as/as? casts; top-level properties and by lazy; runCatching/Result; and a var a lambda writes to, boxed so the write reaches the enclosing frame. |
Constructors, delegation, invocation, String collections | Implemented | Secondary constructors with Kotlin's initialization ORDER (property initializers and init blocks interleaved in declaration order; a secondary's body after the constructor it delegates to); interface delegation (class C(x: I) : I by x), forwarding I's defaulted members too, so a default method calls the delegate's implementation rather than the delegating class's override; property delegation through a custom operator fun getValue/setValue; invoking the result of a call (f()(), lst[0](7), { x: Int -> x }(9), operator fun invoke); and the collection functions on a String receiver, whose result type follows kotlin.text — "abc".map { … } is a List<Char> but "abc".filter { … } is a String. |
| Type arguments, inferred and written down | Implemented | A type variable takes its width from the use site: the argument for fun <T> id(x: T): T, the receiver's type argument for a member of a generic class (stored, var, body and computed properties and method results; nested instantiations and several type parameters resolve per position; a call selecting a SECONDARY constructor reads its own parameters), and the argument written down in SOURCE — a function result (fun mk(): Box<Int>), a parameter, a property of another class, a supertype (class Sub : Box<Int>()), a top-level or local val annotation, and a cast. Unresolved stays untyped, which narrows nothing, so a String or Double argument never reaches the 32-bit wrap. |
Variance, secondary-constructor super, wider stdlib | Planned | Variance and bounds are parsed and discarded (a type test against a NON-reified type parameter is rejected rather than answered; a reified one is compiled); a supertype argument is substituted for a DIRECT parent only; an explicit : super(args) from a secondary constructor and the rest of the standard-library surface are pending. |
Building from source
kotlinrs builds as a standalone Rust crate (it is not a workspace member of the meta repo):
# clone git clone https://github.com/MenkeTechnologies/kotlinrs cd kotlinrs # build (produces target/debug/kotlin) cargo build # run a script or a one-liner ./target/debug/kotlin examples/fib.kt ./target/debug/kotlin -e 'println(6 * 7)' # editor tooling ./target/debug/kotlin --lsp # Language Server Protocol on stdio ./target/debug/kotlin --dap # Debug Adapter Protocol on stdio ./target/debug/kotlin --disasm examples/hello.kt # run tests cargo test
fusevm is pulled from crates.io with the jit and ffi features.
License
kotlinrs is MIT licensed — free and open source. See LICENSE.
Repository & links
- Engineering report — report.html (architecture, fusevm hosting, roadmap, dependency posture)
- Language reference — reference.html (keywords, operators, types, builtins, throwables, stdlib members)
- Source — github.com/MenkeTechnologies/kotlinrs
- The shared VM — fusevm (also behind
zshrs,stryke,awkrs,elisprs,rubylang,phplang,pythonrs,node-js)