Chapter 7
今度はVMトランスレーター。假想マシン(ここではスタックマシン)をアセンブリに変換する。第7章ではpush
、pop
、算術・論理演算だけを実装する。まずはParserを作る。各コマンドをオペレーターとオペランドとに分ける。アセンブラのときと同じくPythonを使う。
class Parser: def __init__(self, file_path): self.file = open(file_path, "r") self.EOF_POS = self.__get_EOF_position(self.file) self.current_command = "" def has_more_lines(self): return self.file.tell() != self.EOF_POS def advance(self): self.current_command = self.__read_command_then_strip() def command_type(self): current_command = self.current_command if current_command == "": return "" else: operator = current_command.split()[0] if ( (operator == "add") or (operator == "sub") or (operator == "neg") or (operator == "eq") or (operator == "gt") or (operator == "lt") or (operator == "and") or (operator == "or") or (operator == "not") ): return "C_ARITHMETIC" elif operator == "push": return "C_PUSH" elif operator == "pop": return "C_POP" elif operator == "label": return "C_LABEL" elif operator == "goto": return "C_GOTO" elif operator == "if-goto": return "C_IF" elif operator == "function": return "C_FUNCTION" elif operator == "return": return "C_RETURN" elif operator == "call": return "C_CALL" def arg1(self): command_type = self.command_type() if command_type == "": return "" elif command_type == "C_ARITHMETIC": return self.current_command else: return self.current_command.split()[1] def arg2(self): command_type = self.command_type() if ( (command_type == "C_PUSH") or (command_type == "C_POP") or (command_type == "C_FUNCTION") or (command_type == "C_CALL") ): return int(self.current_command.split()[2]) else: return "" def close(self): self.file.close() def __get_EOF_position(self, file): file.seek(0, 2) # ファイル末尾に移動して、 pos = file.tell() # その位置を取得して、 self.file.seek(0) # 再度ファイル先頭に戻って、 return pos # 取得したファイル末尾位置を返す。 def __read_command_then_strip(self): command = self.file.readline() command = command.strip() command = command.split("//")[0] if command: return command else: return "" ######################################################################## if __name__ == "__main__": s = Parser("SimpleAdd.vm") #s = Parser("StackTest.vm") #s = Parser("BasicTest.vm") #s = Parser("PointerTest.vm") #s = Parser("StaticTest.vm") while (s.has_more_lines()): s.advance() print("--------------------------") print("コマンド :", s.current_command) print("コマンドタイプ:", s.command_type()) print("第1引数 :", s.arg1()) print("第2引数 :", s.arg2()) s.close()
テストファイル(SimpleAdd.vm):
// This file is part of www.nand2tetris.org // and the book "The Elements of Computing Systems" // by Nisan and Schocken, MIT Press. // File name: projects/07/StackArithmetic/SimpleAdd/SimpleAdd.vm // Pushes and adds two constants. push constant 7 push constant 8 add
実行結果: