コンパイルされた read/load の制限
JVM の read/load は実行時に JDK を再利用するため(Long.parseLong、BigInteger、Double.parseDouble、java.nio.file)、インタプリタと同じ種類の値を解析します。整数、多倍長整数、浮動小数点数、文字列、シンボル、nil/t、リスト、'quote、#'function です。
すべてのバックエンドにおいて、read は標準入力の 1 行から 1 つの S 式を解析します。空行とコメントのみの行はスキップされ(データを含む行が現れるまで読み込みを続けます)、EOF では nil を返し、フォームは 1 行に収まる必要があります。
WASM のリーダーは手書きのパーサーで、より狭い仕様です。
- 整数は 31 ビットです。 整数トークンは
i31に解析され、オーバーフロー時にラップします。多倍長整数の解析はありません。 - 浮動小数点数は読み取られます。 10 進トークン(先頭の
-は省略可、数字、1 つの.、例:1.0、-2.5、.5、5.)はf64裏付けの浮動小数点数に解析され、浮動小数点リテラルのコンパイル方法と一致します。リーダーは指数表記(1e3)や桁区切りカンマをサポートせず、ドットが 2 つあるトークンや数字以外を含むトークン(例:1.2.3、foo.bar)はシンボルのままになります。 - シンボルのインターンは実行時に裏付けられます。 コンパイルされたプログラムに現れるシンボルは、コンパイルされた
evalが使うのと同じオフセットに解決されます。実行時にのみ現れるシンボル(例: ロードしたファイル内のラムダのパラメータ)は実行時テーブルにインターンされるため、同じシンボルが繰り返し現れても一貫性が保たれます。 loadには事前オープン済みディレクトリが必要です。 最初の事前オープン済みディレクトリ(fd 3)からの相対パスで WASI のpath_openを使ってファイルを開くため、--dirを付けて実行してください。
フロントエンドが read 時に解決するリーダーレベルの構文 — backquote テンプレート、#| ... |# ブロックコメント、#+/#- フィーチャー条件、*features* の置換(データ型を参照)— は、コンパイル出力のランタイムリーダーには理解されません。read/read-from-string/計算された load で実行時に読み込まれるファイルでそれらを使うことはできません。
require/provide はコンパイルされたバックエンドではコンパイル時ディレクティブであるため、コンパイル出力のランタイム load には理解されません。計算されたパスやネストした load で実行時に読み込まれるファイルにそれらを含めることはできません(コンパイル時に消費されるリテラルなトップレベルの require/provide のみが機能します)— ランタイムロードされたファイルのパッケージディレクティブと同じ制限です(パッケージを参照)。
read-from-string は同じ実行時リーダーを再利用するため、コンパイルされたバックエンドでは read と同じ種類の値を解析します(また、実行時に解析される #\ の文字リテラルは両コンパイラの対象外です。ソースに直接書かれた文字リテラルは完全にコンパイルされます)。parse-integer はリーダーから独立しており、3 つのバックエンドすべてで動作します。その :start/:end キーワードはインタプリタ専用で、コンパイルされたバックエンドではキーワード名はリテラルでなければなりません。どちらも 3 つのバックエンドすべてで第一級の値(#'parse-integer、#'read-from-string)としても利用できます。単一引数のラッパー経由で渡されるため、キーワード/オプション引数は関数値を通しては利用できません。