本の諸々が一段落したので、最近はLaTeX処理自動化ツールClutTeXの開発を進めています。前(2023年11月)に計画を書いて以降の進捗を書きます。
続きを読む「プログラミング」カテゴリーアーカイブ
Macで試すBinary Hacks Rebooted その1:イントロダクション
去る8月28日に、私が執筆に参加した「Binary Hacks Rebooted」が無事に発売されました。
「Binary Hacks Rebooted」はLinuxを前提に書かれたHackが多いです(特に前半)。しかし、読者の中にはMacを使っているという方も一定数いるのではないかと思います。というか、Macを使っている人にも読んでもらいたいです。
もちろん、Mac上でもDocker, multipass, QEMU等を使ってLinuxを動かせば、本の内容は再現できます。しかし、バイナリアンの気持ちとしては、マシンでネイティブに動いているOSを使ってHackしたいものではないでしょうか。少なくとも私はそうです。(まあMac上でネイティブにLinuxを入れるという手もありますが、それだと機材がMacである必要がないのでは?と私は思ってしまいます。)
また、x86-64 Linuxであれば本の内容がそのまま動くのは当たり前(※)なので、違う環境でどうなるか試行錯誤することによって圧倒的成長💪💪💪が見込まれます。(※と言いつつ、Linuxでもディストロによって、あるいはUbuntuであってもバージョンが違うと無変更で動くかはわからないわけですが。本に載っている実行例はUbuntu 22.04のものが多いと思います。)
というわけで、MacでmacOSを使ってBinary Hacks Rebootedの内容を試したいです。
続きを読むLunarML/Standard MLのブートストラップ問題
LunarMLを含む多くのStandard MLコンパイラーはStandard ML自身で記述されています。すでに動くStandard ML処理系があればSMLで書かれたコンパイラーを動かせますが、Standard ML処理系のない新しいプラットフォームでStandard MLコンパイラーを動かしたい場合はどうすればいいでしょうか?
続きを読む「Binary Hacks Rebooted」が出ます
今月(2024年8月)末にオライリージャパンから出る「Binary Hacks Rebooted」という本の執筆に、著者の一人として参加しました。私は主に浮動小数点数周りの記事を執筆しました。
続きを読むLunarML v0.2.0リリースと最近の進捗
LuaやJavaScriptを出力するStandard MLコンパイラー「LunarML」のバージョン0.2.0をリリースしました。
続きを読むTwoSumの証明に2週間かかった
技術書典16に、Haskellでの型レベルプログラミングの本を出します
今度の5月26日(日)に池袋でオフライン開催される技術書典16に、サークル「だめぽラボ」で新刊「Haskellでの型レベルプログラミング」を出します。既刊も在庫があるものは頒布します。
続きを読むプログラミングではたまにエスパー力が必要になることがある
西暦2262年問題に対処するべきか
西暦2038年問題はみなさんご存知ですよね。2038年1月19日午前3時14分7秒(UTC)を過ぎると 世界中のUNIXがばくはつする問題 time_t
が符号付き32ビットなプログラムで現在時刻を正しく扱えなくなる問題です。
C言語の time_t
は典型的にはUnix epoch(UTCで1970年1月1日午前0時)からの経過時間(うるう秒は考慮しない)を秒単位で保持しており、それが\(2^{31}-1\)に到達するのが2038年1月19日午前3時14分7秒(UTC)なわけですね。
2038年は割と近い将来なので、モダンなC処理系では time_t
を64ビット整数にするなどの対応を行なって2038年問題を乗り切ろうとしています。
それでも、時刻を固定長整数で表現する限り、いつか限界が来ます。「time_t
を64ビット整数にする」という対応は、問題を西暦2038年から西暦292277026596年に先送りしたに過ぎません。
そして、時刻の表現を「秒単位」ではなくもっと細かい単位にするとこの限界はもっと早くやってきます。この記事では、時刻の表現をどういう刻みで何ビットにすると限界がいつになるのかを検討してみます。
続きを読むStandard MLのIOとLunarMLのIO
プログラムにとって入出力は大事です。入出力機構がないと、計算の入力を受け取ることも、出力を出すこともできません。
Standard MLにも当然入出力に使う型と関数が定められています。例えば、print
関数は標準出力に文字列を出力し、flushします。TextIO
や BinIO
などのモジュールを使うと、ファイルの読み書きを行うこともできます。
LunarMLも、これらのモジュールを一部実装しています。しかし、今の実装はやっつけなので、もっとしっかりした(準拠度の高い)実装にしたいです。
Standard MLの入出力
Standard MLの入出力はいくつかのレイヤーに分かれています。
一番高いレイヤーが「手続き的入出力」すなわち IMPERATIVE_IO
や TEXT_IO
や BinIO
です。これらは
- 手続き的な入力
- 手続き的な出力
- ストリームのリダイレクト
などの機能を提供します。
手続き的入出力は、ストリーム入出力のラッパーと思えます。手続き的入出力のストリームの型はストリーム入出力の型を使うと
type instream = StreamIO.instream ref
type outstream = StreamIO.outstream ref
という風に理解できるでしょう。
ストリーム入出力は STREAM_IO
で表されます。機能的には、
- 関数的な(遅延リスト的な)入力
- 手続き的な出力
- バッファリング
を提供します。「関数的な入力」というのは、例えば「一文字読み取る」関数が
val input1 : instream -> (elem * instream) option
という型を持ち、「入力に与えられたストリーム」とは別の「一文字読み取った後のストリーム」を返すということです。同じストリームに input1
を複数回適用すると同じ結果が得られることが期待されます。
ストリーム入出力の下にあるのがプリミティブ入出力です。プリミティブ入出力 PRIM_IO
は、システムコールを抽象化したものだと思えます。機能的には、
- バッファリングなしの、手続的な入出力
- ノンブロッキングIO(オプション)
- ランダムアクセス(オプション)
- OSのファイル記述子へのアクセス(オプション)
- ファイル記述子に対しては、等価性比較、ハッシュ値の取得、大小比較ができることが想定されています。
があります。ただし、プリミティブ入出力はあくまでインターフェースを定めるものであり、特定のシステムコールに紐づいたものではありません。特定のシステムコールを呼び出すプリミティブ入出力の実装を提供するのは openIn
とか stdIn
とかを提供する側の役目です。
Standard MLにはこのほかに、OSのシステムコールに対応する型と関数が規定されています。
LunarMLの入出力
LunarMLは、スクリプト言語の提供する入出力機能をラップしてStandard MLの型と関数として見せたいです。スクリプト言語の提供する入出力機能とは、Luaで言えば io
モジュール、Node.jsで言えば Readable
/Writable
などのストリームです。
スクリプト言語の提供する入出力機能をシステムコールとみなしてプリミティブ入出力として提供できれば良かったのですが、現実にはそううまくはいきません。スクリプト言語の提供する入出力機能にはバッファリングがあるのに対して、プリミティブ入出力にはバッファリングはありません。具体的には出力ストリームのflush操作がプリミティブ入出力にはないのです。書き込み操作の度にflushすればエミュレートできるかもしれませんが、ストリーム入出力のレイヤーでバッファリングを再実装するのかという問題もあります。
今考えているプランは、ストリーム入出力を単なるプリミティブ入出力のラッパーとするのではなく、内部実装として「プリミティブ入出力、あるいはスクリプト言語の提供する(バッファリングされた)ストリーム」の2択を持てるようにする案です。ストリームからプリミティブ入出力のインターフェースを得る場合は、ファイル記述子っぽいものを含めて、逆の操作(ストリーム入出力の構築)を行うときに「スクリプト言語の提供するストリーム」を復元できるようにします。ファイル記述子としては、スクリプト言語の提供するストリームと独自に割り当てる整数をハッシュテーブルで対応させて管理することにします。
まあ、言葉にするのは簡単ですが(これでも結構考えたのですが)、実装するのは面倒くさいです。少しずつやっていきます。