Advertisement
Guest User

Untitled

a guest
Mar 28th, 2020
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 21.56 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. # CO_VARARGS = 4
  13. # # CO_VARKEYWORDS = 8
  14. # #
  15. # # ERR_TOO_MANY_POS_ARGS = 'Too many positional arguments'
  16. # # ERR_TOO_MANY_KW_ARGS = 'Too many keyword arguments'
  17. # # ERR_MULT_VALUES_FOR_ARG = 'Multiple values for arguments'
  18. # # ERR_MISSING_POS_ARGS = 'Missing positional arguments'
  19. # # ERR_MISSING_KWONLY_ARGS = 'Missing keyword-only arguments'
  20. # #
  21. # #
  22. # # def bind_args(func: tp.Any, *args: tp.Any, **kwargs: tp.Any) -> tp.Dict[str, tp.Any]:
  23. # #     """Bind values from `args` and `kwargs` to corresponding arguments of `func`
  24. # #
  25. # #     :param func: function to be inspected
  26. # #     :param args: positional arguments to be bound
  27. # #     :param kwargs: keyword arguments to be bound
  28. # #     :return: `dict[argument_name] = argument_value` if binding was successful,
  29. # #              raise TypeError with one of `ERR_*` error descriptions otherwise
  30. # #     """
  31. # #     code_obj = func.__code__
  32. # #     varargs_flag = code_obj.co_flags & CO_VARARGS
  33. # #     kwargs_flag = code_obj.co_flags & CO_VARKEYWORDS
  34. # #
  35. # #     all_variables = list(code_obj.co_varnames)
  36. # #     num_positional_args: int = code_obj.co_argcount
  37. # #     if len(args) > num_positional_args and not varargs_flag:
  38. # #         raise TypeError(ERR_TOO_MANY_POS_ARGS)
  39. # #
  40. # #     num_kwonly_args: int = code_obj.co_kwonlyargcount
  41. # #     default_values: tp.Tuple[tp.Any] = tp.cast(tp.Tuple[tp.Any], func.__defaults__)
  42. # #     kw_default_values: tp.Dict[str, tp.Any] = func.__kwdefaults__
  43. # #
  44. # #     # Firstly, trying to bind positional arguments
  45. # #     positional_args_binding: tp.Dict[str, tp.Any] = dict()
  46. # #     all_positional_args = all_variables[:num_positional_args].copy()
  47. # #     not_binded_positional_vars = all_variables[:num_positional_args].copy()
  48. # #     # Simply bind `args` to positional arguments
  49. # #     for var_name, value in zip(all_variables[:num_positional_args], args):
  50. # #         positional_args_binding[var_name] = value
  51. # #         not_binded_positional_vars.remove(var_name)
  52. # #
  53. # #     # Then if `kwargs` was given check positional args and bind them if possible
  54. # #     pos_kwargs = {kw: val for kw, val in kwargs.items() if kw in all_positional_args}
  55. # #     for kwarg_name, value in pos_kwargs.items():
  56. # #         if kwarg_name in positional_args_binding:
  57. # #             raise TypeError(ERR_MULT_VALUES_FOR_ARG)
  58. # #         positional_args_binding[kwarg_name] = value
  59. # #         not_binded_positional_vars.remove(kwarg_name)
  60. # #         kwargs.pop(kwarg_name)
  61. # #
  62. # #     # Trying to bind positional arguments to their default values if they exists
  63. # #     if default_values:
  64. # #         # At this moment we already binded all positional arguments without default values
  65. # #         # That's why we remove this args from `not_binded_positional_vars`
  66. # #         for arg in all_positional_args[:num_positional_args - len(default_values)]:
  67. # #             if arg in not_binded_positional_vars:
  68. # #                 not_binded_positional_vars.remove(arg)
  69. # #         for var_name, default_value in zip(not_binded_positional_vars.copy(), default_values):
  70. # #             if var_name not in positional_args_binding:
  71. # #                 positional_args_binding[var_name] = default_value
  72. # #                 not_binded_positional_vars.remove(var_name)
  73. # #
  74. # #     # At this moment we must bind all positional arguments with their default/kwargs/args values
  75. # #     if len(positional_args_binding) < num_positional_args:
  76. # #         raise TypeError(ERR_MISSING_POS_ARGS)
  77. # #
  78. # #     arg_binding: tp.Dict[str, tp.Any] = {**positional_args_binding}
  79. # #     # Now we need to bind keyword arguments
  80. # #     kwargs_binding: tp.Dict[str, tp.Any] = dict()
  81. # #     # Let's go parse kw default values and merge with passed kwargs
  82. # #     if kw_default_values:
  83. # #         for kwarg_name, value in kw_default_values.items():
  84. # #             # Don't overwrite value passed in kwargs
  85. # #             if kwarg_name not in kwargs:
  86. # #                 kwargs[kwarg_name] = value
  87. # #     # At this moment we remove all kwargs that corresponds to the positional argument
  88. # #     if len(kwargs) < num_kwonly_args:
  89. # #         raise TypeError(ERR_MISSING_KWONLY_ARGS)
  90. # #     for kwarg_name, value in kwargs.items():
  91. # #         if kwarg_name in all_variables[num_positional_args:]:
  92. # #             kwargs_binding[kwarg_name] = value
  93. # #     # Merge kwargs_binding to the existing bindings
  94. # #     arg_binding = {**kwargs_binding, **arg_binding}
  95. # #
  96. # #     # After all black magic maybe we need to parse remains arguments
  97. # #     # But what remains? We just binds all possible positional and keyword arguments
  98. # #     # We need to pass values to args and kwargs if they was given
  99. # #     # Remove all already parsed values from args and kwargs
  100. # #     if len(all_variables) > num_positional_args + num_kwonly_args:
  101. # #         args_copy: tp.List[tp.Any] = list(args).copy()
  102. # #         kwargs_copy: tp.Dict[str, tp.Any] = kwargs.copy()
  103. # #         for val in positional_args_binding.values():
  104. # #             if val in args_copy:
  105. # #                 args_copy.remove(val)
  106. # #         for kwarg_name, value in kwargs_binding.items():
  107. # #             if kwarg_name in kwargs_copy:
  108. # #                 kwargs_copy.pop(kwarg_name)
  109. # #
  110. # #         if varargs_flag and not kwargs_flag:
  111. # #             arg_binding[all_variables[-1]] = tuple(args_copy)
  112. # #         elif kwargs_flag and not varargs_flag:
  113. # #             arg_binding[all_variables[-1]] = kwargs_copy
  114. # #         else:
  115. # #             arg_binding[all_variables[-2]] = tuple(args_copy)
  116. # #             arg_binding[all_variables[-1]] = kwargs_copy
  117. # #     return arg_binding
  118.  
  119.  
  120. class Frame:
  121.     """
  122.    Frame header in cpython with description
  123.        https://github.com/python/cpython/blob/3.6/Include/frameobject.h#L17
  124.  
  125.    Text description of frame parameters
  126.        https://docs.python.org/3/library/inspect.html?highlight=frame#types-and-members
  127.    """
  128.  
  129.     def __init__(self,
  130.                  frame_code: types.CodeType,
  131.                  frame_builtins: tp.Dict[str, tp.Any],
  132.                  frame_globals: tp.Dict[str, tp.Any],
  133.                  frame_locals: tp.Dict[str, tp.Any]) -> None:
  134.         self.code = frame_code
  135.         self.builtins = frame_builtins
  136.         self.globals = frame_globals
  137.         self.locals = frame_locals
  138.         self.data_stack: tp.Any = []
  139.         self.instruction_mapping: tp.Any = {instr.offset: instr for instr in dis.get_instructions(self.code)}
  140.         self.max_offset = (len(self.instruction_mapping) - 1) * 2
  141.         self.current_offset: int = 0
  142.         self.loop_iterator_indexes: tp.Any = []
  143.         self.loop_endings: tp.Any = []
  144.         self.allow_change_offset_in_run: bool = True
  145.         self.return_value = None
  146.  
  147.     def top(self) -> tp.Any:
  148.         return self.data_stack[-1]
  149.  
  150.     def top1(self) -> tp.Any:
  151.         return self.data_stack[-2]
  152.  
  153.     def top2(self) -> tp.Any:
  154.         return self.data_stack[-3]
  155.  
  156.     def pop(self) -> tp.Any:
  157.         return self.data_stack.pop()
  158.  
  159.     def push(self, *values: tp.Any) -> None:
  160.         self.data_stack.extend(values)
  161.  
  162.     def popn(self, n: int) -> tp.Any:
  163.         """
  164.        Pop a number of values from the value stack.
  165.        A list of n values is returned, the deepest value first.
  166.        """
  167.         if n > 0:
  168.             returned = self.data_stack[-n:]
  169.             self.data_stack[-n:] = []
  170.             return returned
  171.         else:
  172.             return []
  173.  
  174.     def run(self) -> tp.Any:
  175.         while self.current_offset <= self.max_offset:
  176.             instruction = self.instruction_mapping[self.current_offset]
  177.             getattr(self, instruction.opname.lower() + "_op")(instruction.argval)
  178.             if self.allow_change_offset_in_run:
  179.                 self.current_offset = instruction.offset + 2
  180.             else:
  181.                 self.allow_change_offset_in_run = True
  182.         return self.return_value
  183.  
  184.     def call_function_op(self, arg: int) -> None:
  185.         """
  186.        Operation description:
  187.            https://docs.python.org/3/library/dis.html#opcode-CALL_FUNCTION
  188.  
  189.        Operation realization:
  190.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L3121
  191.        """
  192.         arguments = self.popn(arg)
  193.         f = self.pop()
  194.         self.push(f(*arguments))
  195.  
  196.     def load_name_op(self, arg: str) -> None:
  197.         """
  198.        Partial realization
  199.  
  200.        Operation description:
  201.            https://docs.python.org/3/library/dis.html#opcode-LOAD_NAME
  202.  
  203.        Operation realization:
  204.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L2057
  205.        """
  206.         if arg in self.locals:
  207.             self.push(self.locals[arg])
  208.         elif arg in self.globals:
  209.             self.push(self.globals[arg])
  210.         elif arg in self.builtins:
  211.             self.push(self.builtins[arg])
  212.  
  213.     def load_method_op(self, method_name: str) -> None:
  214.         obj = self.pop()
  215.         if hasattr(obj, method_name):
  216.             self.push(getattr(obj, method_name))
  217.         else:
  218.             raise AttributeError
  219.  
  220.     def call_method_op(self, arg: str) -> None:
  221.         method_pos_args = int(arg)
  222.         args = self.popn(method_pos_args)
  223.         method = self.pop()
  224.         self.push(method(*args))
  225.  
  226.     def load_fast_op(self, arg: str) -> None:
  227.         self.push(self.locals[arg])
  228.  
  229.     def load_global_op(self, arg: str) -> None:
  230.         """
  231.        Operation description:
  232.            https://docs.python.org/3/library/dis.html#opcode-LOAD_GLOBAL
  233.  
  234.        Operation realization:
  235.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L2108
  236.        """
  237.         if arg in self.globals:
  238.             self.push(self.globals[arg])
  239.         elif arg in self.builtins:
  240.             self.push(self.builtins[arg])
  241.  
  242.     def load_const_op(self, arg: tp.Any) -> None:
  243.         """
  244.        Operation description:
  245.            https://docs.python.org/3/library/dis.html#opcode-LOAD_CONST
  246.  
  247.        Operation realization:
  248.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L1088
  249.        """
  250.         self.push(arg)
  251.  
  252.     def return_value_op(self, arg: tp.Any) -> None:
  253.         """
  254.        Operation description:
  255.            https://docs.python.org/3/library/dis.html#opcode-RETURN_VALUE
  256.  
  257.        Operation realization:
  258.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L1641
  259.        """
  260.         self.return_value = self.pop()
  261.  
  262.     def pop_top_op(self, arg: tp.Any) -> None:
  263.         """
  264.        Operation description:
  265.            https://docs.python.org/3/library/dis.html#opcode-POP_TOP
  266.  
  267.        Operation realization:
  268.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L1102
  269.        """
  270.         self.pop()
  271.  
  272.     def make_function_op(self, arg: int) -> None:
  273.         """
  274.        Operation description:
  275.            https://docs.python.org/3/library/dis.html#opcode-MAKE_FUNCTION
  276.  
  277.        Operation realization:
  278.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L3203
  279.  
  280.        Parse stack:
  281.            https://github.com/python/cpython/blob/3.7/Objects/call.c#L158
  282.  
  283.        Call function in cpython:
  284.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L4554
  285.        """
  286.         name = self.pop()  # the qualified name of the function (at TOS)  # noqa
  287.         code = self.pop()  # the code associated with the function (at TOS1)
  288.  
  289.         # TODO: use arg to parse function defaults
  290.  
  291.         def f(*args: tp.Any, **kwargs: tp.Any) -> tp.Any:
  292.             # TODO: parse input arguments using code attributes such as co_argcount
  293.  
  294.             parsed_args: tp.Dict[str, tp.Any] = {}
  295.             for i in range(code.co_argcount):
  296.                 parsed_args[code.co_varnames[i]] = args[i]
  297.             f_locals = dict(self.locals)
  298.             f_locals.update(parsed_args)
  299.  
  300.             frame = Frame(code, self.builtins, self.globals, f_locals)  # Run code in prepared environment
  301.             return frame.run()
  302.  
  303.         self.push(f)
  304.  
  305.     def store_name_op(self, arg: str) -> None:
  306.         """
  307.        Operation description:
  308.            https://docs.python.org/3/library/dis.html#opcode-STORE_NAME
  309.  
  310.        Operation realization:
  311.            https://github.com/python/cpython/blob/3.7/Python/ceval.c#L1923
  312.        """
  313.         const = self.pop()
  314.         self.locals[arg] = const
  315.  
  316.     def delete_global_op(self, arg: str) -> None:
  317.         if arg in self.globals:
  318.             self.globals.pop(arg)
  319.         elif arg in self.builtins:
  320.             self.builtins.pop(arg)
  321.         else:
  322.             raise NameError
  323.  
  324.     def store_fast_op(self, arg: str) -> None:
  325.         self.locals[arg] = self.pop()
  326.  
  327.     def delete_fast_op(self, arg: str) -> None:
  328.         if arg in self.locals:
  329.             self.locals.pop(arg)
  330.         else:
  331.             raise NameError
  332.  
  333.     def store_global_op(self, arg: str) -> None:
  334.         global_op_name = self.pop()
  335.         self.globals[arg] = global_op_name
  336.  
  337.     def inplace_add_op(self, arg: str) -> None:
  338.         right_operand = self.pop()
  339.         self.data_stack[-1] += right_operand
  340.  
  341.     def binary_add_op(self, arg: str) -> None:
  342.         right_operand = self.pop()
  343.         left_operand = self.pop()
  344.         self.push(left_operand + right_operand)
  345.  
  346.     def inplace_subtract_op(self, arg: str) -> None:
  347.         right_operand = self.pop()
  348.         self.data_stack[-1] -= right_operand
  349.  
  350.     def binary_subtract_op(self, arg: str) -> None:
  351.         right_operand = self.pop()
  352.         left_operand = self.pop()
  353.         self.push(left_operand - right_operand)
  354.  
  355.     def inplace_multiply_op(self, arg: str) -> None:
  356.         right_operand = self.pop()
  357.         self.data_stack[-1] *= right_operand
  358.  
  359.     def binary_multiply_op(self, arg: str) -> None:
  360.         right_operand = self.pop()
  361.         left_operand = self.pop()
  362.         self.push(left_operand * right_operand)
  363.  
  364.     def inplace_floor_divide_op(self, arg: str) -> None:
  365.         right_operand = self.pop()
  366.         self.data_stack[-1] //= right_operand
  367.  
  368.     def binary_floor_divide_op(self, arg: str) -> None:
  369.         right_operand = self.pop()
  370.         left_operand = self.pop()
  371.         self.push(left_operand // right_operand)
  372.  
  373.     def inplace_true_divide_op(self, arg: str) -> None:
  374.         right_operand = self.pop()
  375.         self.data_stack[-1] /= right_operand
  376.  
  377.     def binary_true_divide_op(self, arg: str) -> None:
  378.         right_operand = self.pop()
  379.         left_operand = self.pop()
  380.         self.push(left_operand / right_operand)
  381.  
  382.     def inplace_lshift_op(self, arg: str) -> None:
  383.         right_operand = self.pop()
  384.         self.data_stack[-1] <<= right_operand
  385.  
  386.     def binary_lshift_op(self, arg: str) -> None:
  387.         right_operand = self.pop()
  388.         left_operand = self.pop()
  389.         self.push(left_operand << right_operand)
  390.  
  391.     def inplace_rshift_op(self, arg: str) -> None:
  392.         right_operand = self.pop()
  393.         self.data_stack[-1] >>= right_operand
  394.  
  395.     def binary_rshift_op(self, arg: str) -> None:
  396.         right_operand = self.pop()
  397.         left_operand = self.pop()
  398.         self.push(left_operand >> right_operand)
  399.  
  400.     def inplace_modulo_op(self, arg: str) -> None:
  401.         right_operand = self.pop()
  402.         self.data_stack[-1] %= right_operand
  403.  
  404.     def binary_modulo_op(self, arg: str) -> None:
  405.         right_operand = self.pop()
  406.         left_operand = self.pop()
  407.         self.push(left_operand % right_operand)
  408.  
  409.     def inplace_power_op(self, arg: str) -> None:
  410.         right_operand = self.pop()
  411.         self.data_stack[-1] **= right_operand
  412.  
  413.     def binary_power_op(self, arg: str) -> None:
  414.         right_operand = self.pop()
  415.         left_operand = self.pop()
  416.         self.push(left_operand ** right_operand)
  417.  
  418.     def inplace_and_op(self, arg: str) -> None:
  419.         right_operand = self.pop()
  420.         self.data_stack[-1] &= right_operand
  421.  
  422.     def binary_and_op(self, arg: str) -> None:
  423.         right_operand = self.pop()
  424.         left_operand = self.pop()
  425.         self.push(left_operand & right_operand)
  426.  
  427.     def inplace_or_op(self, arg: str) -> None:
  428.         right_operand = self.pop()
  429.         self.data_stack[-1] |= right_operand
  430.  
  431.     def binary_or_op(self, arg: str) -> None:
  432.         right_operand = self.pop()
  433.         left_operand = self.pop()
  434.         self.push(left_operand | right_operand)
  435.  
  436.     def inplace_xor_op(self, arg: str) -> None:
  437.         right_operand = self.pop()
  438.         self.data_stack[-1] ^= right_operand
  439.  
  440.     def binary_xor_op(self, arg: str) -> None:
  441.         right_operand = self.pop()
  442.         left_operand = self.pop()
  443.         self.push(left_operand ^ right_operand)
  444.  
  445.     def get_iter_op(self, arg: str) -> None:
  446.         self.data_stack[-1] = iter(self.top())
  447.         self.loop_iterator_indexes.append(len(self.data_stack) - 1)
  448.  
  449.     def for_iter_op(self, out_loop_offset: int) -> None:
  450.         iterator_stack_idx = self.loop_iterator_indexes[-1]
  451.         iterator = self.data_stack[iterator_stack_idx]
  452.         try:
  453.             iter_res = next(iterator)
  454.             self.push(iter_res)
  455.         except StopIteration:
  456.             self.pop()
  457.             self.current_offset = self.loop_endings.pop()
  458.             self.allow_change_offset_in_run = False
  459.  
  460.     def jump_absolute_op(self, offset: int) -> None:
  461.         self.current_offset = offset
  462.         self.allow_change_offset_in_run = False
  463.  
  464.     def setup_loop_op(self, arg: str):
  465.         self.loop_endings.append(int(arg))
  466.  
  467.     def compare_op_op(self, arg: str) -> None:
  468.         right_operand = self.pop()
  469.         left_operand = self.pop()
  470.         cmp_result = False
  471.         if arg == "==":
  472.             cmp_result = left_operand == right_operand
  473.         elif arg == "!=":
  474.             cmp_result = left_operand != right_operand
  475.         elif arg == "in":
  476.             cmp_result = left_operand in right_operand
  477.         elif arg == "not in":
  478.             cmp_result = left_operand not in right_operand
  479.         elif arg == ">":
  480.             cmp_result = left_operand > right_operand
  481.         elif arg == ">=":
  482.             cmp_result = left_operand >= right_operand
  483.         elif arg == "<":
  484.             cmp_result = left_operand < right_operand
  485.         elif arg == "<=":
  486.             cmp_result = left_operand <= right_operand
  487.         else:
  488.             raise NotImplementedError
  489.         self.push(cmp_result)
  490.  
  491.     def pop_jump_if_false_op(self, arg: str) -> None:
  492.         condition = self.pop()
  493.         if not condition:
  494.             self.current_offset = int(arg)
  495.             self.allow_change_offset_in_run = False
  496.  
  497.     def pop_jump_if_true_op(self, arg: str) -> None:
  498.         condition = self.pop()
  499.         if condition:
  500.             self.current_offset = int(arg)
  501.             self.allow_change_offset_in_run = False
  502.  
  503.     def extended_arg_op(self, arg: str) -> None:
  504.         pass
  505.  
  506.     def unpack_sequence_op(self, arg: str) -> None:
  507.         sequence = list(self.pop())
  508.         self.data_stack.extend(sequence[::-1])
  509.  
  510.     def unary_positive_op(self, arg: str) -> None:
  511.         value = self.top()
  512.         self.data_stack[-1] = +value
  513.  
  514.     def unary_negative_op(self, arg: str) -> None:
  515.         value = self.top()
  516.         self.data_stack[-1] = -value
  517.  
  518.     def unary_invert_op(self, arg: str) -> None:
  519.         value = self.top()
  520.         self.data_stack[-1] = ~value
  521.  
  522.     def unary_not_op(self, arg: str) -> None:
  523.         value = self.top()
  524.         self.data_stack[-1] = not value
  525.  
  526.     def build_list_op(self, arg: str) -> None:
  527.         num_values = int(arg)
  528.         values = list(self.popn(num_values))
  529.         self.push(values)
  530.  
  531.     def build_tuple_op(self, arg: str) -> None:
  532.         num_values = int(arg)
  533.         values = tuple(self.popn(num_values))
  534.         self.push(values)
  535.  
  536.     def build_set_op(self, arg: str) -> None:
  537.         num_values = int(arg)
  538.         values = set(self.popn(num_values))
  539.         self.push(values)
  540.  
  541.     def build_const_key_map_op(self, arg: str) -> None:
  542.         num_values = int(arg)
  543.         keys = self.pop()
  544.         result_dict = dict.fromkeys(keys)
  545.         values = self.popn(num_values)
  546.         for i in range(num_values):
  547.             result_dict[keys[i]] = values[i]
  548.         self.push(result_dict)
  549.  
  550.     def build_map_op(self, arg_count: int) -> None:
  551.         values = self.popn(arg_count)
  552.         keys = self.popn(arg_count)
  553.         result_map = dict()
  554.         for i in range(arg_count):
  555.             result_map[keys[i]] = values[i]
  556.         self.push(result_map)
  557.  
  558.     def build_slice_op(self, num_slice_args: int) -> None:
  559.         if num_slice_args == 2:
  560.             start, end = self.popn(num_slice_args)
  561.             self.push(slice(start, end))
  562.         else:
  563.             start, end, step = self.popn(num_slice_args)
  564.             self.push(slice(start, end, step))
  565.  
  566.     def store_subscr_op(self, arg: str) -> None:
  567.         subscr_value = self.top()
  568.         subscr_obj = self.top1()
  569.         value_to_assign = self.top2()
  570.         subscr_obj[subscr_value] = value_to_assign
  571.  
  572.     def delete_subscr_op(self, arg: str) -> None:
  573.         subscr_value = self.top()
  574.         subscr_obj = self.top1()
  575.         del subscr_obj[subscr_value]
  576.  
  577.     def binary_subscr_op(self, arg: str) -> None:
  578.         subscr_value = self.pop()
  579.         obj = self.pop()
  580.         self.push(obj[subscr_value])
  581.  
  582.  
  583. class VirtualMachine:
  584.     def run(self, code_obj: types.CodeType) -> None:
  585.         """
  586.        :param code_obj: code for interpreting
  587.        """
  588.         globals_context: tp.Dict[str, tp.Any] = {}
  589.         frame = Frame(code_obj, builtins.globals()['__builtins__'], globals_context, globals_context)
  590.         return frame.run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement