diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt b/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt deleted file mode 100644 index 045b94d..0000000 --- a/befunge/src/main/kotlin/befide/befunge/b93/Befunge93.kt +++ /dev/null @@ -1,52 +0,0 @@ -package befide.befunge.b93 - -import befide.befunge.b93.state.* -import befide.befunge.core.* -import befide.befunge.core.util.readAll -import java.io.PipedReader -import java.io.PipedWriter -import java.util.* - - -class Interpreter93(stdinSrc: PipedWriter, stdoutDest: PipedReader) - : MutableInterpreter() { - - override val ip = Pointer93() - override val funge = Funge93() - override val stack = Stack() - - override fun stackDefault() = Data93.ZERO - - override val stdin: PipedReader = PipedReader(stdinSrc) - override val stdout: PipedWriter = PipedWriter(stdoutDest) - - override val instructionSet = B93Instructions() + B93Extras() -} - -fun main(args: Array) { - val stdinSrc = PipedWriter() - val stdoutDest = PipedReader() - - val int = Interpreter93(stdinSrc, stdoutDest) - - int.funge.onChange += { (pos, from, to) -> - println("$pos from $from to $to") - } - - int.onIpChange += { (_, to) -> - println("ip to ${to.pos}") - } - - int.funge.src = """2>:3g" "-!v\ g30 < - |!`"O":+1_:.:03p>03g+:"O"`| - @ ^ p3\" ":< -2 234567890123456789012345678901234567890123456789012345678901234567890123456789""" - -// int.funge.src = """fedc;ba9876;54321>:#._@""" - - while (int.ip.mode != PointerMode.Terminated) { - int.step() - } - - print(stdoutDest.readAll()) -} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Instructions.kt b/befunge/src/main/kotlin/befide/befunge/b93/Instructions93.kt similarity index 86% rename from befunge/src/main/kotlin/befide/befunge/b93/Instructions.kt rename to befunge/src/main/kotlin/befide/befunge/b93/Instructions93.kt index a5b1b11..ec8fffa 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/Instructions.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/Instructions93.kt @@ -45,23 +45,27 @@ class B93Instructions : InstructionSet { '\\' -> pop(2).let { (b, a) -> push(b, a) } '$' -> pop(1) - '.' -> pop(1).let { (n) -> stdout.write("${n.data} ") } - ',' -> pop(1).let { (ch) -> stdout.write(ch.data.toChar().toString()) } + '.' -> pop(1).let { (n) -> stdout?.write("${n.data} ") } + ',' -> pop(1).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(Data93(stdin.read().toLong())) + '~' -> push(Data93(stdin?.read()?.toLong() ?: 0L)) '&' -> { val chars = generateSequence { - stdin.read().takeIf { it.toChar().isDigit() } + stdin?.read()?.toChar()?.takeIf { it.isDigit() } } - val long = chars.joinToString("").toLong() + val long = chars.joinToString("") { + it.toString() + }.ifEmpty { "0" }.toLong() push(Data93(long)) } '@' -> mode = PointerMode.Terminated + ' ' -> do move() while (next.char == ' ') + else -> return false } } diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Interpreter93.kt b/befunge/src/main/kotlin/befide/befunge/b93/Interpreter93.kt new file mode 100644 index 0000000..45ca9cd --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/b93/Interpreter93.kt @@ -0,0 +1,31 @@ +package befide.befunge.b93 + +import befide.befunge.b93.state.* +import befide.befunge.core.* +import befide.befunge.core.util.readAll +import com.sun.imageio.spi.OutputStreamImageOutputStreamSpi +import java.io.* +import java.util.* +import kotlin.concurrent.thread +import kotlin.concurrent.timer + + +class Interpreter93(override var stdin: Reader? = null, override var stdout: Writer? = null) + : MutableInterpreter() { + + override val ip = Pointer93() + override val funge = Funge93() + override val stack = Stack() + + override fun stackDefault() = Data93.ZERO + + override val instructionSet = B93Instructions() + B93Extras() + + override fun run(afterEach: () -> Unit) { + while (mode != PointerMode.Terminated) { + step() + afterEach() + stdout?.flush() + } + } +} diff --git a/befunge/src/main/kotlin/befide/befunge/b93/Main.kt b/befunge/src/main/kotlin/befide/befunge/b93/Main.kt new file mode 100644 index 0000000..edf38f3 --- /dev/null +++ b/befunge/src/main/kotlin/befide/befunge/b93/Main.kt @@ -0,0 +1,67 @@ +package befide.befunge.b93 + +import befide.befunge.core.util.readAll +import java.io.PipedReader +import java.io.PipedWriter +import kotlin.concurrent.thread +import kotlin.concurrent.timer + + +fun runSync() { + val int = Interpreter93(System.`in`.reader(), System.out.writer()) + + // interactive calculator + int.funge.src = "\" :b ]%/*-+[ a\">:#,_&~~\$a3*0p& .@" + + int.run {} + + println() +} + +fun runThreaded() { + val stdout = PipedReader() + val stdin = PipedWriter() + + val int = Interpreter93(PipedReader(stdin), PipedWriter(stdout)) + + // incrementer + int.funge.src = ":.&+" + + val input = timer("input", period = 50L) { + generateSequence { + System.`in`.read().takeUnless { it == -1 } + }.forEach(stdin::write) + } + + val output = timer("output", period = 500L) { + print(stdout.readAll()) + } + + val stepper = thread { + int.run { Thread.sleep(50L) } + } + + // input, output, and computation happen concurrently at this point. + + stepper.join() + + input.cancel() + output.cancel() + + println(stdout.readAll()) + + int.stdout?.close() + stdout.close() + int.stdin?.close() + stdin.close() +} + +fun main(args: Array) { + println("synchronous:") + runSync() + + println() + + println("threaded:") + runThreaded() +} \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/state/Vec2.kt b/befunge/src/main/kotlin/befide/befunge/b93/state/Vec93.kt similarity index 100% rename from befunge/src/main/kotlin/befide/befunge/b93/state/Vec2.kt rename to befunge/src/main/kotlin/befide/befunge/b93/state/Vec93.kt diff --git a/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt index a2f201e..49a06e5 100644 --- a/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/core/Interpreter.kt @@ -8,6 +8,8 @@ import befide.befunge.core.state.Pointer import befide.befunge.core.util.Event import java.io.PipedReader import java.io.PipedWriter +import java.io.Reader +import java.io.Writer interface Interpreter> { val ip: Pointer @@ -20,14 +22,15 @@ interface Interpreter> { val delta: V get() = ip.delta val pos: V get() = ip.pos val instr: D get() = funge[ip.pos] + val next: D get() = funge[funge.next(pos, delta)] val onIpChange: Event> val onStackChange: Event> - val stdin: PipedReader - val stdout: PipedWriter + var stdin: Reader? + val stdout: Writer? fun step() - fun reset() + fun run(afterEach: () -> Unit) } diff --git a/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt b/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt index 335cc61..67d10a2 100644 --- a/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/core/MutableInterpreter.kt @@ -68,9 +68,4 @@ abstract class MutableInterpreter> notifyStack(StackOp.Push) { stack.push(datum) } } } - - override fun reset() { - stdin.readAll() - stdout.flush() - } } \ No newline at end of file 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 c3f147d..f0b8902 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.io.Reader import java.util.* import kotlin.random.Random @@ -19,10 +20,8 @@ infix fun Long.mod(o: Long): Long { fun List.chooseOne(): T = this[Random.nextInt(size)] -fun PipedReader.readAll(): String = generateSequence { - if (ready()) read().toChar() else null -}.joinToString("") +fun Boolean.orNull(block: () -> T): T? = if (this) block() else null -inline fun Stack.pop(n: Int): List { - return (0 until n).map { pop() } -} \ No newline at end of file +fun Reader.readAll(): String = generateSequence { + ready().orNull { read().toChar() } +}.joinToString("")