Implement B93Funge, B93Pointer, and P93Interpreter, excluding IO

Remove Char from IpMode
Change Value to hold Long instead of Int
This commit is contained in:
Jacob
2018-11-15 01:54:17 -05:00
parent 8bfe78abd7
commit ae6cc7e455
7 changed files with 298 additions and 16 deletions

View File

@@ -7,7 +7,7 @@
<compilerArguments>
<option name="jvmTarget" value="1.8" />
<option name="languageVersion" value="1.3" />
<option name="apiVersion" value="1.3" />
<option name="apiVersion" value="1.2" />
<option name="pluginOptions">
<array />
</option>
@@ -37,5 +37,14 @@
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-common:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-junit:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-annotations-common:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-common:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>

View File

@@ -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()
}
}
}

View File

@@ -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<Value>()
override val ip = B93Pointer(Vec(0, 0), Vec(1, 0), IpMode.Normal)
@@ -19,11 +24,229 @@ class B93Interpreter : Interpreter {
override val stackChanged: Event<StackEvent> = Event()
override val ipChanged: Event<IpEvent> = Event()
private val fungeMods = HashMap<Vec,Value>()
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))
}
}

View File

@@ -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
data class B93Pointer(override var pos: Vec, override var delta: Vec, override var mode: IpMode) : Pointer

View File

@@ -3,6 +3,5 @@ package befide.befunge.state
enum class IpMode {
Normal,
String,
Char,
Inactive
}

View File

@@ -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
}

View File

@@ -7,7 +7,7 @@
<compilerArguments>
<option name="jvmTarget" value="1.8" />
<option name="languageVersion" value="1.3" />
<option name="apiVersion" value="1.3" />
<option name="apiVersion" value="1.2" />
<option name="pluginOptions">
<array />
</option>
@@ -29,6 +29,21 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: no.tornado:tornadofx:1.7.17" level="project" />
<orderEntry type="library" name="Maven: org.glassfish:javax.json:1.1.2" level="project" />
<orderEntry type="library" name="Maven: javax.json:javax.json-api:1.1.2" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.60" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-reflect:1.2.60" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-junit:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-annotations-common:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.jetbrains.kotlin:kotlin-test-common:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="module" module-name="befunge" />
<orderEntry type="library" name="Maven: no.tornado:tornadofx:1.7.17" level="project" />
<orderEntry type="library" name="Maven: org.glassfish:javax.json:1.1.2" level="project" />