難解プログラミング言語の作り方/Deadfishをもとにする
このページでは、Deadfishをもとにして新たな言語を作ります。
Deadfishって何ですか
編集Deadfish(直訳:死んだ魚)は、難解プログラミング言語のひとつで、もともとHQ9+のサブセットとする予定だったそうです[1]。 命令は4つですが、HQ9+のような命令はありません。
命令 | 意味 |
---|---|
i |
インクリメント |
d |
デクリメント |
s |
数値を2乗 |
o |
数値を出力 |
たったこれだけ!HQ9+よりも一層作りやすいです。
また、XKCDバリエーションという命令の種類もあります。それはインクリメントがx
、2乗がk
になっています。
さっそく計画しましょう
編集仕様は以下のようにします。
- 数値の型はint型とする。
- 命令以外の文字はそのまま出力。
- これ以外はDeadfishの仕様に従う。
命令を決めましょう。
命令 | 意味 |
---|---|
i |
数値をインクリメントする。 |
d |
数値をデクリメントする。 |
x |
数値を倍にする。 |
z |
数値を0にする。 |
g |
数値の入力を求め、それを数値に代入する。System名前空間[2]のInt32.TryParse[3]、もしくはそれと同等なものを使用する。変換に失敗した場合、0を代入する。 |
o |
数値を出力する。 |
実装しましょう
編集変数の実装
編集数値カウンタを作ります。
int counter = 0;
インタプリタの実装
編集もちろんBrainfuckから流用します。
命令の実装
編集ここで一番大事なのはg命令でInt32.TryParseを使っているところです。仕様を決めるときにそうしたので、Convert.ToInt32[4]などを使うのはダメです。
また、TryParseの2つ目の引数が「out x」となっていますが、関数側が「この変数への変更を反映したいです~」と設定するときにoutをつける必要があるためです。
ふつう関数の中で引数がいじられても元の変数には影響しません。でも、outをつけておくと変更が反映されるのです。似たようなものにrefキーワードがあります。
switch (cmd[i])
{
case 'i':
counter++;
break;
case 'd':
counter--;
break;
case 'x':
counter *= 2; // counter = counter * 2; と同等
break;
case 'z':
counter = 0;
break;
case 'g':
string s = Console.ReadLine();
int x = 0;
if (Int32.TryParse(s, out x))
{
counter = x;
}
else
{
counter = 0;
}
break;
case 'o':
Console.WriteLine(counter);
break;
}
テスト
編集GO!テスト
編集何故GOかと言いますと、プログラムがgo
だからです[5]。数字を入力したら、そのままおうむ返しされます。
コード:go
入力例:
44
出力例:
44
全体図
編集using System;
namespace not_Deadfish
{
class Program
{
static void Main()
{
while (true)
{
int counter = 0;
Console.Write("> ");
string cmd = Console.ReadLine();
for (int i = 0; i < cmd.Length; i++)
{
switch (cmd[i])
{
case 'i':
counter++;
break;
case 'd':
counter--;
break;
case 'x':
counter *= 2; // counter = counter * 2; と同等
break;
case 'z':
counter = 0;
break;
case 'g':
string s = Console.ReadLine();
int x = 0;
if (Int32.TryParse(s, out x))
{
counter = x;
}
else
{
counter = 0;
}
break;
case 'o':
Console.WriteLine(counter);
break;
}
}
Console.WriteLine();
}
}
}
}
脚注
編集- ^ 参考文献4を参照。
- ^ 名前空間とは、複数のクラス、インターフェースなどをまとめ、衝突の可能性を減らすものです。それで、Systemというのはその名の通り.NETの重要な部分を担っています。
- ^ 文字列から数値を取得する関数です。
- ^ TryParseと同じように文字列を数値に変換するが、細かい部分がいくつか異なっています。例えば、変換に失敗したら例外を投げることなどです。
- ^ こういうプログラムはcatプログラムとか呼ばれたりします。よく使われるのでいろんな種類があります。
前は「難解プログラミング言語の作り方/HQ9+をもとにする」です。