From ae6cc7e455c2a0820a16077673ceb3e8c949ad55 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 01:54:17 -0500 Subject: [PATCH 1/6] Implement B93Funge, B93Pointer, and P93Interpreter, excluding IO Remove Char from IpMode Change Value to hold Long instead of Int --- befunge/befunge.iml | 11 +- .../kotlin/befide/befunge/b93/B93Funge.kt | 44 +++- .../befide/befunge/b93/B93Interpreter.kt | 235 +++++++++++++++++- .../kotlin/befide/befunge/b93/B93Pointer.kt | 2 +- .../kotlin/befide/befunge/state/IpMode.kt | 1 - .../main/kotlin/befide/befunge/state/Value.kt | 4 +- ide/ide.iml | 17 +- 7 files changed, 298 insertions(+), 16 deletions(-) diff --git a/befunge/befunge.iml b/befunge/befunge.iml index 6cea5be..c1a7461 100644 --- a/befunge/befunge.iml +++ b/befunge/befunge.iml @@ -7,7 +7,7 @@ @@ -37,5 +37,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt index c7019d4..5244407 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Funge.kt @@ -6,21 +6,57 @@ import befide.befunge.state.* class B93Funge : Funge { override val width = 80 override val height = 25 + private var cars = Array(height) { Array(width) {' '.toLong()}} override fun get(vec: Vec): Value { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + return Value(cars[vec.y][vec.x]) } override fun set(vec: Vec, value: Value) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + cars[vec.y][vec.x] = value.value } override fun nextVec(vec: Vec, delta: Vec): Vec { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + var x = vec.x + delta.x + var y = vec.y + delta.y + if (x >= width || x < 0) { + x %= width + } + if (x < 0) { + x += width + } + if (y >= height || y < 0) { + y %= height + } + if (y < 0) { + y += height + } + + return Vec(x,y) } override fun setString(data: String) { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val strings = data.split('\n') + for (i in strings.size until height) { + cars[i] = Array(width) {' '.toLong()} + } + strings.map { + it.toList().map{it.toLong()} + } + .forEachIndexed { index, list -> + if (index > height) { + return + } + cars[index] = ( + list.toList() + List( + if (list.size <= width) width - list.size else 0 + ){ + ' '.toLong() + } + ) + .subList(0, width) + .toTypedArray() + } } } diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt index 4cfa6f5..ae01f99 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt @@ -1,16 +1,21 @@ package befide.befunge.b93 import befide.befunge.core.Interpreter -import befide.befunge.events.Event -import befide.befunge.events.FungeEvent -import befide.befunge.events.IpEvent -import befide.befunge.events.StackEvent +import befide.befunge.core.Pointer +import befide.befunge.events.* import befide.befunge.state.IpMode import befide.befunge.state.Value import befide.befunge.state.Vec import java.util.* class B93Interpreter : Interpreter { + private companion object { + val RIGHT = Vec(1, 0) + val LEFT = Vec(-1, 0) + val UP = Vec(0, -1) + val DOWN = Vec(0,1) + } + override val funge = B93Funge() override val stack = Stack() override val ip = B93Pointer(Vec(0, 0), Vec(1, 0), IpMode.Normal) @@ -19,11 +24,229 @@ class B93Interpreter : Interpreter { override val stackChanged: Event = Event() override val ipChanged: Event = Event() + private val fungeMods = HashMap() + + + private fun binop(bop: Char) { + val vb = stack.pop() + val va = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vb, va))) + val a = va.value + val b = vb.value + val res = when(bop) { + '+' -> a + b + '-' -> a - b + '*' -> a * b + '/' -> a / b + '`' -> if (a > b) 1L else 0L + else -> null + } + if (res != null) { + val vres = Value(res) + stack.push(vres) + stackChanged.invoke(StackEvent(StackAction.Push, listOf(vres))) + } + } + + private fun unop(uop: Char) { + val vv = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv))) + val v = vv.value + val res = when(uop) { + '!' -> if (v == 0L) 1L else 0L + else -> null + } + if (res != null) { + val vres = Value(res) + stack.push(vres) + stackChanged.invoke(StackEvent(StackAction.Push, listOf(vres))) + } + } + + private fun changeDir(dir: Char) { + val newDelta = when(dir) { + '>' -> RIGHT + '<' -> LEFT + '^' -> UP + 'v' -> DOWN + else -> null + } + if (newDelta != null) { + ip.delta = newDelta + } + } + + private fun randomDir() { + val dirs = listOf('<', '>', '^', 'v') + val ind = Random().nextInt(4) + changeDir(dirs[ind]) + } + + private fun conditional(cop: Char) { + val vcond = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vcond))) + val cond = vcond.value == 0L + val newDelta = when(cop) { + '|' -> if (cond) DOWN else UP + '_' -> if (cond) RIGHT else LEFT + else -> null + } + if (newDelta != null) { + ip.delta = newDelta + } + } + + private fun toggleStrmode() { + val newMode = when (ip.mode) { + IpMode.String -> IpMode.Normal + IpMode.Normal -> IpMode.String + IpMode.Inactive -> IpMode.Inactive + } + ip.mode = newMode + } + + private fun stackop(sop: Char) { + val vv2 = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv2))) + when (sop) { + ':' -> { + val vv2c = vv2.copy() + stack.push(vv2) + stack.push(vv2c) + stackChanged.invoke(StackEvent(StackAction.Push, listOf(vv2, vv2c))) + } + '\\' -> { + val vv1 = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv2))) + stack.push(vv2) + stack.push(vv1) + stackChanged.invoke(StackEvent(StackAction.Push, listOf(vv1, vv2))) + } + '$' -> noOp() + } + } + + private fun output(type: Char) { + val vv = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv))) + val v = vv.value + val out = when (type) { + '.' -> v.toString().toCharArray() + ',' -> charArrayOf(v.toChar()) + else -> charArrayOf() + } + //TODO output {out} chararray + } + + private fun stepIP() { + ip.pos = funge.nextVec(ip.pos, ip.delta) + // No ipChanged here, shown in execInstr + } + + private fun input() { + val inp = 0L //TODO get input + val vinp = Value(inp) + stack.push(vinp) + stackChanged(StackEvent(StackAction.Push, listOf(vinp))) + } + + private fun fget() { + val vy = stack.pop() + val vx = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vy, vx))) + val x = vx.value.toInt() + val y = vy.value.toInt() + if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { + val vv = funge[Vec(x, y)] + stack.push(vv) + stackChanged(StackEvent(StackAction.Push, listOf(vv))) + } + } + + private fun fput() { + val vy = stack.pop() + val vx = stack.pop() + val vv = stack.pop() + stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vy, vx, vv))) + val x = vx.value.toInt() + val y = vy.value.toInt() + if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { + val loc = Vec(x, y) + val old = funge[loc] + funge[loc] = vv + if (!fungeMods.contains(loc)) { + fungeMods[loc] = old + } + fungeChanged(FungeEvent(listOf(FungeChange(loc,old,vv)))) + } + } + + private fun terminate() { + ip.mode = IpMode.Inactive + } + + private fun noOp() {} + + private fun execInstr(instr: Value) { + val car = instr.asChar + when (car) { + null -> noOp() + '+', '-', '*', '/', '%', '`' -> binop(car) + '!' -> unop(car) + '>', '<', '^', 'v' -> changeDir(car) + '?' -> randomDir() + '_', '|' -> conditional(car) + '"' -> toggleStrmode() + ':', '\\', '$' -> stackop(car) + '.', ',' -> output(car) + '#' -> stepIP() + 'g' -> fget() + 'p' -> fput() + '&', '~' -> input() + '@' -> terminate() + else -> noOp() + } + } + + private fun pushCar(v: Value) { + stack.push(v) + stackChanged(StackEvent(StackAction.Push, listOf(v))) + } + override fun step(): Boolean { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val instr = funge[ip.pos] + val currIP = ip.copy() + when (ip.mode) { + IpMode.Inactive -> noOp() + IpMode.Normal -> execInstr(instr) + IpMode.String -> pushCar(instr) + } + if (ip.mode != IpMode.Inactive) { + stepIP() + while (funge[ip.pos].asChar == ' ') { + stepIP() + } + val newIP = ip.copy() + ipChanged(IpEvent(currIP, newIP)) + } + return true } override fun reset() { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + val oldIP = ip.copy() + ip.pos = Vec(0,0) + ip.delta = RIGHT + ip.mode = IpMode.Normal + val newIP = ip.copy() + ipChanged.invoke(IpEvent(oldIP, newIP)) + + stack.clear() + stackChanged(StackEvent(StackAction.Clear, listOf())) + + val changes = fungeMods.map { FungeChange(it.key, funge[it.key], it.value) } + for ((k,v) in fungeMods) { + funge[k] = v + } + fungeChanged(FungeEvent(changes)) } } \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt index f1a2fdf..ffadaf5 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Pointer.kt @@ -4,4 +4,4 @@ import befide.befunge.core.Pointer import befide.befunge.state.IpMode import befide.befunge.state.Vec -data class B93Pointer(override val pos: Vec, override val delta: Vec, override val mode: IpMode) : Pointer \ No newline at end of file +data class B93Pointer(override var pos: Vec, override var delta: Vec, override var mode: IpMode) : Pointer \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt b/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt index 511168b..16af492 100644 --- a/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt +++ b/befunge/src/main/kotlin/befide/befunge/state/IpMode.kt @@ -3,6 +3,5 @@ package befide.befunge.state enum class IpMode { Normal, String, - Char, Inactive } \ No newline at end of file diff --git a/befunge/src/main/kotlin/befide/befunge/state/Value.kt b/befunge/src/main/kotlin/befide/befunge/state/Value.kt index 3884051..dd469fe 100644 --- a/befunge/src/main/kotlin/befide/befunge/state/Value.kt +++ b/befunge/src/main/kotlin/befide/befunge/state/Value.kt @@ -1,7 +1,7 @@ package befide.befunge.state -data class Value(val value: Int) { - constructor(value: Char) : this(value.toInt()) +data class Value(val value: Long) { + constructor(value: Char) : this(value.toLong()) val asChar: Char? = if (value in (32..126)) value.toChar() else null } \ No newline at end of file diff --git a/ide/ide.iml b/ide/ide.iml index d51fa71..176e2b1 100644 --- a/ide/ide.iml +++ b/ide/ide.iml @@ -7,7 +7,7 @@ @@ -29,6 +29,21 @@ + + + + + + + + + + + + + + + From f11bce518b7c463a0616f92e6ef4f2d8cf07b91c Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 01:56:09 -0500 Subject: [PATCH 2/6] Update local Kotlin version --- befunge/befunge.iml | 2 +- ide/ide.iml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/befunge/befunge.iml b/befunge/befunge.iml index c1a7461..da87f9f 100644 --- a/befunge/befunge.iml +++ b/befunge/befunge.iml @@ -7,7 +7,7 @@ diff --git a/ide/ide.iml b/ide/ide.iml index 176e2b1..86b45e9 100644 --- a/ide/ide.iml +++ b/ide/ide.iml @@ -7,7 +7,7 @@ From 34692a4bd91ce783761da30e368542479b0b1c19 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 02:25:16 -0500 Subject: [PATCH 3/6] Add methods to handle pushing and popping to the stack (pop returns Value(0) if it is empty, does not invoke stackChanged) --- .../befide/befunge/b93/B93Interpreter.kt | 93 ++++++++++--------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt index ae01f99..3a9a44d 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt @@ -26,11 +26,42 @@ class B93Interpreter : Interpreter { private val fungeMods = HashMap() + private fun _pop(): Value? { + if (!stack.empty()) + return stack.pop() + return null + } + + private fun popOne(): Value { + val v = _pop() + if (v != null) { + stackChanged(StackEvent(StackAction.Pop, listOf(v))) + } + return Value(0) + } + + private fun popMany(num: Int): List { + val vs = List(num) {_pop()} + stackChanged(StackEvent(StackAction.Pop, vs.filterNotNull())) + return vs.map { it ?: Value(0) } + } + + private fun _push(v: Value) { + stack.push(v) + } + + private fun pushOne(v: Value) { + _push(v) + stackChanged.invoke(StackEvent(StackAction.Push, listOf(v))) + } + + private fun pushMany(vs: List) { + vs.forEach { _push(it) } + stackChanged.invoke(StackEvent(StackAction.Push, vs)) + } private fun binop(bop: Char) { - val vb = stack.pop() - val va = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vb, va))) + val (vb, va) = popMany(2) val a = va.value val b = vb.value val res = when(bop) { @@ -43,14 +74,12 @@ class B93Interpreter : Interpreter { } if (res != null) { val vres = Value(res) - stack.push(vres) - stackChanged.invoke(StackEvent(StackAction.Push, listOf(vres))) + pushOne(vres) } } private fun unop(uop: Char) { - val vv = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv))) + val vv = popOne() val v = vv.value val res = when(uop) { '!' -> if (v == 0L) 1L else 0L @@ -58,8 +87,7 @@ class B93Interpreter : Interpreter { } if (res != null) { val vres = Value(res) - stack.push(vres) - stackChanged.invoke(StackEvent(StackAction.Push, listOf(vres))) + pushOne(vres) } } @@ -83,8 +111,7 @@ class B93Interpreter : Interpreter { } private fun conditional(cop: Char) { - val vcond = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vcond))) + val vcond = popOne() val cond = vcond.value == 0L val newDelta = when(cop) { '|' -> if (cond) DOWN else UP @@ -106,29 +133,23 @@ class B93Interpreter : Interpreter { } private fun stackop(sop: Char) { - val vv2 = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv2))) when (sop) { ':' -> { - val vv2c = vv2.copy() - stack.push(vv2) - stack.push(vv2c) - stackChanged.invoke(StackEvent(StackAction.Push, listOf(vv2, vv2c))) + val vc = stack.peek().copy() + pushOne(vc) } '\\' -> { - val vv1 = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv2))) - stack.push(vv2) - stack.push(vv1) - stackChanged.invoke(StackEvent(StackAction.Push, listOf(vv1, vv2))) + val (v2, v1) = popMany(2) + pushMany(listOf(v1, v2)) + } + '$' -> { + popOne() } - '$' -> noOp() } } private fun output(type: Char) { - val vv = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vv))) + val vv = popOne() val v = vv.value val out = when (type) { '.' -> v.toString().toCharArray() @@ -146,28 +167,21 @@ class B93Interpreter : Interpreter { private fun input() { val inp = 0L //TODO get input val vinp = Value(inp) - stack.push(vinp) - stackChanged(StackEvent(StackAction.Push, listOf(vinp))) + pushOne(vinp) } private fun fget() { - val vy = stack.pop() - val vx = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vy, vx))) + val (vy, vx) = popMany(2) val x = vx.value.toInt() val y = vy.value.toInt() if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { val vv = funge[Vec(x, y)] - stack.push(vv) - stackChanged(StackEvent(StackAction.Push, listOf(vv))) + pushOne(vv) } } private fun fput() { - val vy = stack.pop() - val vx = stack.pop() - val vv = stack.pop() - stackChanged.invoke(StackEvent(StackAction.Pop, listOf(vy, vx, vv))) + val (vy, vx, vv) = popMany(3) val x = vx.value.toInt() val y = vy.value.toInt() if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { @@ -208,18 +222,13 @@ class B93Interpreter : Interpreter { } } - private fun pushCar(v: Value) { - stack.push(v) - stackChanged(StackEvent(StackAction.Push, listOf(v))) - } - override fun step(): Boolean { val instr = funge[ip.pos] val currIP = ip.copy() when (ip.mode) { IpMode.Inactive -> noOp() IpMode.Normal -> execInstr(instr) - IpMode.String -> pushCar(instr) + IpMode.String -> pushOne(instr) } if (ip.mode != IpMode.Inactive) { stepIP() From 247d9d4d52e482ae173f0c48804d11a5c90442c2 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 02:30:36 -0500 Subject: [PATCH 4/6] Change method signatures from popOne and popMany to just pop Change method signatures from pushOne and pushMany to just push --- .../befide/befunge/b93/B93Interpreter.kt | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt index 3a9a44d..6db61d9 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt @@ -1,7 +1,6 @@ package befide.befunge.b93 import befide.befunge.core.Interpreter -import befide.befunge.core.Pointer import befide.befunge.events.* import befide.befunge.state.IpMode import befide.befunge.state.Value @@ -32,7 +31,7 @@ class B93Interpreter : Interpreter { return null } - private fun popOne(): Value { + private fun pop(): Value { val v = _pop() if (v != null) { stackChanged(StackEvent(StackAction.Pop, listOf(v))) @@ -40,7 +39,7 @@ class B93Interpreter : Interpreter { return Value(0) } - private fun popMany(num: Int): List { + private fun pop(num: Int): List { val vs = List(num) {_pop()} stackChanged(StackEvent(StackAction.Pop, vs.filterNotNull())) return vs.map { it ?: Value(0) } @@ -50,18 +49,18 @@ class B93Interpreter : Interpreter { stack.push(v) } - private fun pushOne(v: Value) { + private fun push(v: Value) { _push(v) stackChanged.invoke(StackEvent(StackAction.Push, listOf(v))) } - private fun pushMany(vs: List) { + private fun push(vs: List) { vs.forEach { _push(it) } stackChanged.invoke(StackEvent(StackAction.Push, vs)) } private fun binop(bop: Char) { - val (vb, va) = popMany(2) + val (vb, va) = pop(2) val a = va.value val b = vb.value val res = when(bop) { @@ -74,12 +73,12 @@ class B93Interpreter : Interpreter { } if (res != null) { val vres = Value(res) - pushOne(vres) + push(vres) } } private fun unop(uop: Char) { - val vv = popOne() + val vv = pop() val v = vv.value val res = when(uop) { '!' -> if (v == 0L) 1L else 0L @@ -87,7 +86,7 @@ class B93Interpreter : Interpreter { } if (res != null) { val vres = Value(res) - pushOne(vres) + push(vres) } } @@ -111,7 +110,7 @@ class B93Interpreter : Interpreter { } private fun conditional(cop: Char) { - val vcond = popOne() + val vcond = pop() val cond = vcond.value == 0L val newDelta = when(cop) { '|' -> if (cond) DOWN else UP @@ -136,20 +135,20 @@ class B93Interpreter : Interpreter { when (sop) { ':' -> { val vc = stack.peek().copy() - pushOne(vc) + push(vc) } '\\' -> { - val (v2, v1) = popMany(2) - pushMany(listOf(v1, v2)) + val (v2, v1) = pop(2) + push(listOf(v1, v2)) } '$' -> { - popOne() + pop() } } } private fun output(type: Char) { - val vv = popOne() + val vv = pop() val v = vv.value val out = when (type) { '.' -> v.toString().toCharArray() @@ -167,21 +166,21 @@ class B93Interpreter : Interpreter { private fun input() { val inp = 0L //TODO get input val vinp = Value(inp) - pushOne(vinp) + push(vinp) } private fun fget() { - val (vy, vx) = popMany(2) + val (vy, vx) = pop(2) val x = vx.value.toInt() val y = vy.value.toInt() if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { val vv = funge[Vec(x, y)] - pushOne(vv) + push(vv) } } private fun fput() { - val (vy, vx, vv) = popMany(3) + val (vy, vx, vv) = pop(3) val x = vx.value.toInt() val y = vy.value.toInt() if (0 <= x && x < funge.width && 0 <= y && y <= funge.height) { @@ -228,7 +227,7 @@ class B93Interpreter : Interpreter { when (ip.mode) { IpMode.Inactive -> noOp() IpMode.Normal -> execInstr(instr) - IpMode.String -> pushOne(instr) + IpMode.String -> push(instr) } if (ip.mode != IpMode.Inactive) { stepIP() From d7948e639cd7bb8ccdd962d19764786923bf8f46 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 15:22:33 -0500 Subject: [PATCH 5/6] Minor fixes Add '%' operation (accidentally omitted) Add strMode function to properly handle String mode (broken before) Change null checks to use null say let Add peek function to handle peeking an empty stack (returns 0) Fix '\' operation (broken, did not swap top 2 stack elements) Add temporary output handling for testing Add temporary input handling for testing Add '0' - '9' operations (unintentionally omitted before) Fix skipping spaces while in String mode Step returns whether pointer is inactive or not; whether the program has terminated --- .../befide/befunge/b93/B93Interpreter.kt | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt index 6db61d9..d887514 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt @@ -33,10 +33,11 @@ class B93Interpreter : Interpreter { private fun pop(): Value { val v = _pop() - if (v != null) { - stackChanged(StackEvent(StackAction.Pop, listOf(v))) - } - return Value(0) + val ret = v?.let { + stackChanged(StackEvent(StackAction.Pop, listOf(it))) + it + } ?: Value(0) + return ret } private fun pop(num: Int): List { @@ -59,6 +60,13 @@ class B93Interpreter : Interpreter { stackChanged.invoke(StackEvent(StackAction.Push, vs)) } + private fun peek(): Value { + if (!stack.empty()) { + return stack.peek() + } + return Value(0) + } + private fun binop(bop: Char) { val (vb, va) = pop(2) val a = va.value @@ -68,10 +76,11 @@ class B93Interpreter : Interpreter { '-' -> a - b '*' -> a * b '/' -> a / b + '%' -> a % b '`' -> if (a > b) 1L else 0L else -> null } - if (res != null) { + res?.let { val vres = Value(res) push(vres) } @@ -84,8 +93,8 @@ class B93Interpreter : Interpreter { '!' -> if (v == 0L) 1L else 0L else -> null } - if (res != null) { - val vres = Value(res) + res?.let { + val vres = Value(it) push(vres) } } @@ -98,8 +107,8 @@ class B93Interpreter : Interpreter { 'v' -> DOWN else -> null } - if (newDelta != null) { - ip.delta = newDelta + newDelta?.let { + ip.delta = it } } @@ -117,8 +126,8 @@ class B93Interpreter : Interpreter { '_' -> if (cond) RIGHT else LEFT else -> null } - if (newDelta != null) { - ip.delta = newDelta + newDelta?.let { + ip.delta = it } } @@ -134,12 +143,12 @@ class B93Interpreter : Interpreter { private fun stackop(sop: Char) { when (sop) { ':' -> { - val vc = stack.peek().copy() + val vc = peek().copy() push(vc) } '\\' -> { val (v2, v1) = pop(2) - push(listOf(v1, v2)) + push(listOf(v2, v1)) } '$' -> { pop() @@ -151,10 +160,11 @@ class B93Interpreter : Interpreter { val vv = pop() val v = vv.value val out = when (type) { - '.' -> v.toString().toCharArray() + '.' -> v.toString().toCharArray() + ' ' ',' -> charArrayOf(v.toChar()) else -> charArrayOf() } + print(out) //TEMPORARY //TODO output {out} chararray } @@ -163,9 +173,13 @@ class B93Interpreter : Interpreter { // No ipChanged here, shown in execInstr } - private fun input() { - val inp = 0L //TODO get input - val vinp = Value(inp) + private fun input(type: Char) { + val inp = readLine() + val vinp = Value(when(type) { + '&' -> inp?.toLong() ?: 0L + '~' -> inp?.get(0)?.toLong() ?: 0L + else -> 0L + }) push(vinp) } @@ -198,6 +212,11 @@ class B93Interpreter : Interpreter { ip.mode = IpMode.Inactive } + private fun pushDig(dig: Char) { + val num = dig.toLong() - '0'.toLong() + push(Value(num)) + } + private fun noOp() {} private fun execInstr(instr: Value) { @@ -215,29 +234,40 @@ class B93Interpreter : Interpreter { '#' -> stepIP() 'g' -> fget() 'p' -> fput() - '&', '~' -> input() + '&', '~' -> input(car) '@' -> terminate() + in '0'..'9' -> pushDig(car) else -> noOp() } } + private fun strMode(instr: Value) { + if (instr.asChar == '"') { + toggleStrmode() + return + } + push(instr) + } + override fun step(): Boolean { val instr = funge[ip.pos] val currIP = ip.copy() when (ip.mode) { IpMode.Inactive -> noOp() IpMode.Normal -> execInstr(instr) - IpMode.String -> push(instr) + IpMode.String -> strMode(instr) } if (ip.mode != IpMode.Inactive) { stepIP() - while (funge[ip.pos].asChar == ' ') { - stepIP() + if (ip.mode != IpMode.String) { + while (funge[ip.pos].asChar == ' ') { + stepIP() + } } val newIP = ip.copy() ipChanged(IpEvent(currIP, newIP)) } - return true + return ip.mode != IpMode.Inactive } override fun reset() { From a36f2d212e830bcd8dab605e5b770ea92bb1d7f9 Mon Sep 17 00:00:00 2001 From: Jacob Date: Thu, 15 Nov 2018 21:23:42 -0500 Subject: [PATCH 6/6] Add line to clear fungeMods map in reset() --- befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt index d887514..1e34412 100644 --- a/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt +++ b/befunge/src/main/kotlin/befide/befunge/b93/B93Interpreter.kt @@ -285,6 +285,7 @@ class B93Interpreter : Interpreter { for ((k,v) in fungeMods) { funge[k] = v } + fungeMods.clear() fungeChanged(FungeEvent(changes)) } } \ No newline at end of file