Advertisement
Guest User

Untitled

a guest
Sep 16th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.65 KB | None | 0 0
  1. import sys
  2. from ctypes import POINTER, py_object, Structure, c_ssize_t, c_void_p, sizeof
  3. from typing import Any, Iterator, Optional, Sequence, Union
  4.  
  5.  
  6. __all__ = ("OpStack", )
  7.  
  8.  
  9. class Frame(Structure):
  10. _fields_ = (
  11. ("ob_refcnt", c_ssize_t),
  12. ("ob_type", c_void_p),
  13. ("ob_size", c_ssize_t),
  14. ("f_back", c_void_p),
  15. ("f_code", c_void_p),
  16. ("f_builtins", POINTER(py_object)),
  17. ("f_globals", POINTER(py_object)),
  18. ("f_locals", POINTER(py_object)),
  19. ("f_valuestack", POINTER(py_object)),
  20. ("f_stacktop", POINTER(py_object)),
  21. )
  22.  
  23. if sys.flags.debug:
  24. Frame._fields_ = (
  25. ("_ob_next", POINTER(py_object)),
  26. ("_ob_prev", POINTER(py_object)),
  27. ) + Frame._fields_
  28.  
  29. PTR_SIZE = sizeof(POINTER(py_object))
  30. F_VALUESTACK_OFFSET = sizeof(Frame) - 2 * PTR_SIZE
  31. F_STACKTOP_OFFSET = sizeof(Frame) - PTR_SIZE
  32.  
  33.  
  34. class OpStack(Sequence[Any]):
  35. __slots__ = ("_frame", "_len")
  36.  
  37. def __init__(self, frame):
  38. self._frame = Frame.from_address(id(frame))
  39. stack_start_addr = c_ssize_t.from_address(id(frame) + F_VALUESTACK_OFFSET).value
  40. stack_top_addr = c_ssize_t.from_address(id(frame) + F_STACKTOP_OFFSET).value
  41. self._len = (stack_top_addr - stack_start_addr) // PTR_SIZE
  42.  
  43. def __repr__(self) -> str:
  44. if not self:
  45. return "<OpStack> (empty)>"
  46. return "<OpStack ({})>\n- {}\n".format(
  47. len(self),
  48. "\n- ".join(repr(o) for o in reversed(self)),
  49. )
  50.  
  51. def __len__(self):
  52. return self._len
  53.  
  54. def _preproc_slice(self, idx: Optional[int], default: int) -> int:
  55. if idx is None:
  56. return default
  57. if idx < -self._len or idx >= self._len:
  58. raise IndexError(idx)
  59. if idx < 0:
  60. return idx + self._len
  61. return idx
  62.  
  63. def __getitem__(self, item: Union[int, slice]) -> Any:
  64. if isinstance(item, int):
  65. if item < -self._len or item >= self._len:
  66. raise IndexError(item)
  67. if item < 0:
  68. return self._frame.f_stacktop[item]
  69. return self._frame.f_valuestack[item]
  70.  
  71. if isinstance(item, slice):
  72. item = slice(
  73. self._preproc_slice(item.start, 0),
  74. self._preproc_slice(item.stop, self._len),
  75. item.step
  76. )
  77. return self._frame.f_valuestack[item]
  78.  
  79. raise TypeError(item)
  80.  
  81. def __iter__(self) -> Iterator[Any]:
  82. for i in range(self._len):
  83. yield self._frame.f_valuestack[i]
  84.  
  85. def __reversed__(self) -> Iterator[Any]:
  86. for i in range(self._len - 1, -1, -1):
  87. yield self._frame.f_valuestack[i]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement