Skip to content

Instantly share code, notes, and snippets.

@zipcode
Created March 6, 2012 22:32
Show Gist options
  • Save zipcode/1989461 to your computer and use it in GitHub Desktop.
Save zipcode/1989461 to your computer and use it in GitHub Desktop.
A quick, dirty and *untested* brainfuck interpreter.
import scala.collection.mutable.Queue
object Brainfuck {
def main(args: Array[String]) {
val code = io.Source.fromFile("src.txt") filter ("[]<>.,+-" contains _) toSeq
exec(code)
}
def exec(code: Seq[Char]) {
val program = parse(code)
program(new World())
System.out.println()
}
def parse(code: Seq[Char]): Block = {
val c = Queue[Instruction]()
var ip = 0
while (ip < code.size) {
code(ip) match {
case '-' => { c += Inc(-1) }
case '+' => { c += Inc(1) }
case '<' => { c += Right(-1) }
case '>' => { c += Right(1) }
case '.' => { c += Print() }
case '[' => {
var nest = 1
var tip = ip
while (code(tip) != ']' && nest != 0) {
tip += 1
if (code(tip) == '[') { nest += 1 }
if (code(tip) == ']') { nest -= 1 }
}
c += While(parse(code.slice(ip + 1, tip)))
ip = tip
}
case _ => ()
}
ip += 1
}
Block(c)
}
}
class World {
val data = Array.fill(30000)(0)
var dp = 0
def eqz: Boolean = { data(dp) == 0 }
def inc(n: Int) { data(dp) += n }
def right(n: Int) { dp += n }
def print { System.out.print(data(dp) toChar) }
}
sealed abstract class Instruction {
def apply(w: World)
}
case class Inc(n: Int) extends Instruction {
def apply(w: World) { w.inc(n) }
override def toString: String = {
if (n < 0) {
"-" * -n
} else {
"+" * n
}
}
}
case class Right(n: Int) extends Instruction {
def apply(w: World) { w.right(n) }
override def toString: String = {
if (n < 0) {
"<" * -n
} else {
">" * n
}
}
}
case class Print() extends Instruction {
def apply(w: World) { w.print }
override def toString: String = "."
}
case class Block(code: Seq[Instruction]) extends Instruction {
def apply(w: World) {
for (i <- code) {
i(w)
}
}
override def toString: String = {
code map { _.toString } mkString ""
}
}
case class While(block: Block) extends Instruction {
def apply(w: World) {
while (!w.eqz) {
block(w)
}
}
override def toString: String = {
"[%s]" format block.toString
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment