| 開発者 | クリス・プレッシー |
|---|---|
| 初登場 | 1993 |
| Webサイト | catseye.tc/node/Befunge-93.html |
| 影響を受けた | |
| 第四に、FALSE | |
Befunge は、2 次元スタックベースのリフレクティブな難解なプログラミング言語です。[1]プログラムが 2 次元グリッド上に配置されるという点で、従来の言語とは異なります。「矢印」命令は、制御フローを左、右、上、または下に向け、制御フローを循環的に送信することでループが構築されます。これは、「 ForthとLemmingsの融合」と表現されています。[2]
Befunge は 1993 年に Chris Pressey によって Amiga 用に作成されました。この言語は、自己修正コードと多次元プレイフィールドを特徴とし、可能な限りコンパイルが困難になるように設計されました。それにもかかわらず、この言語用に複数のコンパイラが作成されました。元の Befunge-93 仕様では、プログラムが 80x25 グリッドに制限されていました。チューリング完全ではありませんでしたが、その後 Funge-98 などの拡張機能によって概念が拡張され、チューリング完全性が実現されました。
「Befunge」という名前は、オンライン ディスカッションでの入力ミスに由来しています。コンパイルが困難になるよう設計されていましたが、bef2c や Betty などのコンパイラは、さまざまな手法を使用してこの言語を実装しています。Befunge プログラムは、矢印を使用して制御フローを変更するのが特徴で、乱数シーケンスや古典的な「Hello, World!」メッセージなどの出力を生成できます。
歴史
この言語は、 1993年にChris Pressey [3]によってAmiga用に作成され、可能な限りコンパイルが困難な言語を考案する試みとして作成されました。 コマンドは自己修正コードpを許可していることに注意してください。 それにもかかわらず、その後多くのコンパイラが書かれました。 オリジナルの「Befunge-93」仕様に対する多くの拡張も存在し、最も有名なのはFunge-98で、これは概念を任意の数の次元に拡張し、マルチスレッド化が可能で、複数の命令ポインタが同じ空間で同時に動作します。 Befungeの拡張とその変種は、Fungeoidまたは単にFungesと呼ばれます。
Befunge-93 仕様では、各有効なプログラムを水平方向に 80 命令、垂直方向に 25 命令のグリッドに制限しています。これらの制限を超えるプログラム実行は、グリッドの反対側の対応するポイントに「ラップアラウンド」します。このように、Befunge プログラムは位相的にトーラスと同等です。Befunge-93 プログラムは 1 つのスタックしか持てず、そのストレージ配列は制限されているため、Befunge-93 言語はチューリング完全ではありません(ただし、スタック ワード サイズが無制限の Befunge-93 はチューリング完全であることが示されています)。[4]後の Funge-98 仕様では、プログラムのサイズ制限を削除することでチューリング完全性を実現しています。固定された制限でラップアラウンドするのではなく、Funge-98 命令ポインターの動きは、考案者の Chris Lahey にちなんで「Lahey 空間」と呼ばれるモデルに従います。このモデルでは、グリッドはラッピングに関しては有限サイズのトーラスのように動作しますが、無制限に拡張することも可能です。
語源
Befungeという単語は、オンラインディスカッションで「before」という単語が意図されていた入力ミスに由来しています。 [要出典]
コンパイル
前述のように、Befunge の設計目標は、コンパイルが困難な言語を作成することでした。これは、自己変更コード (「p」命令はプレイフィールドに新しい命令を書き込むことができます) と多次元プレイフィールド (同じ命令を 4 つの異なる方向に実行できます) の実装によって実現されました。
それでも、これらの障害はある程度克服されており、Befunge コンパイラは適切な技術を使用して作成されています。
標準の Befunge-93 ディストリビューションに含まれる bef2c コンパイラは、スレッド コードを使用します。各命令は C コードのスニペットにコンパイルされ、Befunge インタープリタと同様にスニペットを介して制御が流れます (つまり、何らかの「方向」レジスタの値に応じて制御が流れます)。これは、優れたインタープリタに対して大きな利点にはなりません。bef2c コンパイラは「p」モードまたは文字列モードのどちらも処理しないため正しくありませんが、処理することは不可能ではありません (ただし、C 言語はこれに適していない可能性があります)。
たとえば、etty コンパイラは、すべての可能な直線命令をサブプログラムとして扱い、'p' 命令がそのサブプログラムを変更すると、そのサブプログラムは再コンパイルされます。このジャストインタイム コンパイルのバリエーションにより、多くの命令が 'direction' レジスタで介入決定を行うことなくネイティブ コードで実行できるため、インタープリターよりもはるかに優れた利点が得られます。
サンプル Befunge-93 コード
矢印を使用して制御フローを変更する手法は、以下の乱数生成プログラムで実証されています。Befunge 命令ポインターは左上隅から始まり、リダイレクトされなければ右に移動します。矢印をたどって、命令?は命令ポインターをランダムな基本方向に送信し、ポインターが数字に当たると、それをスタックにプッシュします。次に、矢印は に移動し、.スタックから数字を出力して、ポインターを最初の方向のランダマイザーに戻します。このプログラムを終了する方法はない@ため、1 から 9 までの乱数のストリームが無限に生成されます。
v>>>>>v
12345 ^?^ > ? ?^ v?v 6789 >>>> v ^ 。<
次のコードは、典型的な「Hello World!」プログラムの例です。最初に、文字「olleH」がASCII番号としてスタックにプッシュされます。次に、これらはLIFO順序でスタックからポップされ、テキスト文字として出力されて「Hello」になります。スペースは ASCII の文字番号 32 で、ここでは 4 と 8 を掛けて作成され、テキストとして出力されます。残りのコードは、同様の方法で「World!」を出力し、その後に ASCII 文字 10 (改行文字、出力カーソルを新しい行に移動する) が続きます。
> v v ,,,,, 「こんにちは」< > 48 * , v v ,,,,,, 「ワールド!」< > 25 * 、@
次のコードは、少し複雑なバージョンです。ASCII 文字 10 (改行文字) をスタックに追加し、次に "!dlrow ,olleH" をスタックにプッシュします。ここでも、LIFO順序付けとは、"H" がスタックの先頭になり、最初に印刷され、"e" が 2 番目、というように続くことを意味します。文字を印刷するために、プログラムはループに入り、最初にスタックの先頭の値を複製します (したがって、スタックは " \n !dlrow ,olleHH" のようになります)。次に、"_" 操作によって複製された値がポップされ、ゼロの場合は右に進み、そうでない場合は左に進みます (空のスタックをポップするときに 0 を "返す" 準拠のインタープリタを想定しています)。左に進むと、先頭の値がポップされ、ASCII文字として印刷されます。次に、次の文字を複製して「_」テストにループバックし、スタックが空になるまで残りのスタックを出力し続けます。次のポップ値は 0 になり、その時点で「@」がプログラムを終了します。
> 25 * "!dlrow ,olleH" : v
v :, _@ > ^
Befunge-93 説明書一覧
ほとんどの 1 次元プログラミング言語では、コメント テキストとソース コードの間に構文上の区別が必要ですが、その区別は、セットに含まれない文字はすべてコメントであるというBrainfuckのルールと同じくらい些細なことかもしれません。LispやPythonなど+-[]<>,.の言語では、値が使用されていないコンテキストでは文字列をコメントとして扱います。同様に、Befunge にはコメント構文がありません。コードにドキュメントを埋め込むには、プログラマーは単に制御フローを「コメント」領域にルーティングするだけで、その領域のテキストは実行されません。
参照
参考文献
- ^ 「Befunge – Esolang」。
- ^ 「The Befunge FAQ v.4」 1997-11-04。2001-04-17時点のオリジナルよりアーカイブ。2014-01-23に閲覧。
- ^ Ais523 (2008-12-18). 「Chris Pressey」. Esolang . 2014年1月23日閲覧。
{{cite web}}: CS1 maint: 数値名: 著者リスト (リンク) - ^ エルジャン (2014-01-18)。 「トーク:ビフンゲ」。エソラン。2014 年 1 月 23 日に取得。
外部リンク
- Befunge-93 仕様
- Befunge-93 リファレンス実装
- Funge-98 仕様
