Implement B93Funge, B93Pointer, and P93Interpreter, excluding IO
Remove Char from IpMode Change Value to hold Long instead of Int
This commit is contained in:
@@ -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>
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -3,6 +3,5 @@ package befide.befunge.state
|
||||
enum class IpMode {
|
||||
Normal,
|
||||
String,
|
||||
Char,
|
||||
Inactive
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
17
ide/ide.iml
17
ide/ide.iml
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user