このページでは、有名な難解プログラミング言語であるBrainfuckをもとにして新たな難解プログラミング言語を作成する手順を紹介します。
まず最初にするべきことは、どのような言語をつくるのか、計画を立てておかなければなりません。
行き当たりばったりでも何とかなるとは思いますが、やはり計画があったほうがやりやすいでしょう。
このページで作成する言語は、以下のような言語とします。できる限りC#初心者でも実装できるよう、単純にしました。
命令は、+、-、>、<、.、,、?、!とする。Brainfuckには、[と]というループの命令がありましたが、実装が大変なので省きました。
メモリはchar型、セルは256個。ただし、メモリの両端はつながっていないものとする。
byte型の数値1つをポインターとして現在のメモリセルの位置を指し示す。
ここに書いていないものはすべてBrainfuckの仕様に従う。
命令の詳細は以下に示します。
計画が出来上がったので、さっそく作っていきましょう。
これはただ単に変数を作っているだけです。同じ動作のために毎回違うコードを入力するのは面倒なので、インタプリタのループに入れてしまうことにします。
char[] memory = new char[256];
byte ptr = 0;
無限ループを作り、その中で入力を受け付ける文を書いています。そのあと、命令を実行します。
while (true)
{
    char[] memory = new char[256];
    byte ptr = 0;
    Random rnd = new Random();    // ?命令で使います。
    Console.Write("> ");
    string cmd = Console.ReadLine();
    for(int i = 0;i <= cmd.Length; i++)
    {
        // TODO: ここに命令を追加します。
    }
    Console.WriteLine();
}
?命令で使う、Randomクラスは、ハローワールドには(おそらく)出てきません。
Randomクラスは、乱数を生成するためのクラスです。変数にしておかないと利用できません。
よくわからない方は調べて下さい。
ここが最も肝心です。ただ、単純にswitch文で分岐しているだけなので特に難しいところはありません。
switch (cmd[i])
{
    case '+':
        memory[ptr]++;
        break;
    case '-':
        memory[ptr]--;
        break;
    case '>':
        ptr++;
        break;
    case '<':
        ptr--;
        break;
    case '.':
        Console.Write(memory[ptr]);
        break;
    case ',':
        memory[ptr] = Console.ReadKey().KeyChar;
        break;
    case '?':
        memory[ptr] = (char)rnd.Next(0, 65536);    // 65536 = 65535 + 1
        break;
    case '!':
        Console.WriteLine(memory[ptr].ToString());
        break;
}
これらのコードを一つのソースコードにまとめて、うまくできるかためしてみましょう。
テストのコードをいくつか用意してあります。使ってみましょう。
うまくいかない場合はソースコードを見直してみましょう。それでもわからない場合は、全体図を写しましょう。
ポインタを使って文字を出力しています。
コード:
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ +++++ . >
++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ ++++++++++ +++++++-- . < .
出力:
AAA
入力を求められ、入力した文字をそのまま表示します。
コード:
,.
入力例:
R
出力例:
R
0～65535の間の乱数が出力されます。
コード:
?!
出力例:
157
すべてのソースコードをのせます。これをコンパイルすればインタプリタが動作します。
using System;
namespace not_brainfuck
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                char[] memory = new char[256];
                byte ptr = 0;
                Random rnd = new Random();
                Console.Write("> ");
                string cmd = Console.ReadLine();
                for(int i = 0;i < cmd.Length; i++)
                {
                    switch (cmd[i])
                    {
                        case '+':
                            memory[ptr]++;
                            break;
                        case '-':
                            memory[ptr]--;
                            break;
                        case '>':
                            ptr++;
                            break;
                        case '<':
                            ptr--;
                            break;
                        case '.':
                            Console.Write(memory[ptr]);
                            break;
                        case ',':
                            memory[ptr] = Console.ReadKey().KeyChar;
                            break;
                        case '?':
                            memory[ptr] = (char)rnd.Next(0, 65535);
                            break;
                        case '!':
                            Console.WriteLine(((int)memory[ptr]).ToString());
                            break;
                    }
                }
                Console.WriteLine();
            }
        }
    }
}
次は「難解プログラミング言語の作り方/HQ9+をもとにする」です。