ScalaでBrainf*ck
「言語の入門ではまずBrainf*ck処理系を作れ」なる持論を何故か若手の会で発表したこともあり、ScalaでBrainf*ckの処理系書いた。コンパイラ・インタプリタ方式。一回Scalaの () => unit な関数列にコンパイルしてから実行。なんか色々適当。
import java.lang.System
import java.io.FileInputStream
import java.io.InputStream
import java.io.File
import scala.collection.mutable.ArrayBuffer
object BFi{
val in = System.in
val out = System.out
val mem = new Array[Byte](30000)
var pt = 0
def incExp(){
mem(pt) = (mem(pt) + 1).toByte
}
def decExp(){
mem(pt) = (mem(pt) - 1).toByte
}
def nextExp(){
pt = pt + 1
}
def prevExp(){
pt = pt - 1
}
def getExp(){
mem(pt) = in.read.toByte
}
def putExp(){
out.write(mem(pt).toChar)
}
def noneExp(){
}
def makeExp(input: InputStream, c: Int): () => unit = c match{
case '+' => incExp
case '-' => decExp
case '>' => nextExp
case '<' => prevExp
case '.' => putExp
case ',' => getExp
case '[' => makeBlock(input)
case _ => noneExp
}
def makeBlock(input: InputStream): () => unit = {
var exps = new ArrayBuffer[() => unit]
var c = input.read
while(c != ']' && c!= -1){
val exp = makeExp(input, c)
if(exp != noneExp){
exps + exp
}
c = input.read
}
def block(){
while(mem(pt)!=0) exps.foreach(x => x())
}
return block
}
def compile(input: InputStream): () => unit = {
var exps = new ArrayBuffer[() => unit]
var c = input.read
while(c != -1){
val exp = makeExp(input, c)
if(exp != noneExp){
exps + exp
}
c = input.read
}
def block(){
exps.foreach(x => x())
}
return block
}
def main(args: Array[String]){
if(args.length>0){
val sourceFile = new File(args(0))
val input = new FileInputStream(sourceFile)
val body = compile(input)
body()
out.flush
}
}
}while(c!=-1) とかその辺、超ほげすぎる。
% cat echo.bf +[,.] % scala BFi echo.bf hogeghoge hogeghoge あいうえお あいうえお