最も単純で最も頻繁に使用される例は、 コンパイル中にリテラルを計算することです。 たとえば、 以下の定義は、 文字列の配列を 1 行に 1 つの文字列で出力します:
: .strings ( addr u -- ) \ gforth 2* cells bounds U+DO cr i 2@ type 2 cells +LOOP ;
Gforth のような愚かで低能なコンパイラーを使用すると、 ループ反復ごとに 2 cells
が計算されます。 あなたは、
この値をコンパイル時に一度だけ計算し、 定義にコンパイルできます。 以下のようにします:
: .strings ( addr u -- ) \ gforth 2* cells bounds U+DO cr i 2@ type [ 2 cells ] literal +LOOP ;
[
は、 テキスト・インタープリターをインタープリター状態に切り替えます(この例を対話的に入力し、 [
と ]
の間に改行を挿入すると、 ok
プロンプトが表示されます)。 2 cells
のインタープリター機能(interpretation semantics)を実行します。 ここでは数値を計算します。 ]
は、
テキスト・インタープリターをコンパイル状態に戻します。 次に、 この数値を現在のワードにコンパイルする Literal
のコンパイル機能(compilation semantics)を実行します。 see .strings
を使用してワードを逆コンパイルすると、 コンパイルされたコードへの影響を確認できます。
この方法で 2* cells
を [ 2 cells ] literal *
に最適化することもできます。
[
( – ) core “left-bracket”
インタープリター状態にします。 即実行ワードです。
]
( – ) core “right-bracket”
コンパイル状態にします。
Literal
( compilation n – ; run-time – n ) core “Literal”
コンパイル機能(compilation semantics): 実行機能(run-time semantics)をコンパイルします。 実行機能(run-time semantics): n をスタックにプッシュします。 インタープリター機能(interpretation semantics): 未定義です。
ALiteral
( compilation addr – ; run-time – addr ) gforth-0.2 “ALiteral”
literal
と同様に機能しますが、
(クロス・コンパイルされたコードで使用される場合、)リテラルがアドレスであることをクロス・コンパイラーに伝えます。
]L
( compilation: n – ; run-time: – n ) gforth-0.5 “]L”
] literal
と同等。
単一セル以外のデータ型をリテラルとしてコンパイルするためのワードもあります:
2Literal
( compilation w1 w2 – ; run-time – w1 w2 ) double “two-literal”
実行時に w1 w2 がスタックに配置されるように、 適切なコードをコンパイルします。 インタープリター機能(interpretation semantics)は未定義です。
FLiteral
( compilation r – ; run-time – r ) floating “f-literal”
実行時に r が(浮動小数点)スタックに配置されるように、 適切なコードをコンパイルします。 インタープリター機能(interpretation semantics)は未定義です。
SLiteral
( Compilation c-addr1 u ; run-time – c-addr2 u ) string “SLiteral”
コンパイル時: c-addr1, u で指定された文字列を現在の定義にコンパイルします。 実行時: 文字列のアドレスと長さを記述する c-addr2 u を返します。
データ・スタック上のコロン定義の外側から内側にデータを渡したいと思うかもしれません。 :
がコロン colon-sys をプッシュし、
colon-sys より下のモノのにアクセスできなくなるため、 これは機能しません。 たとえば、 以下は機能しません:
5 : foo literal ; \ error: "unstructured"
代わりに、 変数など、 他の方法で値を渡す必要があります:
variable temp 5 temp ! : foo [ temp @ ] literal ;