Forthの基本的なデータ構造は、「単語」を実行可能コードまたは名前付きデータ構造にマップする「辞書」です。 辞書は、センチネル値、通常はヌルポインタが見つかるまで、最新の(最も最近の)定義された単語から最も古い単語に進むリンク付きリストのツリーとし コンテキストスイッチを使用すると、リストの検索が別のリーフから開始されます。 リンクリスト検索は、ブランチがメイントランクにマージされ、最終的にはセンチネル、ルートに戻るように継続されます。いくつかの辞書があります。 メタコンパイルのようなまれなケースでは、辞書が分離されてスタンドアロンになる可能性があります。この効果は、名前空間のネストの効果と似ており、コンテキストに応じてキーワードをオーバーロードする可能性があります。
定義された単語は、一般に、名前フィールド(NF)とリンクフィールド(LF)で構成されるheadとbody、コードフィールド(CF)とパラメータフィールド(PF)で構成されるbodyで構成さ
辞書エントリのHeadとbodyは、連続していない可能性があるため、別々に扱われます。 たとえば、Forthプログラムが新しいプラットフォーム用に再コンパイルされると、ヘッドはコンパイルコンピュータに残り、ボディは新しいプラット 一部の環境(組み込みシステムなど)では、ヘッドが不必要にメモリを占有します。 しかし、いくつかのクロスコンパイラは、ターゲット自体が対話型のForthをサポートすることが期待されている場合、ターゲットにヘッドを置くことができます。
辞書エントリ編集
辞書エントリの正確な形式は規定されておらず、実装は異なります。 ただし、特定のコンポーネントはほとんど常に存在しますが、正確なサイズと順序は異なる場合があります。 構造体として記述すると、辞書エントリは次のようになります。
structure byte: flag \ 3bit flags + length of word's name char-array: name \ name's runtime length isn't known at compile time address: previous \ link field, backward ptr to previous word address: codeword \ ptr to the code to execute this word any-array: parameterfield \ unknown length of data, words, or opcodes end-structure forthword
名前フィールドは、単語の名前の長さ(通常は32バイトまで)を 単語の名前の文字表現は、接頭辞の後に続きます。 Forthの特定の実装に応じて、整列のために1つ以上のNUL(‘\0’)バイトがあるかもしれません。
リンクフィールドには、以前に定義された単語へのポインタが含まれています。 ポインタは、次の最も古い兄弟を指す相対的な変位または絶対アドレスである可能性があります。
コードフィールドポインタは、パラメータフィールド内のコードまたはデータを実行するワードのアドレス、またはプロセッサが直接実行するマシンコードの コロンで定義された単語の場合、コードフィールドポインタは、現在のForth命令ポインタ(IP)を戻りスタックに保存し、単語の実行を継続するための新しいアド これは、プロセッサのコール/リターン命令が行うことと同じです。
compilerEditの構造
コンパイラ自体はモノリシックプログラムではありません。 これは、システムに表示され、プログラマによって使用可能な四つの単語で構成されています。 これにより、プログラマは特別な目的のためにコンパイラの単語を変更することができます。
名前フィールドの”compile time”フラグは、”compile time”動作を持つ単語に設定されます。 ほとんどの単純な単語は、コマンドラインで入力されているか、コードに埋め込まれているかにかかわらず、同じコードを実行します。 これらをコンパイルするとき、コンパイラは単にコードまたはスレッドポインタを単語に配置します。コンパイル時の単語の古典的な例は、IF
WHILE
などの制御構造です。 Forthの制御構造のほとんどすべてとそのコンパイラのほとんどすべては、コンパイル時の単語として実装されています。 条件付きリターンのようないくつかの実装でしか使用されていない制御フローワードを除いて、Forthの制御フローワードはすべてコンパイル時に実行され、プリミティブワードとそのブランチアドレスの様々な組み合わせをコンパイルする。 たとえば、IF
WHILE
BRANCH
?BRANCH
(スタックから値をポップし、falseの場合は分岐 カウントされたループ制御フローワードは同様に機能しますが、カウンタで動作するプリミティブワードの組み合わせなどを設定します。 コンパイル時に、データスタックは、ブランチアドレスの制御構造のバランシング、ネスト、およびバックパッチをサポートするために使用されます。 スニペット:
... DUP 6 < IF DROP 5 ELSE 1 - THEN ...
定義内で次のシーケンスにコンパイルされます。
... DUP LIT 6 < ?BRANCH 5 DROP LIT 5 BRANCH 3 LIT 1 - ...
BRANCH
BRANCH
BRANCH
LIT
は、”リテラル”番号をデータスタックにプッシュするためのプリミティブワードです。
コンパイル状態と解釈stateEdit
単語:
(colon)は、名前をパラメータとして解析し、辞書エントリ(コロン定義)を作成し、コンパイル状態に入ります。 インタプリタは、ユーザー入力デバイスからスペース区切りの単語を読み続けます。 単語が見つかった場合、インタプリタは、解釈セマンティクスではなく、単語に関連付けられたコンパイルセマンティクスを実行します。 単語のデフォルトのコンパイル意味論は、その解釈意味論を現在の定義に追加することです。
単語;
;
(セミコロン)、ほとんどの制御フロー単語、およびその他のいくつかの単語の解釈セマンティクスは、Ans Forthでは定義されていません。
インタプリタの状態は、LITERAL
LITERAL
は、データスタックからオブジェクトを取得し、そのオブジェクトをデータスタックに配置するために現在のコロン定義にセマンティ
Forthでは、インタプリタの現在の状態は、コンパイル状態のときはtrue、そうでない場合はfalseの値を含むフラグSTATE
から読み取ることができます。 これにより、インタプリタの現在の状態に応じて変化する動作を持つ、いわゆる状態スマートな単語の実装が可能になります。
Immediate wordsEdit
単語IMMEDIATE
;
は、即時の単語の例です。 Forthでは、POSTPONE
という単語は名前をパラメータとして受け取り、その単語がimmediateとマークされていても、名前付き単語のコンパイル意味論を現在の定義に追 Forth-83は、それぞれ非即時および即時の単語のコンパイルを強制するために、別々の単語COMPILE
を定義しました。
名前のない単語と実行トークン編集
Ans Forthでは、名前のない単語を:NONAME
;
(セミコロン)までコンパイルし、実行トークンをデータスタックに残す。 実行トークンは、cプログラミング言語の関数ポインタと同様に、コンパイルされたセマンティクスの不透明なハンドルを提供します。
実行トークンは変数に格納することができます。 単語EXECUTE
COMPILE,
(compile-comma)は、データスタックから実行トークンを受け取り、関連するセマンティクスを現在の定義に追加します。
単語'
(tick)は、単語の名前をパラメータとして受け取り、その単語に関連付けられた実行トークンをデータスタック上に返します。 解釈状態では、' RANDOM-WORD EXECUTE
RANDOM-WORD
と同等です。
Edit
単語:
(colon),POSTPONE
'
(tick)は、データスタックの代わりにユーザー入力デバイスから引数を取る単語を解析する例です。 別の例は、単語(
(paren)で、次の右括弧までの単語を読み取り、無視し、コロン定義にコメントを配置するために使用されます。 同様に、単語\
(
(paren)と\
(円記号)は、次のコメントテキストから空白で区切る必要があります。
codeEditの構造
ほとんどのForthシステムでは、コード定義の本体は機械語または何らかの形のスレッドコードのいずれかで構成されています。 非公式のFIG標準(Forth Interest Group)に従う元のForthは、TIL(スレッド化された解釈言語)です。 これは間接スレッドコードとも呼ばれますが、現代では直接スレッドコードとサブルーチンスレッドのForthsも人気があります。 SwiftForth、VFX Forth、iForthなどの最速の最新のForthは、Forthをネイティブマシンコードにコンパイルします。
Data objectsEdit
単語が変数または他のデータオブジェクトの場合、CFはそれを作成した定義語に関連付けられたランタイムコードを指します。 定義語には特徴的な”定義動作”(辞書エントリの作成とデータ空間の割り当てと初期化)があり、この定義語によって構築された単語のクラスのインスタン 例は次のとおりです:
VARIABLE
初期化されていないワンセルのメモリ位置を指定します。 AVARIABLE
CONSTANT
CONSTANT
の引数として指定します)。 インスタンスの動作は値を返します。 この場所にスペースを割り当てることも、文字列やその他の初期化された値を含むように設定することもできます。 インスタンスの動作は、このスペースの先頭のアドレスを返します。
Forthはまた、プログラマがカスタム定義動作とインスタンス動作の両方を指定して、新しいアプリケーション固有の定義単語を定義できる機能を提 いくつかの例には、循環バッファ、I/Oポート上の名前付きビット、および自動的にインデックス化された配列が含まれます。
これらの単語および類似の単語で定義されたデータオブジェクトは、スコープ内でグローバルです。 他の言語のローカル変数によって提供される関数は、Forthのデータスタックによって提供されます(ただし、Forthには実際のローカル変数もあります)。 Forthプログラミングスタイルは、他の言語と比較して非常に少数の名前付きデータ; 通常、このようなデータオブジェクトは、(マルチタスク実装で)多くの単語またはタスクによって使用されるデータを格納するために使用されます。
Forthはデータ型の使用の一貫性を強制するものではありません;値をフェッチして格納したり、データに対して他の操作を実行するために適切な演算子を使用するのはプログラマの責任です。