(rontolisp) docs
← 関数

rontolisp:wasm-export

(rontolisp:wasm-export 'name :as "alias" :params '(type...) :param-names '(name...) :returns type :async t)

WebAssembly コアモジュールへコンパイルする際に、トップレベルの defun を ホストから呼び出し可能にし、その引数と戻り値の WASM 境界型を宣言します。これは 通常の関数ではなくコンパイル時のディレクティブです。インタプリタおよび JVM バックエンドでは、名前付きシンボルをそのまま返す no-op となるため、同じ ソースがすべてのバックエンドで動作します。詳細は WebAssembly へのコンパイル を参照してください。JVM 版の双子は rontolisp:jvm-export で、同じ宣言が コンパイルされたクラス上に型付きで Java から呼び出し可能なメソッドを生成 します。

引数

  • エクスポートするトップレベル defun を指すクォートされたシンボル。defun 名と同じように現在のパッケージで解決されます。
  • :as — WASM エクスポート名の文字列 (例: "factorial"、JavaScript 向け API の camelCase 名など)。デフォルトは (パッケージ修飾子を除いた) 素の Lisp 名 (fact) です。
  • :params — 各引数に対応する境界型指定子のリスト。省略、nil'() の場合は 引数なしを意味します。
  • :param-namesコンポーネントモデルのシグネチャにおける引数名を、:params の各要素に 1 つずつ、シンボルまたは文字列で指定します。それぞれコンポーネント モデルのラベル (lower-kebab-case の語) でなければなりません。デフォルトは p0p1、... です。これはホストやバインディングジェネレータがコンポーネントの型で 目にする名前であり、したがって --emit-wit が印字する名前でもあります。--component 以外では無視されます (コア WASM の引数に 名前はありません)。また rontolisp:wit-export で WIT world を実装している プログラムでは、これを宣言せず world から得ます。
  • :returns — 戻り値の境界型指定子。省略、nil'():void の場合は void の 戻り値 (Lisp の戻り値は破棄される) を宣言します。
  • :asynct の場合、--component でエクスポートを非同期のコンポーネント モデル関数としてリフトします。これにより内部の I/O (printrontolisp:fetch など) がトラップせず動作します。デフォルトは nil (同期・純粋計算のリフト) です。意味を持つのは --component のみで、Preview 1 / --no-wasi のコア エクスポートは無視し、--no-gc --component は拒否します。

型指定子と境界表現は次のとおりです。

DesignatorWIT typeWASM boundaryNotes
:s8 :s16 :s32s8 s16 s32i32:int:s32 の恒久的な別名
:u8 :u16 :u32u8 u16 u32i32
:s64 :u64s64 u64i64:long:s64 の恒久的な別名。2^63 以上の :u64 値はトラップする (どのバックエンドも計算に使う符号付き 64 ビット整数に正確な表現を持たないため)
:floatf64f64rontolisp に単精度浮動小数点数はないため、f32 は境界型ではない
:boolbooli320nil、非ゼロの値はすべて t
:stringstring(ptr, len)線形メモリ上の UTF-8 バイト列
:s-exprstring(ptr, len)線形メモリ上の S 式テキスト (関数以外の任意の値)。対応する WIT 型はない
:bytes(ptr, len) argument / (ptr, cap) -> len result(unsigned-byte 8) ベクタを生のバイト列として運ぶ。どちらの方向にも UTF-8 変換なし。GC コアモジュール形状専用

:bytes結果は呼び出し側バッファ方式 (read(2) の形) です: エクスポートの コアシグネチャの末尾にホストが渡す (ptr, cap) ペアが加わり — cap バイトは エクスポートされた __ronto_alloc で確保します — ラッパーはそこへ最大 cap バイトをコピーし、単一の i32 結果はベクタの全長です。バッファが小さすぎた 場合は切り詰めではなくリトライになります。

境界は値を正確に運ぶか、さもなければトラップします。 宣言した型が表現できない 値 — :u32 で返した負数、:u8 で返した 300:s32 で返した 32 ビット範囲外の 値 — は、静かに折り返されて届くのではなく呼び出しを停止させます。マスクは一切行い ません。これは wasmtime と、より厳格なバインディング生成系 (jco など) とで コンポーネントの挙動を一致させることにもつながります。

表現可能な範囲は、どのバックエンドでも宣言した型そのものの範囲です。デフォルト (GC) バックエンドでは着信する整数は正確な整数として届きます (fixnum に収まれば そのまま、超えればボックス化された 64 ビット整数)。3000000000 という :u32 引数は正確な整数 3000000000 として Lisp コードに届きます。Lisp コード内の 整数演算は任意の大きさで正確です (:u32 引数 1073741823 に 対する (+ x 1) は正確に 1073741824 を返します)。宣言した型で表せない結果 だけが境界でトラップします。非 GC バックエンド (--no-gc) では整数を i64 で 計算し、同じように渡ります。

制限事項

  • --component では、エクスポートは WAVE 構文 (wasmtime run --invoke 'name(args)') で呼び出せる型付き コンポーネントモデルエクスポートになります: 固定幅整数族全体 (:long を 含む) と :float/:bool/void に加えて、:string:s-expr は コンポーネントモデルの string として渡ります (--no-gc:s-expr は ありません)。同期 (デフォルト) のエクスポートは純粋計算で なければならず、内部の I/O はトラップします。印字や fetch を行うエクスポート には :async t を宣言してください。--no-gc --component では :async は 拒否されますが、印字はそのまま動作します (プログラムが印字するときだけ 配線される、組み込みの WASI 0.3 stdout マイクロアダプタを通じて。印字する プログラムのすべてのエクスポートは自動的に async リフトされます)。 エクスポート名は lower-kebab-case である必要があります (そうでない場合は :as で改名します)。また --emit-wit を追加すると、コンポーネントの WIT world (すべてのエクスポートの型付きシグネチャ入り) が .wasm の隣に書き出されます。 コンポーネントモデル関数エクスポートコンパクトなコンポーネント出力 を参照してください。インタプリタおよび JVM では名前付きシンボルを返すだけです。
  • エクスポートできるのはトップレベルの defun のみで、宣言した引数の数はその アリティと一致しなければなりません。また関数値を引数や戻り値とする関数は対象外 です。
  • --component 以外では、エクスポートされる関数は純粋計算です。入力・時刻・ ファイルアクセス (関数内でもトップレベルフォームでも) はサポートされません。 --no-wasi ではそれぞれに定義された答えがあり、素のトラップにはなりません — 出力は破棄、getenv とファイル検索は「無い」と答え、時計はホストが __ronto_set_time で書き込んだ時刻を報告し (設定されるまではシグナル)、 rontolisp:random-bytes は捕捉可能なエラーをシグナル、random は組み込みの 生成器で動作し、トラップするのは標準入力だけです。 No-WASI(リアクター)モード を参照してください。もう 1 つ例外があります: --no-gc では print/princ/terpri が、プログラムが印字する場合にのみ追加される単一の fd_write インポートを通じて動作します (印字を参照)。
  • 非 GC バックエンド (--no-gc) は :int/:long/:float/:bool/:string を サポートしますが、cons/リーダ/プリンタのランタイムを必要とする :s-expr と、 配列を必要とする :bytes はサポートしません。
  • :bytes は GC コアモジュール (Preview 1 / --no-wasi) の境界型です: --component は拒否し (list<u8> リフトは未対応)、対応する WIT 型は ありません。