Esolang Advent Calendar 2012 6日目 難解言語Doubleplusungoodの紹介
こんにちは、ArGxento(あるじぇんと)といいます。はじめましての方ははじめまして。
さて、Esolang Advent Calendar 2012の六日目を担当させていただくわけですが、 今回は当企画のために作った奇妙な言語、Doubleplusungood(ダブルプラスアングッド)について書きたいと思います。 その前にまずはお約束のHello, World!を。
+C++; + + ++C++++ + C; + ++C++++ + C; + ++ + C++; + ++ + C++; + + ++ C++; ++C++;+ ++C++; + + + ++ C++ + C; + + ++C++++ + C; + ++ +C++; + + ++ C++; ++ + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++ C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; ++ ++ ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++ ++ C++ + C; + ++ C++++ + C;+ ++ +C++; + + ++ C++; + ++ C++++ + C; + + ++ C++; ++ ++ ++ C++ + C; ++ + ++ C++ ++ + C; + ++ + C++; + + ++ C++; ++ ++ ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; ++C++++ + C; + ++C++ + C;+ ++ +C++; ++ +C++; ++C++; + ++C++; + + +C++; + + ++ ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; + + ++C++ + C; ++ +C++; + +C++; + ++C++; + + +C++; ++ C++ +C; + ++ C++++ + C; + ++ + C++; + + ++ C++;
(完全なコードと実行結果はこちら)
コンセプトはずばり、C++に、"C++;"でかく、C++をもちいた言語です。
前からジョークのネタとして、C++の演算子オーバーロードで"C++"の文字列だけでできた言語を考えていましたが、今回は それだけでは面白みがないという事で、どこまで命令数を減らせるかを試してみました。 一応書きやすいように標準的な書き方を定めましたが、演算子の優先順位や結合規則を熟知していれば更にトリッキーな 書き方も可能です。
以下に言語の仕様などを記します。
特徴
- C++のDSEL(領域特化組み込み言語)
- 一応スタック指向
仕様
- メモリは数値またはコードブロックがもてるスタック一つ
- 前置インクリメント、後置インクリメント、プラス符号、加算をオーバーロードして実装しているため、C++の演算子の優先順位や結合規則に従う
- 14の命令
- リテラルは整数のみ
数値リテラル
仮数部には前置インクリメントを1、後置インクリメントを0とした二進数を用いる。結合規則に従うため、桁の並びが真逆になる。 倍率部には後置インクリメントを0個以上書き、仮数がその数の4倍左シフトされる。
例 : + ++ + ++C++ + C;
: 10、++C++ ++ + C;
: 16
命令
コード | 説明 |
---|---|
+C++; |
begin : コードブロックの開始。対応するendに達するまでコードが実行されない |
++C++; |
end : コードブロック終了。対応するbeginとの間にあるコードをスタックに積む |
++ ++ ++C++; |
pop : スタックの一番上を取り除く |
+ +C++; |
dup : スタックの一番上を取り除き、同じ物を2つ積む |
++ +C++; |
lrot : スタックの一番下を取り除き、それを一番上に積む |
+ ++C++; |
rrot : スタックの一番上を取り除き、それを一番下に挿入する |
++ ++C++; |
swap : スタックの一番上と上から二番目を交換する |
+ + +C++; |
call : スタックの一番上のコードブロックを取り除き、実行する。コードブロックでない場合はエラー |
++ + +C++; |
if-else : スタックの一番上から3つを取り除き、一番上に積まれていた数値が、0以外ならば上から2番めに積まれていたコードブロックを、0ならば上から3番目だったコードブロックを実行する。 |
+ ++ +C++; |
add : スタックの一番上と上から二番目を取り除き、それらを加算した値を積む。どちらかが数値でなければエラー |
++ ++ +C++; |
neg : スタックの一番上を取り除き、その数値の符号を反転したものを積む。スタックの一番上が数値でなければエラー |
+ + ++C++; |
print : スタックの一番上を取り除き、その数値を出力する。文字コードは環境依存で、スタックの一番上が-128~127の範囲の数値でなければエラー |
++ + ++C++; |
input : ユーザの入力を受け付け、入力された文字の文字コードをスタックに積む |
+ ++ ++C++; |
less-than : スタックの一番上と二番めを取り除き、二番めに積まれていた数値が一番上に積まれていた数値より小さければ1を、そうでなければ0を積む |
デバッグとかすごく適当ですが…
ideone.comで実行できるようにするために、C++03縛りをせざるを得なかったのが結構きつかったです。
あまり時間がなく、ループのサンプルとして1から9までの数字を出力するコードくらいしか用意できませんでした。 こちらです。 しかし、頑張ればFizzBuzzくらいは何とかなりそうです。興味があれば挑戦してみてください。
7日目担当のD_Rascalさん、よろしくおねがいします。