Advertisement
Guest User

Untitled

a guest
Mar 31st, 2020
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.96 KB | None | 0 0
  1. """
  2. Simplified VM code which works for some cases.
  3. You need extend/rewrite code to pass all cases.
  4. """
  5.  
  6. import builtins
  7. import dis
  8. import types
  9. import typing as tp
  10. import operator
  11. import sys
  12. import collections
  13.  
  14.  
  15. class Frame:
  16. def __init__(self, f_code: types.CodeType,
  17. f_locals: tp.Dict[str, tp.Any],
  18. f_globals: tp.Dict[str, tp.Any],
  19. f_prev: tp.Any):
  20. self.f_code = f_code
  21. self.f_globals = f_globals
  22. self.f_locals = f_locals
  23. self.f_prev = f_prev
  24. self.stack: tp.Any = []
  25. self.block_stack: tp.Any = []
  26.  
  27. if f_prev:
  28. self.builtins = f_prev.builtins
  29. else:
  30. self.builtins = builtins.__dict__
  31.  
  32. self.cur_idx = 0
  33. self.co_names = f_code.co_names
  34. self.co_consts = f_code.co_consts
  35. self.co_varnames = f_code.co_varnames
  36. self.instructions = list(dis.get_instructions(f_code))
  37.  
  38.  
  39. def equal_type(l: tp.Any, r: tp.Any) -> bool:
  40. return isinstance(l, type(r))
  41.  
  42.  
  43. class Block(object):
  44. def __init__(self, type: tp.Any, handler: tp.Any, frame: tp.Any) -> None:
  45. self.type = type
  46. self.handler = handler
  47. self.frame = frame
  48.  
  49.  
  50. def build_code_object() -> types.CodeType:
  51. code_str = ''
  52. return compile(code_str, '', 'exec')
  53.  
  54.  
  55. frame_object = Frame(build_code_object(), {}, {}, {})
  56.  
  57.  
  58. class VirtualMachine:
  59. def __init__(self) -> None:
  60. self.frames: tp.Any = []
  61. self.frame = frame_object # Remove it later (change for None)
  62. self.last_exception: tp.Any = ()
  63. self.value = None
  64.  
  65. self.operations = {
  66. 'POWER': operator.pow,
  67. 'MULTIPLY': operator.mul,
  68. 'MATRIX_MULTIPLY': operator.matmul,
  69. 'FLOOR_DIVIDE': operator.floordiv,
  70. 'TRUE_DIVIDE': operator.truediv,
  71. 'MODULO': operator.mod,
  72. 'ADD': operator.add,
  73. 'SUBTRACT': operator.sub,
  74. 'SUBSCR': operator.getitem,
  75. 'LSHIFT': operator.lshift,
  76. 'RSHIFT': operator.rshift,
  77. 'AND': operator.and_,
  78. 'XOR': operator.xor,
  79. 'OR': operator.or_,
  80. }
  81.  
  82. self.compare_funcs = {
  83. '<': operator.lt,
  84. '<=': operator.le,
  85. '==': operator.eq,
  86. '!=': operator.ne,
  87. '>=': operator.ge,
  88. '>': operator.gt,
  89. 'in': lambda x, y: x in y,
  90. 'not in': lambda x, y: x not in y,
  91. 'is': lambda x, y: x is y,
  92. 'is not': lambda x, y: x is not y,
  93. 'exception match': equal_type,
  94. }
  95.  
  96. def run(self, code: types.CodeType) -> None:
  97. """
  98. :param code: code for interpreting
  99. """
  100. frame = Frame(code, {}, {}, None)
  101. self.run_frame(frame)
  102.  
  103. def pop_frame(self) -> tp.Any:
  104. self.frames.pop()
  105. self.frame = self.frames[-1] if self.frames else None
  106.  
  107. def push_frame(self, frame: tp.Any) -> None:
  108. self.frames.append(frame)
  109. self.frame = frame
  110.  
  111. def push(self, *args: tp.Any) -> tp.Any:
  112. for arg in args:
  113. self.frame.stack.append(arg)
  114.  
  115. def pop(self) -> tp.Any:
  116. return self.frame.stack.pop()
  117.  
  118. def popn(self, n: int) -> tp.Any:
  119. return list(reversed([self.pop() for _ in range(n)])) if n else []
  120.  
  121. def top(self) -> tp.Any:
  122. return self.frame.stack[-1]
  123.  
  124. def pop_block(self) -> tp.Any:
  125. return self.frame.block_stack.pop()
  126.  
  127. def push_block(self, type: tp.Any, delta: tp.Any = None) -> tp.Any:
  128. self.frame.block_stack.append(Block(type, delta, self.frame))
  129.  
  130. def parse_byte_and_args(self) -> tp.Tuple[str, tp.Optional[int]]:
  131. instruction = self.frame.instructions[self.frame.cur_idx]
  132. byte_name = instruction.opname
  133. arg = instruction.arg
  134. self.frame.cur_idx += 1
  135. return byte_name, arg
  136.  
  137. def run_func(self, byte_name: str, argument: tp.Optional[int]) -> str:
  138. try:
  139. result = ''
  140. if byte_name.split("_")[0] == "BINARY":
  141. self.run_binary_operation(byte_name)
  142. elif byte_name.split("_")[0] == "INPLACE":
  143. self.run_inplace_operation(byte_name)
  144. else:
  145. bytecode_func = getattr(self, byte_name)
  146. if argument:
  147. return bytecode_func(argument)
  148. else:
  149. return bytecode_func()
  150. except Exception:
  151. result = 'exception'
  152. self.last_exception = sys.exc_info()[:2] + (None,)
  153. return result
  154.  
  155. def handle_exception(self) -> bool:
  156. if self.frame.block_stack:
  157. cur_block = self.pop_block()
  158. if cur_block.type == "except":
  159. self.push_block('except-handler')
  160. exc_type, value, tb = self.last_exception
  161. self.push(tb, value, exc_type)
  162. self.push(tb, value, exc_type)
  163. self.frame.cur_idx = cur_block.delta
  164. return True
  165. return False
  166.  
  167. def run_frame(self, frame: tp.Any) -> tp.Any:
  168. self.push_frame(frame)
  169. func_result: tp.Any = None
  170. while len(self.frame.instructions) > frame.cur_idx:
  171. byte_name, arg = self.parse_byte_and_args()
  172. func_result = self.run_func(byte_name, arg)
  173. if func_result == "exception":
  174. handled = self.handle_exception()
  175. if not handled:
  176. exception, value, traceback = self.last_exception
  177. exc = exception(value)
  178. exc.__traceback__ = traceback
  179. raise exc
  180. if func_result == "yield":
  181. func_result = False
  182. break
  183.  
  184. self.pop_frame()
  185. return func_result
  186.  
  187. def find_associated(self, name: str) -> str:
  188. if name in self.frame.f_locals:
  189. val = self.frame.f_locals[name]
  190. elif name in self.frame.co_varnames:
  191. raise UnboundLocalError("local variable '%s' referenced before assignment" % name)
  192. elif name in self.frame.f_globals:
  193. val = self.frame.f_globals[name]
  194. elif name in self.frame.builtins:
  195. val = self.frame.builtins[name]
  196. else:
  197. raise NameError("variable '%s' is not defined" % name)
  198. return val
  199.  
  200. def run_binary_operation(self, operation: str) -> None:
  201. arg1, arg2 = self.popn(2)
  202. operation_name = operation.replace("BINARY_", "")
  203. self.push(self.operations[operation_name](arg1, arg2))
  204.  
  205. def run_inplace_operation(self, operation: str) -> None:
  206. arg1, arg2 = self.popn(2)
  207. operation_name = operation.replace("INPLACE_", "")
  208. self.push(self.operations[operation_name](arg1, arg2))
  209.  
  210. def call_func_op(self, arg: int) -> None:
  211. args = self.popn(arg)
  212. f = self.pop()
  213. self.push(f(*args))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement