Repository navigation
Expand file tree
/
Copy pathget_stack.py
More file actions
89 lines (70 loc) · 2.73 KB
/
Copy pathget_stack.py
File metadata and controls
89 lines (70 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# https://gist.github.com/crusaderky/cf0575cfeeee8faa1bb1b3480bc4a87a
import sys
from ctypes import POINTER, py_object, Structure, c_ssize_t, c_void_p, sizeof
from typing import Any, Iterator, Optional, Sequence, Union
__all__ = ("OpStack",)
class Frame(Structure):
_fields_ = (
("ob_refcnt", c_ssize_t),
("ob_type", c_void_p),
("ob_size", c_ssize_t),
("f_back", c_void_p),
("f_code", c_void_p),
("f_builtins", POINTER(py_object)),
("f_globals", POINTER(py_object)),
("f_locals", POINTER(py_object)),
("f_valuestack", POINTER(py_object)),
("f_stacktop", POINTER(py_object)),
)
if sys.flags.debug:
Frame._fields_ = (
("_ob_next", POINTER(py_object)),
("_ob_prev", POINTER(py_object)),
) + Frame._fields_
PTR_SIZE = sizeof(POINTER(py_object))
F_VALUESTACK_OFFSET = sizeof(Frame) - 2 * PTR_SIZE
F_STACKTOP_OFFSET = sizeof(Frame) - PTR_SIZE
class OpStack(Sequence[Any]):
__slots__ = ("_frame", "_len")
def __init__(self, frame):
self._frame = Frame.from_address(id(frame))
# stack_start_addr = c_ssize_t.from_address(id(frame) + F_VALUESTACK_OFFSET).value
# stack_top_addr = c_ssize_t.from_address(id(frame) + F_STACKTOP_OFFSET).value
# self._len = (stack_top_addr - stack_start_addr) // PTR_SIZE
def __repr__(self) -> str:
if not self:
return "<OpStack> (empty)>"
return "<OpStack ({})>\n- {}\n".format(
len(self), "\n- ".join(repr(o) for o in reversed(self)),
)
def __len__(self):
return self._len
def _preproc_slice(self, idx: Optional[int], default: int) -> int:
if idx is None:
return default
if idx < -self._len or idx >= self._len:
raise IndexError(idx)
if idx < 0:
return idx + self._len
return idx
def __getitem__(self, item: Union[int, slice]) -> Any:
# if isinstance(item, int):
# if item < -self._len or item >= self._len:
# raise IndexError(item)
# if item < 0:
return self._frame.f_stacktop[item]
# return self._frame.f_valuestack[item]
# if isinstance(item, slice):
# item = slice(
# self._preproc_slice(item.start, 0),
# self._preproc_slice(item.stop, self._len),
# item.step,
# )
# return self._frame.f_valuestack[item]
# raise TypeError(item)
def __iter__(self) -> Iterator[Any]:
for i in range(self._len):
yield self._frame.f_valuestack[i]
def __reversed__(self) -> Iterator[Any]:
for i in range(self._len - 1, -1, -1):
yield self._frame.f_valuestack[i]