思想
位置づけ
Zax が解くべき問題は「頂点数ぶん繰り返し評価される小さな数式を、ユーザーがインスペクタの 1 行に書けるようにする」ことである。この用途からくる要求は次の 3 つ。
- 入力は 1 個の値を返す純粋な式である。文も宣言も要らない。
- 評価は数万回単位で繰り返される。したがって実行時の型判定・分岐・確保は避けたい。
- 失敗はビルド時までに分かってほしい。頂点 12345 番で初めて型エラーが出るのは論外。
結果として Zax は「コンパイル時にすべての型を解決し、実行時は型タグ付きの固定長スタックを 舐めるだけ」という形に落ち着いている。
設計判断
| 判断 | 理由 |
|---|---|
| RPN を採用 | パーサが要らない。優先順位・結合性・括弧の設計を丸ごと回避でき、字句解析器の出力をそのまま線形に走査すればコード生成が終わる |
| 式のみ (文なし) | プログラム全体が「変数の組から 1 値への写像」になり、要素ごとの独立評価 = 並列化が自明になる |
| 静的型付け | 実行時型ディスパッチを消せる。命令が自分の引数型・結果型を持つため、評価器の内側ループに型検査が一切ない |
| ホストが変数を宣言 | 式の側が新しい名前を作れない。どの属性が参照されたかがコンパイル結果から静的に分かるので、ホストは必要な入力だけを用意できる |
| スカラ・4 次元までのベクトルのみ | すべての値が float4 1 個に収まり、値表現が固定長になる。SIMD 演算をそのまま使える |
| 最適化しない | 式は数トークンから数十トークン。コンパイル時間と実装の単純さを優先し、定数畳み込みも共通部分式除去も行わない (定数プールの重複排除のみ) |
意図的に持たない機能
分岐・ループ・ユーザー定義関数・変数への代入・局所束縛・再帰・行列型・真偽型・文字列型・ 配列添字アクセスはいずれも存在しない。
この帰結として、プログラムの実行時間は命令数に比例する定数であり、停止しない式は書けない。 スタックの必要段数もコンパイル時に確定するため、実行時のメモリ確保も起こらない。
分岐がないことの帰結
条件分岐は値の重み付けで表現する。比較演算子が 1.0 / 0.0 を返すのはこのためである。
lerp の第 3 引数が 0 か 1 のときは選択そのものになる。閾値判定は step でも書ける。
論理演算も同様に算術で代用する。
| 論理 | 書き方 |
|---|---|
| AND | * または min |
| OR | max |
| NOT | ! または 1.0 swap - |
| XOR | != |
両辺とも常に評価される (短絡しない) ため、0 除算や定義域外を含む枝を条件で回避することは
できない。max や clamp で入力側を潰しておく必要がある。