Skip to content

Commit

Permalink
Add Kotlin/JS
Browse files Browse the repository at this point in the history
  • Loading branch information
ephemient committed Dec 2, 2023
1 parent 3f51e6e commit c168fd9
Show file tree
Hide file tree
Showing 22 changed files with 2,071 additions and 41 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
kt/gradlew linguist-generated
kt/gradlew.bat linguist-generated

# generated by Kotlin/JS
kt/kotlin-js-store/yarn.lock

# generated by Poetry
py/poetry.lock linguist-generated

Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/kt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ jobs:
path: |
kt/aoc2023-exe/build/bin/*/debugExecutable/*.kexe
kt/aoc2023-exe/build/bin/*/releaseExecutable/*.kexe
- uses: actions/upload-artifact@v3
with:
name: aoc2023-js
path: kt/build/js/packages/aoc2023-aoc2023-exe/kotlin/*

run-jvm:
needs: [ get-inputs, build ]
Expand Down Expand Up @@ -84,3 +88,22 @@ jobs:
- run: linuxX64/releaseExecutable/aoc2023-exe.kexe
env:
AOC2023_DATADIR: inputs

run-node:
needs: [ get-inputs, build ]
runs-on: ubuntu-latest

steps:
- uses: actions/download-artifact@v3
with:
name: inputs
path: inputs
- uses: actions/download-artifact@v3
with:
name: aoc2023-js
- uses: actions/setup-node@v4
with:
node-version: 21.3.0
- run: node aoc2023-aoc2023-exe.js
env:
AOC2023_DATADIR: inputs
2 changes: 1 addition & 1 deletion kt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Run [kotlinx.benchmark](https://github.com/Kotlin/kotlinx-benchmark) ([JMH](http
Print solutions for the inputs provided in local data files:

```sh
./gradlew :aoc2023-exe:jvmRun :aoc2023-exe:run{Debug,Release}Executable{LinuxX64,Macos{X64,Arm64}}
./gradlew :aoc2023-exe:jvmRun :aoc2023-exe:runReleaseExecutable{LinuxX64,Macos{X64,Arm64}} :aoc2023-exe:jsNodeProductionRun
```

Run all checks, including [Detekt](https://detekt.github.io/) static code analysis and [ktlint](https://ktlint.github.io/) formatter:
Expand Down
15 changes: 14 additions & 1 deletion kt/aoc2023-exe/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
id("com.github.ephemient.aoc2023.detekt")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.jvm.platform")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.native.platforms")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.js.platform")
}

application {
Expand All @@ -20,6 +21,12 @@ kotlin {
withJava()
}

js {
useCommonJs()
nodejs()
binaries.executable()
}

targets.withType<KotlinJvmTarget> {
mainRun {
mainClass = application.mainClass
Expand All @@ -36,7 +43,6 @@ kotlin {
commonMain {
dependencies {
implementation(projects.aoc2023Lib)
implementation(libs.kotlinx.coroutines)
}
}

Expand All @@ -51,6 +57,12 @@ kotlin {
implementation(libs.okio)
}
}

jsMain {
dependencies {
implementation(libs.kotlin.wrappers.node)
}
}
}
}

Expand All @@ -62,6 +74,7 @@ benchmark {
targets {
register("jvmTest")
}

configurations {
getByName("main") {
warmups = 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.github.ephemient.aoc2023.exe

import com.github.ephemient.aoc2023.days
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

internal suspend fun mainImpl(vararg args: String): Unit = withContext(Dispatchers.Default) {
internal fun mainImpl(args: Array<out String>) {
for (day in days) {
if (args.isNotEmpty() && day.name !in args) continue
println("Day ${day.name}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.github.ephemient.aoc2023.exe

internal expect suspend fun getDayInput(day: Int): String
internal expect fun getDayInput(day: Int): String
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Scope
import kotlinx.benchmark.Setup
import kotlinx.benchmark.State
import kotlinx.coroutines.runBlocking

@State(Scope.Benchmark)
class Day1Bench {
private lateinit var input: String

@Setup
fun setup() {
input = runBlocking {
getDayInput(1)
}
input = getDayInput(1)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Scope
import kotlinx.benchmark.Setup
import kotlinx.benchmark.State
import kotlinx.coroutines.runBlocking

@State(Scope.Benchmark)
class Day2Bench {
private lateinit var input: String

@Setup
fun setup() {
input = runBlocking {
getDayInput(2)
}
input = getDayInput(2)
}

@Benchmark
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.github.ephemient.aoc2023.exe

import node.buffer.BufferEncoding
import node.fs.readFileSync
import node.process.process

internal actual fun getDayInput(day: Int): String {
val dataDir = process.env["AOC2023_DATADIR"]?.ifEmpty { null } ?: "."
return readFileSync("$dataDir/day$day.txt", BufferEncoding.utf8)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.ephemient.aoc2023.exe

import node.process.process

@ExperimentalJsExport
@JsExport
fun main() {
mainImpl(with(process.argv) { copyOfRange(2, size) })
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package com.github.ephemient.aoc2023.exe

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File

@Suppress("InjectDispatcher")
internal actual suspend fun getDayInput(day: Int): String = withContext(Dispatchers.IO) {
internal actual fun getDayInput(day: Int): String =
File(System.getenv("AOC2023_DATADIR")?.ifEmpty { null } ?: ".", "day$day.txt").readText()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

package com.github.ephemient.aoc2023.exe

suspend fun main(vararg args: String): Unit = mainImpl(*args)
fun main(vararg args: String) {
mainImpl(args)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ package com.github.ephemient.aoc2023.exe

import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.toKString
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import okio.Path.Companion.toPath
import okio.buffer
import platform.posix.getenv

@OptIn(ExperimentalForeignApi::class)
internal actual suspend fun getDayInput(day: Int): String = withContext(Dispatchers.IO) {
internal actual fun getDayInput(day: Int): String {
val dataDir = (getenv("AOC2023_DATADIR")?.toKString()?.ifEmpty { null } ?: ".").toPath()
okio.FileSystem.SYSTEM.source(dataDir / "day$day.txt").buffer().readUtf8()
return okio.FileSystem.SYSTEM.source(dataDir / "day$day.txt").buffer().readUtf8()
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.github.ephemient.aoc2023.exe

import kotlinx.coroutines.runBlocking

fun main(vararg args: String): Unit = runBlocking {
mainImpl(*args)
fun main(vararg args: String) {
mainImpl(args)
}
7 changes: 6 additions & 1 deletion kt/aoc2023-lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ plugins {
id("com.github.ephemient.aoc2023.detekt")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.jvm.platform")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.native.platforms")
id("com.github.ephemient.aoc2023.kotlin.multiplatform.js.platform")
}

kotlin {
js {
browser()
nodejs()
}

sourceSets {
commonTest {
dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ val days = listOf(
data class Day(
val day: Int,
val name: String = day.toString(),
val solver: (String) -> List<suspend () -> Any?>,
val solver: (String) -> List<() -> Any?>,
)
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.github.ephemient.aoc2023

import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

class Day1Test {
@Test
fun part1() = runTest {
fun part1() {
assertEquals(142, Day1(example1).part1())
}

@Test
fun part2() = runTest {
fun part2() {
assertEquals(281, Day1(example2).part2())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.github.ephemient.aoc2023

import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

class Day2Test {
@Test
fun part1() = runTest {
fun part1() {
assertEquals(8, Day2(example).part1())
}

@Test
fun part2() = runTest {
fun part2() {
assertEquals(2286, Day2(example).part2())
}

Expand Down
6 changes: 5 additions & 1 deletion kt/buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ gradlePlugin {
id = "com.github.ephemient.aoc2023.kotlin.multiplatform.native.platforms"
implementationClass = "com.github.ephemient.aoc2023.buildsrc.KotlinMultiplatformNativePlatformsPlugin"
}
create("KotlinMultiplatformJsPlatformPlugin") {
id = "com.github.ephemient.aoc2023.kotlin.multiplatform.js.platform"
implementationClass = "com.github.ephemient.aoc2023.buildsrc.KotlinMultiplatformJsPlatformPlugin"
}
}
}

dependencies {
implementation(kotlin("gradle-plugin", libs.versions.kotlin.get()))
implementation(kotlin("gradle-plugin", libs.versions.kotlin.asProvider().get()))
implementation(libs.detekt.plugin)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package com.github.ephemient.aoc2023.buildsrc
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getValue
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin

class KotlinMultiplatformBasePlugin : Plugin<Project> {
override fun apply(target: Project) {
Expand Down Expand Up @@ -42,3 +45,18 @@ class KotlinMultiplatformNativePlatformsPlugin : Plugin<Project> {
}
}
}

class KotlinMultiplatformJsPlatformPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.rootProject.apply<NodeJsRootPlugin>()
target.rootProject.configure<NodeJsRootExtension> {
nodeVersion = "21.3.0"
}

target.apply<KotlinMultiplatformBasePlugin>()
target.pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") {
val kotlin: KotlinMultiplatformExtension by target.extensions
kotlin.js()
}
}
}
5 changes: 2 additions & 3 deletions kt/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ detekt = "1.23.4"
graal-sdk = "23.1.1"
junit-jupiter = "5.10.1"
kotlin = "1.9.21"
kotlin-wrappers = "18.16.12-pre.652"
kotlinx-benchmark = "0.4.9"
kotlinx-coroutines = "1.7.3"
okio = "3.6.0"
native-image-plugin = "0.9.28"

Expand All @@ -21,9 +21,8 @@ detekt-plugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", v
graal-sdk = { module = "org.graalvm.sdk:graal-sdk", version.ref = "graal-sdk" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" }
kotlin-wrappers-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node", version.ref = "kotlin-wrappers" }
kotlinx-benchmark = { module = "org.jetbrains.kotlinx:kotlinx-benchmark-runtime", version.ref = "kotlinx-benchmark" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
okio = { module = "com.squareup.okio:okio", version.ref = "okio" }

[bundles]
Expand Down
Loading

0 comments on commit c168fd9

Please sign in to comment.