PyNerva 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of PyNerva might be problematic. Click here for more details.
- nervapy/__init__.py +50 -0
- nervapy/abi.py +91 -0
- nervapy/arm/__init__.py +124 -0
- nervapy/arm/__main__.py +0 -0
- nervapy/arm/abi.py +138 -0
- nervapy/arm/formats.py +49 -0
- nervapy/arm/function.py +2405 -0
- nervapy/arm/generic.py +10797 -0
- nervapy/arm/instructions.py +519 -0
- nervapy/arm/isa.py +409 -0
- nervapy/arm/literal_pool.py +331 -0
- nervapy/arm/microarchitecture.py +211 -0
- nervapy/arm/pseudo.py +652 -0
- nervapy/arm/registers.py +1458 -0
- nervapy/arm/vfpneon.py +4092 -0
- nervapy/arm.py +13 -0
- nervapy/c/__init__.py +1 -0
- nervapy/c/types.py +436 -0
- nervapy/codegen.py +99 -0
- nervapy/common/__init__.py +4 -0
- nervapy/common/function.py +5 -0
- nervapy/common/regalloc.py +121 -0
- nervapy/constant_data.py +282 -0
- nervapy/encoder.py +246 -0
- nervapy/formats/__init__.py +2 -0
- nervapy/formats/elf/__init__.py +4 -0
- nervapy/formats/elf/file.py +178 -0
- nervapy/formats/elf/image.py +106 -0
- nervapy/formats/elf/section.py +422 -0
- nervapy/formats/elf/symbol.py +281 -0
- nervapy/formats/macho/__init__.py +2 -0
- nervapy/formats/macho/file.py +123 -0
- nervapy/formats/macho/image.py +143 -0
- nervapy/formats/macho/section.py +322 -0
- nervapy/formats/macho/symbol.py +158 -0
- nervapy/formats/mscoff/__init__.py +8 -0
- nervapy/formats/mscoff/image.py +132 -0
- nervapy/formats/mscoff/section.py +181 -0
- nervapy/formats/mscoff/symbol.py +148 -0
- nervapy/function.py +136 -0
- nervapy/literal.py +731 -0
- nervapy/loader.py +188 -0
- nervapy/name.py +159 -0
- nervapy/parse.py +52 -0
- nervapy/stream.py +58 -0
- nervapy/util.py +126 -0
- nervapy/writer.py +518 -0
- nervapy/x86_64/__init__.py +324 -0
- nervapy/x86_64/__main__.py +407 -0
- nervapy/x86_64/abi.py +517 -0
- nervapy/x86_64/amd.py +6464 -0
- nervapy/x86_64/avx.py +102029 -0
- nervapy/x86_64/crypto.py +1533 -0
- nervapy/x86_64/encoding.py +424 -0
- nervapy/x86_64/fma.py +19138 -0
- nervapy/x86_64/function.py +2707 -0
- nervapy/x86_64/generic.py +23384 -0
- nervapy/x86_64/instructions.py +500 -0
- nervapy/x86_64/isa.py +476 -0
- nervapy/x86_64/lower.py +126 -0
- nervapy/x86_64/mask.py +2593 -0
- nervapy/x86_64/meta.py +143 -0
- nervapy/x86_64/mmxsse.py +17265 -0
- nervapy/x86_64/nacl.py +327 -0
- nervapy/x86_64/operand.py +1204 -0
- nervapy/x86_64/options.py +21 -0
- nervapy/x86_64/pseudo.py +686 -0
- nervapy/x86_64/registers.py +1225 -0
- nervapy/x86_64/types.py +17 -0
- nervapy/x86_64/uarch.py +580 -0
- pynerva-0.0.5.dist-info/METADATA +310 -0
- pynerva-0.0.5.dist-info/RECORD +74 -0
- pynerva-0.0.5.dist-info/WHEEL +4 -0
- pynerva-0.0.5.dist-info/licenses/LICENSE.rst +15 -0
nervapy/loader.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Loader:
|
|
8
|
+
def __init__(self, code_size, data_size=0):
|
|
9
|
+
from nervapy.util import is_int
|
|
10
|
+
|
|
11
|
+
if not is_int(code_size):
|
|
12
|
+
raise TypeError("code size must be an integer")
|
|
13
|
+
if not is_int(data_size):
|
|
14
|
+
raise TypeError("data size must be an integer")
|
|
15
|
+
if code_size <= 0:
|
|
16
|
+
raise ValueError("code size must be positive")
|
|
17
|
+
if data_size < 0:
|
|
18
|
+
raise ValueError("data size must be non-negative")
|
|
19
|
+
|
|
20
|
+
import mmap
|
|
21
|
+
|
|
22
|
+
self.allocation_granularity = max(mmap.ALLOCATIONGRANULARITY, mmap.PAGESIZE)
|
|
23
|
+
self.code_address = None
|
|
24
|
+
self.code_size = self.allocation_size(code_size)
|
|
25
|
+
self.data_address = None
|
|
26
|
+
self.data_size = self.allocation_size(data_size)
|
|
27
|
+
|
|
28
|
+
self._release_memory = None
|
|
29
|
+
|
|
30
|
+
osname = sys.platform.lower()
|
|
31
|
+
if (
|
|
32
|
+
osname == "darwin"
|
|
33
|
+
or osname.startswith("linux")
|
|
34
|
+
or osname.startswith("freebsd")
|
|
35
|
+
):
|
|
36
|
+
import ctypes
|
|
37
|
+
|
|
38
|
+
if osname == "darwin":
|
|
39
|
+
libc = ctypes.cdll.LoadLibrary("libc.dylib")
|
|
40
|
+
elif osname.startswith("freebsd"):
|
|
41
|
+
libc = ctypes.cdll.LoadLibrary("libc.so.7")
|
|
42
|
+
else:
|
|
43
|
+
libc = ctypes.cdll.LoadLibrary("libc.so.6")
|
|
44
|
+
|
|
45
|
+
# void* mmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset)
|
|
46
|
+
mmap_function = libc.mmap
|
|
47
|
+
mmap_function.restype = ctypes.c_void_p
|
|
48
|
+
mmap_function.argtype = [
|
|
49
|
+
ctypes.c_void_p,
|
|
50
|
+
ctypes.c_size_t,
|
|
51
|
+
ctypes.c_int,
|
|
52
|
+
ctypes.c_int,
|
|
53
|
+
ctypes.c_int,
|
|
54
|
+
ctypes.c_size_t,
|
|
55
|
+
]
|
|
56
|
+
# int munmap(void* addr, size_t len)
|
|
57
|
+
munmap_function = libc.munmap
|
|
58
|
+
munmap_function.restype = ctypes.c_int
|
|
59
|
+
munmap_function.argtype = [ctypes.c_void_p, ctypes.c_size_t]
|
|
60
|
+
|
|
61
|
+
def munmap(address, size):
|
|
62
|
+
munmap_result = munmap_function(ctypes.c_void_p(address), size)
|
|
63
|
+
assert munmap_result == 0
|
|
64
|
+
|
|
65
|
+
self._release_memory = lambda address_size: munmap(
|
|
66
|
+
address_size[0], address_size[1]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Allocate code segment
|
|
70
|
+
code_address = mmap_function(
|
|
71
|
+
None,
|
|
72
|
+
self.code_size,
|
|
73
|
+
mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
|
|
74
|
+
mmap.MAP_ANON | mmap.MAP_PRIVATE,
|
|
75
|
+
-1,
|
|
76
|
+
0,
|
|
77
|
+
)
|
|
78
|
+
if code_address == -1:
|
|
79
|
+
raise OSError("Failed to allocate memory for code segment")
|
|
80
|
+
self.code_address = code_address
|
|
81
|
+
|
|
82
|
+
if self.data_size > 0:
|
|
83
|
+
# Allocate data segment
|
|
84
|
+
data_address = mmap_function(
|
|
85
|
+
None,
|
|
86
|
+
self.data_size,
|
|
87
|
+
mmap.PROT_READ | mmap.PROT_WRITE,
|
|
88
|
+
mmap.MAP_ANON | mmap.MAP_PRIVATE,
|
|
89
|
+
-1,
|
|
90
|
+
0,
|
|
91
|
+
)
|
|
92
|
+
if data_address == -1:
|
|
93
|
+
raise OSError("Failed to allocate memory for data segment")
|
|
94
|
+
self.data_address = data_address
|
|
95
|
+
elif osname == "win32":
|
|
96
|
+
import ctypes
|
|
97
|
+
|
|
98
|
+
# From WinNT.h
|
|
99
|
+
PAGE_READWRITE = 0x04
|
|
100
|
+
PAGE_EXECUTE_READWRITE = 0x40
|
|
101
|
+
MEM_COMMIT = 0x1000
|
|
102
|
+
MEM_RESERVE = 0x2000
|
|
103
|
+
MEM_RELEASE = 0x8000
|
|
104
|
+
|
|
105
|
+
# LPVOID WINAPI VirtualAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect)
|
|
106
|
+
VirtualAlloc_function = ctypes.windll.kernel32.VirtualAlloc
|
|
107
|
+
VirtualAlloc_function.restype = ctypes.c_void_p
|
|
108
|
+
VirtualAlloc_function.argtypes = [
|
|
109
|
+
ctypes.c_void_p,
|
|
110
|
+
ctypes.c_size_t,
|
|
111
|
+
ctypes.c_ulong,
|
|
112
|
+
ctypes.c_ulong,
|
|
113
|
+
]
|
|
114
|
+
# BOOL WINAPI VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
|
|
115
|
+
VirtualFree_function = ctypes.windll.kernel32.VirtualFree
|
|
116
|
+
VirtualFree_function.restype = ctypes.c_int
|
|
117
|
+
VirtualFree_function.argtypes = [
|
|
118
|
+
ctypes.c_void_p,
|
|
119
|
+
ctypes.c_size_t,
|
|
120
|
+
ctypes.c_ulong,
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
def VirtualFree(address, size):
|
|
124
|
+
VirtualFree_result = VirtualFree_function(address, 0, MEM_RELEASE)
|
|
125
|
+
assert VirtualFree_result != 0
|
|
126
|
+
|
|
127
|
+
self._release_memory = lambda address_size: VirtualFree(
|
|
128
|
+
address_size[0], address_size[1]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Allocate code segment
|
|
132
|
+
code_address = VirtualAlloc_function(
|
|
133
|
+
None, self.code_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE
|
|
134
|
+
)
|
|
135
|
+
if not code_address:
|
|
136
|
+
raise OSError("Failed to allocate memory for code segment")
|
|
137
|
+
self.code_address = code_address
|
|
138
|
+
|
|
139
|
+
if self.data_size > 0:
|
|
140
|
+
# Allocate data segment
|
|
141
|
+
data_address = VirtualAlloc_function(
|
|
142
|
+
None, self.data_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE
|
|
143
|
+
)
|
|
144
|
+
if not data_address:
|
|
145
|
+
raise OSError("Failed to allocate memory for data segment")
|
|
146
|
+
self.data_address = data_address
|
|
147
|
+
elif osname == "nacl":
|
|
148
|
+
import dynacl
|
|
149
|
+
|
|
150
|
+
# Allocate code segment
|
|
151
|
+
self.allocation = dynacl.allocate(self.code_size, self.data_size)
|
|
152
|
+
self.code_address = self.allocation.code_address
|
|
153
|
+
self.data_address = self.allocation.data_address
|
|
154
|
+
self.copy_code = self._nacl_copy_code
|
|
155
|
+
else:
|
|
156
|
+
raise ValueError("Unknown host OS: " + osname)
|
|
157
|
+
|
|
158
|
+
def allocation_size(self, segment_size):
|
|
159
|
+
import nervapy.util
|
|
160
|
+
|
|
161
|
+
return nervapy.util.roundup(segment_size, self.allocation_granularity)
|
|
162
|
+
|
|
163
|
+
def copy_code(self, code_segment):
|
|
164
|
+
import ctypes
|
|
165
|
+
|
|
166
|
+
ctypes.memmove(
|
|
167
|
+
self.code_address, ctypes.c_char_p(bytes(code_segment)), len(code_segment)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def _nacl_copy_code(self, code_segment):
|
|
171
|
+
code_offset = 0
|
|
172
|
+
self.allocation.dyncode_create(code_segment, code_offset)
|
|
173
|
+
|
|
174
|
+
def copy_data(self, data_segment):
|
|
175
|
+
import ctypes
|
|
176
|
+
|
|
177
|
+
ctypes.memmove(
|
|
178
|
+
self.data_address, ctypes.c_char_p(bytes(data_segment)), len(data_segment)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def __del__(self):
|
|
182
|
+
if self._release_memory is not None:
|
|
183
|
+
if self.code_address is not None:
|
|
184
|
+
self._release_memory((self.code_address, self.code_size))
|
|
185
|
+
self.code_address = None
|
|
186
|
+
if self.data_address is not None:
|
|
187
|
+
self._release_memory((self.data_address, self.data_size))
|
|
188
|
+
self.data_address = None
|
nervapy/name.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
import six
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Name:
|
|
8
|
+
def __init__(self, name=None, prename=None):
|
|
9
|
+
assert name is None or isinstance(name, str)
|
|
10
|
+
assert prename is None or isinstance(prename, str)
|
|
11
|
+
assert (
|
|
12
|
+
name is None or prename is None
|
|
13
|
+
), "Either name or prename, but not both, can be specified"
|
|
14
|
+
self.name = name
|
|
15
|
+
self.prename = prename
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
|
+
if self.name is not None:
|
|
19
|
+
return self.name
|
|
20
|
+
elif self.prename is not None:
|
|
21
|
+
return "<" + self.prename + ">"
|
|
22
|
+
else:
|
|
23
|
+
return "<?>"
|
|
24
|
+
|
|
25
|
+
def __repr__(self):
|
|
26
|
+
return str(self)
|
|
27
|
+
|
|
28
|
+
def __hash__(self):
|
|
29
|
+
return hash(self.name) ^ id(self)
|
|
30
|
+
|
|
31
|
+
def __eq__(self, other):
|
|
32
|
+
return isinstance(other, Name) and (self is other or self.name == other.name)
|
|
33
|
+
|
|
34
|
+
def __ne__(self, other):
|
|
35
|
+
return not isinstance(other, Name) or (
|
|
36
|
+
self is not other and self.name != other.name
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def check_name(name):
|
|
41
|
+
"""Verifies that the name is appropriate for a symbol"""
|
|
42
|
+
if not isinstance(name, str):
|
|
43
|
+
raise TypeError("Invalid name %s: string required" % str(name))
|
|
44
|
+
import re
|
|
45
|
+
|
|
46
|
+
if not re.match("^[_a-zA-Z]\\w*$", name):
|
|
47
|
+
raise ValueError("Invalid name: " + name)
|
|
48
|
+
if name.startswith("__"):
|
|
49
|
+
raise ValueError(
|
|
50
|
+
"Invalid name %s: names starting with __ are reserved for PeachPy purposes"
|
|
51
|
+
% name
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class Namespace:
|
|
56
|
+
def __init__(self, scope_name):
|
|
57
|
+
assert scope_name is None or isinstance(scope_name, Name)
|
|
58
|
+
# Name of the namespace.
|
|
59
|
+
self.scope_name = scope_name
|
|
60
|
+
# Map from name string to either Name or Namespace object
|
|
61
|
+
self.names = dict()
|
|
62
|
+
# Map from prename string to a set of Name and Namespace objects
|
|
63
|
+
self.prenames = dict()
|
|
64
|
+
|
|
65
|
+
def __str__(self):
|
|
66
|
+
return str(self.scope_name)
|
|
67
|
+
|
|
68
|
+
def __hash__(self):
|
|
69
|
+
return hash(self.scope_name)
|
|
70
|
+
|
|
71
|
+
def __eq__(self, other):
|
|
72
|
+
return isinstance(other, Namespace) and self.scope_name == other.scope_name
|
|
73
|
+
|
|
74
|
+
def __ne__(self, other):
|
|
75
|
+
return not isinstance(other, Namespace) or self.scope_name != other.scope_name
|
|
76
|
+
|
|
77
|
+
def add_scoped_name(self, scoped_name):
|
|
78
|
+
assert isinstance(scoped_name, tuple)
|
|
79
|
+
scope_name, subscoped_name = scoped_name[0], scoped_name[1:]
|
|
80
|
+
assert isinstance(scope_name, Name)
|
|
81
|
+
scope = scope_name
|
|
82
|
+
if subscoped_name:
|
|
83
|
+
scope = Namespace(scope_name)
|
|
84
|
+
scope.add_scoped_name(subscoped_name)
|
|
85
|
+
if scope_name.name:
|
|
86
|
+
assert scope_name.prename is None
|
|
87
|
+
if scope_name.name in self.names:
|
|
88
|
+
if subscoped_name and isinstance(
|
|
89
|
+
self.names[scope_name.name], Namespace
|
|
90
|
+
):
|
|
91
|
+
self.names[scope_name.name].add_scoped_name(subscoped_name)
|
|
92
|
+
else:
|
|
93
|
+
raise ValueError("Name %s already exists" % scope_name.name)
|
|
94
|
+
else:
|
|
95
|
+
self.names[scope_name.name] = scope
|
|
96
|
+
else:
|
|
97
|
+
assert scope_name.name is None
|
|
98
|
+
self.prenames.setdefault(scope_name.prename, set())
|
|
99
|
+
if subscoped_name:
|
|
100
|
+
for subscope in iter(self.prenames[scope_name.prename]):
|
|
101
|
+
if (
|
|
102
|
+
isinstance(subscope, Namespace)
|
|
103
|
+
and subscope.scope_name is scope_name
|
|
104
|
+
):
|
|
105
|
+
subscope.add_scoped_name(subscoped_name)
|
|
106
|
+
return
|
|
107
|
+
self.prenames[scope_name.prename].add(scope)
|
|
108
|
+
|
|
109
|
+
def assign_names(self):
|
|
110
|
+
# Step 1: assign names to symbols with prenames with no conflicts
|
|
111
|
+
for prename in six.iterkeys(self.prenames):
|
|
112
|
+
if prename is not None:
|
|
113
|
+
if len(self.prenames[prename]) == 1 and prename not in self.names:
|
|
114
|
+
name_object = next(iter(self.prenames[prename]))
|
|
115
|
+
self.names[prename] = name_object
|
|
116
|
+
if isinstance(name_object, Namespace):
|
|
117
|
+
name_object = name_object.scope_name
|
|
118
|
+
name_object.name = prename
|
|
119
|
+
|
|
120
|
+
# Step 2: assign names to symbols with conflicting prenames
|
|
121
|
+
for prename, prename_objects in six.iteritems(self.prenames):
|
|
122
|
+
if prename is not None:
|
|
123
|
+
suffix = 0
|
|
124
|
+
suffixed_name = prename + str(suffix)
|
|
125
|
+
for name_object in iter(prename_objects):
|
|
126
|
+
# Check that the name wasn't already assigned at Step 1
|
|
127
|
+
if name_object.name is None:
|
|
128
|
+
# Generate a non-conflicting name by appending a suffix
|
|
129
|
+
while suffixed_name in self.names:
|
|
130
|
+
suffix += 1
|
|
131
|
+
suffixed_name = prename + str(suffix)
|
|
132
|
+
self.names[suffixed_name] = name_object
|
|
133
|
+
if isinstance(name_object, Namespace):
|
|
134
|
+
name_object = name_object.scope_name
|
|
135
|
+
name_object.name = suffixed_name
|
|
136
|
+
|
|
137
|
+
# Step 3: assign names to symbols without prenames
|
|
138
|
+
if None in self.prenames:
|
|
139
|
+
unnamed_objects = self.prenames[None]
|
|
140
|
+
suffix = 0
|
|
141
|
+
suffixed_name = "__local" + str(suffix)
|
|
142
|
+
for name_object in iter(unnamed_objects):
|
|
143
|
+
# Generate a non-conflicting name by appending a suffix
|
|
144
|
+
while suffixed_name in self.names:
|
|
145
|
+
suffix += 1
|
|
146
|
+
suffixed_name = "__local" + str(suffix)
|
|
147
|
+
self.names[suffixed_name] = name_object
|
|
148
|
+
if isinstance(name_object, Namespace):
|
|
149
|
+
name_object = name_object.scope_name
|
|
150
|
+
name_object.name = suffixed_name
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def name(self):
|
|
155
|
+
return self.scope_name.name
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def prename(self):
|
|
159
|
+
return self.scope_name.prename
|
nervapy/parse.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def parse_assigned_variable_name(stack_frames, constructor_name):
|
|
6
|
+
"""Analyses the provided stack frames and parses Python assignment expressions like
|
|
7
|
+
some.namespace.variable_name = some.module.name.`constructor_name`(...)
|
|
8
|
+
from the caller's call site and returns the name of the variable being assigned as a string.
|
|
9
|
+
If the assignment expression is not found, returns None.
|
|
10
|
+
"""
|
|
11
|
+
if isinstance(stack_frames, list) and len(stack_frames) > 1:
|
|
12
|
+
parent_stack_frame = stack_frames[1]
|
|
13
|
+
if isinstance(parent_stack_frame, tuple) and len(parent_stack_frame) == 6:
|
|
14
|
+
_, _, _, _, source_lines, _ = parent_stack_frame
|
|
15
|
+
if isinstance(source_lines, list) and source_lines:
|
|
16
|
+
source_line = source_lines[0]
|
|
17
|
+
if source_line:
|
|
18
|
+
import re
|
|
19
|
+
|
|
20
|
+
assignment_regexp = (
|
|
21
|
+
r"(?:\w+\.)*(\w+)\s*=\s*(?:\w+\.)*"
|
|
22
|
+
+ re.escape(constructor_name)
|
|
23
|
+
+ r"\(.*\)"
|
|
24
|
+
)
|
|
25
|
+
match = re.match(assignment_regexp, source_line.strip())
|
|
26
|
+
if match:
|
|
27
|
+
return match.group(1)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def parse_with_variable_name(stack_frames, constructor_name):
|
|
31
|
+
"""Analyses the provided stack frames and parses Python with expressions like
|
|
32
|
+
with `constructor_name`(...) as variable_name:
|
|
33
|
+
from the caller's call site and returns the name of the variable named in the statement as a string.
|
|
34
|
+
If a with statement is not found, returns None.
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(stack_frames, list) and len(stack_frames) > 1:
|
|
37
|
+
parent_stack_frame = stack_frames[1]
|
|
38
|
+
if isinstance(parent_stack_frame, tuple) and len(parent_stack_frame) == 6:
|
|
39
|
+
_, _, _, _, source_lines, _ = parent_stack_frame
|
|
40
|
+
if isinstance(source_lines, list) and source_lines:
|
|
41
|
+
source_line = source_lines[0]
|
|
42
|
+
if source_line:
|
|
43
|
+
import re
|
|
44
|
+
|
|
45
|
+
with_regexp = (
|
|
46
|
+
r"with\s+(?:\w+\.)*"
|
|
47
|
+
+ re.escape(constructor_name)
|
|
48
|
+
+ r"\(.*\)\s+as\s+([_a-zA-Z]\w*)\s*:"
|
|
49
|
+
)
|
|
50
|
+
match = re.match(with_regexp, source_line.strip())
|
|
51
|
+
if match:
|
|
52
|
+
return match.group(1)
|
nervapy/stream.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
active_stream = None
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class InstructionStream(object):
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.instructions = list()
|
|
10
|
+
self.previous_stream = None
|
|
11
|
+
|
|
12
|
+
def __enter__(self):
|
|
13
|
+
global active_stream
|
|
14
|
+
self.previous_stream = active_stream
|
|
15
|
+
active_stream = self
|
|
16
|
+
return self
|
|
17
|
+
|
|
18
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
19
|
+
global active_stream
|
|
20
|
+
active_stream = self.previous_stream
|
|
21
|
+
self.previous_stream = None
|
|
22
|
+
|
|
23
|
+
def __iter__(self):
|
|
24
|
+
return iter(self.instructions)
|
|
25
|
+
|
|
26
|
+
def __len__(self):
|
|
27
|
+
return len(self.instructions)
|
|
28
|
+
|
|
29
|
+
def __getitem__(self, i):
|
|
30
|
+
try:
|
|
31
|
+
return self.instructions[i]
|
|
32
|
+
except IndexError:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
def add_instruction(self, instruction):
|
|
36
|
+
if instruction is not None:
|
|
37
|
+
self.instructions.append(instruction)
|
|
38
|
+
|
|
39
|
+
def issue(self, count=1):
|
|
40
|
+
for i in range(count):
|
|
41
|
+
if self.instructions:
|
|
42
|
+
active_stream.add_instruction(self.instructions.pop(0))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class NullStream:
|
|
46
|
+
def __init__(self):
|
|
47
|
+
self.previous_stream = None
|
|
48
|
+
|
|
49
|
+
def __enter__(self):
|
|
50
|
+
global active_stream
|
|
51
|
+
self.previous_stream = active_stream
|
|
52
|
+
active_stream = None
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
56
|
+
global active_stream
|
|
57
|
+
active_stream = self.previous_stream
|
|
58
|
+
self.previous_stream = None
|
nervapy/util.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# This file is part of PeachPy package and is licensed under the Simplified BSD license.
|
|
2
|
+
# See license.rst for the full text of the license.
|
|
3
|
+
|
|
4
|
+
import six
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def int_size(n):
|
|
8
|
+
assert is_int64(n)
|
|
9
|
+
if is_int8(n):
|
|
10
|
+
return 1
|
|
11
|
+
elif is_int16(n):
|
|
12
|
+
return 2
|
|
13
|
+
elif is_int32(n):
|
|
14
|
+
return 4
|
|
15
|
+
else:
|
|
16
|
+
return 8
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_int(n):
|
|
20
|
+
return isinstance(n, six.integer_types)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def is_int64(n):
|
|
24
|
+
return (
|
|
25
|
+
isinstance(n, six.integer_types)
|
|
26
|
+
and -9223372036854775808 <= n <= 18446744073709551615
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_sint64(n):
|
|
31
|
+
return (
|
|
32
|
+
isinstance(n, six.integer_types)
|
|
33
|
+
and -9223372036854775808 <= n <= 9223372036854775807
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_uint64(n):
|
|
38
|
+
return isinstance(n, six.integer_types) and 0 <= n <= 18446744073709551615
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def is_int32(n):
|
|
42
|
+
return isinstance(n, six.integer_types) and -2147483648 <= n <= 4294967295
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def is_sint32(n):
|
|
46
|
+
return isinstance(n, six.integer_types) and -2147483648 <= n <= 2147483647
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def is_uint32(n):
|
|
50
|
+
return isinstance(n, six.integer_types) and 0 <= n <= 4294967295
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def is_int16(n):
|
|
54
|
+
return isinstance(n, six.integer_types) and -32768 <= n <= 65535
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def is_sint16(n):
|
|
58
|
+
return isinstance(n, six.integer_types) and -32768 <= n <= 32767
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def is_uint16(n):
|
|
62
|
+
return isinstance(n, six.integer_types) and 0 <= n <= 65535
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def is_int8(n):
|
|
66
|
+
return isinstance(n, six.integer_types) and -128 <= n <= 255
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def is_uint8(n):
|
|
70
|
+
return isinstance(n, six.integer_types) and 0 <= n <= 255
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def is_sint8(n):
|
|
74
|
+
return isinstance(n, six.integer_types) and -128 <= n <= 127
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def roundup(n, q):
|
|
78
|
+
import math
|
|
79
|
+
|
|
80
|
+
return int(math.ceil(float(n) / float(q)) * q)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def ilog2(n):
|
|
84
|
+
if n & (n - 1) != 0:
|
|
85
|
+
raise ValueError("%u is not an power of 2" % n)
|
|
86
|
+
if n == 0:
|
|
87
|
+
return 0
|
|
88
|
+
else:
|
|
89
|
+
l = 0
|
|
90
|
+
while n != 1:
|
|
91
|
+
l += 1
|
|
92
|
+
n >>= 1
|
|
93
|
+
return l
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def unique(seq):
|
|
97
|
+
seq_values = set()
|
|
98
|
+
unique_seq = []
|
|
99
|
+
for value in seq:
|
|
100
|
+
if value not in seq_values:
|
|
101
|
+
seq_values.add(value)
|
|
102
|
+
unique_seq.append(value)
|
|
103
|
+
return unique_seq
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def append_unique(value, sequence=None):
|
|
107
|
+
if sequence is None:
|
|
108
|
+
return [value]
|
|
109
|
+
else:
|
|
110
|
+
if value not in sequence:
|
|
111
|
+
sequence.append(value)
|
|
112
|
+
return sequence
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def pairwise(iterable):
|
|
116
|
+
import itertools
|
|
117
|
+
|
|
118
|
+
a, b = itertools.tee(iterable)
|
|
119
|
+
next(b, None)
|
|
120
|
+
return itertools.izip(a, b)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def diff(sequence):
|
|
124
|
+
import operator
|
|
125
|
+
|
|
126
|
+
return map(operator.__sub__, pairwise(sequence))
|