PythonのStringIOをJSXで実装してみた。

JSXという言語がリリースされたので、例のごとくPythonのStringIOをJSXで書いてみた。
(__iter__()とnext()は未実装で手を抜きました。また、テストコード書いてないので不具合あるかも...)

ちなみにPythonのStringIOは下記の理由により移植が容易。
1. 依存ライブラリが皆無。
2. 単純
3. コード量が少ない。

参考にした資料。

コード

書いたコードは例のごとくgithubにpushしました。

/**
 * StringIO
 * @see Python <a href='http://docs.python.org/library/stringio.html'>StringIO</
a> modules.
 */

class buildin {
  static function min(x:number, y:number):number {
    return Math.min(x, y);
  }
  static function max(x:number, y:number):number {
    return Math.max(x, y);
  }
}

class string {
  static function find(str:string, sub:string, start:number):number {
    str = str.slice(start, str.length);
    var res = str.indexOf(sub);
    if (res > -1) {
      res += start;
    }
    return res;
  }
}

class StringIO {
  var buf:string;
  var len:number;
  var buflist = []:Array.<string>;
  var pos:number;
  var closed:boolean;
  var softspace:number;

  static function _complain_ifclosed(closed:boolean):void {
    throw new Error('I/O operation on closed file');
  }

  function constructor(buf:string) {
    this.buf = buf;
    this.len = buf.length;
    this.pos = 0;
    this.closed = false;
    this.softspace = 0;  
  }

  function __iter__():void {
    throw new Error("Not implemented error.");
  }

  function next():void {
    throw new Error("Not implemented error.");
  }

  function close():void {
    if (!this.closed) {
      this.closed = true;
      this.buf = "";
      this.pos = 0;
    }
  }

  function isatty():boolean {
    StringIO._complain_ifclosed(this.closed);
    return false;
  }

  function seek(pos:number):void {
    StringIO._complain_ifclosed(this.closed);
    if (this.buflist.length > 0) {
        this.buf += this.buflist.join('');
        this.buflist = []:Array.<string>;
    }
    this.pos = buildin.max(0, pos);
  }

  function seek(pos:number, mode:number):void {
    StringIO._complain_ifclosed(this.closed);
    if (this.buflist.length > 0) {
        this.buf += this.buflist.join('');
        this.buflist = []:Array.<string>;
    }
    if (mode == 1) {
        pos += this.pos;
    }
    else if (mode == 2) {
        pos += this.len;
    }
    this.pos = buildin.max(0, pos);
  }

  function tell():number {
    return this.pos;
  }

  function read():string {
    StringIO._complain_ifclosed(this.closed);
    if(this.buflist.length > 0) {
        this.buf += this.buflist.join('');
        this.buflist = []:Array.<string>;
    }
    var newpos = buildin.min(this.pos - 1, this.len);
    var r = this.buf.slice(this.pos, newpos);
    this.pos = newpos;
    return r;
  }

  function readline():string {
    StringIO._complain_ifclosed(this.closed);
    if (this.buflist.length > 0) {
      this.buf += this.buflist.join('');
      this.buflist = []:Array.<string>;
    }
    var i = string.find(this.buf, '\n', this.pos);
    var newpos:number;
    if (i < 0) {
      newpos = this.len;
    } else {
      newpos = i + 1;
    }
    var r = this.buf.slice(this.pos, newpos);
    this.pos = newpos;
    return r;
  }

  function readlines(sizehint:number):Array.<string> {
    var total = 0;
    var lines = []:Array.<string>;
    var line = this.readline();
    while (line != "") {
      lines.push(line);
      total += line.length;
      if (0 < sizehint && sizehint <= total) {
        break;
      }
      line = this.readline();
    }
    return lines;
  }

  function truncate():void {
    StringIO._complain_ifclosed(this.closed);
    var size = this.pos;
    this.buf = this.getvalue().slice(0, size);
    this.len = size;
  }

  function truncate(size:number):void {
    StringIO._complain_ifclosed(this.closed);
    if (size < 0) {
      throw new Error('Negative size not allowed');
    } else if (size < this.pos) {
      this.pos = size;
    }
    this.buf = this.getvalue().slice(0, size);
    this.len = size;
  }

  function write(s:string):void {
  }

  function writelines(iterable:Array.<string>):void {
    var key:number;
    var line:string;
    for (key in iterable) {
        line = iterable[key];
        this.write(line);
    }
  }

  function flush():void {
    StringIO._complain_ifclosed(this.closed);
  }

  function getvalue():string {
    if (this.buflist.length > 0) {
        this.buf += this.buflist.join('');
        this.buflist = []:Array.<string>;
    }
    return this.buf;
  }
}

所要時間は1時間程度?

まとめ

StringIOをJSXへ移植することについて

- これ移植したところで、誰かが幸せになるとか、処理が楽になるとかではないです。ごめんなさい>

  • 完全な趣味ですm(_)m
JSXについて

JavaScriptの実装を少し変更しただけです。オーバロードはよい機能。
下記は不明点です。

  • JSと比べると===演算がない?
  • Arrayに一つの型以外が入る場合、どのような型宣言するのだろうか。
  • JSの組み込みErrorオブジェクトを継承し独自のエラーオブジェクトを作る際はどうすればよいのだろうか?
  • if(obj)みたいな条件分岐でコンパイルエラーになったのだけど、どう書けばよいのだろうか。
    • 今回の例だと、if (this.buflist) {と書きたいのだが、if (this.buflist.length > 0) {と書いて回避。
個人的な感想。

よさげな言語だった。

今度はもう少し大きめなの書いてみようかな。
過去にTornadoのテンプレートエンジンをJSに移植したのだけど、Tornado2.4で内容変わってそうなので、JSとIolanguageとJSXあたりに。