4番目のCPU。 これは何ですか (パート2)

前回の記事では、最も単純なForth CPU J1を取り上げました。 今こそ、この砦がどのような言語であるか、そしてこのプロセッサ用にどのようにコンパイルするかを伝える時です。



言語の文法


Fortはパーサーにとって理想的な言語です。 プログラムは単語で構成され、単語はスペースで区切られます。 単語は機能の類似物であり、たとえば次のとおりです。



 open read close
      
      





これは、3つの機能-オープン、読み取り、クローズのシーケンシャルパフォーマンスを意味します。 フォート内のコメントは通常次のようになります。



 \   (   )
      
      





すべてが非常に簡単です。 動揺させることができる唯一のものは、逆ポーランド記法(RPN)です。 たとえば、3つの数字を追加すると、次のように記述されます。



 1 2 3 + +  1 2 + 3 +
      
      





Fortプログラムは次のようなものです。

-既存のものに基づいてあなたの言葉の定義

-これらの単語を呼び出すことによっていくつかのアクションを実行する



標準語


最低限の単語を定義して、それに基づいて構造を構築することができます。 各単語について、Fortで一般的なコメントを使用して、単語を呼び出す前と呼び出した後のスタックの状態を記述しようとします。



noop ( -- ):

+ ( ab -- a+b ):

xor ( ab -- a^b ):

and ( ab -- a&b ):

or ( ab -- a|b ):

invert ( a -- ~a ):

= ( ab -- a==b?1:0 ):

< ( ab -- a<b?1:0 ):

swap ( ab -- ba ):

dup ( a -- aa ):

drop ( ab -- a ):

over ( ab -- aba):

nip ( ab -- b ):

>r ( a -- ):

r> ( -- a ):

@ ( a -- [a] ):

! ( ab -- ): ([b]:=a)

1- ( a -- a-1):







これらの単語はすべて、1つのALU命令J1で実装できます(「!」を除く、トリックがあります-スタックから2つの要素を削除する必要がありますが、J1はこれを行う方法を知りません)。



命令で実装できる単語がいくつかありますが、複雑にすることはしませんが、独自の単語の作成に移りましょう。



新しい単語を作成する


単語を説明するには、次の構文を使用します。



 : my-word ( before -- after ) ........ ;
      
      





ここで、コロンは新しい単語の宣言を意味し、my-wordは実際の単語、最後のセミコロンは関数からの戻りです(結局、単語の呼び出しは本質的にCALL命令なので、RETURNでなければなりません)。



たとえば、そのような単語があります-腐敗(abc-bca)。 スタック内の最後の3つの数字を円でシフトします(つまり、スタックの先頭から3番目の数字を先頭に配置します)。 標準の単語は2つの数字のみで動作するため、3番目の数字は一時的にどこかに保存する必要があります。 これを行うには、呼び出しスタックrが必要です。 例:

 : rot ( abc -- bca ) >r ( ab ) swap ( ba ) r> ( bac ) swap ( bca ) ; (  ) 1 2 3 rot (  2 3 1   )
      
      





別の興味深い命令を次に示します(3番目に応じて2つの数値のいずれかを返します)。



 : merge ( abm -- m?b:a ) >r ( ab ) over xor ( aa^b ) r> and ( aa^b&m ) xor ;
      
      





この言葉はすでにもっと複雑に見えます。 しかし一方で、Fortは、コード全体とは別に簡単にチェックできる短い単語を書くことを強制します。 そして、コードもシンプルで簡単になります。 この常識は、1970年代にチャールズムーアで発生しました。



制御構造およびその他の言語要素


この言語には、変数、定数、ループ、分岐があります。 変数と定数の説明は次のようになります。



 ( :  constant  ) 0 constant false 1 constant true 42 constant answer ( : variable  ) variable x variable y (  -    .   x=2;y=x+1   ) 2 x ! ( x = 2 ) x @ ( stackTop = x ) 1 + ( stackTop = stackTop + 1 ) y ! ( y = stackTop )
      
      





do..while形式のループは、次のように記述されます。begin... condition until:



 5 begin 1 - dup 0 = until
      
      





サイクルの前に、スタックに番号5を置き、サイクルでは1ずつ減らします。 結果をゼロと比較し、ゼロでない場合はサイクルを繰り返します。



条件演算子は、スタックの最上位の値に応じて、そのブランチの1つを実行します。 スタックの先頭から番号が削除されます。



 (   : condition IF ... THEN condition IF ... ELSE ... THEN )
      
      





基本的な言語構成は次のとおりです。 カウンターと前提条件、および他の多くのサイクルもありますが、これはすでに1つの投稿の形式を超えています。



おわりに


言語は非常にシンプルで面白いです。 慣れれば、コードを読むことさえできます。 J1の簡単なコンパイラはこちらから入手できます 。 今のところほとんどコンパイルできませんが、誰かが興味を持つかもしれません。 また、エミュレーターと同様にGoで記述されています。



実際には、ほとんどのスペースバイトコード(場合によってはCよりも少ない)しか占有しないため、主に組み込みでForthを使用しています。 Forthの重大なプロジェクトのうち、OpenFirmwareとOLPCラップトップのBIOS(実際にはopenfirmware)に名前を付けることができます。 ところで、OLPCにはWebサイトと要塞の優れた教科書があります。



All Articles