技術

6.5. 簡単なテスト

LLVMによるプログラミング言語の実装チュートリアル日本語訳
第6章 万華鏡: 言語の拡張: ユーザ定義演算子
第5節 簡単なテスト

にわかに信じがたいが、この章で施した簡単な拡張によって、実用的な言語となった。
これによって、I/Oや数学やその他諸々について、いろんな面白いことが出来る。
例えば、順次演算子(sequencing operator)を追加出来る。(printdは、与えられた値とその後に改行を印字するよう定義されている。)
訳注: printdの実装は万華鏡そのもののソースに含まれている。

ready> extern printd(x);
Read extern:
declare double @printd(double)

ready> def binary : 1 (x y) 0;  # オペランドを無視し、優先順位が低い演算子
..
ready> printd(123) : printd(456) : printd(789);
123.000000
456.000000
789.000000
Evaluated to 0.000000

次のように、基本的な演算子も定義出来る。

# 単項演算子 論理否定。
def unary!(v)
  if v then
    0
  else
    1;

# 単項演算子 符号の反転
def unary-(v)
  0-v;

# ">"を"<"と同じ優先順位で定義する。
def binary> 10 (LHS RHS)
  RHS < LHS;

# 二項演算子 論理和。(ショートサーキットはしない。)
def binary| 5 (LHS RHS)
  if LHS then
    1
  else if RHS then
    1
  else
    0;

# 二項演算子 論理積。(ショートサーキットはしない。)
def binary& 6 (LHS RHS)
  if !LHS then
    0
  else
    !!RHS;

# 関連する演算子よりわずかに低い優先順位で"="を定義する。
def binary = 9 (LHS RHS)
  !(LHS < RHS | LHS > RHS);

# 式を順番に並べるために、オペランドを無視しRHSを返す低い優先順位の演算子として":"を定義する。
def binary : 1 (x y) y;

訳注: 論理和と論理積は一見ショートサーキットするように見えるが、LHSとRHSはあくまでも関数の引数であるため関数(演算子)呼び出しのタイミングで両方とも評価される。

以前やったif/then/elseのサポートによって、I/O用の面白い関数も定義できる。
例えば、以下のコードは、与えられた値を反転した”密度”を表す文字を印字する。
低い値であれば、濃い文字となる。

ready>

extern putchard(char)
def printdensity(d)
  if d > 8 then
    putchard(32)  # ' '
  else if d > 4 then
    putchard(46)  # '.'
  else if d > 2 then
    putchard(43)  # '+'
  else
    putchard(42); # '*'
...
ready> printdensity(1): printdensity(2): printdensity(3):
       printdensity(4): printdensity(5): printdensity(9):
       putchard(10);
**++.
Evaluated to 0.000000

基本的な演算子をベースとして、より面白いものを定義することが出来る。
例えば、複素数平面上にける関数を、何回か反復して解く、以下のような小さな関数がある。

# 指定された地点が枝分かれするかどうか決定する。
# 複素数平面における、z = z^2 + cを解く。
def mandleconverger(real imag iters creal cimag)
  if iters > 255 | (real*real + imag*imag > 4) then
    iters
  else
    mandleconverger(real*real - imag*imag + creal,
                    2*real*imag + cimag,
                    iters+1, creal, cimag);

# 反復を抜けたときの反復回数を返す。
def mandleconverge(real imag)
  mandleconverger(real, imag, 0, real, imag);

“z = z2 + c”という関数は、マンデルブロ集合の計算における基礎となる、シンプルで美しく非常におもしろい効果を持つ式である。
mandelconverge関数は、反復を抜けるのに掛かった反復回数(最大255)を返す。
この関数はそれ自身では役立たないが、この関数の結果を二次元平面に描画すると、マンデルブロ集合を見ることが出来る。
ここでは、putchardの使用に限られるので、絵的に凄いものにはならないが、上記の密度プロッタを使うことで以下のようにすることが出来る。

# 与えれた2次元の範囲でマンデルブロ集合を計算しプロットする。
def mandelhelp(xmin xmax xstep   ymin ymax ystep)
  for y = ymin, y < ymax, ystep in (
    (for x = xmin, x < xmax, xstep in
       printdensity(mandleconverge(x,y)))
    : putchard(10)
  )

# mandel - これはマンデルブロ集合のプロットに役立つ便利な関数である。
# 位置と、倍率を受け取る。
def mandel(realstart imagstart realmag imagmag)
  mandelhelp(realstart, realstart+realmag*78, realmag,
             imagstart, imagstart+imagmag*40, imagmag);

これによってマンデルブロ集合のプロットを試すことが出来る。
さぁ、やってみよう!

