
Это статья — продолжение прошлой статьи, в которой я писал API для маленькой виртуальной машины. Ну а сегодня я постараюсь прикрепить некий человеко подобный язык, работающий на моей виртуальной машине.
Для простоты использования я соединил прошлые файлы в один, что теперь имеет имя: ovm.py . Также используем такую интересную вещь как перечисления. Они есть в стандартом наборе, в модуле enum.
from ovm import VM
from enum import Enum, autoДалее напишу вновь самый обыкновенный класс и перечисления.
class TypeCommand(Enum):
PUSH = auto()
POP = auto()
PEEK = auto()
ADD = auto()
SUB = auto()
MIL = auto()
DIV = auto()
HALT = auto()
SET = auto()
GET = auto()class ByteCode:
def __init__(self, code):
self.__code = code
self.__vm = VM()
Переменная code, а если быть точнее, список принимает набор команд и затем обрабатывает их в методе execute, что приведён ниже.
def execute(self):
pos = 0
lenCode = len(self.__code)
while pos < lenCode:
current = self.__code[pos]
if current == TypeCommand.PUSH:
pos += 1
self.__vm.push(self.__code[pos])
elif current == TypeCommand.POP:
print(self.__vm.pop())
elif current == TypeCommand.PEEK:
print(self.__vm.peek())
elif current == TypeCommand.ADD:
self.__vm.add()
elif current == TypeCommand.SUB:
self.__vm.sub()
elif current == TypeCommand.MUL:
self.__vm.mul()
elif current == TypeCommand.DIV:
self.__vm.div()
elif current == TypeCommand.HALT:
self.__vm.halt(status=0)
elif current == TypeCommand.SET:
pos += 2
self.__vm.set(self.__code[pos - 1],self.__code[pos])
elif current == TypeCommand.GET:
pos += 1
print(self.__vm.get(self.__code[pos]))
pos += 1В приведённом выше коде мы идём по всему списку элементов и считываем их, то есть выполняем.
Теперь хотелось бы, чтоб мы могли набирать самый обыкновенный текст и он смог выполняться. Хм… Для этого чуда из говно кода я сделаю статический метод.
@staticmethod
def read(src):
lst = src.split()
commands = []
for index, el in enumerate(lst):
# print(f"{index} - {el}")
if el == "push":
index += 1
commands.append(TypeCommand.PUSH)
commands.append(int(lst[index]))
elif el == "pop": commands.append(TypeCommand.POP)
elif el == "peek": commands.append(TypeCommand.PEEK)
return commandsКак можете заметить, я не реализовал все возможности виртуальной машины, но этого вполне достаточно для демонстрации.
$ python -i bytecode.pyПример.
>>> bc = ByteCode(ByteCode.read("push 7 pop"))
>>> bc.execute()И вновь у меня очень маленькая статья. По моему, её даже статьишкой назвать нельзя, а скорее запиской. Ссылки никаких давать не буду ибо на это сложно смотреть без слёз. До новых бед!
