Skip to content

Instantly share code, notes, and snippets.

@KisaragiEffective
Last active October 29, 2019 11:35
Show Gist options
  • Save KisaragiEffective/5b3e54c049ed02b930a0936fd5ae0dd6 to your computer and use it in GitHub Desktop.
Save KisaragiEffective/5b3e54c049ed02b930a0936fd5ae0dd6 to your computer and use it in GitHub Desktop.
頼むからILぐらいちゃんと吐いてくれ
package com.github.kisaragieffective.bfvm
import com.github.kisaragieffective.bfvm.instruction.*
import java.net.HttpURLConnection
import java.net.URL
var errors = 0
fun main() {
// `-+><,.[]`以外の8文字は無視しても差し支えない
val m = "++++++++[>++++++++<-]>+."//checkGithub()
debug(m)
debug("m.len is ${m.length}")
// exitProcess(0)
var eatenIndex = 0
val instructions = mutableListOf<BFInstruction>()
val squareBrackets = mutableSetOf<Int>()
eater@ while (eatenIndex <= m.lastIndex) {
var p: Regex
var mr: MatchResult?
p = Regex("\\[-](?<value>\\+*+)")
mr = p.find(m, eatenIndex)
if (mr != null) { // found
debug("HIT LDC!")
instructions += BFLoadConstant(mr.groups["value"]!!.value.length)
eatenIndex += mr.range.last - mr.range.first
continue@eater
}
// [>+<-]
p = Regex("\\[(?<rmv>>)\\+(?<lmv><)-\\]")
mr = p.find(m, eatenIndex)
if (mr != null) { // found
if (mr.groups["rmv"] == mr.groups["lmv"]) {
debug("HIT BCPY!")
instructions += BFBreakingCopy(mr.groups["rmv"]!!.value.length)
eatenIndex += mr.range.last - mr.range.first
continue@eater
}
}
// [<+>-]
p = Regex("\\[(?<lmv><)\\+(?<rmv>>)-\\]")
mr = p.find(m, eatenIndex)
if (mr != null) { // found
if (mr.groups["rmv"] != mr.groups["lmv"]) {
debug("HIT BCPY!")
instructions += BFBreakingCopy(-mr.groups["rmv"]!!.value.length)
eatenIndex += mr.range.last - mr.range.first
continue@eater
}
}
// [>+++++++<-]
p = Regex("\\[(?<rmv>>)(?<mult>\\+)(?<lmv><)-\\]")
mr = p.find(m, eatenIndex)
if (mr != null) { // found
val groups = mr.groups
if (groups["rmv"] != groups["lmv"]) {
instructions += BFBreakingMultiple(groups["rmv"]!!.value.length, groups["mult"]!!.value.length)
eatenIndex += mr.range.last - mr.range.first
continue@eater
}
}
// [<+++++++>-]
p = Regex("\\[(?<lmv><)(?<mult>\\+)(?<rmv>>)-\\]")
mr = p.find(m, eatenIndex)
if (mr != null) { // found
val groups = mr.groups
if (groups["rmv"] != groups["lmv"]) {
debug("HIT BMUL!")
instructions += BFBreakingMultiple(-groups["rmv"]!!.value.length, groups["mult"]!!.value.length)
eatenIndex += mr.range.last - mr.range.first
continue@eater
}
}
// +
p = Regex("\\++")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
instructions += BFAdd(len)
eatenIndex += len
continue@eater
}
// -
p = Regex("-+")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
instructions += BFMinus(len)
eatenIndex += len
continue@eater
}
// >
p = Regex(">+")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
instructions += BFPtrRight(len)
eatenIndex += len
continue@eater
}
// <
p = Regex("<+")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
instructions += BFPtrLeft(len)
eatenIndex += len
continue@eater
}
// ,
p = Regex(",+")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
if (len != 1) {
warn("You used `,` operator multiple times, but it has no effects.")
}
instructions += BFReadChar
eatenIndex += 1 // 複数回同じ番地に同じ値を読み込んでも意味ないのでは?
continue@eater
}
// .
p = Regex("\\.+")
mr = p.find(m, eatenIndex)
if (mr != null && mr.range.first == eatenIndex) { // found
val len = mr.range.last - mr.range.first + 1
for (_z in 1..len) {
instructions += BFPutChar
}
eatenIndex += len
continue@eater
}
// [
var sbidx = m.indexOf('[', eatenIndex)
if (sbidx != -1 && sbidx !in squareBrackets) {
var nest = 0
var lastBreak = -1
for (j in sbidx until m.length) {
if (m[j] == '[') {
nest++
} else if (m[j] == ']') {
nest--
}
if (nest == 0) {
lastBreak = j
break
}
}
if (lastBreak == -1) {
error("Square brackets mismatch: `]` * $nest near $eatenIndex")
}
instructions += BFLabel(sbidx)
instructions += BFJumpEquals(lastBreak)
eatenIndex++
squareBrackets += sbidx
continue@eater
}
// ]
sbidx = m.indexOf(']', eatenIndex)
debug("sbidx is ${sbidx}, i is $eatenIndex, in? is ${sbidx !in squareBrackets}")
if (sbidx != -1) {
var nest = 0
var lastBreak = -1
debug("`]` detected: $sbidx")
for (j in sbidx downTo 0) {
if (m[j] == ']') {
nest++
} else if (m[j] == '[') {
nest--
}
if (nest == 0) {
lastBreak = j
break
}
}
if (lastBreak == -1) {
error("Square brackets mismatch: `[` * $nest near $eatenIndex")
}
if (sbidx !in squareBrackets) {
instructions += BFLabel(sbidx)
instructions += BFJumpNotEquals(lastBreak)
squareBrackets += sbidx
}
eatenIndex++
continue@eater
}
debug("remain is ${m.slice(eatenIndex..(m.lastIndex))}")
}
for (instruction in instructions) {
val ir = when (instruction) {
is BFAdd -> "ADD ${instruction.amount}"
is BFLabel -> ":${instruction.idx}"
is BFMinus -> "MINUS ${instruction.amount}"
is BFPtrLeft -> "PTR -${instruction.amount}"
is BFPtrRight -> "PTR ${instruction.amount}"
BFPutChar -> "PUTCHAR"
BFReadChar -> "READCHAR"
is BFJumpEquals -> "JE :${instruction.offset}"
is BFJumpNotEquals -> "JNE :${instruction.offset}"
is BFBreakingCopy -> "BCP ${instruction.offset}"
is BFBreakingMultiple -> "BMPL ${instruction.offset}, ${instruction.times}"
is BFLoadConstant -> "LCD ${instruction.value}"
BFLoadZero -> "LCD 0"
}
println(ir)
}
}
fun warn(mes: String) {
println("[WARN] $mes")
}
fun error(mes: String) {
println("[ERROR] $mes")
errors++
}
fun debug(mes: String) {
println("[DEBUG] $mes")
}
fun checkGithub() = (URL("https://raw.githubusercontent.com/kostya/benchmarks/master/brainfuck/mandel.b").openConnection() as HttpURLConnection).apply {
requestMethod = "GET"
connect()
}.inputStream.bufferedReader().lineSequence().joinToString("").replace(Regex("[^-+,.><\\[\\]]+"), "")
inline fun handleRegex(regex: String, f: () -> Unit) {
val rex = Regex(regex)
f()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment