/test/pending/run/reify_brainf_ck.scala

https://github.com/pedrofurla/scala · Scala · 85 lines · 72 code · 13 blank · 0 comment · 11 complexity · f54fe7d33e3018ee4838aa56b7f11298 MD5 · raw file

  1. import scala.tools.nsc.reporters._
  2. import scala.tools.nsc.Settings
  3. import reflect.runtime.Mirror.ToolBox
  4. object Test extends App {
  5. val code = scala.reflect.Code.lift{
  6. import scala.annotation._
  7. trait Func[T] {
  8. val zero: T
  9. def inc(t: T): T
  10. def dec(t: T): T
  11. def in: T
  12. def out(t: T): Unit
  13. }
  14. object ByteFunc extends Func[Byte] {
  15. override val zero: Byte = 0
  16. override def inc(t: Byte) = ((t + 1) & 0xFF).toByte
  17. override def dec(t: Byte) = ((t - 1) & 0xFF).toByte
  18. override def in: Byte = readByte
  19. override def out(t: Byte) { print(t.toChar) }
  20. }
  21. case class Tape[T](left: List[T], cell: T, right: List[T])(implicit func: Func[T]) {
  22. private def headOf(list:List[T]) = if (list.isEmpty) func.zero else list.head
  23. private def tailOf(list:List[T]) = if (list.isEmpty) Nil else list.tail
  24. def isZero = cell == func.zero
  25. def execute(ch: Char) = (ch: @switch) match {
  26. case '+' => copy(cell = func.inc(cell))
  27. case '-' => copy(cell = func.dec(cell))
  28. case '<' => Tape(tailOf(left), headOf(left), cell :: right)
  29. case '>' => Tape(cell :: left, headOf(right), tailOf(right))
  30. case '.' => func.out(cell); this
  31. case ',' => copy(cell = func.in)
  32. case '[' | ']' => this
  33. case _ => error("Unexpected token: " + ch)
  34. }
  35. }
  36. object Tape {
  37. def empty[T](func: Func[T]) = Tape(Nil, func.zero, Nil)(func)
  38. }
  39. class Brainfuck[T](func:Func[T]) {
  40. def execute(p: String) {
  41. val prog = p.replaceAll("[^\\+\\-\\[\\]\\.\\,\\>\\<]", "")
  42. @tailrec def braceMatcher(pos: Int, stack: List[Int], o2c: Map[Int, Int]): Map[Int,Int] =
  43. if(pos == prog.length) o2c else (prog(pos): @switch) match {
  44. case '[' => braceMatcher(pos + 1, pos :: stack, o2c)
  45. case ']' => braceMatcher(pos + 1, stack.tail, o2c + (stack.head -> pos))
  46. case _ => braceMatcher(pos + 1, stack, o2c)
  47. }
  48. val open2close = braceMatcher(0, Nil, Map())
  49. val close2open = open2close.map(_.swap)
  50. @tailrec def ex(pos:Int, tape:Tape[T]): Unit =
  51. if(pos < prog.length) ex((prog(pos): @switch) match {
  52. case '[' if tape.isZero => open2close(pos)
  53. case ']' if ! tape.isZero => close2open(pos)
  54. case _ => pos + 1
  55. }, tape.execute(prog(pos)))
  56. println("---running---")
  57. ex(0, Tape.empty(func))
  58. println("\n---done---")
  59. }
  60. }
  61. val bf = new Brainfuck(ByteFunc)
  62. bf.execute(""">+++++++++[<++++++++>-]<.>+++++++[<++
  63. ++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]
  64. <.#>+++++++++++[<+++++>-]<.>++++++++[<++
  65. +>-]<.+++.------.--------.[-]>++++++++[<++++>
  66. -]<+.[-]++++++++++.""")
  67. };
  68. val reporter = new ConsoleReporter(new Settings)
  69. val toolbox = new ToolBox(reporter)
  70. val ttree = toolbox.typeCheck(code.tree)
  71. toolbox.runExpr(ttree)
  72. }