-
Notifications
You must be signed in to change notification settings - Fork 0
/
calculator.py
52 lines (44 loc) · 2.03 KB
/
calculator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from src import log, VMCrypt
import re
# just a example use of the VM
class calc:
def __init__(self) -> None:
self.vm = VMCrypt(verbose=True)
self.vm.reset_memory()
def run(self) -> None:
log.info("Simple calculator using a custom VM")
log.info("Supported operations -> +, -, *, /")
while True:
user_input = log.input(">>>")
try:
first, operator, second = self.parse_input(user_input)
log.success(f"Result -> {self.calculate(first, operator, second)}")
except Exception as e:
log.failure(e)
def parse_input(self, expression: str) -> tuple:
match = re.match(r'(-?\d+)\s*([\+\-\*/])\s*(-?\d+)', expression)
if not match: raise ValueError("Invalid expression format")
first, operator, second = match.groups()
return int(first), operator, int(second)
def calculate(self, first: int, operator: str, second: int) -> int:
program = self.generate_program(first, operator, second)
self.vm.reset_memory()
self.vm.load_program(program)
self.vm.run()
return self.vm.regs[2]
def generate_program(self, first: int, operator: str, second: int) -> bytearray:
program = bytearray()
LOAD_IMM, ADD, SUB, MUL, DIV, HALT, LOAD_REG = 0x01, 0x10, 0x11, 0x12, 0x13, 0xFF, 0x02
program += bytes([LOAD_IMM, 0x00]) + first.to_bytes(4, 'little', signed=True)
program += bytes([LOAD_IMM, 0x01]) + second.to_bytes(4, 'little', signed=True)
program += bytes([LOAD_IMM, 0x02]) + (0).to_bytes(4, 'little', signed=True)
ops = {
'+': bytes([ADD, 0x02, 0x00]) + bytes([ADD, 0x02, 0x01]),
'-': bytes([LOAD_REG, 0x02, 0x00]) + bytes([SUB, 0x02, 0x01]),
'*': bytes([MUL, 0x02, 0x00, 0x01]),
'/': bytes([LOAD_REG, 0x02, 0x00]) + bytes([DIV, 0x02, 0x01])
}
program += ops.get(operator, bytearray())
program += bytes([HALT])
return program
calc().run()