Skip to content
volt
GitHub

Kotlin

The other way, Kotlin calling a Volt library, is in Other languages.

One line imports Kotlin files, as one imports a C header:

use std::io;
use { "shapes.kt" } as shapes; // or several: use { "a.kt", "b.kt" } as x;
fn main() -> void {
val p: shapes::Point = { x: 3.0, y: 4.0 }; // a data class of plain vals, by value
std::println("{}", p.length());
val t = shapes::Tally::new(); // a class: its constructor is new(...)
t.add(2);
std::println("{}", t.total()); // a property is a method
val r = shapes::try_parse("x"); // what it throws, as an error
if (r.err) {
std::println("{}", r.err);
}
}

The Kotlin is ordinary: nothing in it is marked for Volt, and internal declarations count as well as public ones (only private and protected ones are left out). voltc runs bolt import, which reads the files’ declarations, writes a shim of @CName functions that call them, and builds both with kotlinc-native -produce static into one archive with the Kotlin/Native runtime. It caches the result and redoes it when a file (or the compiler) changes. It works the same with voltc run main.volt and in a bolt package. bolt reads $KOTLINC_NATIVE for the compiler, else kotlinc-native on the PATH.

Kotlin Volt
fun f(x: T): R at the top level fn f(x: T) -> R; a default argument is passed like any other
Int, Long, Short, Byte i32, i64, i16, i8
UInt…UByte, Double, Float, Boolean u32…u8, f64, f32, bool
String str in, std::string out (a copy)
List<T> (Collection, Iterable) of numbers or strings T[..], str[..] in; std::vec<T>, std::vec<std::string> out
T? T?
an exception it throws the plain form stops the program with it; try_f(...) gives it as kotlin_error::PANIC, its toString()
a data class whose constructor’s parameters are all vals of numbers, Booleans, such classes or enum classes, with no other stored property a Volt struct with those fields, passed by value
any other class, and an object an owned handle; copy shares the object, as a second Kotlin reference does
an enum class a Volt enum, by its entries’ order
the primary constructor, or the T() Kotlin writes itself T::new(...); a secondary constructor T::new_<its first parameter>(...)
a member fun a method
an object’s or a companion object’s fun T::f(...)
a property (val, var, or a constructor’s val) a method without arguments: t.total()
a top-level const val or val of a number, Boolean or string a val
overloads (describe(x: Int), describe(x: Double)) Volt overloads (ones Volt can’t tell apart, two Kotlin types it names alike, are left out)
vararg xs: T, the last parameter, of numbers or strings xs: T[..], spread into the call
typealias Meters = Double its type, and a Volt alias: geo::Meters
fun Point.shifted(...), an extension of one of the files’ types a method of it
fun String.exclaim(), fun Int.squared() an attach fn on str, i32: "hey".exclaim()
a nested class, enum class or object (Garage.Car, a companion object’s too) Garage_Car, as nested C++ types are named; an inner class is left out
a suspend fun what it gives, when it finishes without suspending; one that suspends throws (nothing would resume it): the plain form stops the program, try_f gives PANIC

Generic functions, interfaces, a function whose result type isn’t written (fun f() = ...), an extension of a type Volt can’t attach to (a nullable or generic one), an extension property and a vararg that isn’t last aren’t callable from Volt; they’re left out, listed in a comment of the generated declarations (VOLT_SHOW_IMPORT=1 voltc check main.volt prints them). Each Volt fn has the Kotlin declaration it calls in a comment above it (// Kotlin: fun scaled(k: Double): Point), which an editor’s hover shows. A Kotlin name that is a Volt keyword gets a _ after it (move is move_). The program links the archive from bolt’s cache with -lpthread -ldl -lm -lstdc++; two Kotlin imports in one program share one runtime.