From fcb017e6df9af853dfc1e2a85d8a5ed8c43991cc Mon Sep 17 00:00:00 2001 From: allem Date: Tue, 27 Nov 2018 03:12:18 -0500 Subject: [PATCH] separate instructionset type --- .../kotlin/befide/befunge/b93/Befunge93.kt | 117 ++---------------- .../befunge/b93/Befunge93Instructions.kt | 67 ++++++++++ .../befide/befunge/b93/{ => state}/Funge93.kt | 8 +- .../befunge/b93/{ => state}/LongData.kt | 5 +- .../befunge/b93/{ => state}/Pointer93.kt | 10 +- .../befide/befunge/b93/{ => state}/Vec2.kt | 2 +- .../befide/befunge/core/InstructionSet.kt | 9 ++ .../kotlin/befide/befunge/core/Interpreter.kt | 72 +++-------- .../befide/befunge/core/MutableInterpreter.kt | 66 ++++++++++ .../befide/befunge/core/events/FungeChange.kt | 10 ++ .../befide/befunge/core/events/IpChange.kt | 6 + .../befide/befunge/core/events/StackChange.kt | 8 ++ .../kotlin/befide/befunge/core/state/Data.kt | 5 + .../kotlin/befide/befunge/core/state/Funge.kt | 17 +++ .../befide/befunge/core/state/MutableFunge.kt | 10 ++ .../befunge/core/state/MutablePointer.kt | 9 ++ .../befide/befunge/core/state/Pointer.kt | 9 ++ .../befunge/{events => core/util}/Event.kt | 2 +- .../kotlin/befide/befunge/core/util/Misc.kt | 5 + 19 files changed, 263 insertions(+), 174 deletions(-) create mode 100644 befunge/src/main/kotlin/befide/befunge/b93/Befunge93Instructions.kt rename befunge/src/main/kotlin/befide/befunge/b93/{ => state}/Funge93.kt (90%) rename befunge/src/main/kotlin/befide/befunge/b93/{ => state}/LongData.kt (91%) rename befunge/src/main/kotlin/befide/befunge/b93/{ => state}/Pointer93.kt (50%) rename befunge/src/main/kotlin/befide/befunge/b93/{ => state}/Vec2.kt (95%) create mode 100644 befunge/src/main/kotlin/befide/befunge/core/InstructionSet.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/events/FungeChange.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/events/IpChange.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/events/StackChange.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/state/Data.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/state/MutableFunge.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/state/MutablePointer.kt create mode 100644 befunge/src/main/kotlin/befide/befunge/core/state/Pointer.kt rename befunge/src/main/kotlin/befide/befunge/{events => core/util}/Event.kt (98%) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt b/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt index 9619afd..9bc073c 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt @@ -1,125 +1,32 @@ package befide.befunge.b93 +import befide.befunge.b93.state.* import befide.befunge.core.* -import befide.befunge.core.util.chooseOne +import befide.befunge.core.events.IpChange +import befide.befunge.core.events.StackChange import befide.befunge.core.util.readAll -import befide.befunge.events.Event +import befide.befunge.core.util.Event import java.io.PipedReader import java.io.PipedWriter import java.util.* class Interpreter93(stdinSrc: PipedWriter, stdoutDest: PipedReader) - : Interpreter { + : MutableInterpreter() { override val ip = Pointer93() override val funge = Funge93() override val stack = Stack() + override fun stackDefault() = LongData.ZERO + override val onIpChange = Event>() override val onStackChange = Event>() override val stdin: PipedReader = PipedReader(stdinSrc) override val stdout: PipedWriter = PipedWriter(stdoutDest) - private fun notifyIp(op: () -> Unit) { - val from = ip.copy() - op() - val to = ip.copy() - onIpChange(IpChange(from, to)) - } - - private fun move(dir: Vec2? = null) = notifyIp { - ip.pos = funge.next(ip.pos, dir ?: ip.delta) - } - - private fun pop(): LongData { - val d = if (stack.empty()) LongData.ZERO else stack.pop() - onStackChange(StackChange(StackOp.Pop, d)) - return d - } - - private fun push(vararg data: LongData) { - for (d in data) { - stack.push(d) - onStackChange(StackChange(StackOp.Push, d)) - } - } - - private fun argPop(n: Int, op: (Array) -> Unit) { - val args = (0 until n).map { pop() }.toTypedArray() - op(args) - } - - private var mode - get() = ip.mode - set(mode) = notifyIp { ip.mode = mode } - - private var delta - get() = ip.delta - set(delta) = notifyIp { ip.delta = delta } - - override fun step() { - val instr = funge[ip.pos] - - when (mode) { - PointerMode.Terminated -> return - PointerMode.String -> when (instr.char) { - null -> Unit - - '"' -> mode = PointerMode.Normal - - else -> push(instr) - } - PointerMode.Normal -> when (instr.char) { - null -> Unit - in "0123456789abcdef" -> push(LongData(instr.char.toString().toLong(16))) - - '+' -> argPop(2) { (b, a) -> push(a + b) } - '-' -> argPop(2) { (b, a) -> push(a - b) } - '*' -> argPop(2) { (b, a) -> push(a * b) } - '/' -> argPop(2) { (b, a) -> push(a / b) } - '%' -> argPop(2) { (b, a) -> push(a mod b) } - '!' -> argPop(1) { (n) -> push(LongData(if (n.data == 0L) 1L else 0L)) } - '`' -> argPop(2) { (b, a) -> push(LongData(if (a.data > b.data) 1L else 0L)) } - - '>' -> delta = Vec2.RIGHT - '<' -> delta = Vec2.LEFT - 'v' -> delta = Vec2.DOWN - '^' -> delta = Vec2.UP - '?' -> delta = Vec2.DIRS.chooseOne() - '#' -> move() - - '_' -> argPop(1) { (n) -> delta = if (n.data == 0L) Vec2.RIGHT else Vec2.LEFT } - '|' -> argPop(1) { (n) -> delta = if (n.data == 0L) Vec2.DOWN else Vec2.UP } - - '"' -> mode = PointerMode.String - - ':' -> argPop(1) { (n) -> push(n, n) } - '\\' -> argPop(2) { (b, a) -> push(b, a) } - '$' -> pop() - - '.' -> argPop(1) { (n) -> stdout.write("${n.data} ") } - ',' -> argPop(1) { (ch) -> stdout.write(ch.data.toChar().toString()) } - - 'p' -> argPop(3) { (y, x, n) -> funge[Vec2(x.data.toInt(), y.data.toInt())] = n } - 'g' -> argPop(2) { (y, x) -> push(funge[Vec2(x.data.toInt(), y.data.toInt())]) } - - '~' -> push(LongData(stdin.read().toLong())) - '&' -> { - val chars = generateSequence { - stdin.read().takeIf { it.toChar().isDigit() } - } - val long = chars.joinToString("").toLong() - push(LongData(long)) - } - - '@' -> mode = PointerMode.Terminated - } - } - - move() - } + override val instructionSet = Befunge93Instructions() override fun reset() { stdin.readAll() @@ -133,9 +40,9 @@ fun main(args: Array) { val int = Interpreter93(stdinSrc, stdoutDest) -// int.onIpChange += { -// println(it.to.pos) -// } + int.onIpChange += { + println(it.to.pos) + } int.funge.src = """2>:3g" "-!v\ g30 < |!`"O":+1_:.:03p>03g+:"O"`| @@ -144,7 +51,7 @@ fun main(args: Array) { while (int.ip.mode != PointerMode.Terminated) { int.step() - print(stdoutDest.readAll()) } + print(stdoutDest.readAll()) } \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Befunge93Instructions.kt b/befunge/src/main/kotlin/befide/befunge/b93/Befunge93Instructions.kt new file mode 100644 index 0000000..2f1323a --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/b93/Befunge93Instructions.kt @@ -0,0 +1,67 @@ +package befide.befunge.b93 + +import befide.befunge.b93.state.LongData +import befide.befunge.b93.state.PointerMode +import befide.befunge.b93.state.Vec2 +import befide.befunge.core.InstructionSet +import befide.befunge.core.MutableInterpreter +import befide.befunge.core.util.chooseOne + +class Befunge93Instructions : InstructionSet { + override fun MutableInterpreter.handle() { + when (mode) { + PointerMode.Terminated -> return + PointerMode.String -> when (instr.char) { + null -> Unit + '"' -> mode = PointerMode.Normal + else -> push(instr) + } + PointerMode.Normal -> when (instr.char) { + null -> Unit + + in "0123456789abcdef" -> push(LongData(instr.char.toString().toLong(16))) + + '+' -> pop(2).let { (b, a) -> push(a + b) } + '-' -> pop(2).let { (b, a) -> push(a - b) } + '*' -> pop(2).let { (b, a) -> push(a * b) } + '/' -> pop(2).let { (b, a) -> push(a / b) } + '%' -> pop(2).let { (b, a) -> push(a mod b) } + '!' -> pop(1).let { (n) -> push(LongData(if (n.data == 0L) 1L else 0L)) } + '`' -> pop(2).let { (b, a) -> push(LongData(if (a.data > b.data) 1L else 0L)) } + + '>' -> delta = Vec2.RIGHT + '<' -> delta = Vec2.LEFT + 'v' -> delta = Vec2.DOWN + '^' -> delta = Vec2.UP + '?' -> delta = Vec2.DIRS.chooseOne() + '#' -> move() + + '_' -> pop().let { n -> delta = if (n.data == 0L) Vec2.RIGHT else Vec2.LEFT } + '|' -> pop().let { n -> delta = if (n.data == 0L) Vec2.DOWN else Vec2.UP } + + '"' -> mode = PointerMode.String + + ':' -> pop().let { n -> push(n, n) } + '\\' -> pop(2).let { (b, a) -> push(b, a) } + '$' -> pop() + + '.' -> pop().let { n -> stdout.write("${n.data} ") } + ',' -> pop().let { ch -> stdout.write(ch.data.toChar().toString()) } + + 'p' -> pop(3).let { (y, x, n) -> funge[Vec2(x.data.toInt(), y.data.toInt())] = n } + 'g' -> pop(2).let { (y, x) -> push(funge[Vec2(x.data.toInt(), y.data.toInt())]) } + + '~' -> push(LongData(stdin.read().toLong())) + '&' -> { + val chars = generateSequence { + stdin.read().takeIf { it.toChar().isDigit() } + } + val long = chars.joinToString("").toLong() + push(LongData(long)) + } + + '@' -> mode = PointerMode.Terminated + } + } + } +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Funge93.kt b/befunge/src/main/kotlin/befide/befunge/b93/state/Funge93.kt similarity index 90% rename from befunge/src/main/kotlin/befide/befunge/b93/Funge93.kt rename to befunge/src/main/kotlin/befide/befunge/b93/state/Funge93.kt index 51b0fab..7ae26f1 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/Funge93.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/state/Funge93.kt @@ -1,8 +1,8 @@ -package befide.befunge.b93 +package befide.befunge.b93.state -import befide.befunge.core.FungeChange -import befide.befunge.core.MutableFunge -import befide.befunge.events.Event +import befide.befunge.core.events.FungeChange +import befide.befunge.core.state.MutableFunge +import befide.befunge.core.util.Event class Funge93 : MutableFunge { diff --git a/befunge/src/main/kotlin/befide/befunge/b93/LongData.kt b/befunge/src/main/kotlin/befide/befunge/b93/state/LongData.kt similarity index 91% rename from befunge/src/main/kotlin/befide/befunge/b93/LongData.kt rename to befunge/src/main/kotlin/befide/befunge/b93/state/LongData.kt index b7c961e..a5b5fb8 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/LongData.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/state/LongData.kt @@ -1,11 +1,10 @@ -package befide.befunge.b93 +package befide.befunge.b93.state -import befide.befunge.core.Data +import befide.befunge.core.state.Data import befide.befunge.core.util.mod data class LongData(val data: Long) : Data { - companion object { val SPACE = LongData(' ') val ZERO = LongData(0) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Pointer93.kt b/befunge/src/main/kotlin/befide/befunge/b93/state/Pointer93.kt similarity index 50% rename from befunge/src/main/kotlin/befide/befunge/b93/Pointer93.kt rename to befunge/src/main/kotlin/befide/befunge/b93/state/Pointer93.kt index f4b39e2..1a102d4 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/Pointer93.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/state/Pointer93.kt @@ -1,6 +1,7 @@ -package befide.befunge.b93 +package befide.befunge.b93.state -import befide.befunge.core.MutablePointer +import befide.befunge.core.state.MutablePointer +import befide.befunge.core.state.Pointer enum class PointerMode { Normal, String, Terminated @@ -9,4 +10,7 @@ enum class PointerMode { data class Pointer93(override var pos: Vec2 = Vec2.ZERO, override var delta: Vec2 = Vec2.RIGHT, override var mode: PointerMode = PointerMode.Normal) - : MutablePointer \ No newline at end of file + : MutablePointer { + + override fun copy(): Pointer = Pointer93(pos, delta, mode) +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Vec2.kt b/befunge/src/main/kotlin/befide/befunge/b93/state/Vec2.kt similarity index 95% rename from befunge/src/main/kotlin/befide/befunge/b93/Vec2.kt rename to befunge/src/main/kotlin/befide/befunge/b93/state/Vec2.kt index d9d1d7f..a654756 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/Vec2.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/state/Vec2.kt @@ -1,4 +1,4 @@ -package befide.befunge.b93 +package befide.befunge.b93.state import befide.befunge.core.util.mod diff --git a/befunge/src/main/kotlin/befide/befunge/core/InstructionSet.kt b/befunge/src/main/kotlin/befide/befunge/core/InstructionSet.kt new file mode 100644 index 0000000..54659a8 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/InstructionSet.kt @@ -0,0 +1,9 @@ +package befide.befunge.core + +import befide.befunge.core.state.Data + +interface InstructionSet> { + fun MutableInterpreter.handle() + + fun step(inter: MutableInterpreter) = inter.handle() +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt index a2483b4..a2f201e 100644 --- a/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt @@ -1,69 +1,26 @@ package befide.befunge.core -import befide.befunge.events.Event +import befide.befunge.core.events.IpChange +import befide.befunge.core.events.StackChange +import befide.befunge.core.state.Data +import befide.befunge.core.state.Funge +import befide.befunge.core.state.Pointer +import befide.befunge.core.util.Event import java.io.PipedReader import java.io.PipedWriter -import java.util.* - -interface Pointer> { - val pos: V - val delta: V - val mode: M -} - -interface MutablePointer> - : Pointer { - - override var pos: V - override var delta: V - override var mode: M -} - -interface Data { - val char: Char? -} - -data class FungeChange -(val funge: Funge, - val pos: V, - val from: D, - val to: D) - -interface Funge { - val size: V - - val data: List> - val src: String - - fun next(pos: V, delta: V): V - - operator fun get(pos: V): D - - val onChange: Event> -} - -interface MutableFunge - : Funge { - - override var data: List> - override var src: String - - operator fun set(pos: V, data: D) -} - -data class IpChange> -(val from: Pointer, val to: Pointer) - -enum class StackOp { Push, Pop } - -data class StackChange -(val op: StackOp, val data: D) interface Interpreter> { val ip: Pointer val funge: Funge val stack: List + fun stackDefault(): D + + val mode: M get() = ip.mode + val delta: V get() = ip.delta + val pos: V get() = ip.pos + val instr: D get() = funge[ip.pos] + val onIpChange: Event> val onStackChange: Event> @@ -72,4 +29,5 @@ interface Interpreter> { fun step() fun reset() -} \ No newline at end of file +} + diff --git a/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt b/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt new file mode 100644 index 0000000..e48ee38 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt @@ -0,0 +1,66 @@ +package befide.befunge.core + +import befide.befunge.core.events.IpChange +import befide.befunge.core.events.StackChange +import befide.befunge.core.events.StackOp +import befide.befunge.core.state.Data +import befide.befunge.core.state.MutableFunge +import befide.befunge.core.state.MutablePointer +import java.util.* + +abstract class MutableInterpreter> + : Interpreter { + abstract override val ip: MutablePointer + abstract override val funge: MutableFunge + abstract override val stack: Stack + + abstract val instructionSet: InstructionSet + + override fun step() { + instructionSet.step(this) + move() + } + + fun notifyIp(op: () -> Unit) { + val from = ip.copy() + op() + val to = ip.copy() + onIpChange(IpChange(from, to)) + } + + fun notifyStack(op: StackOp, block: () -> D): D { + val res = block() + onStackChange(StackChange(op, res)) + return res + } + + override var mode: M + get() = ip.mode + set(mode) = notifyIp { ip.mode = mode } + + override var delta: V + get() = ip.delta + set(delta) = notifyIp { ip.delta = delta } + + override var pos: V + get() = ip.pos + set(pos) = notifyIp { ip.pos = pos } + + fun move(delta: V? = null) { + pos = funge.next(pos, delta ?: this.delta) + } + + fun pop(): D = notifyStack(StackOp.Pop) { + if (stack.empty()) stackDefault() else stack.pop() + } + + fun pop(n: Int): List { + return (0 until n).map { notifyStack(StackOp.Pop) { stack.pop() } } + } + + fun push(vararg data: D) { + for (datum in data) { + notifyStack(StackOp.Push) { stack.push(datum) } + } + } +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/events/FungeChange.kt b/befunge/src/main/kotlin/befide/befunge/core/events/FungeChange.kt new file mode 100644 index 0000000..6edd2d1 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/events/FungeChange.kt @@ -0,0 +1,10 @@ +package befide.befunge.core.events + +import befide.befunge.core.state.Data +import befide.befunge.core.state.Funge + +data class FungeChange +(val funge: Funge, + val pos: V, + val from: D, + val to: D) \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/events/IpChange.kt b/befunge/src/main/kotlin/befide/befunge/core/events/IpChange.kt new file mode 100644 index 0000000..579fd64 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/events/IpChange.kt @@ -0,0 +1,6 @@ +package befide.befunge.core.events + +import befide.befunge.core.state.Pointer + +data class IpChange> +(val from: Pointer, val to: Pointer) \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/events/StackChange.kt b/befunge/src/main/kotlin/befide/befunge/core/events/StackChange.kt new file mode 100644 index 0000000..8e687b5 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/events/StackChange.kt @@ -0,0 +1,8 @@ +package befide.befunge.core.events + +import befide.befunge.core.state.Data + +enum class StackOp { Push, Pop } + +data class StackChange +(val op: StackOp, val data: D) \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/state/Data.kt b/befunge/src/main/kotlin/befide/befunge/core/state/Data.kt new file mode 100644 index 0000000..96e41de --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/state/Data.kt @@ -0,0 +1,5 @@ +package befide.befunge.core.state + +interface Data { + val char: Char? +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt b/befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt new file mode 100644 index 0000000..ca55a47 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt @@ -0,0 +1,17 @@ +package befide.befunge.core.state + +import befide.befunge.core.events.FungeChange +import befide.befunge.core.util.Event + +interface Funge { + val size: V + + val data: List> + val src: String + + fun next(pos: V, delta: V): V + + operator fun get(pos: V): D + + val onChange: Event> +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/state/MutableFunge.kt b/befunge/src/main/kotlin/befide/befunge/core/state/MutableFunge.kt new file mode 100644 index 0000000..63e66d6 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/state/MutableFunge.kt @@ -0,0 +1,10 @@ +package befide.befunge.core.state + +interface MutableFunge + : Funge { + + override var data: List> + override var src: String + + operator fun set(pos: V, data: D) +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/state/MutablePointer.kt b/befunge/src/main/kotlin/befide/befunge/core/state/MutablePointer.kt new file mode 100644 index 0000000..2107f3d --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/state/MutablePointer.kt @@ -0,0 +1,9 @@ +package befide.befunge.core.state + +interface MutablePointer> + : Pointer { + + override var pos: V + override var delta: V + override var mode: M +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/core/state/Pointer.kt b/befunge/src/main/kotlin/befide/befunge/core/state/Pointer.kt new file mode 100644 index 0000000..85d9cf9 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/core/state/Pointer.kt @@ -0,0 +1,9 @@ +package befide.befunge.core.state + +interface Pointer> { + val pos: V + val delta: V + val mode: M + + fun copy(): Pointer +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/events/Event.kt b/befunge/src/main/kotlin/befide/befunge/core/util/Event.kt similarity index 98% rename from befunge/src/main/kotlin/befide/befunge/events/Event.kt rename to befunge/src/main/kotlin/befide/befunge/core/util/Event.kt index 9ac2afa..5c3abc9 100644 --- a/befunge/src/main/kotlin/befide/befunge/events/Event.kt +++ b/befunge/src/main/kotlin/befide/befunge/core/util/Event.kt @@ -1,4 +1,4 @@ -package befide.befunge.events +package befide.befunge.core.util import java.util.function.Consumer diff --git a/befunge/src/main/kotlin/befide/befunge/core/util/Misc.kt b/befunge/src/main/kotlin/befide/befunge/core/util/Misc.kt index 61b497b..c3f147d 100644 --- a/befunge/src/main/kotlin/befide/befunge/core/util/Misc.kt +++ b/befunge/src/main/kotlin/befide/befunge/core/util/Misc.kt @@ -1,6 +1,7 @@ package befide.befunge.core.util import java.io.PipedReader +import java.util.* import kotlin.random.Random @@ -21,3 +22,7 @@ fun List.chooseOne(): T = this[Random.nextInt(size)] fun PipedReader.readAll(): String = generateSequence { if (ready()) read().toChar() else null }.joinToString("") + +inline fun Stack.pop(n: Int): List { + return (0 until n).map { pop() } +} \ No newline at end of file