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(2).let { (b, a) -> push(b, a) }
|
||||||
'$' -> pop(1)
|
'$' -> pop(1)
|
||||||
|
|
||||||
'.' -> pop(1).let { (n) -> stdout.write("${n.data} ") }
|
'.' -> pop(1).let { (n) -> stdout?.write("${n.data} ") }
|
||||||
',' -> pop(1).let { (ch) -> stdout.write(ch.data.toChar().toString()) }
|
',' -> 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 }
|
'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())]) }
|
'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 {
|
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))
|
push(Data93(long))
|
||||||
}
|
}
|
||||||
|
|
||||||
'@' -> mode = PointerMode.Terminated
|
'@' -> mode = PointerMode.Terminated
|
||||||
|
|
||||||
|
' ' -> do move() while (next.char == ' ')
|
||||||
|
|
||||||
else -> return false
|
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 befide.befunge.core.util.Event
|
||||||
import java.io.PipedReader
|
import java.io.PipedReader
|
||||||
import java.io.PipedWriter
|
import java.io.PipedWriter
|
||||||
|
import java.io.Reader
|
||||||
|
import java.io.Writer
|
||||||
|
|
||||||
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>
|
||||||
@@ -20,14 +22,15 @@ interface Interpreter<V, D : Data, M : Enum<M>> {
|
|||||||
val delta: V get() = ip.delta
|
val delta: V get() = ip.delta
|
||||||
val pos: V get() = ip.pos
|
val pos: V get() = ip.pos
|
||||||
val instr: D get() = funge[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 onIpChange: Event<IpChange<V, M>>
|
||||||
val onStackChange: Event<StackChange<D>>
|
val onStackChange: Event<StackChange<D>>
|
||||||
|
|
||||||
val stdin: PipedReader
|
var stdin: Reader?
|
||||||
val stdout: PipedWriter
|
val stdout: Writer?
|
||||||
|
|
||||||
fun step()
|
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) }
|
notifyStack(StackOp.Push) { stack.push(datum) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reset() {
|
|
||||||
stdin.readAll()
|
|
||||||
stdout.flush()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package befide.befunge.core.util
|
package befide.befunge.core.util
|
||||||
|
|
||||||
import java.io.PipedReader
|
import java.io.PipedReader
|
||||||
|
import java.io.Reader
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.random.Random
|
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 <T> List<T>.chooseOne(): T = this[Random.nextInt(size)]
|
||||||
|
|
||||||
fun PipedReader.readAll(): String = generateSequence {
|
fun <T> Boolean.orNull(block: () -> T): T? = if (this) block() else null
|
||||||
if (ready()) read().toChar() else null
|
|
||||||
}.joinToString("")
|
|
||||||
|
|
||||||
inline fun <reified T> Stack<T>.pop(n: Int): List<T> {
|
fun Reader.readAll(): String = generateSequence {
|
||||||
return (0 until n).map { pop() }
|
ready().orNull { read().toChar() }
|
||||||
}
|
}.joinToString("")
|
||||||
|
|||||||
Reference in New Issue
Block a user