Environment - akamah/garbanzo GitHub Wiki

環境とフレーム

変数を束縛する対応関係のことを、フレームと呼ぶ。

現在のフレーム

まず最初に、現在のフレームは必ず一つは存在するとする。これは、ファイルシステムで言う所の「.」に当たるものとする。

フレームの拡張

関数を呼び出す時や、スコープをネストさせる時などは、親フレームを指定し、フレームを拡張することができる。 親フレームには、「..」のようにアクセスができるものとする。 親フレームを指定しないこともでき、そうすることで隔離された環境を構成することもできる。 拡張ができるのだから、もちろん破棄することもできる。

これらの操作は、現在の環境フレームを設定する命令(setenv)によって行われる。

フレームへのアクセス

変数のshadowingが嫌だったので、変数へは相対パスでアクセスするようにする。

a = 1
b = 2
{
  a = 10
  print(a) # => 10
  print(../a) # => 1
  print(b) # => ERROR!
}

のような感じで。

ルート

特殊なキーとして、ルート('/')を与える。ここに関数やモジュールを定義することで、どこからでもアクセスができるようになる。

フレームにおいては、単にルートを指し示すだけのエントリなので、そのフレームの先祖に必ずしも存在しなくても良い。

スコープ

スコープは以下の手順で作成される。

  1. 新しいフレーム(単なるStoreオブジェクト)を作成する
  2. 作成したフレームに、親フレームとして現在のフレームを設定する
  3. そこにsetenvする

また、脱出する場合は、

  1. '..'に示されたところへsetenvする

関数

関数は、それが定義された環境(env)と、その内容(body)を含む。 基本的に、外部からそれらの内容を覗くことは許されない。

関数の呼び出しは、次の手順で行う。

  1. 引数をまとめたデータストアオブジェクトを作成する。ルートが指定されていない場合は、呼び出し元と同じルートを指定。
  2. そこに、親となる環境(env)を設定させる。
  3. 作成したデータストアオブジェクトを環境としてsetenvする。
  4. コードを実行
  5. 戻り値を値として返す。

注意するべきは、関数の呼び出し元から、関数の定義された環境を取得できないようにすること。