better multithreaded streams behavior
This commit is contained in:
@@ -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<Vec2, Data93, PointerMode>() {
|
||||
|
||||
override val ip = Pointer93()
|
||||
override val funge = Funge93()
|
||||
override val stack = Stack<Data93>()
|
||||
|
||||
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<String>) {
|
||||
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())
|
||||
}
|
||||
@@ -45,23 +45,27 @@ class B93Instructions : InstructionSet<Vec2, Data93, PointerMode> {
|
||||
'\\' -> 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
|
||||
}
|
||||
}
|
||||
31
befunge/src/main/kotlin/befide/befunge/b93/Interpreter93.kt
Normal file
31
befunge/src/main/kotlin/befide/befunge/b93/Interpreter93.kt
Normal file
@@ -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<Vec2, Data93, PointerMode>() {
|
||||
|
||||
override val ip = Pointer93()
|
||||
override val funge = Funge93()
|
||||
override val stack = Stack<Data93>()
|
||||
|
||||
override fun stackDefault() = Data93.ZERO
|
||||
|
||||
override val instructionSet = B93Instructions() + B93Extras()
|
||||
|
||||
override fun run(afterEach: () -> Unit) {
|
||||
while (mode != PointerMode.Terminated) {
|
||||
step()
|
||||
afterEach()
|
||||
stdout?.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
67
befunge/src/main/kotlin/befide/befunge/b93/Main.kt
Normal file
67
befunge/src/main/kotlin/befide/befunge/b93/Main.kt
Normal file
@@ -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<String>) {
|
||||
println("synchronous:")
|
||||
runSync()
|
||||
|
||||
println()
|
||||
|
||||
println("threaded:")
|
||||
runThreaded()
|
||||
}
|
||||
@@ -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<V, D : Data, M : Enum<M>> {
|
||||
val ip: Pointer<V, M>
|
||||
@@ -20,14 +22,15 @@ interface Interpreter<V, D : Data, M : Enum<M>> {
|
||||
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<IpChange<V, M>>
|
||||
val onStackChange: Event<StackChange<D>>
|
||||
|
||||
val stdin: PipedReader
|
||||
val stdout: PipedWriter
|
||||
var stdin: Reader?
|
||||
val stdout: Writer?
|
||||
|
||||
fun step()
|
||||
fun reset()
|
||||
fun run(afterEach: () -> Unit)
|
||||
}
|
||||
|
||||
|
||||
@@ -68,9 +68,4 @@ abstract class MutableInterpreter<V, D : Data, M : Enum<M>>
|
||||
notifyStack(StackOp.Push) { stack.push(datum) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
stdin.readAll()
|
||||
stdout.flush()
|
||||
}
|
||||
}
|
||||
@@ -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 <T> List<T>.chooseOne(): T = this[Random.nextInt(size)]
|
||||
|
||||
fun PipedReader.readAll(): String = generateSequence {
|
||||
if (ready()) read().toChar() else null
|
||||
}.joinToString("")
|
||||
fun <T> Boolean.orNull(block: () -> T): T? = if (this) block() else null
|
||||
|
||||
inline fun <reified T> Stack<T>.pop(n: Int): List<T> {
|
||||
return (0 until n).map { pop() }
|
||||
}
|
||||
fun Reader.readAll(): String = generateSequence {
|
||||
ready().orNull { read().toChar() }
|
||||
}.joinToString("")
|
||||
|
||||
Reference in New Issue
Block a user