0

この Python インタープリターは、Self-modifying Brainf*** (SMBF) と呼ばれる言語用に作成しました。今日、プログラムが最初のセルまたはテープの後にコードを動的に作成すると、実行されないというバグを発見しました。このインタープリターは、リンク先のページの Ruby インタープリターにできるだけ近くなるように作成しました。このバグは、元の Ruby インタープリターにも存在する可能性があることに注意してください。私は知りません、私はそれを使用していません。

SMBF が通常の BF と異なる点は、ソース コードがテープ上のポインターの開始セルの左側に配置されていることです。したがって、プログラム<.はソースの最後の文字 (ピリオド) を出力します。これは機能します。

一部のコードを削除したため、まだ実行可能ですが、この投稿ではスペースが少なくて済みます。

通訳:

from __future__ import print_function
import os, sys

class Tape(bytearray):
    def __init__(self):
        self.data = bytearray(b'\0' * 1000)
        self.center = len(self.data) // 2

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        try:
            return self.data[index + self.center]
        except:
            return 0

    def __setitem__(self, index, val):

        i = index + self.center

        if i < 0 or i >= len(self.data):
            # resize the data array to be large enough

            new_size = len(self.data)

            while True:
                new_size *= 2
                test_index = index + (new_size // 2)
                if test_index >= 0 and test_index < new_size:
                    # array is big enough now
                    break

            # generate the new array
            new_data = bytearray(b'\0' * new_size)
            new_center = new_size // 2

            # copy old data into new array
            for j in range(0, len(self.data)):
                new_data[j - self.center + new_center] = self.data[j]

            self.data = new_data
            self.center = new_center

        self.data[index + self.center] = val & 0xff

class Interpreter():
    def __init__(self, data):
        self.tape = Tape()

        # copy the data into the tape
        for i in range(0, len(data)):
            self.tape[i - len(data)] = data[i]

        # program start point

        self.entrypoint = -len(data)

    def call(self):
        pc = self.entrypoint
        ptr = 0

        # same as -len(self.tape) // 2 <= pc + self.tape.center < len(self.tape) // 2
        while -len(self.tape) <= pc < 0: # used to be "while pc < 0:"
            c = chr(self.tape[pc])
            if   c == '>':
                ptr += 1
            elif c == '<':
                ptr -= 1
            elif c == '+':
                self.tape[ptr] += 1
            elif c == '-':
                self.tape[ptr] -= 1
            elif c == '.':
                print(chr(self.tape[ptr]), end="")
            elif c == ',':
                sys.stdin.read(1)
            elif c == '[':
                if self.tape[ptr] == 0:
                    # advance to end of loop
                    loop_level = 1
                    while loop_level > 0:
                        pc += 1
                        if   chr(self.tape[pc]) == '[': loop_level += 1
                        elif chr(self.tape[pc]) == ']': loop_level -= 1
            elif c == ']':
                # rewind to the start of the loop
                loop_level = 1
                while loop_level > 0:
                    pc -= 1
                    if   chr(self.tape[pc]) == '[': loop_level -= 1
                    elif chr(self.tape[pc]) == ']': loop_level += 1
                pc -= 1
            pc += 1

            # DEBUG
            #print(pc, self.tape.data.find(b'.'))

def main():
    # Working "Hello, World!" program.
    #data = bytearray(b'<[.<]>>>>>>>>+\x00!dlroW ,olleH')

    # Should print a period, but doesn't.
    data = bytearray(b'>++++++++++++++++++++++++++++++++++++++++++++++')

    intr = Interpreter(data)
    intr.call()
    #print(intr.tape.data.decode('ascii').strip('\0'))

if __name__ == "__main__":
    main()

問題:

この行は、私がプログラムを設定する方法です (これを Ideone.com で実行できるようにします)。

data = bytearray(b'++++++++++++++++++++++++++++++++++++++++++++++')

.プログラムは、現在のセル (ピリオド) を出力する必要がある ASCII の 10 進数値である 46 になるまでセルに追加します。しかし、何らかの理由で、プログラム カウンターpcがそのセルに到達しません。見つけたすべてのコードをテープの最後までプログラムに実行させたいのですが、テープの中心を考慮してプログラム カウンターを取得するのに苦労しています。でサイズ変更され__setitem__ます。

関連する行は(私が試していたものです):

while -len(self.tape) <= pc < 0:

もともとはこれでした:

while pc < 0:

だから私はwhileラインを調整する必要があるとwhile True:思う.try/exceptchr(self.tape[pc])

誰が何が間違っているのか、それを修正する方法を見ていますか?

4

1 に答える 1