ready> mandel(-2.3, -1.3, 0.05, 0.07);
*******************************+++++++++++*************************************
*************************+++++++++++++++++++++++*******************************
**********************+++++++++++++++++++++++++++++****************************
*******************+++++++++++++++++++++.. ...++++++++*************************
*****************++++++++++++++++++++++.... ...+++++++++***********************
***************+++++++++++++++++++++++.....   ...+++++++++*********************
**************+++++++++++++++++++++++....     ....+++++++++********************
*************++++++++++++++++++++++......      .....++++++++*******************
************+++++++++++++++++++++.......       .......+++++++******************
***********+++++++++++++++++++....                ... .+++++++*****************
**********+++++++++++++++++.......                     .+++++++****************
*********++++++++++++++...........                    ...+++++++***************
********++++++++++++............                      ...++++++++**************
********++++++++++... ..........                        .++++++++**************
*******+++++++++.....                                   .+++++++++*************
*******++++++++......                                  ..+++++++++*************
*******++++++.......                                   ..+++++++++*************
*******+++++......                                     ..+++++++++*************
*******.... ....                                      ...+++++++++*************
*******.... .                                         ...+++++++++*************
*******+++++......                                    ...+++++++++*************
*******++++++.......                                   ..+++++++++*************
*******++++++++......                                   .+++++++++*************
*******+++++++++.....                                  ..+++++++++*************
********++++++++++... ..........                        .++++++++**************
********++++++++++++............                      ...++++++++**************
*********++++++++++++++..........                     ...+++++++***************
**********++++++++++++++++........                     .+++++++****************
**********++++++++++++++++++++....                ... ..+++++++****************
***********++++++++++++++++++++++.......       .......++++++++*****************
************+++++++++++++++++++++++......      ......++++++++******************
**************+++++++++++++++++++++++....      ....++++++++********************
***************+++++++++++++++++++++++.....   ...+++++++++*********************
*****************++++++++++++++++++++++....  ...++++++++***********************
*******************+++++++++++++++++++++......++++++++*************************
*********************++++++++++++++++++++++.++++++++***************************
*************************+++++++++++++++++++++++*******************************
******************************+++++++++++++************************************
*******************************************************************************
*******************************************************************************
*******************************************************************************
Evaluated to 0.000000
ready> mandel(-2, -1, 0.02, 0.04);
**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
***********++++++++++++++++++++++++++++++++++++++++++++++++++........        .
**********++++++++++++++++++++++++++++++++++++++++++++++.............
********+++++++++++++++++++++++++++++++++++++++++++..................
*******+++++++++++++++++++++++++++++++++++++++.......................
******+++++++++++++++++++++++++++++++++++...........................
*****++++++++++++++++++++++++++++++++............................
*****++++++++++++++++++++++++++++...............................
****++++++++++++++++++++++++++......   .........................
***++++++++++++++++++++++++.........     ......    ...........
***++++++++++++++++++++++............
**+++++++++++++++++++++..............
**+++++++++++++++++++................
*++++++++++++++++++.................
*++++++++++++++++............ ...
*++++++++++++++..............
*+++....++++................
*..........  ...........
*
*..........  ...........
*+++....++++................
*++++++++++++++..............
*++++++++++++++++............ ...
*++++++++++++++++++.................
**+++++++++++++++++++................
**+++++++++++++++++++++..............
***++++++++++++++++++++++............
***++++++++++++++++++++++++.........     ......    ...........
****++++++++++++++++++++++++++......   .........................
*****++++++++++++++++++++++++++++...............................
*****++++++++++++++++++++++++++++++++............................
******+++++++++++++++++++++++++++++++++++...........................
*******+++++++++++++++++++++++++++++++++++++++.......................
********+++++++++++++++++++++++++++++++++++++++++++..................
Evaluated to 0.000000
ready> mandel(-0.9, -1.4, 0.02, 0.03);
*******************************************************************************
*******************************************************************************
*******************************************************************************
**********+++++++++++++++++++++************************************************
*+++++++++++++++++++++++++++++++++++++++***************************************
+++++++++++++++++++++++++++++++++++++++++++++**********************************
++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
+++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
+++++++++++++++++++++++++++++++....   ......+++++++++++++++++++****************
+++++++++++++++++++++++++++++.......  ........+++++++++++++++++++**************
++++++++++++++++++++++++++++........   ........++++++++++++++++++++************
+++++++++++++++++++++++++++.........     ..  ...+++++++++++++++++++++**********
++++++++++++++++++++++++++...........        ....++++++++++++++++++++++********
++++++++++++++++++++++++.............       .......++++++++++++++++++++++******
+++++++++++++++++++++++.............        ........+++++++++++++++++++++++****
++++++++++++++++++++++...........           ..........++++++++++++++++++++++***
++++++++++++++++++++...........                .........++++++++++++++++++++++*
++++++++++++++++++............                  ...........++++++++++++++++++++
++++++++++++++++...............                 .............++++++++++++++++++
++++++++++++++.................                 ...............++++++++++++++++
++++++++++++..................                  .................++++++++++++++
+++++++++..................                      .................+++++++++++++
++++++........        .                               .........  ..++++++++++++
++............                                         ......    ....++++++++++
..............                                                    ...++++++++++
..............                                                    ....+++++++++
..............                                                    .....++++++++
.............                                                    ......++++++++
...........                                                     .......++++++++
.........                                                       ........+++++++
.........                                                       ........+++++++
.........                                                           ....+++++++
........                                                             ...+++++++
.......                                                              ...+++++++
                                                                    ....+++++++
                                                                   .....+++++++
                                                                    ....+++++++
                                                                    ....+++++++
                                                                    ....+++++++
Evaluated to 0.000000
ready> ^D

この時点で、万華鏡が現実的でパワフルな言語であると気付き始めたはずだ。
自己相似には見えないかもしれないが、マンデルブロ集合をプロットすることは出来る。(It may not be self-similar :), but it can be used to plot things that are!)

これを、このチュートリアルのユーザ定義演算子の追加の章の結論とする。
言語を拡張する能力の追加により、我々は言語の強化に成功した。
また我々は、万華鏡の簡単で面白いユーザアプリケーションを構築するために、どうやってこれを使用できるか示した。
この時点で、万華鏡は様々な実用的アプリケーションを構築出来るし、副作用有りで関数を呼び出すことも出来るが、実はまだ変数を定義したり書き換えたりが出来ない。

いろんな言語において、変数を変更する機能は著しく重要である。
しかし、変更可能な変数のサポートを追加する方法は、まだ全く明らかになっていない。
次の章で、フロントエンドでSSAを構築することなく、変更可能な変数を追加する方法を説明する。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください