Last active
August 29, 2015 14:05
-
-
Save CaffeinatedDave/8b1cb33502e15563bbb9 to your computer and use it in GitHub Desktop.
West London Hack Night - Brainfuck interpreter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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