SHARE
TWEET

Untitled

a guest Sep 16th, 2019 70 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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]
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top