LLVMで動くオブジェクト指向言語を作ってレイトレした
先月のエントリでEsquisというプログラミング言語を作っていると書いたが、あれからいろいろ機能を足して、レイトレーシングのプログラムが動くようになった。
できたもの
https://github.com/yhara/esquis/releases/tag/v0.0.1
先月のエントリでEsquisというプログラミング言語を作っていると書いたが、あれからいろいろ機能を足して、レイトレーシングのプログラムが動くようになった。
https://github.com/yhara/esquis/releases/tag/v0.0.1
百均でミルクフォーマー買った。150円だった。ミルクフォーマーはスタバの店舗で売ってるのを見たことあるけど、2000円以上してたので、百均にあると聞いてびっくりした。
作りがちゃっちくて、グリコのおまけ感ある。とりあえず使う前に洗おうと思ったが、本体は防水じゃないので、棒の部分だけ取り外す必要があるんだけど、これがまためちゃめちゃ固い。しかし隙間にスプーンの柄を突っ込んだりして頑張ってるうちになんとか取り外すことに成功。その後は常識の範囲内の硬さになった。
使い方だけど、カップに牛乳を入れて、こいつを突っ込んでスイッチを入れるとモーターがすごい勢いで回転し、牛乳に空気が入るという寸法。液体全体が泡になるのではなく、上部に泡が発生するという感じ。牛乳はホットでもアイスでもよい。
成果物としてどういうものが得られるのかよく分かってなかったんだけど、要するにお店のカプチーノとかの上に乗ってる泡状のやつ、あれが手に入ります。150円にしては意外なほどふわふわになる。なんとなく専用の機械とかでやってるのかなぁと思ってたけどこんな単純な機構で再現できるのか。
ということであとは発生させた泡をどのように活用するかという話になるが、スタバのサイトによると泡立った牛乳の上からコーヒーを注ぐということらしい。なるほど。
野菜を買いすぎたので、夕食の野菜炒めを多めに作って、半分を翌日の弁当にしてみた。普段は会社に来られるお弁当屋さんの弁当を買ってて、それと比べるとボリュームも彩りもないけど、意外とこれで良いじゃんっていう感じだった。コンビニが近いので味噌汁だけカップのを買うとかもできるし。一人暮らしだとどの野菜を買ってもたいてい大きすぎるので、こうやって消費先が増えるのは良い。
弁当を作ること自体は興味がありつつ手を付けてなかったんだけど、最近ちょうどいい大きさのランチボックスを見かけて、とりあえず買うだけ買っておいたのが役に立った。(市販の弁当箱はたくさんあるんだけど、米は冷凍して持っていくので、おかずだけ入れるやつが欲しかったのだった) 二段になってるので、慣れてきたら二段目を冷凍食品で埋めたりするのもいいかも。
このブログはSinatraで作っていて、テストはRack::Testで書いてたのだけど、思い立ってCapybaraで書き直した。
というのはある種のバグがRack::Testだと漏れちゃうんですよね。例えばフォームをsubmitしたときにビューのtypoで正しいリクエストが飛ばない、みたいなやつ。Rack::TestだとこういうPOSTリクエストに対しこういう挙動をする、は書けるんだけど、ボタンを押したときにどういうPOSTが飛ぶか、はCapybaraでないと書けない。
もっと規模が大きければRack::Testでコントローラのテストを書いて、Capybaraでintegraiton testを書いて…みたいな構成もあり得るけど、このブログの場合は規模が小さいのでCapybaraによるE2Eテストだけあれば良いかなと思う。
以下、Rack::Testから移行するに当たって「これどうするんだろ?」ってなったことをメモしておく。
これをRubyに移植した。aobenchが自作言語のターゲットとしてまだちょっと大きいなと思ってより小さいサンプルを探していたのだけど、最後のステップまで移植したら結局aobenchとあんまり変わらないようなものになった。ただaobenchのコードはちゃんと理解していなかったので、少し理解が深まった気がして面白かった。あと画像が出るプログラムはやっぱり楽しい。
ソースはgistに上げた。ray5.rbまであり、それぞれ以下のようになっている。
上に貼ったのはray5.rbの出力結果だ。よく見ると元記事と微妙に球の位置が違うことが分かるが、オリジナルは時間tを受け取ってアニメーションするようになっていて、tの値が違うのが原因と思われる(最初、アルゴリズム部分に間違いがあるのかと思って焦った)。
昨年から、Esquisという言語を作っている。Rubyっぽい文法の静的型付け言語になる予定で、実行はLLVM IRを経由して行う。
ということで、(クラスベースの)オブジェクト指向言語をLLVM IRで表現する方法について考えていたので、分かったことをまとめておく。既存の実装としては主にCrystalの生成するLLVM IRを参考にした。
LLVMにはstruct型というものがあり、オブジェクトはこれで表現することができる。問題はどのようなstruct型を定義するかだ。
最初に考えたのは、EsObjという型を作って、すべてのオブジェクトを表現するという方法だ。
去年の夏頃から、BiwaSchemeにsyntax-rulesを入れようと思ってぼちぼち調べてたんだけど、どうもこれは本腰入れて調べないと進捗しないなということで、年末からいろいろ文献を読むなどしていた。
その成果がこちら。
orrというマクロを素朴に展開すると、マクロ内で使っているtという変数名が呼び出し側で定義しているtと衝突してしまう。これを自動でt.0とt.1にリネームしている、という図。
ソースコードはブランチにpushしてある。まだhygenic macroに対応したエクスパンダが本体とは独立に存在するという状態で、最終的にはこれで本体のエクスパンダ(Biwascheme.Interpreter.expand)を置き換えるということになる。
メモ。
LLVM IRは基本的に以下のような構造をしている。
; (レジスタ名) = (命令名) (引数 ...)
%2 = mul i64 %0, %1
ところがコンパイラが生成した.llファイルを見ていると、引数の部分に別の命令が入っていたりする。
%4 = mul i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32), %3
インドカレー屋のレジの横に置いてある甘いやつが好きなんだけど、ネットで買えるっぽいので注文してみた。ジップロック的なものに入ってるので便利。
![]() マウスフレッシュ スウィート フェンネル - sweet fennel 【100gパック】 | 【レビューで50円クーポン進呈】 口直し インド スパイス カレー エスニック アジア 食品 食材 |
あれの正体はフェンネルシードというハーブに砂糖をかけたもので、消化促進に効果があるらしい。食べてみると心なしか胃がすっきりするような気がするが、そうするとなんかもうちょっと食べられる気がしてお菓子とか食べてしまうので、プラマイゼロかもしれない。