Advertisement
Guest User

last_vm

a guest
Apr 4th, 2020
641
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.88 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.  
  11.  
  12. class Block(object):
  13.     def __init__(self, block_type: str, depth: int, handler: tp.Optional[str]):
  14.         self.type = block_type
  15.         self.handler = handler
  16.         self.depth = depth
  17.  
  18. def bind_args(code: types.CodeType, defaults: tp.Tuple[tp.Any], kwdefaults: tp.Dict[str, tp.Any],
  19.               args: tp.Any, kwargs: tp.Any) -> tp.Dict[str, tp.Any]:
  20.     parsed_args: tp.Dict[str, tp.Any] = dict()
  21.     argcount: int = code.co_argcount
  22.     kw_argcount: int = code.co_kwonlyargcount
  23.     names: tp.Tuple[str, ...] = code.co_varnames
  24.     flags = set()
  25.     for flag_key in dis.COMPILER_FLAG_NAMES.keys():
  26.         if flag_key & code.co_flags:
  27.             flags.add(flag_key)
  28.  
  29.     args_in = 4 in flags
  30.     kwargs_in = 8 in flags
  31.  
  32.     # default kwargs and args
  33.     args_name_index = argcount + kw_argcount
  34.     if args_in:
  35.         parsed_args[names[args_name_index]] = ()
  36.         args_name = names[args_name_index]
  37.         if kwargs_in:
  38.             parsed_args[names[args_name_index + 1]] = {}
  39.             kwargs_name = names[args_name_index + 1]
  40.     else:
  41.         if kwargs_in:
  42.             parsed_args[names[args_name_index]] = {}
  43.             kwargs_name = names[args_name_index]
  44.  
  45.     # defaults
  46.     if len(defaults) > 0:
  47.         default_in: tp.Tuple[str, ...] = names[argcount - len(defaults):argcount]
  48.         no_default = names[:argcount - len(defaults)]
  49.         for key, value in zip(default_in, defaults):
  50.             parsed_args[key] = value
  51.     else:
  52.         default_in = ()
  53.         no_default = names[:argcount]
  54.  
  55.     # kwdefaults
  56.     if len(kwdefaults) > 0:
  57.         kwdefault_in = set(kwdefaults)
  58.         for key, value in kwdefaults.items():
  59.             parsed_args[key] = value
  60.     else:
  61.         kwdefault_in = set()
  62.  
  63.     # args
  64.     if len(args) > argcount:
  65.         if args_in:
  66.             for index, arg in enumerate(args[:argcount]):
  67.                 parsed_args[names[index]] = arg
  68.             parsed_args[args_name] = tuple(args[argcount:])
  69.         else:
  70.             raise TypeError("args")
  71.     else:
  72.         for index, arg in enumerate(args):
  73.             parsed_args[names[index]] = arg
  74.  
  75.     # kwargs
  76.     new_kwargs = dict()
  77.     for name, value in kwargs.items():
  78.         if name in names:
  79.             if name in parsed_args and name not in default_in and name not in kwdefault_in:
  80.                 raise TypeError("kwargs")
  81.             else:
  82.                 parsed_args[name] = value
  83.         else:
  84.             if kwargs_in:
  85.                 new_kwargs[name] = value
  86.             else:
  87.                 raise TypeError("kwargs")
  88.  
  89.     if kwargs_in:
  90.         parsed_args[kwargs_name] = new_kwargs
  91.  
  92.     # other
  93.     for name in no_default:
  94.         if name not in parsed_args:
  95.             raise TypeError("other")
  96.  
  97.     # kwonly
  98.     if kw_argcount > 0:
  99.         kw_only = names[argcount:argcount + kw_argcount]
  100.         for name in kw_only:
  101.             if name not in parsed_args:
  102.                 raise TypeError("kwonly")
  103.  
  104.     return parsed_args
  105.  
  106.  
  107. class Frame:
  108.  
  109.     def __init__(self,
  110.                  frame_code: types.CodeType,
  111.                  frame_builtins: tp.Dict[str, tp.Any],
  112.                  frame_globals: tp.Dict[str, tp.Any],
  113.                  frame_locals: tp.Dict[str, tp.Any]) -> None:
  114.         self.code = frame_code
  115.         self.builtins = frame_builtins
  116.         self.globals = frame_globals
  117.         self.locals = frame_locals
  118.         self.data_stack: tp.Any = []
  119.         self.return_value = None
  120.         self.block_stack: tp.List[Block] = []
  121.         self.last_exception = None
  122.         self.next_instr = None
  123.         self.jump_pos = 0
  124.  
  125.     def top(self) -> tp.Any:
  126.         return self.data_stack[-1]
  127.  
  128.     def pop(self) -> tp.Any:
  129.         return self.data_stack.pop()
  130.  
  131.     def pop_block(self) -> tp.Any:
  132.         return self.block_stack.pop()
  133.  
  134.     def unwind_block(self, block: tp.Any) -> None:
  135.         if block.type == 'except-handler':
  136.             offset = 3
  137.         else:
  138.             offset = 0
  139.         while len(self.data_stack) > block.level + offset:
  140.             self.pop()
  141.         if block.type == 'except-handler':
  142.             tb, value, exctype = self.popn(3)
  143.             self.last_exception = exctype, value, tb
  144.  
  145.     def push(self, *values: tp.Any) -> None:
  146.         self.data_stack.extend(values)
  147.  
  148.     def push_block(self, block_type: str, handler: tp.Optional[str] = None) -> None:
  149.         depth = len(self.data_stack)
  150.         self.block_stack.append(Block(block_type, depth, handler))
  151.  
  152.     def popn(self, n: int) -> tp.Any:
  153.         if n > 0:
  154.             returned = self.data_stack[-n:]
  155.             self.data_stack[-n:] = []
  156.             return returned
  157.         else:
  158.             return []
  159.  
  160.     def run(self) -> tp.Any:
  161.         current_pos = 0
  162.         instr_list = list(dis.get_instructions(self.code))
  163.         while current_pos < len(instr_list):
  164.             instruction = instr_list[current_pos]
  165.             if current_pos < len(instr_list) - 1:
  166.                 self.next_instr = instr_list[current_pos + 1].argval
  167.             getattr(self, instruction.opname.lower() + "_op")(instruction.argval)
  168.             if self.jump_pos:
  169.                 current_pos = 0
  170.                 for inst in instr_list:
  171.                     if inst.offset >= self.jump_pos:
  172.                         break
  173.                     current_pos += 1
  174.                 self.jump_pos = 0
  175.             else:
  176.                 current_pos += 1
  177.         return self.return_value
  178.  
  179.     def call_function_op(self, arg: int) -> None:
  180.         arguments = self.popn(arg)
  181.         f = self.pop()
  182.         self.push(f(*arguments))
  183.  
  184.     def call_function_kw_op(self, args: int) -> None:
  185.         keys = self.pop()
  186.         values = self.popn(len(keys))
  187.         arguments = self.popn(args - len(keys))
  188.         kwargs = {key: value for key, value in zip(keys, values)}
  189.         func = self.pop()
  190.         self.push(func(*arguments, **kwargs))
  191.  
  192.     def load_name_op(self, arg: str) -> None:
  193.         if arg in self.locals:
  194.             self.push(self.locals[arg])
  195.         elif arg in self.globals:
  196.             self.push(self.globals[arg])
  197.         elif arg in self.builtins:
  198.             self.push(self.builtins[arg])
  199.         else:
  200.             raise NameError
  201.  
  202.     def load_global_op(self, arg: str) -> None:
  203.         if arg in self.globals:
  204.             self.push(self.globals[arg])
  205.         elif arg in self.builtins:
  206.             self.push(self.builtins[arg])
  207.         else:
  208.             raise NameError
  209.  
  210.     def load_const_op(self, arg: tp.Any) -> None:
  211.         self.push(arg)
  212.  
  213.     def load_fast_op(self, name: str) -> None:
  214.         self.push(self.locals[name])
  215.  
  216.     def store_fast_op(self, name: str) -> None:
  217.         if name in self.locals:
  218.             self.locals[name] = self.pop()
  219.         else:
  220.             raise UnboundLocalError
  221.  
  222.     def delete_fast_op(self, name: str) -> None:
  223.         if name in self.locals:
  224.             del self.locals[name]
  225.         else:
  226.             raise UnboundLocalError
  227.  
  228.     def load_attr_op(self, attr: str) -> None:
  229.         obj = self.pop()
  230.         val = getattr(obj, attr)
  231.         self.push(val)
  232.  
  233.     def store_attr_op(self, name: str) -> None:
  234.         val, obj = self.popn(2)
  235.         setattr(obj, name, val)
  236.  
  237.     def delete_attr_op(self, name: str) -> None:
  238.         obj = self.pop()
  239.         delattr(obj, name)
  240.  
  241.     def delete_global_op(self, name: str) -> None:
  242.         del self.globals[name]
  243.  
  244.     def delete_name_op(self, name: str) -> None:
  245.         del self.locals[name]
  246.  
  247.     def return_value_op(self, *args: tp.Any) -> None:
  248.         self.return_value = self.pop()
  249.  
  250.     def pop_top_op(self, *args: tp.Any) -> None:
  251.         self.pop()
  252.  
  253.     def pop_block_op(self, *args: tp.Any) -> None:
  254.         self.pop_block()
  255.  
  256.     def import_name_op(self, name: str) -> None:
  257.         lvl, froml = self.popn(2)
  258.         self.push(__import__(name, self.globals, self.locals, froml, lvl))
  259.  
  260.     def import_from_op(self, name: str) -> None:
  261.         self.push(getattr(self.top(), name))
  262.  
  263.     def import_star_op(self, arg: tp.Any = None) -> None:
  264.         mod = self.pop()
  265.         for attr in dir(mod):
  266.             if attr[0] != '_':
  267.                 self.locals[attr] = getattr(mod, attr)
  268.  
  269.     def make_function_op(self, arg: int) -> None:
  270.         name = self.pop()
  271.         code = self.pop()
  272.         if arg & 0x08:
  273.             pass
  274.         if arg & 0x04:
  275.             pass
  276.         if arg & 0x02:
  277.             kwonly_defaults = self.pop()
  278.         else:
  279.             kwonly_defaults = {}
  280.         if arg & 0x01:
  281.             defaults = self.pop()
  282.         else:
  283.             defaults = ()
  284.         local = self.locals
  285.  
  286.         def f(*args: tp.Any, **kwargs: tp.Any) -> tp.Any:
  287.             parsed_args: tp.Dict[str, tp.Any] = bind_args(code, defaults, kwonly_defaults, args, kwargs)
  288.             f_locals = dict(local)
  289.             f_locals.update(parsed_args)
  290.  
  291.             frame = Frame(code, self.builtins, self.globals, f_locals)  # Run code in prepared environment
  292.             return frame.run()
  293.         f.__name__ = name
  294.  
  295.         self.push(f)
  296.  
  297.     def store_name_op(self, arg: str) -> None:
  298.         const = self.pop()
  299.         self.locals[arg] = const
  300.  
  301.     def load_method_op(self, method_name: str) -> None:
  302.         obj = self.pop()
  303.         method = getattr(obj, method_name)
  304.         if hasattr(method, '__self__'):
  305.             self.push(None)
  306.             self.push(method)
  307.         else:
  308.             self.push(method)
  309.             self.push(obj)
  310.  
  311.     def call_method_op(self, argc: int) -> None:
  312.         arguments = self.popn(argc)
  313.         x, y = self.popn(2)
  314.         if y is None:
  315.             self.push(x(*arguments))
  316.         else:
  317.             self.push(y(*arguments))
  318.  
  319.     # Logic
  320.  
  321.     comp_ops = {
  322.         '<': lambda x, y: x < y,
  323.         '<=': lambda x, y: x <= y,
  324.         '==': lambda x, y: x == y,
  325.         '!=': lambda x, y: x != y,
  326.         '>': lambda x, y: x > y,
  327.         '>=': lambda x, y: x >= y,
  328.         'is': lambda x, y: x is y,
  329.         'is not': lambda x, y: x is not y,
  330.         'in': lambda x, y: x in y,
  331.         'not in': lambda x, y: x not in y,
  332.     }
  333.  
  334.     def compare_op_op(self, operation: str) -> None:
  335.         x, y = self.popn(2)
  336.         if operation in self.comp_ops:
  337.             self.push(self.comp_ops[operation](x, y))
  338.         # EXCEPTION!!!
  339.  
  340.     # Unary Operations
  341.  
  342.     def unary_negative_op(self, *args: tp.Any) -> None:
  343.         self.push(-self.pop())
  344.  
  345.     def unary_positive_op(self, *args: tp.Any) -> None:
  346.         self.push(abs(self.pop()))
  347.  
  348.     def unary_not_op(self, *args: tp.Any) -> None:
  349.         self.push(not self.pop())
  350.  
  351.     def unary_invert_op(self, *args: tp.Any) -> None:
  352.         self.push(~self.pop())
  353.  
  354.     # Inplace Operations
  355.  
  356.     def inplace_power_op(self, *args: tp.Any) -> None:
  357.         x, y = self.popn(2)
  358.         self.push(x ** y)
  359.  
  360.     def inplace_multiply_op(self, *args: tp.Any) -> None:
  361.         x, y = self.popn(2)
  362.         self.push(x * y)
  363.  
  364.     def inplace_matrix_multiply_op(self, *args: tp.Any) -> None:
  365.         x, y = self.popn(2)
  366.         self.push(x @ y)
  367.  
  368.     def inplace_floor_divide_op(self, *args: tp.Any) -> None:
  369.         x, y = self.popn(2)
  370.         self.push(x // y)
  371.  
  372.     def inplace_true_divide_op(self, *args: tp.Any) -> None:
  373.         x, y = self.popn(2)
  374.         self.push(x / y)
  375.  
  376.     def inplace_modulo_op(self, *args: tp.Any) -> None:
  377.         x, y = self.popn(2)
  378.         self.push(x % y)
  379.  
  380.     def inplace_add_op(self, *args: tp.Any) -> None:
  381.         x, y = self.popn(2)
  382.         self.push(x + y)
  383.  
  384.     def inplace_subtract_op(self, *args: tp.Any) -> None:
  385.         x, y = self.popn(2)
  386.         self.push(x - y)
  387.  
  388.     def inplace_lshift_op(self, *args: tp.Any) -> None:
  389.         x, y = self.popn(2)
  390.         self.push(x << y)
  391.  
  392.     def inplace_rshift_op(self, *args: tp.Any) -> None:
  393.         x, y = self.popn(2)
  394.         self.push(x >> y)
  395.  
  396.     def inplace_and_op(self, *args: tp.Any) -> None:
  397.         x, y = self.popn(2)
  398.         self.push(x & y)
  399.  
  400.     def inplace_xor_op(self, *args: tp.Any) -> None:
  401.         x, y = self.popn(2)
  402.         self.push(x ^ y)
  403.  
  404.     def inplace_or_op(self, *args: tp.Any) -> None:
  405.         x, y = self.popn(2)
  406.         self.push(x | y)
  407.  
  408.     # Binary Operations
  409.  
  410.     def binary_power_op(self, *args: tp.Any) -> None:
  411.         self.inplace_power_op(args)
  412.  
  413.     def binary_multiply_op(self, *args: tp.Any) -> None:
  414.         self.inplace_multiply_op(args)
  415.  
  416.     def binary_matrix_multiply_op(self, *args: tp.Any) -> None:
  417.         self.inplace_matrix_multiply_op(args)
  418.  
  419.     def binary_floor_divide_op(self, *args: tp.Any) -> None:
  420.         self.inplace_floor_divide_op(args)
  421.  
  422.     def binary_true_divide_op(self, *args: tp.Any) -> None:
  423.         self.inplace_true_divide_op(args)
  424.  
  425.     def binary_modulo_op(self, *args: tp.Any) -> None:
  426.         self.inplace_modulo_op(args)
  427.  
  428.     def binary_add_op(self, *args: tp.Any) -> None:
  429.         self.inplace_add_op(args)
  430.  
  431.     def binary_subtract_op(self, *args: tp.Any) -> None:
  432.         self.inplace_subtract_op(args)
  433.  
  434.     def binary_lshift_op(self, *args: tp.Any) -> None:
  435.         self.inplace_lshift_op(args)
  436.  
  437.     def binary_rshift_op(self, *args: tp.Any) -> None:
  438.         self.inplace_rshift_op(args)
  439.  
  440.     def binary_and_op(self, *args: tp.Any) -> None:
  441.         self.inplace_and_op(args)
  442.  
  443.     def binary_xor_op(self, *args: tp.Any) -> None:
  444.         self.inplace_xor_op(args)
  445.  
  446.     def binary_or_op(self, *args: tp.Any) -> None:
  447.         self.inplace_or_op(args)
  448.  
  449.     def binary_subscr_op(self, *args: tp.Any) -> None:
  450.         x, y = self.popn(2)
  451.         self.push(x[y])
  452.  
  453.     def store_subscr_op(self, *args: tp.Any) -> None:
  454.         x, y = self.popn(2)
  455.         x[y] = self.pop()
  456.         self.push(x)
  457.         self.push(y)
  458.  
  459.     def delete_subscr_op(self, *args: tp.Any) -> None:
  460.         x, y = self.popn(2)
  461.         del x[y]
  462.         self.push(x)
  463.         self.push(y)
  464.  
  465.     def store_global_op(self, name: str) -> None:
  466.         self.globals[name] = self.pop()
  467.  
  468.     # Stack
  469.  
  470.     def dup_top_op(self, *args: tp.Any) -> None:
  471.         self.push(self.top())
  472.  
  473.     def dup_top_two_op(self, *args: tp.Any) -> None:
  474.         x = self.pop()
  475.         y = self.top()
  476.         self.push(x)
  477.         self.push(y)
  478.         self.push(x)
  479.  
  480.     def rot_two_op(self, *args: tp.Any) -> None:
  481.         x, y = self.popn(2)
  482.         self.push(y)
  483.         self.push(x)
  484.  
  485.     def rot_three_op(self, *args: tp.Any) -> None:
  486.         x, y, z = self.popn(3)
  487.         self.push(z)
  488.         self.push(y)
  489.         self.push(x)
  490.  
  491.     """"
  492.    def pop_except_op(self) -> None:
  493.        block = self.pop_block()
  494.        if block.type != 'except-handler':
  495.            raise Exception("popped block is not an except handler")
  496.        self.unwind_block(block)
  497.    """
  498.  
  499.     # Jumps
  500.  
  501.     def jump_forward_op(self, ind: int) -> None:
  502.         self.jump_pos = ind
  503.  
  504.     def jump_absolute_op(self, ind: int) -> None:
  505.         self.jump_pos = ind
  506.  
  507.     def pop_jump_if_true_op(self, ind: int) -> None:
  508.         if self.pop():
  509.             self.jump_pos = ind
  510.  
  511.     def pop_jump_if_false_op(self, ind: int) -> None:
  512.         if not self.pop():
  513.             self.jump_pos = ind
  514.  
  515.     def jump_if_true_or_pop_op(self, ind: int) -> None:
  516.         if self.top():
  517.             self.jump_pos = ind
  518.         else:
  519.             self.pop()
  520.  
  521.     def jump_if_false_or_pop(self, ind: int) -> None:
  522.         if not self.top():
  523.             self.jump_pos = ind
  524.         else:
  525.             self.pop()
  526.  
  527.     # Loop
  528.  
  529.     def setup_loop_op(self, args: tp.Any) -> None:
  530.         self.push_block('loop', args)
  531.  
  532.     def get_iter_op(self, args: tp.Any) -> None:
  533.         self.push(iter(self.pop()))
  534.  
  535.     def for_iter_op(self, step: int, *args: tp.Any) -> None:
  536.         iterat = self.pop()
  537.         try:
  538.             next_it = iterat.__next__()
  539.             self.push(iterat)
  540.             self.push(next_it)
  541.         except StopIteration:
  542.             self.jump_pos = step
  543.  
  544.     # Building
  545.  
  546.     def build_list_op(self, size: int) -> None:
  547.         self.push(self.popn(size))
  548.  
  549.     def build_list_unpack_op(self, size: int) -> None:
  550.         elems = self.popn(size)
  551.         unp_list: tp.List[tp.Any] = []
  552.         for elem in elems:
  553.             unp_list += elem
  554.         self.push(unp_list)
  555.  
  556.     def list_append_op(self, i: int) -> None:
  557.         new_list = self.pop()
  558.         list.append(new_list[-i], new_list)
  559.         self.push(new_list)
  560.  
  561.     def build_tuple_op(self, size: int) -> None:
  562.         self.push(tuple(self.popn(size)))
  563.  
  564.     def build_tuple_unpack_op(self, size: int) -> None:
  565.         elems = self.popn(size)
  566.         unp_tuple: tp.Tuple[tp.Any, ...] = tuple()
  567.         for elem in elems:
  568.             unp_tuple += elem
  569.         self.push(unp_tuple)
  570.  
  571.     def build_map_op(self, size: int) -> None:
  572.         elems = self.popn(2 * size)
  573.         new_map = {}
  574.         for i in range(0, 2 * size, 2):
  575.             new_map[elems[i]] = elems[i + 1]
  576.         self.push(new_map)
  577.  
  578.     def build_map_unpack_op(self, size: int) -> None:
  579.         elems = self.popn(size)
  580.         unp_map: tp.Dict[tp.Any, tp.Any] = {}
  581.         for elem in elems:
  582.             unp_map.update(elem)
  583.         self.push(unp_map)
  584.  
  585.     def build_const_key_map_op(self, size: int) -> None:
  586.         keys = self.pop()
  587.         values = self.popn(size)
  588.         new_map = {key: value for key, value in zip(keys, values)}
  589.         self.push(new_map)
  590.  
  591.     def build_set_op(self, size: int) -> None:
  592.         self.push(set(self.popn(size)))
  593.  
  594.     def build_set_unpack_op(self, size: int) -> None:
  595.         elems = self.popn(size)
  596.         self.push(set().union(*elems))
  597.  
  598.     def build_slice_op(self, args: int) -> None:
  599.         if args == 2:
  600.             x, y = self.popn(2)
  601.             self.push(slice(x, y))
  602.         elif args == 3:
  603.             x, y, z = self.popn(3)
  604.             self.push(slice(x, y, z))
  605.         else:
  606.             raise Exception('incorrect set of arguments for slice')
  607.  
  608.     def build_string_op(self, size: int) -> None:
  609.         elems = self.popn(size)
  610.         string = ''
  611.         for elem in elems:
  612.             string += elem
  613.         self.push(string)
  614.  
  615.     def format_value_op(self, flags: tp.Any) -> None:
  616.         pass
  617.  
  618.     def unpack_sequence_op(self, count: int) -> None:
  619.         seq = self.pop()
  620.         for x in reversed(seq):
  621.             self.push(x)
  622.  
  623.     def extended_arg_op(self, ext: tp.Any) -> None:
  624.         instr_arg = self.next_instr
  625.         instr_arg |= ext << 8
  626.         self.next_instr = instr_arg
  627.     """
  628.    def do_raise(self, exc: tp.Any, cause: tp.Any) -> tp.Any:
  629.        if exc is None:
  630.            exc_type, val, tb = self.last_exception
  631.            if exc_type is None:
  632.                return 'exception'
  633.            else:
  634.                return 'reraise'
  635.        elif type(exc) == type:
  636.            exc_type = exc
  637.            val = exc()
  638.        elif isinstance(exc, BaseException):
  639.            exc_type = type(exc)
  640.            val = exc
  641.        else:
  642.            return 'exception'
  643.        if cause:
  644.            if type(cause) == type:
  645.                cause = cause()
  646.            elif not isinstance(cause, BaseException):
  647.                return 'exception'
  648.            val.__cause__ = cause
  649.        self.last_exception = exc_type, val, val.__traceback__
  650.        return 'exception'
  651.      def raise_varargs_op(self, argc: int) -> None:
  652.        cause = exc = None
  653.        if argc == 2:
  654.            cause = self.pop()
  655.            exc = self.pop()
  656.        elif argc == 1:
  657.            exc = self.pop()
  658.        return self.do_raise(exc, cause)
  659.        """
  660.  
  661.  
  662. class VirtualMachine:
  663.     def run(self, code_obj: types.CodeType) -> None:
  664.         """
  665.      :param code_text_or_obj: code for interpreting
  666.      """
  667.         globals_context: tp.Dict[str, tp.Any] = {}
  668.         frame = Frame(code_obj, builtins.globals()['__builtins__'], globals_context, globals_context)
  669.         return frame.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement