コンパイラ内部(型付き状態ABI 2)
エントリーは関数1で、型は [Result<Memory,Int>] -> [Result<Memory,Int>,Int] です。Errで新しいコンパイルを初期化し、以降は各Okが不変の状態を次の呼び出しへ渡します。戻り値にはフェーズを含めます。0は初期化、1は字句解析、2は構文解析、3/30/31/32はメタデータ検証、4は関数の検査、5は許可エフェクトの検査、50は到達可能性の解決、6はモジュールの出力計画、7はジョブの出力、99は診断、100は完了です。ドライバーは、それ以外の内部状態を解釈しません。
関数の対応表
| 関数 | 役割 |
|---|---|
| 1 | 型付き状態の作成と不変の入力テーブルの初期化 |
| 90 | 1ステップの振り分け |
| 2 | ホスト不要の字句解析の遷移。Int入力12個・Int出力18個 |
| 3–8 | 診断、ゼロ埋めの領域確保、出力ジョブの追加、数値の出力、ビット演算 |
| 10–11 | 字句解析器の初期化と入力、トークンと位置範囲の保存 |
| 12–14 | 期待トークンの検査、関数メタデータ、反復式の構文解析 |
| 15–16 | 上限と最大スタックを追跡する、型付きスタックのpop/push |
| 17–21 | 検査フレーム、分岐・反復のスナップショット、復元、合流 |
| 22–25 | ホストメタデータとエフェクト名の検証 |
| 26–27 | 関数・ホストのシグネチャ適用とエフェクトの和集合 |
| 28–30 | 関数の完了、個々の命令の検査、検査器の進行 |
| 31–32 | 許可エフェクトの検証と、到達する関数・インポートの閉包 |
| 40–47 | 位置範囲、型、要約、エフェクト配列、JSON引用したテキストの出力 |
| 48–52 | 到達するホスト宣言をID順に出力 |
| 53–58 | 到達する関数、構造化した本体、具体的な命令の出力 |
| 59–61 | モジュールのエクスポートの計画、出力ジョブの実行、リテラル断片の出力 |
| 62–68 | 名目的な型宣言、レコードのフィールド、ホスト参照の検証、型の出力 |
| 100–104 | 言語側のページ参照・更新・コピー・充填・等価比較 |
記号の関数同士の呼び出しには循環がありません。入力されたソースの呼び出しの循環は、Dicks自身で再帰呼び出しすることなく、コンパイラの明示的な検証フレームで検出します。構文解析には、再帰的に確保するASTオブジェクトの代わりにトークンのリンクを使います。コード生成は、検査済みのリンクをジョブスタックでたどります。
メモリーの領域
すべてのアドレスはバイトオフセットではなく、セルの添字です。セルは符号付き64ビット整数です。メモリーレコードは16,384ページのリストを持ち、各ページは4,096個のIntセルのリストです。言語の検査付きリスト操作で範囲を強制します。更新時は永続木の経路上のノードをコピーし、変わらないブロックは共有します。各関数はメモリーレコードを受け取って返し、読み取り専用の補助関数は受け取るだけです。メモリーを読み書きするホストはありません。
| 開始位置 | 内容 |
|---|---|
| 0–99 | コンパイラのフェーズ、カーソル、個数、診断、一時的なフェーズ状態 |
| 100–110 | 永続化する字句解析器の状態11個 |
| 200 | 構文解析器の64要素のブロックスタック(要素間隔3) |
| 1,024 | トークン(要素間隔10、最大65,536) |
| 700,000 | 関数(要素間隔32、最大256) |
| 720,000 | 関数ごとの入出力型配列(要素間隔2,048) |
| 1,250,000 | 関数IDの参照表(添字+1、0は存在しないことを示す) |
| 1,320,000 | ホストIDの参照表(添字+1、0は存在しないことを示す) |
| 2,000,000 | 宣言順のホストレコード(要素間隔16) |
| 3,100,000 | 共通化したエフェクトのテキストのポインター・長さの記録 |
| 4,200,000 | 関数ごとのエフェクトのビット集合(1ワード60ビット) |
| 6,000,000 | 不変の外部ABI配列とUnicodeスカラー文字列 |
| 10,000,000 | 名目的な型の記述子(要素間隔40) |
| 11,000,000 | 名目的な型IDの参照表 |
| 16,000,000 | 再利用可能な検査用領域 |
| 48,000,000 | 出力ジョブのスタック(要素間隔4) |
トークンは、オペコード、0または正数で表す省略可能な飛距離、ソースのバイトオフセット、バイト長、行、列、閉じトークンへのリンク、elseトークンへのリンク、開始トークンへのリンク、予約フィールドを持ちます。オフセットと範囲は元のUTF-8バイト列を指し、CRLFは1つの改行です。
関数レコードは、ID、ヘッダートークン、入力ポインターと個数、出力ポインターと個数、本体の開始・終了、暗黙関数のフラグ、検証状態(未訪問・処理中・完了)、呼び出しの深さ、非同期フラグ、最大スタック、到達可能フラグを持ちます。到達不能として出力から除くものも含め、すべての定義を検査します。
検査フレームは1,320セルです。親・フレームのカーソルと未処理呼び出しのメタデータ、1,024個のスタック型、5ワードの初期化ビット、256個の固定ローカル型を持ちます。ブロックのスナップショットは2,080セルで、親・開始位置・領域の印に加え、基準スタックと最初の分岐のスタック、初期化ビットを保持します。ブロックは合流時に、関数フレームは完了時に領域の印を戻します。再利用するセルは確保時にゼロにするため、ある関数の初期化済みローカル変数や型が別の関数へ漏れることはありません。
条件分岐では、その後へ処理が続く分岐だけを合流し、スタック全体の型を比較して、初期化済みローカル変数の集合の積を取ります。固定ローカル型は両分岐で共有します。ループは本体を検証しますが、実行回数が0の場合があるため、入力時のスタックと初期化状態へ戻します。呼び出しは先に対象を検証し、エフェクト・非同期性・深さを伝播します。その後、入力型をスタックの逆順で適用し、出力型を積みます。各呼び出しのfuelと割り当て予算に収めるため、シグネチャの適用は少しずつ進めます。
出力ジョブは、種類と3つの数値オペランドを持ちます。ジョブは断片を出力するか、さらに小さなジョブを計画します。JSONテキストのジョブは、引用符・バックスラッシュ・制御文字を記号のコード内でエスケープします。任意のABIテキストが実行可能なコードになることはありません。命令のジョブは、Rustシードと同じ具体的な演算、ソースの範囲、fuelの計上地点、後片付けのブロックを出力します。