Scala勉強中

D言語で書いた Brainf*ckの処理系をそのまま Scalaで再実装。
両方もっと面白く書けるとは思うのだけど、それはそれ今後の課題と致します。(逃

import std.stdio;
import std.string : indexOf;
import std.algorithm;
import std.conv;
import std.range;
import std.array;

struct Source
{
    string code = "";
    uint   position = 0;
    uint[] jmps;

    char get()   { return code[ position++ ]; }
    bool empty() { return code.length == position; }
    void push()  { jmps ~= position; }
    void jamp()  { position = jmps[$-1]; }
    void pop()   { jmps = jmps[0..$-1]; }
}

unittest
{
    Source src = Source( "+-[><].," );
    assert( src.get == '+' );
    assert( src.get == '-' );
    assert( src.get == '[' );
    src.push;
    assert( src.position == 3 );
    assert( src.jmps == [3] );
    assert( src.get == '>' );
    assert( src.get == '<' );
    assert( src.position == 5 );
    assert( src.get == ']' );
    src.jamp();
    assert( src.position == 3 );
    assert( src.jmps == [3] );
    assert( src.get == '>' );
    assert( src.get == '<' );
    assert( src.position == 5 );
    src.pop;
    assert( src.jmps == [] );

}

struct Record
{
    uint[] tape = [0];
    uint   position = 0;

    void inc() { tape[ position ]++; }
    void dec() { if(tape[position]==0) throw new Exception("おこだよ!"); tape[position]--; }

    void next() { position++; if(tape.length <= position) tape ~= 0; }
    void prev() { if(position==0) throw new Exception("ダメなの!"); position--; }

    uint current() { return tape[ position ]; }
}

string exec( Source src, Record rec )
{
    string result = "";
    while( !src.empty )
    {
        char c = src.get;
        switch( c )
        //switch( src.get )
        {
            case '+' : { rec.inc; } break;
            case '-' : { rec.dec; } break;
            case '>' : { rec.next; } break;
            case '<' : { rec.prev; } break;
            case '[' : { src.push; } break;
            case ']' : { rec.current == 0 ? src.pop : src.jamp; } break;
            case '.' : { result ~= rec.current.to!char; } break;
            default : {} break;
        }        
    }
    return result;
}

unittest
{
    static Source src = Source( "+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+." );
    static Record rec = Record();
    assert( exec( src, rec ) == "Hello, world!" );

    assert( 
        Source( ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+." ).exec( Record() )
        ==
        "Hello World!"
    );

    assert(
        Source( ">+++[>+++[<<++++++++>>-]<-]<.++>+++[>+++[<<+++>>-]<-]<.+++++++..+++.--->++[>++[>++[>++[>++[<<<<<-->>>>>-]<-]<-]<-]<-]<.+>+++[<---->-]<." ).exec( Record() )
        ==
        "Hello,!"
    );
}

void main( string[] args )
{
    Source( args[1] ).exec( Record() ).writeln;
    return;
}
import java.lang.String
import scala.collection.mutable._

class Source( code: String ) {
  var position = 0;
  var jmps:Stack[Int] = Stack()

  def get:Char      = { val result = code( position ); position += 1; result }
  def empty:Boolean = { code.length == position }
  def push          = { jmps = jmps.push( position ) }
  def jamp          = { position = jmps.last }
  def pop           = { jmps.pop }
}

class Record() {
  var position = 0
  var tape:ListBuffer[Int] = ListBuffer(0)

  def inc  = { tape( position ) += 1 }
  def dec  = { tape( position ) -= 1 }
  def next = { position += 1; if( tape.length <= position ) tape += 0 }
  def prev = { position -= 1 }

  def current:Int = { tape( position ) }
}

object bf2 {

    def exec( src: Source, rec: Record ): String = {
      var result = ""
      while( !src.empty ) {
        src.get match {
          case '+' => rec.inc
          case '-' => rec.dec
          case '>' => rec.next
          case '<' => rec.prev
          case '[' => src.push
          case ']' => if( rec.current == 0 ) src.pop else src.jamp
          case '.' => result += rec.current.toChar
          case _ => println("not match")
        }
      }
      result
    }

  def main( args: Array[ String ] ): Unit = {
    val src = new Source("+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.")
    val rec = new Record
    println( exec( src, rec ) )
  }
}