separate instructionset type
This commit is contained in:
@@ -1,125 +1,32 @@
|
|||||||
package befide.befunge.b93
|
package befide.befunge.b93
|
||||||
|
|
||||||
|
import befide.befunge.b93.state.*
|
||||||
import befide.befunge.core.*
|
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.core.util.readAll
|
||||||
import befide.befunge.events.Event
|
import befide.befunge.core.util.Event
|
||||||
import java.io.PipedReader
|
import java.io.PipedReader
|
||||||
import java.io.PipedWriter
|
import java.io.PipedWriter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class Interpreter93(stdinSrc: PipedWriter, stdoutDest: PipedReader)
|
class Interpreter93(stdinSrc: PipedWriter, stdoutDest: PipedReader)
|
||||||
: Interpreter<Vec2, LongData, PointerMode> {
|
: MutableInterpreter<Vec2, LongData, PointerMode>() {
|
||||||
|
|
||||||
override val ip = Pointer93()
|
override val ip = Pointer93()
|
||||||
override val funge = Funge93()
|
override val funge = Funge93()
|
||||||
override val stack = Stack<LongData>()
|
override val stack = Stack<LongData>()
|
||||||
|
|
||||||
|
override fun stackDefault() = LongData.ZERO
|
||||||
|
|
||||||
override val onIpChange = Event<IpChange<Vec2, PointerMode>>()
|
override val onIpChange = Event<IpChange<Vec2, PointerMode>>()
|
||||||
override val onStackChange = Event<StackChange<LongData>>()
|
override val onStackChange = Event<StackChange<LongData>>()
|
||||||
|
|
||||||
override val stdin: PipedReader = PipedReader(stdinSrc)
|
override val stdin: PipedReader = PipedReader(stdinSrc)
|
||||||
override val stdout: PipedWriter = PipedWriter(stdoutDest)
|
override val stdout: PipedWriter = PipedWriter(stdoutDest)
|
||||||
|
|
||||||
private fun notifyIp(op: () -> Unit) {
|
override val instructionSet = Befunge93Instructions()
|
||||||
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<LongData>) -> 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 fun reset() {
|
override fun reset() {
|
||||||
stdin.readAll()
|
stdin.readAll()
|
||||||
@@ -133,9 +40,9 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
val int = Interpreter93(stdinSrc, stdoutDest)
|
val int = Interpreter93(stdinSrc, stdoutDest)
|
||||||
|
|
||||||
// int.onIpChange += {
|
int.onIpChange += {
|
||||||
// println(it.to.pos)
|
println(it.to.pos)
|
||||||
// }
|
}
|
||||||
|
|
||||||
int.funge.src = """2>:3g" "-!v\ g30 <
|
int.funge.src = """2>:3g" "-!v\ g30 <
|
||||||
|!`"O":+1_:.:03p>03g+:"O"`|
|
|!`"O":+1_:.:03p>03g+:"O"`|
|
||||||
@@ -144,7 +51,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
while (int.ip.mode != PointerMode.Terminated) {
|
while (int.ip.mode != PointerMode.Terminated) {
|
||||||
int.step()
|
int.step()
|
||||||
print(stdoutDest.readAll())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(stdoutDest.readAll())
|
||||||
}
|
}
|
||||||
@@ -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<Vec2, LongData, PointerMode> {
|
||||||
|
override fun MutableInterpreter<Vec2, LongData, PointerMode>.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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package befide.befunge.b93
|
package befide.befunge.b93.state
|
||||||
|
|
||||||
import befide.befunge.core.FungeChange
|
import befide.befunge.core.events.FungeChange
|
||||||
import befide.befunge.core.MutableFunge
|
import befide.befunge.core.state.MutableFunge
|
||||||
import befide.befunge.events.Event
|
import befide.befunge.core.util.Event
|
||||||
|
|
||||||
class Funge93
|
class Funge93
|
||||||
: MutableFunge<Vec2, LongData> {
|
: MutableFunge<Vec2, LongData> {
|
||||||
@@ -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
|
import befide.befunge.core.util.mod
|
||||||
|
|
||||||
data class LongData(val data: Long)
|
data class LongData(val data: Long)
|
||||||
: Data {
|
: Data {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val SPACE = LongData(' ')
|
val SPACE = LongData(' ')
|
||||||
val ZERO = LongData(0)
|
val ZERO = LongData(0)
|
||||||
@@ -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 {
|
enum class PointerMode {
|
||||||
Normal, String, Terminated
|
Normal, String, Terminated
|
||||||
@@ -9,4 +10,7 @@ enum class PointerMode {
|
|||||||
data class Pointer93(override var pos: Vec2 = Vec2.ZERO,
|
data class Pointer93(override var pos: Vec2 = Vec2.ZERO,
|
||||||
override var delta: Vec2 = Vec2.RIGHT,
|
override var delta: Vec2 = Vec2.RIGHT,
|
||||||
override var mode: PointerMode = PointerMode.Normal)
|
override var mode: PointerMode = PointerMode.Normal)
|
||||||
: MutablePointer<Vec2, PointerMode>
|
: MutablePointer<Vec2, PointerMode> {
|
||||||
|
|
||||||
|
override fun copy(): Pointer<Vec2, PointerMode> = Pointer93(pos, delta, mode)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package befide.befunge.b93
|
package befide.befunge.b93.state
|
||||||
|
|
||||||
import befide.befunge.core.util.mod
|
import befide.befunge.core.util.mod
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package befide.befunge.core
|
||||||
|
|
||||||
|
import befide.befunge.core.state.Data
|
||||||
|
|
||||||
|
interface InstructionSet<V, D : Data, M : Enum<M>> {
|
||||||
|
fun MutableInterpreter<V, D, M>.handle()
|
||||||
|
|
||||||
|
fun step(inter: MutableInterpreter<V, D, M>) = inter.handle()
|
||||||
|
}
|
||||||
@@ -1,69 +1,26 @@
|
|||||||
package befide.befunge.core
|
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.PipedReader
|
||||||
import java.io.PipedWriter
|
import java.io.PipedWriter
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
interface Pointer<V, M : Enum<M>> {
|
|
||||||
val pos: V
|
|
||||||
val delta: V
|
|
||||||
val mode: M
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MutablePointer<V, M : Enum<M>>
|
|
||||||
: Pointer<V, M> {
|
|
||||||
|
|
||||||
override var pos: V
|
|
||||||
override var delta: V
|
|
||||||
override var mode: M
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Data {
|
|
||||||
val char: Char?
|
|
||||||
}
|
|
||||||
|
|
||||||
data class FungeChange<V, D : Data>
|
|
||||||
(val funge: Funge<V, D>,
|
|
||||||
val pos: V,
|
|
||||||
val from: D,
|
|
||||||
val to: D)
|
|
||||||
|
|
||||||
interface Funge<V, D : Data> {
|
|
||||||
val size: V
|
|
||||||
|
|
||||||
val data: List<List<D>>
|
|
||||||
val src: String
|
|
||||||
|
|
||||||
fun next(pos: V, delta: V): V
|
|
||||||
|
|
||||||
operator fun get(pos: V): D
|
|
||||||
|
|
||||||
val onChange: Event<FungeChange<V, D>>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MutableFunge<V, D : Data>
|
|
||||||
: Funge<V, D> {
|
|
||||||
|
|
||||||
override var data: List<List<D>>
|
|
||||||
override var src: String
|
|
||||||
|
|
||||||
operator fun set(pos: V, data: D)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class IpChange<V, M : Enum<M>>
|
|
||||||
(val from: Pointer<V, M>, val to: Pointer<V, M>)
|
|
||||||
|
|
||||||
enum class StackOp { Push, Pop }
|
|
||||||
|
|
||||||
data class StackChange<D : Data>
|
|
||||||
(val op: StackOp, val data: D)
|
|
||||||
|
|
||||||
interface Interpreter<V, D : Data, M : Enum<M>> {
|
interface Interpreter<V, D : Data, M : Enum<M>> {
|
||||||
val ip: Pointer<V, M>
|
val ip: Pointer<V, M>
|
||||||
val funge: Funge<V, D>
|
val funge: Funge<V, D>
|
||||||
val stack: List<D>
|
val stack: List<D>
|
||||||
|
|
||||||
|
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<IpChange<V, M>>
|
val onIpChange: Event<IpChange<V, M>>
|
||||||
val onStackChange: Event<StackChange<D>>
|
val onStackChange: Event<StackChange<D>>
|
||||||
|
|
||||||
@@ -72,4 +29,5 @@ interface Interpreter<V, D : Data, M : Enum<M>> {
|
|||||||
|
|
||||||
fun step()
|
fun step()
|
||||||
fun reset()
|
fun reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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<V, D : Data, M : Enum<M>>
|
||||||
|
: Interpreter<V, D, M> {
|
||||||
|
abstract override val ip: MutablePointer<V, M>
|
||||||
|
abstract override val funge: MutableFunge<V, D>
|
||||||
|
abstract override val stack: Stack<D>
|
||||||
|
|
||||||
|
abstract val instructionSet: InstructionSet<V, D, M>
|
||||||
|
|
||||||
|
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<D> {
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package befide.befunge.core.events
|
||||||
|
|
||||||
|
import befide.befunge.core.state.Data
|
||||||
|
import befide.befunge.core.state.Funge
|
||||||
|
|
||||||
|
data class FungeChange<V, D : Data>
|
||||||
|
(val funge: Funge<V, D>,
|
||||||
|
val pos: V,
|
||||||
|
val from: D,
|
||||||
|
val to: D)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package befide.befunge.core.events
|
||||||
|
|
||||||
|
import befide.befunge.core.state.Pointer
|
||||||
|
|
||||||
|
data class IpChange<V, M : Enum<M>>
|
||||||
|
(val from: Pointer<V, M>, val to: Pointer<V, M>)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package befide.befunge.core.events
|
||||||
|
|
||||||
|
import befide.befunge.core.state.Data
|
||||||
|
|
||||||
|
enum class StackOp { Push, Pop }
|
||||||
|
|
||||||
|
data class StackChange<D : Data>
|
||||||
|
(val op: StackOp, val data: D)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package befide.befunge.core.state
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
val char: Char?
|
||||||
|
}
|
||||||
17
befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt
Normal file
17
befunge/src/main/kotlin/befide/befunge/core/state/Funge.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package befide.befunge.core.state
|
||||||
|
|
||||||
|
import befide.befunge.core.events.FungeChange
|
||||||
|
import befide.befunge.core.util.Event
|
||||||
|
|
||||||
|
interface Funge<V, D : Data> {
|
||||||
|
val size: V
|
||||||
|
|
||||||
|
val data: List<List<D>>
|
||||||
|
val src: String
|
||||||
|
|
||||||
|
fun next(pos: V, delta: V): V
|
||||||
|
|
||||||
|
operator fun get(pos: V): D
|
||||||
|
|
||||||
|
val onChange: Event<FungeChange<V, D>>
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package befide.befunge.core.state
|
||||||
|
|
||||||
|
interface MutableFunge<V, D : Data>
|
||||||
|
: Funge<V, D> {
|
||||||
|
|
||||||
|
override var data: List<List<D>>
|
||||||
|
override var src: String
|
||||||
|
|
||||||
|
operator fun set(pos: V, data: D)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package befide.befunge.core.state
|
||||||
|
|
||||||
|
interface MutablePointer<V, M : Enum<M>>
|
||||||
|
: Pointer<V, M> {
|
||||||
|
|
||||||
|
override var pos: V
|
||||||
|
override var delta: V
|
||||||
|
override var mode: M
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package befide.befunge.core.state
|
||||||
|
|
||||||
|
interface Pointer<V, M : Enum<M>> {
|
||||||
|
val pos: V
|
||||||
|
val delta: V
|
||||||
|
val mode: M
|
||||||
|
|
||||||
|
fun copy(): Pointer<V, M>
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package befide.befunge.events
|
package befide.befunge.core.util
|
||||||
|
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package befide.befunge.core.util
|
package befide.befunge.core.util
|
||||||
|
|
||||||
import java.io.PipedReader
|
import java.io.PipedReader
|
||||||
|
import java.util.*
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
@@ -21,3 +22,7 @@ fun <T> List<T>.chooseOne(): T = this[Random.nextInt(size)]
|
|||||||
fun PipedReader.readAll(): String = generateSequence {
|
fun PipedReader.readAll(): String = generateSequence {
|
||||||
if (ready()) read().toChar() else null
|
if (ready()) read().toChar() else null
|
||||||
}.joinToString("")
|
}.joinToString("")
|
||||||
|
|
||||||
|
inline fun <reified T> Stack<T>.pop(n: Int): List<T> {
|
||||||
|
return (0 until n).map { pop() }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user