JUNのブログ

JUNのブログ

活動記録や技術メモ

Brainfuck インタプリタを作った

Brainfuckインタプリタを作りました.

Brainfuckって何?

Brainfuckって言語です.

言語仕様とかはWikipedia参照

ja.wikipedia.org

+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+.

これで Hello World! と出力するプログラムです.

qiita.com

インタプリタのコード

実装は愚直にWikipediaに書いてあるBrainfuckの言語仕様をそのまま実装していくだけです.

言語は一番慣れているPythonで書きました.

ファイルパスをコマンドライン引数で受け取って, それを処理する方がインタプリタっぽいですが, 面倒だったのでコードに直接書き込む感じにしました.

"""Brainfuckインタプリタ
言語仕様はWikipediaから: https://ja.wikipedia.org/wiki/Brainfuck
"""

# Trueにすると途中経過を可視化する
vis = True
output_str = ""

# Brainfuck program
code = "+++++++++[>++++++++>+++++++++++>+++>+<<<<-]>.>++.+++++++..+++.>+++++.<<+++++++++++++++.>.+++.------.--------.>+.>+."

# 少なくとも30000個の要素を持つバイトの配列(各要素はゼロで初期化される)
memory_arr = [0 for _ in range(30000)]

# インストラクションポインタ(プログラム中のある文字を指す)
inst_ptr = 0

# データポイント(前述の配列のどれかの要素を指す。最も左の要素を指すよう初期化される)
data_ptr = 0

while True:
    c = code[inst_ptr]

    if vis:
        import time
        print(code)
        vis_inst_ptr = "".join(["*" if i == inst_ptr else " " for i in range(len(code))])
        print(vis_inst_ptr)
        print(" ".join(map(lambda x: str(x).ljust(3), memory_arr[:10])))
        vis_data_ptr = "    ".join(["*" if i == data_ptr else "" for i in range(10)])
        print(vis_data_ptr)
        print(
            f"inst_ptr: {inst_ptr}\t"
            f"char: {c}\t"
            f"data_ptr: {data_ptr}\t"
            f"arr[data_ptr]: {memory_arr[data_ptr]}\n")
        time.sleep(0.01)

    if c == ">":
        data_ptr += 1
    elif c == "<":
        data_ptr -= 1
    elif c == "+":
        memory_arr[data_ptr] = memory_arr[data_ptr] + 1
    elif c == "-":
        memory_arr[data_ptr] = memory_arr[data_ptr] - 1
    elif c == ".":
        if vis:
            output_str += chr(memory_arr[data_ptr])
        else:
            print(chr(memory_arr[data_ptr]), end="")
    elif c == ",":
        memory_arr[data_ptr] = int(input("waiting for input: "))
    elif c == "[":
        if memory_arr[data_ptr] == 0:
            while code[inst_ptr] != "]":
                inst_ptr += 1
    elif c == "]":
        if memory_arr[data_ptr] != 0:
            while code[inst_ptr] != "[":
                inst_ptr -= 1

    inst_ptr += 1

    if inst_ptr == len(code):
        print("[interpreter output]: exit program!!")
        if vis:
            print(f"[program output]: {output_str}")
        break

可視化するとこんな感じ f:id:JUN_NETWORKS:20200301021956p:plain

感想

完走した感想(激うまギャク)ですが, めっちゃ簡単でお手頃なのに, 結構しっかりと達成感があって作ってて楽しかったです.

昔, 後輩が「Brainfuckインタプリタ作るのって簡単ですよ」的なことを言っていたのですが, 本当に簡単でした.

次はCコンパイラか自作OSか自作CPU作りたいなぁ...