Kotlin support
Kotlin support would be great and nearly works but Kotlin relies on kotlin/Intrinsics and other stdlib classes for many operations that it performs.
Even the most basic RobotPlayer will be rejected by the instrumenter because Kotlin inserts non-null checks using Intrinsics.requireNonNull.
@file:JvmName("RobotPlayer")
package kotlin_test
import battlecode.common.RobotController
fun run(rc: RobotController) {
println("Hello World")
}
These particular checks can be disabled with -Xno-param-assertions and -Xno-call-assertions, but Kotlin relies on its stdlib for all kinds of things which can't be disabled.
fun check(x: String?) {
val y = x!! // inserts call to Intrinsics.throwNpe()
...
}
fun listOperations() {
val a = 1..6 // references kotlin/ranges/IntRange
val b = a.map { it * 2 } // references kotlin/collections/CollectionsKt
}
I'm using Kotlin 1.0.6 if that matters.
See also http://battlecodeforum.org/t/anyone-interested-in-kotlin/134
Regarding the nonNull checks and similar things, it would be great if the instrumenter specifically made such assertions have a 0 cost to avoid penalizing bots just based on the language used even if the algorithms are exactly the same.
Because of Kotlin's pretty extensive interop features, the only thing needed to get it working should be allowing kotlin's stdlib packages.
I agree with @HalfVoxel though, Intrinsics should probably be ignored bytecode-wise, and possibly Typeintrinsics too.
I'll make a pull request for this if one of the project members weighs in on whether to count Intrinsics.
@Pear0 That would be great. Intrinsics should definitely be free. kotlin.reflect should be disabled, unfortunately; this prevents doing things like ::method, but is the best way to do things safely without exposing too many new attack surfaces on the battlecode infrastructure. We can loosen the restrictions once we've audited kotlin.reflect, but I at least don't have enough time to do that right now :/
I'm sorry this feature has taken so long, we've been busy putting out other fires.
Some things I've found:
As it turns out, because Kotlin targets 1.6, it doesn't use invokedynamic. It generates inner class wrappers for method and constructor references so ::Random and String::equals. (they still don't work because they reference interfaces in kotlin/reflect)
Disallowing kotlin/reflect also has the side-effect of disabling delegators which rely on kotlin/reflect/KProperty.