以下ではインタプリタでの追加設定について書いていきます。雑記・考察ログを見たい人は「オペコードなどについて考察する」をお読みください。アセンブリ言語だけの最新の仕様だけ知りたい人は設定一覧をお読みください。専門用語の一覧は用語集に掲載されています。Twitterで出た質問はTogetterにまとめてあります(part1, part2, part3)。ソースコードの例としては非再帰フィボナッチと再帰フィボナッチとquicksortと開平があります。
擬似ハードウェアは擬似CPUと擬似メモリからなる。
アドレスをキーとして8bitを値とした連想配列である。書き込んでいない番地から読み込もうとしたときというのは高い確率でバグなので、番地を乱数種とした擬似乱数が返り、かつそのアクセスが別の場所にこっそり記録されるという仕様になっている。
central processing unitとは名ばかりで、processingはインタプリタが代行してくれている以上、擬似CPUはレジスタとフラグからなる構造体のことに過ぎない。
コマンドライン引数で与えられたファイルを開き、構文解析してロードする。その段階のものをデバッグ出力し、次にロードしたものを実行する。その結果得られたログ(独自拡張であり、かつ現状では常に空)を出力したあと、仮想ハードウェアを出力して終了する。-x
が与えられているときは、ロードしたもののログ出力はなく、代わりに各命令の実行前に毎回一時停止する。コマンドライン引数がない場合は、複数のサンプルファイルそれぞれに対し「ロード→デバッグ出力→実行」を行う。
セミコロンから行末までをコメントとし、無視する独自拡張が実装されている。
各命令に擬似乱数で仮の長さを割り振り、0x14830000 = 344129536を起点として各命令にアドレスを割り振っていく。各命令の2進数表現が確定していない以上、当然擬似メモリ上には実際には命令は載っておらず、従って自己書き換えコードのようなことは実現できない。またこの時にラベルからアドレスを引く連想配列も作られ、krz fistir xx
のような命令を実行するときには「その連想配列の中からアドレスを引き、それをxxに代入」といった処理となる。
基本的には、「nxの次の命令のアドレスをxxに入れ、nxの命令を取得する」→「nxの命令に従って擬似ハードウェアの値を変更していく」→「nxにxxの値をコピーする」だけである。
擬似ハードウェアの初期状態:
ロードされた命令に当たるアドレス以外の値がnxに入っていると、実行したときにエラーを吐く。ただし、nxが0xbda574b8 = 3181737144であるときはインタプリタが特別に解釈し、f5の値が初期値と同じである場合に限り処理が正常終了する。メモリの初期状態は「ゼロ引数の関数を呼んでおり、リターンアドレスは0xbda574b8 = 3181737144である」という状況である。要するに、インタプリタはゼロ引数関数を期待し実行し、関数が呼び出し規約を守っていれば正常終了することを期待しているのである。
インタプリタには以下の組み込み関数がある。
関数のアドレス | 引数の数 | 挙動 |
3126834864 | 1 | 引数を何らかの場所にデバッグ出力する。 |
0xa0000000 - 0xaffffffc、つまり2684354560〜2952790012のメモリ空間はインタプリタ側では用いないので、将来の衝突の心配なくユーザー側で用いることができる。