Advertisement
Guest User

Untitled

a guest
Mar 31st, 2020
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.61 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.  
  13.  
  14. class Frame:
  15. def __init__(self, f_code: types.CodeType,
  16. f_locals: tp.Dict[str, tp.Any],
  17. f_globals: tp.Dict[str, tp.Any],
  18. f_prev: tp.Any):
  19. self.f_code = f_code
  20. self.f_globals = f_globals
  21. self.f_locals = f_locals
  22. self.f_prev = f_prev
  23. self.stack: tp.Any = []
  24. self.block_stack: tp.Any = []
  25.  
  26. if f_prev:
  27. self.f_builtins = f_prev.f_builtins
  28. else:
  29. self.f_builtins = builtins.__dict__
  30.  
  31. self.cur_idx = 0
  32. self.co_names = f_code.co_names
  33. self.co_consts = f_code.co_consts
  34. self.co_varnames = f_code.co_varnames
  35. self.instructions = list(dis.get_instructions(f_code))
  36.  
  37.  
  38. def equal_type(l: tp.Any, r: tp.Any) -> bool:
  39. return isinstance(l, type(r))
  40.  
  41.  
  42. class Block(object):
  43. def __init__(self, type: tp.Any, handler: tp.Any, frame: tp.Any) -> None:
  44. self.type = type
  45. self.handler = handler
  46. self.frame = frame
  47.  
  48.  
  49. def build_code_object() -> types.CodeType:
  50. code_str = ''
  51. return compile(code_str, '', 'exec')
  52.  
  53.  
  54. frame_object = Frame(build_code_object(), {}, {}, {})
  55.  
  56.  
  57. class VirtualMachine:
  58. def __init__(self) -> None:
  59. self.frames: tp.Any = []
  60. self.frame = frame_object # Remove it later (change for None)
  61. self.last_exception: tp.Any = ()
  62. self.value = None
  63.  
  64. self.operations = {
  65. 'POWER': operator.pow,
  66. 'MULTIPLY': operator.mul,
  67. 'MATRIX_MULTIPLY': operator.matmul,
  68. 'FLOOR_DIVIDE': operator.floordiv,
  69. 'TRUE_DIVIDE': operator.truediv,
  70. 'MODULO': operator.mod,
  71. 'ADD': operator.add,
  72. 'SUBTRACT': operator.sub,
  73. 'SUBSCR': operator.getitem,
  74. 'LSHIFT': operator.lshift,
  75. 'RSHIFT': operator.rshift,
  76. 'AND': operator.and_,
  77. 'XOR': operator.xor,
  78. 'OR': operator.or_,
  79. }
  80.  
  81. self.compare_funcs = {
  82. '<': operator.lt,
  83. '<=': operator.le,
  84. '==': operator.eq,
  85. '!=': operator.ne,
  86. '>=': operator.ge,
  87. '>': operator.gt,
  88. 'in': lambda x, y: x in y,
  89. 'not in': lambda x, y: x not in y,
  90. 'is': lambda x, y: x is y,
  91. 'is not': lambda x, y: x is not y,
  92. 'exception match': equal_type,
  93. }
  94.  
  95. def run(self, code: types.CodeType) -> None:
  96. """
  97. :param code: code for interpreting
  98. """
  99. frame = Frame(code, {}, {}, None)
  100. self.run_frame(frame)
  101.  
  102. def pop_frame(self) -> tp.Any:
  103. self.frames.pop()
  104. self.frame = self.frames[-1] if self.frames else None
  105.  
  106. def push_frame(self, frame: tp.Any) -> None:
  107. self.frames.append(frame)
  108. self.frame = frame
  109.  
  110. def push(self, *args: tp.Any) -> tp.Any:
  111. for arg in args:
  112. self.frame.stack.append(arg)
  113.  
  114. def pop(self) -> tp.Any:
  115. return self.frame.stack.pop()
  116.  
  117. def popn(self, n: int) -> tp.Any:
  118. return list(reversed([self.pop() for _ in range(n)])) if n else []
  119.  
  120. def top(self) -> tp.Any:
  121. return self.frame.stack[-1]
  122.  
  123. def pop_block(self) -> tp.Any:
  124. return self.frame.block_stack.pop()
  125.  
  126. def push_block(self, type: tp.Any, delta: tp.Any = None) -> tp.Any:
  127. self.frame.block_stack.append(Block(type, delta, self.frame))
  128.  
  129. def parse_byte_and_args(self) -> tp.Tuple[str, tp.Optional[int]]:
  130. instruction = self.frame.instructions[self.frame.cur_idx]
  131. byte_name = instruction.opname
  132. arg = instruction.arg
  133. self.frame.cur_idx += 1
  134. return byte_name, arg
  135.  
  136. def run_func(self, byte_name: str, argument: tp.Optional[int]) -> tp.Any:
  137. try:
  138. result = None
  139. if byte_name.split("_")[0] == "BINARY":
  140. self.run_binary_operation(byte_name)
  141. elif byte_name.split("_")[0] == "INPLACE":
  142. self.run_inplace_operation(byte_name)
  143. else:
  144. bytecode_fn = getattr(self, byte_name.lower() + '_op')
  145. if argument is None:
  146. result = bytecode_fn()
  147. else:
  148. result = bytecode_fn(argument)
  149. except Exception:
  150. result = 'exception'
  151. self.last_exception = sys.exc_info()[:2] + (None,)
  152. return result
  153.  
  154. def handle_exception(self) -> bool:
  155. if self.frame.block_stack:
  156. cur_block = self.pop_block()
  157. if cur_block.type == "except":
  158. self.push_block('except-handler')
  159. exc_type, value, tb = self.last_exception
  160. self.push(tb, value, exc_type)
  161. self.push(tb, value, exc_type)
  162. self.frame.cur_idx = cur_block.delta
  163. return True
  164. return False
  165.  
  166. def run_frame(self, frame: tp.Any) -> tp.Any:
  167. self.push_frame(frame)
  168. func_result: tp.Any = None
  169. while len(self.frame.instructions) > frame.cur_idx:
  170. byte_name, arg = self.parse_byte_and_args()
  171. func_result = self.run_func(byte_name, arg)
  172. if func_result == "exception":
  173. handled = self.handle_exception()
  174. if not handled:
  175. exception, value, traceback = self.last_exception
  176. exc = exception(value)
  177. exc.__traceback__ = traceback
  178. raise exc
  179. if func_result == "yield":
  180. func_result = False
  181. break
  182.  
  183. self.pop_frame()
  184. return func_result
  185.  
  186. def run_binary_operation(self, operation: str) -> None:
  187. arg1, arg2 = self.popn(2)
  188. operation_name = operation.replace("BINARY_", "")
  189. self.push(self.operations[operation_name](arg1, arg2))
  190.  
  191. def run_inplace_operation(self, operation: str) -> None:
  192. arg1, arg2 = self.popn(2)
  193. operation_name = operation.replace("INPLACE_", "")
  194. self.push(self.operations[operation_name](arg1, arg2))
  195.  
  196. def call_function_op(self, arg: int) -> None:
  197. args = self.popn(arg)
  198. f = self.pop()
  199. self.push(f(*args))
  200.  
  201. def load_name_op(self, arg: tp.Any) -> None:
  202. name = self.frame.co_names[arg]
  203. if name in self.frame.f_locals:
  204. val = self.frame.f_locals[name]
  205. elif name in self.frame.f_globals:
  206. val = self.frame.f_globals[name]
  207. elif name in self.frame.f_builtins:
  208. val = self.frame.f_builtins[name]
  209. else:
  210. raise NameError("name '%s' is not defined" % name)
  211. self.push(val)
  212.  
  213. def load_global_op(self, arg: tp.Any) -> None:
  214. name = self.frame.co_names[arg]
  215. if name in self.frame.f_globals:
  216. val = self.frame.f_globals[name]
  217. elif name in self.frame.f_builtins:
  218. val = self.frame.f_builtins[name]
  219. else:
  220. raise NameError("global name '%s' is not defined" % name)
  221.  
  222. self.push(val)
  223.  
  224. def load_const_op(self, arg: tp.Any) -> None:
  225. self.push(self.frame.co_consts[arg])
  226.  
  227. def return_value_op(self) -> tp.Any:
  228. return self.pop()
  229.  
  230. def pop_top_op(self) -> None:
  231. self.pop()
  232.  
  233. def make_function_op(self, arg: int) -> None:
  234. def fill_args() -> None:
  235. if arg & 0x08:
  236. parsed_args['closure'] = self.pop()
  237. if arg & 0x04:
  238. parsed_args['annotations'] = self.pop()
  239. if arg & 0x02:
  240. parsed_args['kwdefaults'] = self.pop()
  241. if arg & 0x01:
  242. parsed_args['defaults'] = self.pop()
  243.  
  244. func_code, func_name = self.popn(2)
  245. parsed_args: tp.Dict[str, tp.Any] = {}
  246. fill_args()
  247.  
  248. func = Function(func_name, func_code, self.frame.f_globals, self, parsed_args)
  249.  
  250. self.push(func)
  251.  
  252. def store_name_op(self, arg: tp.Any) -> None:
  253. self.frame.f_locals[self.frame.co_names[arg]] = self.pop()
  254.  
  255. def store_global_op(self, arg: tp.Any) -> None:
  256. self.frame.f_globals[self.frame.co_names[arg]] = self.pop()
  257.  
  258. def compare_op_op(self, name: tp.Any) -> None:
  259. arg1, arg2 = self.popn(2)
  260. self.push(self.compare_funcs[dis.cmp_op[name]](arg1, arg2))
  261.  
  262. def pop_jump_if_true_op(self, jump: int) -> None:
  263. if self.pop():
  264. self.frame.cur_idx = jump//2
  265.  
  266. def setup_loop_op(self, jump: int) -> None:
  267. self.push_block('loop', jump)
  268.  
  269. def get_iter_op(self) -> None:
  270. self.push(iter(self.pop()))
  271.  
  272. def for_iter_op(self, jump: int) -> None:
  273. iterator = self.top()
  274. try:
  275. next_val = iterator.__next__()
  276. self.push(next_val)
  277. except StopIteration:
  278. self.pop()
  279. self.frame.cur_idx += jump // 2
  280.  
  281. def jump_absolute_op(self, jump: int) -> None:
  282. self.frame.cur_idx = jump//2
  283.  
  284. def pop_block_op(self) -> tp.Any:
  285. return self.pop_block()
  286.  
  287. def unpack_sequence_op(self, v: tp.Any) -> None:
  288. self.push(*reversed(self.pop()))
  289.  
  290. def pop_jump_if_true_op(self, jump: int) -> None:
  291. if self.pop():
  292. self.frame.cur_idx = jump // 2
  293.  
  294. def pop_jump_if_false_op(self, jump):
  295. if not self.pop():
  296. self.frame.cur_idx = jump // 2
  297.  
  298. class Function(object):
  299. def __init__(self, name: tp.Any, code: tp.Any, globals_nm: tp.Any, vm: tp.Any, kwargs_defaults: tp.Any) -> None:
  300. self.__name__ = name
  301. self.__doc__ = code.co_consts[0] if code.co_consts else None
  302.  
  303. self.f_globals = dict(globals_nm)
  304. self.f_globals.update(vm.frame.f_locals)
  305. self.f_globals.update({name: self})
  306. self.code = code
  307. self.f_locals = {"__name__": self.code.co_name}
  308. self.f_locals.update(kwargs_defaults.get("closure", {}))
  309. self.f_locals.update(kwargs_defaults.get("kwdefaults", {}))
  310.  
  311. self.var_names = self.code.co_varnames
  312. self.defaults = kwargs_defaults.get("defaults", ())
  313. self.vm = vm
  314.  
  315. if self.code.co_flags & 0x04:
  316. self.args_used = True
  317. else:
  318. self.args_used = False
  319.  
  320. if self.code.co_flags & 0x08:
  321. self.kwargs_used = True
  322. else:
  323. self.kwargs_used = False
  324.  
  325. def __call__(self, *args: tp.Any, **kwargs: tp.Any) -> tp.Any:
  326. self.parse_args_kwargs(*args, **kwargs)
  327. self.frame = Frame(self.code, self.f_locals, self.f_globals, self.vm.frame)
  328.  
  329. return self.vm.run_frame(self.frame)
  330.  
  331. @staticmethod
  332. def check_func(args: tp.Any, code: tp.Any, defaults: tp.Any) -> tp.Any:
  333. if len(args) > code.co_argcount:
  334. raise TypeError()
  335. if len(args) + len(defaults) < code.co_argcount:
  336. raise TypeError()
  337.  
  338. def parse_args_kwargs(self, *args: tp.Any, **kwargs: tp.Any) -> tp.Any:
  339. if self.args_used:
  340. self.f_locals.update({self.var_names[i]: args[i] for i in range(self.code.co_argcount)})
  341. args_left = args[self.code.co_argcount:]
  342.  
  343. if self.kwargs_used:
  344. for key in self.var_names[self.code.co_argcount:self.code.co_argcount + self.code.co_kwonlyargcount]:
  345. if key in kwargs:
  346. self.f_locals[key] = kwargs[key]
  347. del kwargs[key]
  348. self.f_locals[self.var_names[self.code.co_argcount + self.code.co_kwonlyargcount + 1]] = kwargs
  349. self.f_locals[self.var_names[self.code.co_argcount + self.code.co_kwonlyargcount]] = args_left
  350. else:
  351. Function.check_func(args, self.code, self.defaults)
  352. self.f_locals.update({self.var_names[i]: args[i] for i in range(len(args))})
  353. default_args_num = len(args) + len(self.defaults) - self.code.co_argcount
  354. if default_args_num < 0:
  355. raise NotImplementedError
  356.  
  357. for i in range(len(args), self.code.co_argcount):
  358. default_idx = default_args_num + i - len(args)
  359. self.f_locals[self.var_names[i]] = self.defaults[default_idx]
  360.  
  361. for key in self.var_names[:self.code.co_argcount]:
  362. if key in kwargs:
  363. self.f_locals[key] = kwargs[key]
  364. del kwargs[key]
  365.  
  366. if self.kwargs_used:
  367. self.f_locals[self.var_names[self.code.co_argcount]] = kwargs
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement