Repository navigation
Expand file tree
/
Copy pathvar_pointer.py
More file actions
119 lines (94 loc) · 3.01 KB
/
Copy pathvar_pointer.py
File metadata and controls
119 lines (94 loc) · 3.01 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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import inspect
import warnings
from types import FrameType as Frame
from typing import Any, Dict, Optional, TypeVar, Union
from varname import nameof
from _pointers import force_update_locals
from .base_pointers import BasePointer
from .exceptions import NullPointerError, VariableLifetimeError
from .util import NULL, Nullable, handle
__all__ = "VarPointer", "to_var_ptr"
T = TypeVar("T")
class VarPointer(BasePointer[T]):
def __init__(self, name: str, frame: Frame) -> None:
self.name: Optional[str] = name
self._frame = frame
self._address = id(~self)
def _get_scope(self) -> Dict[str, Any]:
if not self.name:
raise NullPointerError("pointer is NULL")
frame = self._frame
if self.name in frame.f_globals:
return frame.f_globals
if self.name in frame.f_locals:
return frame.f_locals
raise VariableLifetimeError(f'variable "{self.name}" no longer exists')
@handle
def move(
self,
target: Union[T, "BasePointer[T]"],
*,
unsafe: bool = False,
) -> None:
if unsafe:
warnings.warn("unsafe has no effect on variable pointers")
if not self.name:
raise NullPointerError("pointer is NULL")
scope = self._get_scope()
if (scope is self._frame.f_locals) and (
self._frame.f_locals is not self._frame.f_globals
):
force_update_locals(
self._frame,
self.name,
(
~target
if isinstance(
target,
BasePointer,
)
else target
),
)
else:
scope[self.name] = (
~target
if isinstance(
target,
BasePointer,
)
else target
)
@property
def address(self) -> Optional[int]:
return self._address
def _cleanup(self) -> None:
pass
def __repr__(self) -> str:
return f"VarPointer(name={self.name!r})"
def dereference(self) -> T:
if not self.name:
raise NullPointerError("pointer is NULL")
return self._get_scope()[self.name]
def assign(self, value: Nullable[Union["VarPointer[T]", T]], *, frame: int = 2) -> None:
if value is NULL:
self._address = 0
self.name = None
return
fframe = inspect.currentframe()
assert fframe
assert fframe.f_back
self.name = nameof(value, frame=frame)
self._address = id(value)
def __irshift__(
self,
value: Nullable[Union["VarPointer[T]", T]],
):
self.assign(value, frame=3)
return self
def to_var_ptr(value: T) -> VarPointer[T]:
frame = inspect.currentframe()
assert frame
assert frame.f_back
name = nameof(value, frame=2)
return VarPointer(name, frame.f_back)