構文
プログラムの形
プログラムはトークンの列であり、それ以上の構造を持たない。実行後にスタックへちょうど 1 個の値が
残らなければならない。0 個なら EmptyExpression、2 個以上なら ExtraOperands になる。
トークン分割
- 空白 (
char.IsWhiteSpace) は区切り文字であり読み飛ばされる。 ;からその行の末尾 (\n) まではコメント。- それ以外の位置から、空白または
;が現れるまでを 1 トークンとして切り出す。 - 切り出した文字列を 3.3 節の順序で分類する。
つまり トークンの区切りは空白 (とコメント) だけである。1+2 は 3 トークンではなく
1+2 という 1 個の不正トークンになる。1;comment は 1 の直後にコメントが来た扱いになる。
分類の順序
切り出した文字列 t は次の順に判定される。先にマッチしたものが勝つ。
| 順 | 条件 | 種別 |
|---|---|---|
| 1 | t が記号表に完全一致 |
Symbol |
| 2 | t[0] == '#' |
Swizzle (本体が不正なら InvalidSwizzle) |
| 3 | t[0] == '@' |
Variable (本体が識別子でなければ InvalidToken) |
| 4 | t が数値の開始形 |
数値リテラル (解析失敗なら InvalidNumberLiteral) |
| 5 | t が識別子 |
Identifier |
| 6 | それ以外 | InvalidToken |
記号表: + - * / // % ... > < >= <= == != !
「数値の開始形」とは、先頭が数字または .、あるいは先頭が + / - で 2 文字目が数字または . であること。
したがって -3 は整数リテラル -3 であり、減算演算子ではない。減算は空白で区切られた単独の - である。
数値リテラル
.eEのいずれかを含むか、末尾にf/Fが付いていれば float、そうでなければ int。- 例:
3は int、3.03f3e0は float、.5は float 0.5、1.5e-3は float。 - 16 進数・アンダースコア区切り・
NaN/Infinity表記は受け付けない (INF定数は存在する)。 - 解析は
CultureInfo.InvariantCulture固定なので、小数点は常に.。
識別子と名前解決
letter は char.IsLetter 準拠なので ASCII 以外の文字も使える (ホストが宣言する変数名次第)。
識別子トークンは次の順に解決される。この探索順は固定で、後から名前を隠すことはできない。
unpack(...と同義)- スタック操作語
dupdropswapoverrot - 組み込み定数 (
PIなど) - 組み込み関数 (
sinなど) - 見つからなければ
UnknownName
変数参照
ホストが名前と型の組で宣言した変数だけを参照できる。式の側で変数を定義・代入することはできない。
宣言表にない名前は UnknownVariable。同じ変数を何度参照しても命令は毎回出力される (値はキャッシュされない)。
型と値
| 型 | 表記 | 次元 | バイト数 | 備考 |
|---|---|---|---|---|
ZaxValueType.Int |
int |
1 | 4 | 32bit 符号付き整数 |
Float |
float |
1 | 4 | IEEE 754 単精度 |
Float2 |
float2 |
2 | 8 | |
Float3 |
float3 |
3 | 12 | |
Float4 |
float4 |
4 | 16 |
int と float がスカラ、float2 から float4 がベクトルである。
行列型・真偽型・文字列型はない。真偽値は float の 1.0 / 0.0 で表す。
3.8 型昇格
2 項以上の演算では引数型を次の規則で 1 つに昇格する。
| 左 \ 右 | int | float | floatN |
|---|---|---|---|
| int | int | float | floatN |
| float | float | float | floatN |
| floatM | floatM | floatM | M = N なら floatN、そうでなければエラー |
- 次元の異なるベクトル同士は昇格できない (
float2とfloat3の加算はTypeMismatch)。 - スカラとベクトルの混在はスカラ側が全成分へブロードキャストされる。
- ベクトルの暗黙の幅拡張 (
float3からfloat4) は起こらない。
シグネチャ規則
すべての演算子・関数は次の 6 クラスのいずれかに属し、引数型と結果型の推論規則が決まる。 4 章・5 章の表の「クラス」列はこれを指す。
| クラス | 引数の要求 | 実引数型 | 結果型 |
|---|---|---|---|
| Ei (elementwise, int 保存) | 昇格可能であること | 昇格結果 | 昇格結果 |
| Ef (elementwise, float 化) | 昇格可能であること | 昇格結果を float 化 | 同左 |
| Io (整数専用) | 全引数が厳密に int |
int |
int |
| Rs (スカラへ縮約) | 昇格可能であること | 昇格結果を float 化 | float |
F3 (float3 専用) |
全引数が厳密に float3 |
float3 |
float3 |
| Cn (構築) | 全引数がスカラ | float |
アリティ次元のベクトル |
「float 化」は int を float に置き換える操作であり、ベクトル型はそのまま。
int が保たれるのは Ei クラスに int だけを与えたときのみである。2 3 + は int 5、
2 3.0 + は float 5.0、2 3 / は float 0.666… になる (/ は Ef のため)。
結果型の強制
ホストは期待する結果型を指定できる。式の生成型がそれと異なる場合、
intからfloatへの暗黙変換のみが許され、末尾にConvert命令が追加される。- それ以外は
ResultTypeMismatch。float3を要求する箇所にfloat4を書くことはできない。
期待型が指定されない場合は生成型がそのまま結果型になる。
言語側に float から int への変換手段はない。int 値は int リテラル、int 型のホスト変数、
および Ei / Io 演算の結果としてのみ生じる。
3.11 文法まとめ
字句上の落とし穴
- 空白必須:
1 2+は不正トークン。すべてのトークンを空白で区切る。 -3は負のリテラル:5 -3 -は 5 と -3 を push してから減算するので 8 になる。 減算のつもりなら5 3 -。同様に+5はリテラル 5 であり加算ではない。- 名前は隠せない: ホストが
dupやPIという変数を宣言しても、@付きでしか参照されないため 衝突はしないが、識別子側の意味を変えることもできない。