Hatena::Groupxn--272ax3f

スクリプト言語の作り方9日目

スクリプト言語の作り方9日目

クラスとオブジェクトを扱う構文

class Position {
    x = y = 0
    def move (nx, ny) {
        x = nx; y = ny
    }
}
p = Position.new
p.move(3, 4)
p.x = 10
print p.x + p.y

クラスのための文法規則

member     : def | simple
class_body : "{" [ member ] { (";" | EOL) [ member ] } "}"
defcalss   : "class" IDENTIFIER [ "extends" IDENTIFIER ] class_body
postfix    : "." IDENTIFIER | "(" [ args ] ")"
program    : [ defclass | def | statement ] (";" | EOL )
  • class_bodyblock と同じ形
  • postfix. によるアクセスも受け付けるように

eval メソッドの実装

以下で (S) がつくのは Stone 言語の、(J) がつくのは Java の用語

Doteval

AssignExcomputeAssign

  • 左辺(A)がフィールド (ドット式) であれば
  • そうでなければ、従来の代入式と同じく評価する

(A) は代入式の、(D) はドット式の被演算子を表す


クロージャを使ったオブジェクトの表現

def position () {
    x = y = 0
    fun (nx, ny) {
        x = nx; y = ny
    }
}
class Position {
    x = y = 0
    def move (nx, ny) {
        x = nx; y = ny
    }
}
クロージャ
内側の名前 (x 及び y) を position 関数局所変数に束縛
メソッド
内側の名前 (x 及び y) を Position オブジェクトのフィールドに束縛

環境とオブジェクト関連付けることで、フィールドの読み書きは環境の読み書きとなる

cf. JavaScript ではオブジェクトが環境を構成する

  • StoneObject#getEnve == env のチェックを加えないと、p.value としたとき大域変数 value の値が取れてしまったりする
  • クラスの継承は親クラスのコンストラクタを先に呼び出すことで実現