試作言語Yellow

http://www.geocities.jp/takt0_h/yellow/index.html

Yellowは、拙作の言語Cyanに対する私の不満を解消するために設計されました。Cyanと比べて以下のような特徴があります。

  • 構文木を表すオブジェクトの種類を最低限に減らした
  • パッケージシステムを導入した

また、処理系の特徴としては、

  • 継続を中心とする評価システムを実装した
  • 継続の効率化を図った

などが挙げられます。それぞれについて、簡単に説明していきます。

構文木の単純化

Cyanの構文木は、porter, quote, function, parameters, blockなど、多くの種類のオブジェクトを用いて表現していました。Yellowではこれらをメッセンジャーとリストによって置き換えます。

foo()           # foo.$|()|() と同じ
'foo            # quote.$|()|(foo) と同じ
^(foo){ bar }   # lambda.$|()|([foo], bar) と同じ
foo{ bar; baz } # foo.$|()|(bar, baz) と同じ

$|..|という記法は、特殊な文字を含む識別子(ここではシンボル)を得るためのものです。

Yellowの式は、以下に表すような分類ができます。

  • メッセンジャー
  • リスト
    • コンスセル
    • 空リスト
  • シンボル
    • nil
    • その他
  • 自己評価型オブジェクト

ここで、空リストとnilは同一のオブジェクトです。

私はこれらの式を、S式にメッセンジャーを追加したものとして、まとめて「Mes式」と呼んでいます。
コンスセルはcarとcdrを持ち、それぞれの位置にMes式が書けます。
メッセンジャーは、receiver, message, argsをもち、receiverにはMes式が、messageにはシンボルが、argsにはリストが書けます。
Mes式にS式よりも優れた面があるのかはまだわかりませんが、リストをただのデータにすることで扱いやすくなっているのではないかと思っています。

パッケージシステム

YellowにはCommon Lispから取り入れたパッケージシステムがあります。ただし、その機能はCommon Lispよりもはるかに劣っています。また、現状では、Yellowで書かれたプログラムからカレントパッケージを変更したり、新しいパッケージを定義することができません。(技術的な制約ではなく、単に実装されていないだけです。すみません。)
パッケージシステムを導入した目的は、オブジェクトにメッセージとして送るシンボルをパッケージにインターンされたものにすれば、パッケージシステムによってメソッドのスコープを制限できると考えたからです。つまり、Cyanではグローバルな変更となるオブジェクトへのメソッドの追加が、Yellowではパッケージローカルとなるわけです。
仕組みは単純で、オブジェクトはメッセージを同一性によって比較するため、異なるパッケージに属するシンボルは異なるメッセージとして認識されます。よって、それぞれのメッセージに対して異なるメソッドを定義でき、さらにシンボルがエクスポートされていない場合はそのメッセージに対応したメソッドを直接呼び出すことができないのです。(ただし、内部シンボルへのアクセス方法も提供されているので、完全には隠せていません。)

yell-user> def(<object>.foo)^: "normal foo"
 => $<closure ...>
yell-user> def(<object>.:foo)^: "keword foo"
 => $<closure ...>
yell-user> t.foo
 => "normal foo"
yell-user> t.yell-user:::foo
 => "normal foo"
yell-user> t.keyword:::foo
 => "keyword foo"

パッケージシステムをメッセージングによるオブジェクト指向に応用するというのは、なかなか面白いのではないかと思います。

継続

Yellowの処理系にとって、継続はまさに心臓部です。評価器は存在せず、継続が自己の「次の継続」を返すことで評価が行われます。
Yellowのプログラムが実行される手順を示します。

  1. ソースコードをパーズしてオブジェクトを取り出す
  2. オブジェクトをコンパイルして命令列を生成する
  3. 命令列と環境とデータスタックで継続を作る
  4. 継続の次の継続を求め、その継続のそのまた次の継続を求め……、と繰り返す
  5. 命令列が空の継続が返ってきたら、1に戻る

このように、どこにも評価器は現れません。
継続というのは、評価器が持つ状態として考えることができます。ならば、いっそ評価器自身を継続にしてしまってはどうか?という発想からこのような仕組みができました。
この仕組みは、似たようなものを一つにまとめたという点でシンプルさには一役買っています。しかし、「この上にさらに例外処理のシステムを構築しよう」と思い考え始めたところ、一体どう実装したらよいのかわからなくなってしまいました。きちんとした設計を伴わず勢いで作ってしまったと後悔しています。

最後に

Yellowという言語は、開発途中で設計ミスをしたと感じ、完成に至らなかった多くの言語たちの1つです。ですから、申し訳ないのですが、今後バージョンアップの予定はありません。ただ、「こうすればもっと良くなる」といった意見があれば、次の言語設計に生かすため、歓迎いたします。

そして、「Cyanはどうした?」と思っていらっしゃる方々。Cyanもまた1つの「試案」であり、その修正を行うよりは新たな言語を作ったほうがよいと判断し、Yellowを作りました。今後、どうなっていくかは私にもわかりません。新言語「Magenta」が後継として出てくるかもしれません。いろいろな可能性を探っていきたいと思っているので、ご理解いただけたらと思います。