Skip to content

Instantly share code, notes, and snippets.

@parrot-studio
Last active April 11, 2019 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parrot-studio/a38965f997bf3f35c92e4ce7e7a6faa7 to your computer and use it in GitHub Desktop.
Save parrot-studio/a38965f997bf3f35c92e4ce7e7a6faa7 to your computer and use it in GitHub Desktop.
BrainF**k interpreter by Kotlin
object BF {
private val commends = mapOf(
'>' to "pinc",
'<' to "pdec",
'+' to "inc",
'-' to "dec",
'.' to "out",
',' to "inp",
'[' to "jmp",
']' to "ret"
)
fun execute(code: String): Unit {
val coms = parse(code)
val str = Machine(coms).execute()
println(str)
}
private fun parse(code: String): Sequence<String> {
return code.asSequence()
.map { commends.getOrDefault(it, "") }
.filter { it != "" }
}
class Machine(coms: Sequence<String>) {
private val cmap: Map<Int, String>
private val jmap: Map<Int, Int>
private val buffer: MutableMap<Int, Int> = mutableMapOf()
private var result: String = ""
init {
val cs = generateSequence(0) { it + 1 }.zip(coms).toList()
cmap = cs.toMap()
jmap = parseJump(cs)
}
fun execute(): String {
return stepExecute(1, 0, 0)
}
private fun parseJump(cs: List<Pair<Int, String>>): Map<Int, Int> {
val sj = cs.filter { it.second == "jmp" }.map { it.first }
val ej = cs.filter { it.second == "ret" }.map { it.first }
val list = sj.zip(ej) + ej.zip(sj)
return list.toMap()
}
private fun stepExecute(step: Int, cind: Int, pind: Int): String {
val com = cmap.getOrDefault(cind, "fin")
when (com) {
"pinc" -> stepExecute(step + 1, cind + 1, pind + 1)
"pdec" -> stepExecute(step + 1, cind + 1, pind - 1)
"inc" -> {
increment(pind)
stepExecute(step + 1, cind + 1, pind)
}
"dec" -> {
decrement(pind)
stepExecute(step + 1, cind + 1, pind)
}
"out" -> {
output(pind)
stepExecute(step + 1, cind + 1, pind)
}
"inp" -> stepExecute(step + 1, cind + 1, pind) // do nothing
"jmp" -> stepExecute(step + 1, jumpTo(cind, pind), pind)
"ret" -> stepExecute(step + 1, returnTo(cind, pind), pind)
}
return result
}
private fun increment(pind: Int): Unit {
val value = buffer.getOrDefault(pind, 0)
buffer[pind] = value + 1
}
private fun decrement(pind: Int): Unit {
val value = buffer.getOrDefault(pind, 0)
buffer[pind] = value - 1
}
private fun output(pind: Int): Unit {
val value = buffer.getOrDefault(pind, 0)
result += value.toChar()
}
private fun jumpTo(cind: Int, pind: Int): Int {
val value = buffer.getOrDefault(pind, 0)
val jv = jmap[cind]
checkNotNull(jv, { "jump index error" })
return if (value == 0) jv else cind + 1
}
private fun returnTo(cind: Int, pind: Int): Int {
val value = buffer.getOrDefault(pind, 0)
val jv = jmap[cind]
checkNotNull(jv, { "jump index error" })
return if (value != 0) jv else cind + 1
}
}
}
fun main() {
val hello = """
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.
>++.+++++++..+++.>-.------------.<++++++++.
--------.+++.------.--------.>+.
""".trimIndent()
BF.execute(hello) // -> Hello, world!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment