From 25086a3c7ea7d3be33427734b1d8a7767c7a222a Mon Sep 17 00:00:00 2001 From: "alexander.nutz" Date: Wed, 3 Apr 2024 07:17:27 +0200 Subject: [PATCH] task processor, add locations to parser combinator --- src/main/kotlin/blitz/async/Processor.kt | 70 ++++++++++++++++++++++ src/main/kotlin/blitz/parse/comb/Parser.kt | 28 +++++---- 2 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/blitz/async/Processor.kt diff --git a/src/main/kotlin/blitz/async/Processor.kt b/src/main/kotlin/blitz/async/Processor.kt new file mode 100644 index 0000000..861644c --- /dev/null +++ b/src/main/kotlin/blitz/async/Processor.kt @@ -0,0 +1,70 @@ +package blitz.async + +import blitz.collections.SynchronizedList +import blitz.logic.then + +abstract class Processor { + protected val tasks = SynchronizedList(mutableListOf()) + + + fun tick() { + for (task in tasks) { + if (task.counter >= task.priority) { + task.fn() + task.counter = 0 + } else { + task.counter ++ + } + } + } + + abstract fun add(task: Task) + + abstract fun remove(task: Task) + + /** priority 0 means every tick; 1 means every second tick; 2 means every third tick, ... */ + data class Task( + internal val priority: Int = 0, // every tick + internal val fn: () -> Unit + ) { + internal var counter: Int = 0 + } + + companion object { + fun singleThread(): Processor = + SingleThreadProcessor() + + fun manualTick(): Processor = + object : Processor() { + override fun add(task: Task) { + tasks.add(task) + } + + override fun remove(task: Task) { + tasks.remove(task) + } + } + } +} + +internal class SingleThreadProcessor: Processor() { + private fun createThread() = Thread { while (true) { tick() } } + + private var thread: Thread? = null + + override fun add(task: Task) { + tasks.add(task) + if (thread == null) { + thread = createThread() + thread!!.start() + } + } + + override fun remove(task: Task) { + tasks.remove(task) + tasks.isEmpty().then { + runCatching { thread?.interrupt() } + thread = null + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/blitz/parse/comb/Parser.kt b/src/main/kotlin/blitz/parse/comb/Parser.kt index 04c270c..9491db5 100644 --- a/src/main/kotlin/blitz/parse/comb/Parser.kt +++ b/src/main/kotlin/blitz/parse/comb/Parser.kt @@ -1,11 +1,10 @@ package blitz.parse.comb import blitz.str.collectToString -import kotlin.math.max -@JvmInline -value class Parsable( - val str: String +data class Parsable( + val str: String, + val loc: Int? = null ) typealias Parser = (Parsable) -> Pair? @@ -26,21 +25,24 @@ infix fun Parser.or(other: Parser): Parser = { } fun Parsable.spaces(): Parsable { - return Parsable(str.trimStart(' ')) + val new = str.trimStart(' ') + return Parsable(new, loc?.let { it + str.length - new.length }) } fun Parsable.whitespaces(): Parsable { - return Parsable(str.trimStart()) + val new = str.trimStart() + return Parsable(new, loc?.let { it + str.length - new.length }) } fun Parsable.require(what: String): Parsable? { if (str.startsWith(what)) - return Parsable(str.substring(what.length)) + return Parsable(str.substring(what.length), loc?.let { it + what.length }) return null } fun Parsable.untilRequire(c: String, map: (String) -> T?): Pair? { - return map(str.substringBefore(c))?.let { Parsable(str.substringAfter(c)) to it } + val before = str.substringBefore(c) + return map(before)?.let { Parsable(str.substringAfter(c), loc?.let { it + before.length }) to it } } fun Parsable.asLongAs(vararg li: Char, map: (String) -> T?): Pair? { @@ -52,7 +54,7 @@ fun Parsable.asLongAs(vararg li: Char, map: (String) -> T?): Pair Parsable.map(parser: Parser): Pair? = @@ -89,17 +91,19 @@ fun Pair.require(what: String): Pair? = fun Parsable.array(sep: String, map: (Parsable) -> Pair?): Pair> { val out = mutableListOf() + var loc = loc var curr = str fun step() = - map(Parsable(curr))?.also { + map(Parsable(curr, loc))?.also { curr = it.first.str + loc = it.first.loc } while (true) { val r = step() ?: break out.add(r.second) - curr = (Parsable(curr).require(sep) ?: break).str + curr = (Parsable(curr, loc).require(sep) ?: break).str } - return Parsable(curr) to out + return Parsable(curr, loc) to out } \ No newline at end of file