エンタープライズギークス (Enterprise Geeks)

企業システムの企画・開発に携わる技術者集団のブログです。開発言語やフレームワークなどアプリケーション開発に関する各種情報を発信しています。ウルシステムズのエンジニア有志が運営しています。

JavaScriptでLispインタープリターを作ろう(6) ~反復の導入~

前回の記事では変数を導入した。これで、反復処理を記述するための土台がひとまず整ったことになる。それでは早速、反復処理であるwhileを導入してみよう。

反復処理を行うwhile

反復処理は、インタープリターのevaluate関数に以下の記述を追加する事で導入できる。

var evaluate = function(x, env) {
  if (Array.isArray(x)) {
    if (x[0] === 'while') { // whileループ                     追加行1
      while (evaluate(x[1], env)) {                         // 追加行2
        x.slice(2).forEach(function(a){evaluate(a, env);}); // 追加行3
      }                                                     // 追加行4
      return null;                                          // 追加行5
    } else if (x[0] === 'def') { // 変数定義
    // ・・・以下略・・・

上記のコードについて簡単に説明しておこう。
まず「追加行2」の部分ではJavaScriptwhileループに入っている。ここでwhileの第1引数を評価(evaluate)し、ループを継続するかをチェックしている。そして「追加行3」の部分で、whileで実行したいコードを順次評価している。

以下にソースコード全体を掲載する。

このwhileループを試してみよう。たとえばJavaScriptにおいて以下のようなコードを書きたいとする。

var i = 0;
while (i < 3) {
  console.log(i);
  i = i + 1;
}

これを、このインタープリターで記述すると以下のようになる。

evaluate(['do',
           ['def', 'i', 0],
           ['while', ['<', 'i', 3],
             ['console.log', 'i'],
             ['set!', 'i', ['+', 'i', 1]]]],
         globalEnv);

このソースコードJavaScript版とほぼ同じであるため、対応関係がよくお分かり頂けるのではないだろうか。

さて、以上で反復処理も記述可能になった。これにより、「順次・反復・分岐」のすべての制御構文がサポートできたことになる。

次回はいよいよ関数を導入する。

[近棟 稔]