Skip to content

Instantly share code, notes, and snippets.

@CaffeinatedDave
Last active August 29, 2015 14:05
Show Gist options
  • Save CaffeinatedDave/8b1cb33502e15563bbb9 to your computer and use it in GitHub Desktop.
Save CaffeinatedDave/8b1cb33502e15563bbb9 to your computer and use it in GitHub Desktop.
West London Hack Night - Brainfuck interpreter
object Compiler extends Application {
val program = "++++++++++" +
"[" +
">+++++++" +
">++++++++++" +
">+++" +
">+" +
"<<<<-" +
"]" +
">++." + // "H"
">+." + // "e"
"+++++++.." + // "ll"
"+++." + // "o"
">++." + // " "
"<<+++++++++++++++." + // "W"
">." + // "o"
"+++." + // "r"
"------." + // "l"
"--------." + // "d"
">+." + // "!"
">."
run(program)
def run(program: String) {
run(program.toList, List[Char](), List[Int](), List[Int](), ("go", 0))
}
def run(progRemain: List[Char], progRun: List[Char], memTapeBack: List[Int], memTapeForward: List[Int], action: (String, Int)) {
action match {
case ("back", c) => {
(progRun, c) match {
case (']' :: t, x) => {
run(']' :: progRemain, t, memTapeBack, memTapeForward, ("back", x+1))
}
case ('[' :: t, 0) => {
run('[' :: progRemain, t, memTapeBack, memTapeForward, ("go", 0))
}
case ('[' :: t, x) => {
run('[' :: progRemain, t, memTapeBack, memTapeForward, ("back", x-1))
}
case (h :: t, x) => {
run(h :: progRemain, t, memTapeBack, memTapeForward, ("back", x))
}
case (Nil, _) => {
throw new Exception
}
}
}
case ("skip", c) => {
(progRemain, c) match {
case ('[' :: t, x) => {
run(t, '[' :: progRun, memTapeBack, memTapeForward, ("skip", x+1))
}
case (']' :: t, 0) => {
run(t, ']' :: progRun, memTapeBack, memTapeForward, ("go", 0))
}
case (']' :: t, x) => {
run(t, ']' :: progRun, memTapeBack, memTapeForward, ("skip", x-1))
}
case (h :: t, x) => {
run(t, h :: progRun, memTapeBack, memTapeForward, ("skip", x))
}
case (Nil, _) => {
throw new Exception
}
}
}
case ("go", x) => {
progRemain match {
case Nil => // Program ended!
case '>' :: t => {
memTapeForward match {
case Nil => run(t, '>' :: progRun, 0 :: memTapeBack, List[Int](), ("go", x))
case (h :: t2) => run(t, '>' :: progRun, h :: memTapeBack, t2, ("go", x))
}
}
case '<' :: t => {
//move memory -1
memTapeBack match {
case Nil => run(t, '<' :: progRun, List[Int](), 0 :: memTapeForward, ("go", x))
case (h :: t2) => run(t, '<' :: progRun, t2, h :: memTapeForward, ("go", x))
}
}
case '+' :: t => {
//incr memory val
memTapeForward match {
case Nil => run(t, '+' :: progRun, memTapeBack, List[Int](1), ("go", x))
case (h :: t2) => run(t, '+' :: progRun, memTapeBack, h + 1 :: t2, ("go", x))
}
}
case '-' :: t => {
//decr memory val
memTapeForward match {
case Nil => run(t, '-' :: progRun, memTapeBack, List[Int](-1), ("go", x))
case (h :: t2) => run(t, '-' :: progRun, memTapeBack, h - 1 :: t2, ("go", x))
}
}
case '.' :: t => {
//print out char for mem value
memTapeForward match {
case Nil => print(0.toChar)
case (h :: _) => print(h.toChar)
}
run(t, '.' :: progRun, memTapeBack, memTapeForward, ("go", x))
}
case ',' :: t => {
//read in char and place in mem value
memTapeForward match {
case Nil => run(t, ',' :: progRun, memTapeBack, Console.in.read :: List[Int](), ("go", x))
case _ :: t2 => run(t, ',' :: progRun, memTapeBack, Console.in.read :: t2, ("go", x))
}
}
case '[' :: t => {
//Start loop.
if (memTapeForward.head == 0) {
// Not this time...
run(t, '[' :: progRun, memTapeBack, memTapeForward, ("skip", 0))
} else {
// Onwards
run(t, '[' :: progRun, memTapeBack, memTapeForward, ("go", x))
}
}
case ']' :: t => {
//End loop.
if (memTapeForward.head == 0) {
// Onwards
run(t, ']' :: progRun, memTapeBack, memTapeForward, ("go", x))
} else {
// Nope, back around we go!
run(']' :: t, progRun, memTapeBack, memTapeForward, ("back", 0))
}
}
case _ :: t => {
// Any other char gets skipped (and always will be, so can just drop it from the program)
run(t, progRun, memTapeBack, memTapeForward, ("go", x))
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment