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を構築することなく、変更可能な変数を追加する方法を説明する。
最近のコメント
たかたむ
はじめまして。初リアルフォース(R3ですが)で,同…
nokiyameego
ZFS poolのデバイスラベル破損で悩んていたと…
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…