ScalaでBrainf*ckのインタプリタを書いてみたよ

Scalaで書いた作品その3です。まぁ、今までハロワと妙なEclipse Pluginしか書いてないので、全くScalaらしからぬコードだと思うけど。

とりあえずコードを貼ると、モヒモヒした人達がScalaっぽくしてくれるんじゃないかなぁ…。

とりあえずブログ上のテキストだとモヒりにくいと思ったから、githubに上げた…ら、案の定モヒられています。

object Brainfuck {

  var commands = Map(
    '>' -> incrementPointer,
    '<' -> decrementPointer,
    '+' -> incrementMemoryAtPointer,
    '-' -> decrementMemoryAtPointer,
    '.' -> outputMemoryAtPointer,
    ',' -> inputMemoryAtPointer,
    '[' -> openLoop,
    ']' -> closeLoop
  )

  def main(args:Array[String]) {
    val program = readSource
    val env = new Environment(program)
    while (env.isEof == false) {
      commands.get(env.programChar) match {
        case Some(command) => command.execute(env)
        case _ => ;
      }
      env.progress
    }
  }

  def readSource = {
    // output "Hello, world!"
    """
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
------------.<++++++++.--------.+++.------.--------.>+.
    """
  }
}
class Environment(val program: String) {
  val memory = new Array[Int](3000)
  var pointer = 0
  var counter = 0

  def isEof = {
    counter >= program.length
  }

  def programChar = {
    program(counter)
  }

  def progress:Unit = {
    counter += 1
  }

  def memoryAtPointer = {
    memory(pointer)
  }
}
abstract class Command {
  def execute(env: Environment)
}
object incrementPointer extends Command {
  def execute(env: Environment) = {
    require(env != null)
    env.pointer += 1
  }
}
object decrementPointer extends Command {
  def execute(env: Environment) = {
    require(env != null)
    env.pointer -= 1
  }
}
object incrementMemoryAtPointer extends Command {
  def execute(env: Environment) = {
    require(env != null)
    env.memory(env.pointer) += 1
  }
}
object decrementMemoryAtPointer extends Command {
  def execute(env: Environment) = {
    require(env != null)
    env.memory(env.pointer) -= 1
  }
}
object inputMemoryAtPointer extends Command {
  def execute(env: Environment) {
    require(env != null)
    env.memory(env.pointer) = Console.in.read
  }
}
object outputMemoryAtPointer extends Command {
  def execute(env: Environment) {
    require(env != null)
    print(env.memoryAtPointer.toChar)
  }
}
object openLoop extends Command {
  def execute(env: Environment) = {
    require(env != null)
    if (env.memoryAtPointer == 0) {
      var depth = 0
      while (env.programChar != ']' || depth != 1) {
        if (env.programChar == '[') {
          depth += 1
        } else if (env.programChar == ']') {
          depth -= 1
        }
        env.counter += 1
      }
    }
  }
}
object closeLoop extends Command {
  def execute(env: Environment) = {
    require(env != null)
    if (env.memoryAtPointer != 0) {
      var depth = 0
      while (env.programChar != '[' || depth != 1) {
        if (env.programChar == ']') {
          depth += 1
        } else if (env.programChar == '[') {
          depth -= 1
        }
        env.counter -= 1
      }
    }
  }
}