読者です 読者をやめる 読者になる 読者になる

Scalaでbrainfuck

何となくScalabrainfuckの処理系を実装した。

package brainfuck

sealed trait Inst
case object PINC extends Inst
case object PDEC extends Inst
case object INC extends Inst
case object DEC extends Inst
case object OUT extends Inst
case object IN extends Inst
case object NOP extends Inst
final case class JZ(dst:Int) extends Inst
final case class JNZ(dst:Int) extends Inst

class TM(val Ops:Array[Inst]){
  var IP:Int=_
  val memory:Array[Byte]=new Array[Byte](30000)
  var pointer:Int=_
  var Op:Inst=_
  
  def fetch={
    Op=Ops(IP)
    IP+=1
  }

  def decode={}

  def execute={
    Op match{
      case PINC =>pointer+=1
      case PDEC =>pointer-=1
      case INC  =>memory(pointer)=(memory(pointer)+1).asInstanceOf[Byte]
      case DEC  =>memory(pointer)=(memory(pointer)-1).asInstanceOf[Byte]
      case OUT  =>print(new String(Array(memory(pointer)),"UTF-8"))
      case IN   =>{
        var a=System.in.read()
        if (a == -1) IP = -1
        memory(pointer)=a.toByte
      }
      case JZ(dst) => if (memory(pointer)==0) IP=dst
      case JNZ(dst)=> if (memory(pointer)!=0) IP=dst
      case NOP=>{}
    } 
  }
  def run=while (IP<Ops.size && IP>=0){fetch;decode;execute}
}

object Compiler{
  def compile(code:String):Array[Inst]={
    var ops:Array[Inst]=Array.empty
    var stack=new scala.collection.mutable.Stack[Int]
    code.zipWithIndex.foreach{ 
      case(c:Char,index:Int)=>{
        c match {
          case '>' =>ops=ops:+PINC
          case '<' =>ops=ops:+PDEC
          case '+' =>ops=ops:+INC
          case '-' =>ops=ops:+DEC
          case '.' =>ops=ops:+OUT
          case ',' =>ops=ops:+IN
          case '[' =>{
            ops=ops:+NOP
            stack.push(index)
          }
          case ']' =>{
            val src=stack.pop
            ops(src)=JZ(index+1)
            ops=ops:+JNZ(src+1)
          }
        }
      }
    }
    ops
  }
}

何せscalaを勉強し始めたのが一昨日だけにもっと上手い書き方があるような気がしてならない。
特に

  • 命令セットの列挙型としての扱い方
  • IntとByteの変換

の部分。