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を構築することなく、変更可能な変数を追加する方法を説明する。
最近のコメント
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
peta_okechan
針金みたいなパーツを引っ張ると外れます。 他の方の…
虎徹ファン交換
虎徹の標準ファンを外す際に、どのようにして外されま…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…