mapFolding 0.5.0__py3-none-any.whl → 0.5.1__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.
- mapFolding/__init__.py +93 -58
- mapFolding/basecamp.py +5 -5
- mapFolding/beDRY.py +5 -5
- mapFolding/oeis.py +26 -25
- mapFolding/theSSOT.py +3 -15
- mapFolding/theSSOTdatatypes.py +10 -20
- {mapFolding-0.5.0.dist-info → mapFolding-0.5.1.dist-info}/METADATA +2 -1
- mapFolding-0.5.1.dist-info/RECORD +14 -0
- {mapFolding-0.5.0.dist-info → mapFolding-0.5.1.dist-info}/top_level.txt +0 -1
- mapFolding/reference/flattened.py +0 -377
- mapFolding/reference/hunterNumba.py +0 -132
- mapFolding/reference/irvineJavaPort.py +0 -120
- mapFolding/reference/jax.py +0 -208
- mapFolding/reference/lunnan.py +0 -153
- mapFolding/reference/lunnanNumpy.py +0 -123
- mapFolding/reference/lunnanWhile.py +0 -121
- mapFolding/reference/rotatedEntryPoint.py +0 -240
- mapFolding/reference/total_countPlus1vsPlusN.py +0 -211
- mapFolding/someAssemblyRequired/__init__.py +0 -5
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -19
- mapFolding/someAssemblyRequired/makeJob.py +0 -56
- mapFolding/someAssemblyRequired/synthesizeModuleJAX.py +0 -27
- mapFolding/someAssemblyRequired/synthesizeNumba.py +0 -345
- mapFolding/someAssemblyRequired/synthesizeNumbaGeneralized.py +0 -397
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +0 -155
- mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +0 -123
- mapFolding/syntheticModules/numbaCount.py +0 -158
- mapFolding/syntheticModules/numba_doTheNeedful.py +0 -13
- mapFolding-0.5.0.dist-info/RECORD +0 -39
- tests/__init__.py +0 -1
- tests/conftest.py +0 -335
- tests/test_computations.py +0 -42
- tests/test_oeis.py +0 -128
- tests/test_other.py +0 -175
- tests/test_tasks.py +0 -40
- /mapFolding/{syntheticModules/__init__.py → py.typed} +0 -0
- {mapFolding-0.5.0.dist-info → mapFolding-0.5.1.dist-info}/LICENSE +0 -0
- {mapFolding-0.5.0.dist-info → mapFolding-0.5.1.dist-info}/WHEEL +0 -0
- {mapFolding-0.5.0.dist-info → mapFolding-0.5.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
from mapFolding import (
|
|
2
|
-
computationState,
|
|
3
|
-
EnumIndices,
|
|
4
|
-
formatFilenameModuleDEFAULT,
|
|
5
|
-
FREAKOUT,
|
|
6
|
-
getAlgorithmDispatcher,
|
|
7
|
-
getAlgorithmSource,
|
|
8
|
-
getFilenameFoldsTotal,
|
|
9
|
-
getPathFilenameFoldsTotal,
|
|
10
|
-
getPathJobRootDEFAULT,
|
|
11
|
-
getPathPackage,
|
|
12
|
-
getPathSyntheticModules,
|
|
13
|
-
hackSSOTdatatype,
|
|
14
|
-
indexMy,
|
|
15
|
-
indexTrack,
|
|
16
|
-
moduleOfSyntheticModules,
|
|
17
|
-
myPackageNameIs,
|
|
18
|
-
ParametersNumba,
|
|
19
|
-
parametersNumbaDEFAULT,
|
|
20
|
-
parametersNumbaFailEarly,
|
|
21
|
-
parametersNumbaMinimum,
|
|
22
|
-
parametersNumbaSuperJit,
|
|
23
|
-
parametersNumbaSuperJitParallel,
|
|
24
|
-
setDatatypeElephino,
|
|
25
|
-
setDatatypeFoldsTotal,
|
|
26
|
-
setDatatypeLeavesTotal,
|
|
27
|
-
setDatatypeModule,
|
|
28
|
-
Z0Z_getDatatypeModuleScalar,
|
|
29
|
-
Z0Z_getDecoratorCallable,
|
|
30
|
-
Z0Z_identifierCountFolds,
|
|
31
|
-
Z0Z_setDatatypeModuleScalar,
|
|
32
|
-
Z0Z_setDecoratorCallable,
|
|
33
|
-
)
|
|
34
|
-
from mapFolding.someAssemblyRequired.makeJob import makeStateJob
|
|
35
|
-
from numpy import integer
|
|
36
|
-
from numpy.typing import NDArray
|
|
37
|
-
from types import ModuleType
|
|
38
|
-
from collections.abc import Callable, Sequence
|
|
39
|
-
from typing import Any, cast
|
|
40
|
-
from Z0Z_tools import autoDecodingRLE, updateExtendPolishDictionaryLists
|
|
41
|
-
import ast
|
|
42
|
-
import autoflake
|
|
43
|
-
import collections
|
|
44
|
-
import copy
|
|
45
|
-
import importlib.util
|
|
46
|
-
import inspect
|
|
47
|
-
import more_itertools
|
|
48
|
-
import numba
|
|
49
|
-
import numpy
|
|
50
|
-
from os import PathLike
|
|
51
|
-
from pathlib import Path
|
|
52
|
-
import python_minifier
|
|
53
|
-
import warnings
|
|
54
|
-
|
|
55
|
-
youOughtaKnow = collections.namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
|
|
56
|
-
|
|
57
|
-
# idk how to use this
|
|
58
|
-
class ASTBodyTransformer:
|
|
59
|
-
"""
|
|
60
|
-
A helper class to apply multiple transformations on an AST FunctionDef's body.
|
|
61
|
-
This abstraction eliminates the need to write repetitive loops for removals,
|
|
62
|
-
replacements, or insertions.
|
|
63
|
-
"""
|
|
64
|
-
def __init__(self, functionDefinition: ast.FunctionDef) -> None:
|
|
65
|
-
self.functionDefinition = functionDefinition
|
|
66
|
-
|
|
67
|
-
def replaceIn_body(self, predicate: Callable[[ast.stmt], bool], replacementBuilder: Callable[[ast.stmt], ast.stmt | None]) -> None:
|
|
68
|
-
newBody: list[ast.stmt] = []
|
|
69
|
-
for statement in self.functionDefinition.body:
|
|
70
|
-
if predicate(statement):
|
|
71
|
-
replacementStatement = replacementBuilder(statement)
|
|
72
|
-
if replacementStatement is not None:
|
|
73
|
-
newBody.append(replacementStatement)
|
|
74
|
-
else:
|
|
75
|
-
newBody.append(statement)
|
|
76
|
-
self.functionDefinition.body = newBody
|
|
77
|
-
|
|
78
|
-
def atIndexInsert(self, index: int, statement: ast.stmt) -> None:
|
|
79
|
-
self.functionDefinition.body.insert(index, statement)
|
|
80
|
-
|
|
81
|
-
def removeAllOf(self, predicate: Callable[[ast.stmt], bool]) -> None:
|
|
82
|
-
self.replaceIn_body(predicate, lambda stmt: None)
|
|
83
|
-
|
|
84
|
-
def Z0Z_apply(self) -> ast.FunctionDef:
|
|
85
|
-
ast.fix_missing_locations(self.functionDefinition)
|
|
86
|
-
return self.functionDefinition
|
|
87
|
-
|
|
88
|
-
# Generic
|
|
89
|
-
class ifThis:
|
|
90
|
-
"""Generic AST node predicate builder."""
|
|
91
|
-
@staticmethod
|
|
92
|
-
def nameIs(allegedly: str) -> Callable[[ast.AST], bool]:
|
|
93
|
-
return lambda node: (isinstance(node, ast.Name) and node.id == allegedly)
|
|
94
|
-
|
|
95
|
-
@staticmethod
|
|
96
|
-
def isCallWithAttribute(moduleName: str, callableName: str) -> Callable[[ast.AST], bool]:
|
|
97
|
-
return lambda node: (isinstance(node, ast.Call)
|
|
98
|
-
and isinstance(node.func, ast.Attribute)
|
|
99
|
-
and isinstance(node.func.value, ast.Name)
|
|
100
|
-
and node.func.value.id == moduleName
|
|
101
|
-
and node.func.attr == callableName)
|
|
102
|
-
|
|
103
|
-
@staticmethod
|
|
104
|
-
def isCallWithName(callableName: str) -> Callable[[ast.AST], bool]:
|
|
105
|
-
return lambda node: (isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == callableName)
|
|
106
|
-
|
|
107
|
-
@staticmethod
|
|
108
|
-
def isAssignTarget(identifier: str):
|
|
109
|
-
return lambda node: (isinstance(node, ast.Assign)
|
|
110
|
-
and node.targets
|
|
111
|
-
and isinstance(node.targets[0], ast.Name)
|
|
112
|
-
and node.targets[0].id == identifier)
|
|
113
|
-
|
|
114
|
-
@staticmethod
|
|
115
|
-
def anyOf(*predicates: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
116
|
-
return lambda node: any(pred(node) for pred in predicates)
|
|
117
|
-
|
|
118
|
-
@staticmethod
|
|
119
|
-
def isUnpackingAnArray(identifier:str):
|
|
120
|
-
return lambda node: (isinstance(node, ast.Assign)
|
|
121
|
-
and isinstance(node.targets[0], ast.Name)
|
|
122
|
-
and isinstance(node.value, ast.Subscript)
|
|
123
|
-
and isinstance(node.value.value, ast.Name)
|
|
124
|
-
and node.value.value.id == identifier
|
|
125
|
-
and isinstance(node.value.slice, ast.Attribute)
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
class Then:
|
|
129
|
-
"""Generic actions."""
|
|
130
|
-
@staticmethod
|
|
131
|
-
def copy_astCallKeywords(astCall: ast.Call) -> dict[str, Any]:
|
|
132
|
-
"""Extract keyword parameters from a decorator AST node."""
|
|
133
|
-
dictionaryKeywords: dict[str, Any] = {}
|
|
134
|
-
for keywordItem in astCall.keywords:
|
|
135
|
-
if isinstance(keywordItem.value, ast.Constant) and keywordItem.arg is not None:
|
|
136
|
-
dictionaryKeywords[keywordItem.arg] = keywordItem.value.value
|
|
137
|
-
return dictionaryKeywords
|
|
138
|
-
|
|
139
|
-
@staticmethod
|
|
140
|
-
def make_astCall(name: str, args: Sequence[ast.expr] | None = None, list_astKeywords: Sequence[ast.keyword] | None = None, dictionaryKeywords: dict[str, Any] | None = None) -> ast.Call:
|
|
141
|
-
list_dictionaryKeywords = [ast.keyword(arg=keyName, value=ast.Constant(value=keyValue)) for keyName, keyValue in dictionaryKeywords.items()] if dictionaryKeywords else []
|
|
142
|
-
return ast.Call(
|
|
143
|
-
func=ast.Name(id=name, ctx=ast.Load()),
|
|
144
|
-
args=list(args) if args else [],
|
|
145
|
-
keywords=list_dictionaryKeywords + list(list_astKeywords) if list_astKeywords else [],
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
class NodeReplacer(ast.NodeTransformer):
|
|
149
|
-
"""
|
|
150
|
-
A node transformer that replaces or removes AST nodes based on a condition.
|
|
151
|
-
This transformer traverses an AST and for each node checks a predicate. If the predicate
|
|
152
|
-
returns True, the transformer uses the replacement builder to obtain a new node. Returning
|
|
153
|
-
None from the replacement builder indicates that the node should be removed.
|
|
154
|
-
|
|
155
|
-
Attributes:
|
|
156
|
-
findMe: A function that determines whether a node should be replaced.
|
|
157
|
-
nodeReplacementBuilder: A function that returns a new node or None to remove the node.
|
|
158
|
-
|
|
159
|
-
Methods:
|
|
160
|
-
visit(node: ast.AST) -> Optional[ast.AST]:
|
|
161
|
-
Visits each node in the AST, replacing or removing it based on the predicate.
|
|
162
|
-
"""
|
|
163
|
-
def __init__(self, findMe: Callable[[ast.AST], bool], nodeReplacementBuilder: Callable[[ast.AST], ast.AST | None]) -> None:
|
|
164
|
-
self.findMe = findMe
|
|
165
|
-
self.nodeReplacementBuilder = nodeReplacementBuilder
|
|
166
|
-
|
|
167
|
-
def visit(self, node: ast.AST) -> ast.AST | None | Any:
|
|
168
|
-
if self.findMe(node):
|
|
169
|
-
return self.nodeReplacementBuilder(node)
|
|
170
|
-
return super().visit(node)
|
|
171
|
-
|
|
172
|
-
# Confusing: suspiciously specific but still reusable
|
|
173
|
-
def thisIsNumbaDotJit(Ima: ast.AST) -> bool:
|
|
174
|
-
return ifThis.isCallWithAttribute(Z0Z_getDatatypeModuleScalar(), Z0Z_getDecoratorCallable())(Ima)
|
|
175
|
-
|
|
176
|
-
def thisIsJit(Ima: ast.AST) -> bool:
|
|
177
|
-
return ifThis.isCallWithName(Z0Z_getDecoratorCallable())(Ima)
|
|
178
|
-
|
|
179
|
-
def thisIsAnyNumbaJitDecorator(Ima: ast.AST) -> bool:
|
|
180
|
-
return thisIsNumbaDotJit(Ima) or thisIsJit(Ima)
|
|
181
|
-
|
|
182
|
-
# Domain-based
|
|
183
|
-
class UniversalImportTracker:
|
|
184
|
-
def __init__(self) -> None:
|
|
185
|
-
self.dictionaryImportFrom: dict[str, set] = collections.defaultdict(set)
|
|
186
|
-
self.setImport = set()
|
|
187
|
-
|
|
188
|
-
def addAst(self, astImport_: ast.Import | ast.ImportFrom) -> None:
|
|
189
|
-
if isinstance(astImport_, ast.Import):
|
|
190
|
-
for alias in astImport_.names:
|
|
191
|
-
self.setImport.add(alias.name)
|
|
192
|
-
elif isinstance(astImport_, ast.ImportFrom):
|
|
193
|
-
if astImport_.module is not None:
|
|
194
|
-
self.dictionaryImportFrom[astImport_.module].update((alias.name, alias.asname) for alias in astImport_.names)
|
|
195
|
-
|
|
196
|
-
def addImportStr(self, module: str) -> None:
|
|
197
|
-
self.setImport.add(module)
|
|
198
|
-
|
|
199
|
-
def addImportFromStr(self, module: str, name: str, asname: str | None = None) -> None:
|
|
200
|
-
self.dictionaryImportFrom[module].add((name, asname))
|
|
201
|
-
|
|
202
|
-
def makeListAst(self) -> list[ast.ImportFrom | ast.Import]:
|
|
203
|
-
listAstImportFrom = []
|
|
204
|
-
for module, setOfNameTuples in sorted(self.dictionaryImportFrom.items()):
|
|
205
|
-
listAliases = []
|
|
206
|
-
for name, asname in setOfNameTuples:
|
|
207
|
-
listAliases.append(ast.alias(name=name, asname=asname))
|
|
208
|
-
listAstImportFrom.append(ast.ImportFrom(module=module, names=listAliases, level=0))
|
|
209
|
-
|
|
210
|
-
listAstImport = [ast.Import(names=[ast.alias(name=name, asname=None)]) for name in sorted(self.setImport)]
|
|
211
|
-
return listAstImportFrom + listAstImport
|
|
212
|
-
|
|
213
|
-
def update(self, *fromTracker: 'UniversalImportTracker') -> None:
|
|
214
|
-
"""
|
|
215
|
-
Update this tracker with imports from one or more other trackers.
|
|
216
|
-
|
|
217
|
-
Parameters:
|
|
218
|
-
*fromTracker: One or more UniversalImportTracker objects to merge from.
|
|
219
|
-
"""
|
|
220
|
-
# Merge all import-from dictionaries
|
|
221
|
-
dictionaryMerged = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(tracker.dictionaryImportFrom for tracker in fromTracker), destroyDuplicates=True, reorderLists=True)
|
|
222
|
-
|
|
223
|
-
# Convert lists back to sets for each module's imports
|
|
224
|
-
self.dictionaryImportFrom = {module: set(listNames) for module, listNames in dictionaryMerged.items()}
|
|
225
|
-
|
|
226
|
-
# Update direct imports
|
|
227
|
-
for tracker in fromTracker:
|
|
228
|
-
self.setImport.update(tracker.setImport)
|
|
229
|
-
|
|
230
|
-
# Intricate and specialized
|
|
231
|
-
class RecursiveInliner(ast.NodeTransformer):
|
|
232
|
-
"""
|
|
233
|
-
Class RecursiveInliner:
|
|
234
|
-
A custom AST NodeTransformer designed to recursively inline function calls from a given dictionary
|
|
235
|
-
of function definitions into the AST. Once a particular function has been inlined, it is marked
|
|
236
|
-
as completed to avoid repeated inlining. This transformation modifies the AST in-place by substituting
|
|
237
|
-
eligible function calls with the body of their corresponding function.
|
|
238
|
-
Attributes:
|
|
239
|
-
dictionaryFunctions (Dict[str, ast.FunctionDef]):
|
|
240
|
-
A mapping of function name to its AST definition, used as a source for inlining.
|
|
241
|
-
callablesCompleted (Set[str]):
|
|
242
|
-
A set to track function names that have already been inlined to prevent multiple expansions.
|
|
243
|
-
Methods:
|
|
244
|
-
inlineFunctionBody(callableTargetName: str) -> Optional[ast.FunctionDef]:
|
|
245
|
-
Retrieves the AST definition for a given function name from dictionaryFunctions
|
|
246
|
-
and recursively inlines any function calls within it. Returns the function definition
|
|
247
|
-
that was inlined or None if the function was already processed.
|
|
248
|
-
visit_Call(callNode: ast.Call) -> ast.AST:
|
|
249
|
-
Inspects calls within the AST. If a function call matches one in dictionaryFunctions,
|
|
250
|
-
it is replaced by the inlined body. If the last statement in the inlined body is a return
|
|
251
|
-
or an expression, that value or expression is substituted; otherwise, a constant is returned.
|
|
252
|
-
visit_Expr(node: ast.Expr) -> Union[ast.AST, List[ast.AST]]:
|
|
253
|
-
Handles expression nodes in the AST. If the expression is a function call from
|
|
254
|
-
dictionaryFunctions, its statements are expanded in place, effectively inlining
|
|
255
|
-
the called function's statements into the surrounding context.
|
|
256
|
-
"""
|
|
257
|
-
def __init__(self, dictionaryFunctions: dict[str, ast.FunctionDef]):
|
|
258
|
-
self.dictionaryFunctions = dictionaryFunctions
|
|
259
|
-
self.callablesCompleted: set[str] = set()
|
|
260
|
-
|
|
261
|
-
def inlineFunctionBody(self, callableTargetName: str) -> ast.FunctionDef | None:
|
|
262
|
-
if (callableTargetName in self.callablesCompleted):
|
|
263
|
-
return None
|
|
264
|
-
|
|
265
|
-
self.callablesCompleted.add(callableTargetName)
|
|
266
|
-
inlineDefinition = self.dictionaryFunctions[callableTargetName]
|
|
267
|
-
for astNode in ast.walk(inlineDefinition):
|
|
268
|
-
self.visit(astNode)
|
|
269
|
-
return inlineDefinition
|
|
270
|
-
|
|
271
|
-
def visit_Call(self, node: ast.Call) -> Any | ast.Constant | ast.Call | ast.AST:
|
|
272
|
-
callNodeVisited = self.generic_visit(node)
|
|
273
|
-
if (isinstance(callNodeVisited, ast.Call) and isinstance(callNodeVisited.func, ast.Name) and callNodeVisited.func.id in self.dictionaryFunctions):
|
|
274
|
-
inlineDefinition = self.inlineFunctionBody(callNodeVisited.func.id)
|
|
275
|
-
if (inlineDefinition and inlineDefinition.body):
|
|
276
|
-
statementTerminating = inlineDefinition.body[-1]
|
|
277
|
-
if (isinstance(statementTerminating, ast.Return) and statementTerminating.value is not None):
|
|
278
|
-
return self.visit(statementTerminating.value)
|
|
279
|
-
elif (isinstance(statementTerminating, ast.Expr) and statementTerminating.value is not None):
|
|
280
|
-
return self.visit(statementTerminating.value)
|
|
281
|
-
return ast.Constant(value=None)
|
|
282
|
-
return callNodeVisited
|
|
283
|
-
|
|
284
|
-
def visit_Expr(self, node: ast.Expr) -> ast.AST | list[ast.AST]:
|
|
285
|
-
if (isinstance(node.value, ast.Call)):
|
|
286
|
-
if (isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions):
|
|
287
|
-
inlineDefinition = self.inlineFunctionBody(node.value.func.id)
|
|
288
|
-
if (inlineDefinition):
|
|
289
|
-
return [self.visit(stmt) for stmt in inlineDefinition.body]
|
|
290
|
-
return self.generic_visit(node)
|
|
291
|
-
|
|
292
|
-
class UnpackArrays(ast.NodeTransformer):
|
|
293
|
-
"""
|
|
294
|
-
A class that transforms array accesses using enum indices into local variables.
|
|
295
|
-
|
|
296
|
-
This AST transformer identifies array accesses using enum indices and replaces them
|
|
297
|
-
with local variables, adding initialization statements at the start of functions.
|
|
298
|
-
|
|
299
|
-
Parameters:
|
|
300
|
-
enumIndexClass (Type[EnumIndices]): The enum class used for array indexing
|
|
301
|
-
arrayName (str): The name of the array being accessed
|
|
302
|
-
|
|
303
|
-
Attributes:
|
|
304
|
-
enumIndexClass (Type[EnumIndices]): Stored enum class for index lookups
|
|
305
|
-
arrayName (str): Name of the array being transformed
|
|
306
|
-
substitutions (dict): Tracks variable substitutions and their original nodes
|
|
307
|
-
|
|
308
|
-
The transformer handles two main cases:
|
|
309
|
-
1. Scalar array access - array[EnumIndices.MEMBER]
|
|
310
|
-
2. Array slice access - array[EnumIndices.MEMBER, other_indices...]
|
|
311
|
-
For each identified access pattern, it:
|
|
312
|
-
1. Creates a local variable named after the enum member
|
|
313
|
-
2. Adds initialization code at function start
|
|
314
|
-
3. Replaces original array access with the local variable
|
|
315
|
-
"""
|
|
316
|
-
|
|
317
|
-
def __init__(self, enumIndexClass: type[EnumIndices], arrayName: str) -> None:
|
|
318
|
-
self.enumIndexClass = enumIndexClass
|
|
319
|
-
self.arrayName = arrayName
|
|
320
|
-
self.substitutions: dict[str, Any] = {}
|
|
321
|
-
|
|
322
|
-
def extract_member_name(self, node: ast.AST) -> str | None:
|
|
323
|
-
"""Recursively extract enum member name from any node in the AST."""
|
|
324
|
-
if isinstance(node, ast.Attribute) and node.attr == 'value':
|
|
325
|
-
innerAttribute = node.value
|
|
326
|
-
while isinstance(innerAttribute, ast.Attribute):
|
|
327
|
-
if (isinstance(innerAttribute.value, ast.Name) and innerAttribute.value.id == self.enumIndexClass.__name__):
|
|
328
|
-
return innerAttribute.attr
|
|
329
|
-
innerAttribute = innerAttribute.value
|
|
330
|
-
return None
|
|
331
|
-
|
|
332
|
-
def transform_slice_element(self, node: ast.AST) -> ast.AST:
|
|
333
|
-
"""Transform any enum references within a slice element."""
|
|
334
|
-
if isinstance(node, ast.Subscript):
|
|
335
|
-
if isinstance(node.slice, ast.Attribute):
|
|
336
|
-
member_name = self.extract_member_name(node.slice)
|
|
337
|
-
if member_name:
|
|
338
|
-
return ast.Name(id=member_name, ctx=node.ctx)
|
|
339
|
-
elif isinstance(node, ast.Tuple):
|
|
340
|
-
# Handle tuple slices by transforming each element
|
|
341
|
-
return ast.Tuple(elts=cast(list[ast.expr], [self.transform_slice_element(elt) for elt in node.elts]), ctx=node.ctx)
|
|
342
|
-
elif isinstance(node, ast.Attribute):
|
|
343
|
-
member_name = self.extract_member_name(node)
|
|
344
|
-
if member_name:
|
|
345
|
-
return ast.Name(id=member_name, ctx=ast.Load())
|
|
346
|
-
return node
|
|
347
|
-
|
|
348
|
-
def visit_Subscript(self, node: ast.Subscript) -> ast.AST:
|
|
349
|
-
# Recursively visit any nested subscripts in value or slice
|
|
350
|
-
node.value = self.visit(node.value)
|
|
351
|
-
node.slice = self.visit(node.slice)
|
|
352
|
-
# If node.value is not our arrayName, just return node
|
|
353
|
-
if not (isinstance(node.value, ast.Name) and node.value.id == self.arrayName):
|
|
354
|
-
return node
|
|
355
|
-
|
|
356
|
-
# Handle scalar array access
|
|
357
|
-
if isinstance(node.slice, ast.Attribute):
|
|
358
|
-
memberName = self.extract_member_name(node.slice)
|
|
359
|
-
if memberName:
|
|
360
|
-
self.substitutions[memberName] = ('scalar', node)
|
|
361
|
-
return ast.Name(id=memberName, ctx=ast.Load())
|
|
362
|
-
|
|
363
|
-
# Handle array slice access
|
|
364
|
-
if isinstance(node.slice, ast.Tuple) and node.slice.elts:
|
|
365
|
-
firstElement = node.slice.elts[0]
|
|
366
|
-
memberName = self.extract_member_name(firstElement)
|
|
367
|
-
sliceRemainder = [self.visit(elem) for elem in node.slice.elts[1:]]
|
|
368
|
-
if memberName:
|
|
369
|
-
self.substitutions[memberName] = ('array', node)
|
|
370
|
-
if len(sliceRemainder) == 0:
|
|
371
|
-
return ast.Name(id=memberName, ctx=ast.Load())
|
|
372
|
-
return ast.Subscript(value=ast.Name(id=memberName, ctx=ast.Load()), slice=ast.Tuple(elts=sliceRemainder, ctx=ast.Load()) if len(sliceRemainder) > 1 else sliceRemainder[0], ctx=ast.Load())
|
|
373
|
-
|
|
374
|
-
# If single-element tuple, unwrap
|
|
375
|
-
if isinstance(node.slice, ast.Tuple) and len(node.slice.elts) == 1:
|
|
376
|
-
node.slice = node.slice.elts[0]
|
|
377
|
-
|
|
378
|
-
return node
|
|
379
|
-
|
|
380
|
-
def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.FunctionDef:
|
|
381
|
-
node = cast(ast.FunctionDef, self.generic_visit(node))
|
|
382
|
-
|
|
383
|
-
initializations = []
|
|
384
|
-
for name, (kind, original_node) in self.substitutions.items():
|
|
385
|
-
if kind == 'scalar':
|
|
386
|
-
initializations.append(ast.Assign(targets=[ast.Name(id=name, ctx=ast.Store())], value=original_node))
|
|
387
|
-
else: # array
|
|
388
|
-
initializations.append(
|
|
389
|
-
ast.Assign(
|
|
390
|
-
targets=[ast.Name(id=name, ctx=ast.Store())],
|
|
391
|
-
value=ast.Subscript(value=ast.Name(id=self.arrayName, ctx=ast.Load()),
|
|
392
|
-
slice=ast.Attribute(value=ast.Attribute(
|
|
393
|
-
value=ast.Name(id=self.enumIndexClass.__name__, ctx=ast.Load()),
|
|
394
|
-
attr=name, ctx=ast.Load()), attr='value', ctx=ast.Load()), ctx=ast.Load())))
|
|
395
|
-
|
|
396
|
-
node.body = initializations + node.body
|
|
397
|
-
return node
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
"""Synthesize one file to compute `foldsTotal` of `mapShape`."""
|
|
2
|
-
from mapFolding.someAssemblyRequired.synthesizeNumba import *
|
|
3
|
-
|
|
4
|
-
def doUnrollCountGaps(FunctionDefTarget: ast.FunctionDef, stateJob: computationState, allImports: UniversalImportTracker) -> tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
5
|
-
"""The initial results were very bad."""
|
|
6
|
-
FunctionDefTarget = findAndReplaceWhileLoopIn_body(FunctionDefTarget, 'indexDimension', stateJob['my'][indexMy.dimensionsTotal])
|
|
7
|
-
FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, 'indexDimension')
|
|
8
|
-
FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, 'connectionGraph')
|
|
9
|
-
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, 'connectionGraph', stateJob['connectionGraph'], allImports, stateJob['my'][indexMy.dimensionsTotal])
|
|
10
|
-
for index in range(stateJob['my'][indexMy.dimensionsTotal]):
|
|
11
|
-
class ReplaceConnectionGraph(ast.NodeTransformer):
|
|
12
|
-
def visit_Subscript(self, node: ast.Subscript) -> ast.AST:
|
|
13
|
-
node = cast(ast.Subscript, self.generic_visit(node))
|
|
14
|
-
if (isinstance(node.value, ast.Name) and node.value.id == "connectionGraph" and
|
|
15
|
-
isinstance(node.slice, ast.Tuple) and len(node.slice.elts) >= 1):
|
|
16
|
-
firstElement = node.slice.elts[0]
|
|
17
|
-
if isinstance(firstElement, ast.Constant) and firstElement.value == index:
|
|
18
|
-
newName = ast.Name(id=f"connectionGraph_{index}", ctx=ast.Load())
|
|
19
|
-
remainingIndices = node.slice.elts[1:]
|
|
20
|
-
if len(remainingIndices) == 1:
|
|
21
|
-
newSlice = remainingIndices[0]
|
|
22
|
-
else:
|
|
23
|
-
newSlice = ast.Tuple(elts=remainingIndices, ctx=ast.Load())
|
|
24
|
-
return ast.copy_location(ast.Subscript(value=newName, slice=newSlice, ctx=node.ctx), node)
|
|
25
|
-
return node
|
|
26
|
-
transformer = ReplaceConnectionGraph()
|
|
27
|
-
FunctionDefTarget = transformer.visit(FunctionDefTarget)
|
|
28
|
-
return FunctionDefTarget, allImports
|
|
29
|
-
|
|
30
|
-
def writeJobNumba(mapShape: Sequence[int], algorithmSource: ModuleType, callableTarget: str | None = None, parametersNumba: ParametersNumba | None = None, pathFilenameWriteJob: str | PathLike[str] | None = None, unrollCountGaps: bool | None = False, **keywordArguments: Any | None) -> Path:
|
|
31
|
-
""" Parameters: **keywordArguments: most especially for `computationDivisions` if you want to make a parallel job. Also `CPUlimit`. """
|
|
32
|
-
|
|
33
|
-
""" Notes:
|
|
34
|
-
Hypothetically, everything can now be configured with parameters and functions. And changing how the job is written is relatively easy.
|
|
35
|
-
|
|
36
|
-
Overview
|
|
37
|
-
- the code starts life in theDao.py, which has many optimizations; `makeNumbaOptimizedFlow` increase optimization especially by using numba; `writeJobNumba` increases optimization especially by limiting its capabilities to just one set of parameters
|
|
38
|
-
- the synthesized module must run well as a standalone interpreted-Python script
|
|
39
|
-
- the next major optimization step will (probably) be to use the module synthesized by `writeJobNumba` to compile a standalone executable
|
|
40
|
-
- Nevertheless, at each major optimization step, the code is constantly being improved and optimized, so everything must be well organized and able to handle upstream and downstream changes
|
|
41
|
-
|
|
42
|
-
Minutia
|
|
43
|
-
- perf_counter is for testing. When I run a real job, I delete those lines
|
|
44
|
-
- avoid `with` statement
|
|
45
|
-
|
|
46
|
-
Necessary
|
|
47
|
-
- Move the function's parameters to the function body,
|
|
48
|
-
- initialize identifiers with their state types and values,
|
|
49
|
-
|
|
50
|
-
Optimizations
|
|
51
|
-
- replace static-valued identifiers with their values
|
|
52
|
-
- narrowly focused imports
|
|
53
|
-
"""
|
|
54
|
-
|
|
55
|
-
# NOTE get the raw ingredients: data and the algorithm
|
|
56
|
-
stateJob = makeStateJob(mapShape, writeJob=False, **keywordArguments)
|
|
57
|
-
pythonSource = inspect.getsource(algorithmSource)
|
|
58
|
-
astModule = ast.parse(pythonSource)
|
|
59
|
-
setFunctionDef = {statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
|
|
60
|
-
|
|
61
|
-
if not callableTarget:
|
|
62
|
-
if len(setFunctionDef) == 1:
|
|
63
|
-
FunctionDefTarget = setFunctionDef.pop()
|
|
64
|
-
callableTarget = FunctionDefTarget.name
|
|
65
|
-
else:
|
|
66
|
-
raise ValueError(f"I did not receive a `callableTarget` and {algorithmSource.__name__=} has more than one callable: {setFunctionDef}. Please select one.")
|
|
67
|
-
else:
|
|
68
|
-
listFunctionDefTarget = [statement for statement in setFunctionDef if statement.name == callableTarget]
|
|
69
|
-
FunctionDefTarget = listFunctionDefTarget[0] if listFunctionDefTarget else None
|
|
70
|
-
if not FunctionDefTarget: raise ValueError(f"I received `{callableTarget=}` and {algorithmSource.__name__=}, but I could not find that function in that source.")
|
|
71
|
-
|
|
72
|
-
# NOTE `allImports` is a complementary container to `FunctionDefTarget`; the `FunctionDefTarget` cannot track its own imports very well.
|
|
73
|
-
allImports = UniversalImportTracker()
|
|
74
|
-
for statement in astModule.body:
|
|
75
|
-
if isinstance(statement, (ast.Import, ast.ImportFrom)):
|
|
76
|
-
allImports.addAst(statement)
|
|
77
|
-
|
|
78
|
-
# NOTE remove the parameters from the function signature
|
|
79
|
-
for pirateScowl in FunctionDefTarget.args.args.copy():
|
|
80
|
-
match pirateScowl.arg:
|
|
81
|
-
case 'my':
|
|
82
|
-
FunctionDefTarget, allImports = findAndReplaceArraySubscriptIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], ['taskIndex', 'dimensionsTotal'], allImports)
|
|
83
|
-
case 'track':
|
|
84
|
-
FunctionDefTarget, allImports = findAndReplaceTrackArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
85
|
-
case 'connectionGraph':
|
|
86
|
-
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
87
|
-
case 'gapsWhere':
|
|
88
|
-
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
89
|
-
case 'foldGroups':
|
|
90
|
-
FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, pirateScowl.arg)
|
|
91
|
-
# FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
92
|
-
# continue
|
|
93
|
-
FunctionDefTarget.args.args.remove(pirateScowl)
|
|
94
|
-
|
|
95
|
-
# NOTE replace identifiers with static values with their values
|
|
96
|
-
FunctionDefTarget, allImports = findAndReplaceAnnAssignIn_body(FunctionDefTarget, allImports)
|
|
97
|
-
FunctionDefTarget = findAstNameReplaceWithConstantIn_body(FunctionDefTarget, 'dimensionsTotal', int(stateJob['my'][indexMy.dimensionsTotal]))
|
|
98
|
-
FunctionDefTarget = findThingyReplaceWithConstantIn_body(FunctionDefTarget, 'foldGroups[-1]', int(stateJob['foldGroups'][-1]))
|
|
99
|
-
|
|
100
|
-
# NOTE an attempt at optimization
|
|
101
|
-
if unrollCountGaps:
|
|
102
|
-
FunctionDefTarget, allImports = doUnrollCountGaps(FunctionDefTarget, stateJob, allImports)
|
|
103
|
-
|
|
104
|
-
# NOTE starting the count and printing the total
|
|
105
|
-
pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateJob['mapShape'])
|
|
106
|
-
astLauncher = makeLauncherBasicJobNumba(FunctionDefTarget.name, pathFilenameFoldsTotal)
|
|
107
|
-
FunctionDefTarget, allImports = insertReturnStatementIn_body(FunctionDefTarget, stateJob['foldGroups'], allImports)
|
|
108
|
-
|
|
109
|
-
# NOTE add the perfect decorator
|
|
110
|
-
FunctionDefTarget, allImports = decorateCallableWithNumba(FunctionDefTarget, allImports, parametersNumba)
|
|
111
|
-
if thisIsNumbaDotJit(FunctionDefTarget.decorator_list[0]):
|
|
112
|
-
astCall = cast(ast.Call, FunctionDefTarget.decorator_list[0])
|
|
113
|
-
astCall.func = ast.Name(id=Z0Z_getDecoratorCallable(), ctx=ast.Load())
|
|
114
|
-
FunctionDefTarget.decorator_list[0] = astCall
|
|
115
|
-
|
|
116
|
-
# NOTE add imports, make str, remove unused imports
|
|
117
|
-
astImports = allImports.makeListAst()
|
|
118
|
-
astModule = ast.Module(body=cast(list[ast.stmt], astImports + [FunctionDefTarget] + [astLauncher]), type_ignores=[])
|
|
119
|
-
ast.fix_missing_locations(astModule)
|
|
120
|
-
pythonSource = ast.unparse(astModule)
|
|
121
|
-
pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
|
|
122
|
-
# pythonSource = python_minifier.minify(pythonSource, remove_annotations = False, remove_pass = False, remove_literal_statements = False, combine_imports = True, hoist_literals = False, rename_locals = False, rename_globals = False, remove_object_base = False, convert_posargs_to_args = False, preserve_shebang = True, remove_asserts = False, remove_debug = False, remove_explicit_return_none = False, remove_builtin_exception_brackets = False, constant_folding = False)
|
|
123
|
-
|
|
124
|
-
# NOTE put on disk
|
|
125
|
-
if pathFilenameWriteJob is None:
|
|
126
|
-
filename = getFilenameFoldsTotal(stateJob['mapShape'])
|
|
127
|
-
pathRoot = getPathJobRootDEFAULT()
|
|
128
|
-
pathFilenameWriteJob = Path(pathRoot, Path(filename).stem, Path(filename).with_suffix('.py'))
|
|
129
|
-
else:
|
|
130
|
-
pathFilenameWriteJob = Path(pathFilenameWriteJob)
|
|
131
|
-
pathFilenameWriteJob.parent.mkdir(parents=True, exist_ok=True)
|
|
132
|
-
|
|
133
|
-
pathFilenameWriteJob.write_text(pythonSource)
|
|
134
|
-
|
|
135
|
-
return pathFilenameWriteJob
|
|
136
|
-
|
|
137
|
-
if __name__ == '__main__':
|
|
138
|
-
mapShape: list[int] = [5,5]
|
|
139
|
-
from mapFolding.syntheticModules import numbaCount
|
|
140
|
-
algorithmSource: ModuleType = numbaCount
|
|
141
|
-
|
|
142
|
-
callableTarget = 'countSequential'
|
|
143
|
-
|
|
144
|
-
parametersNumba = parametersNumbaDEFAULT
|
|
145
|
-
parametersNumba['boundscheck'] = True
|
|
146
|
-
|
|
147
|
-
pathFilenameWriteJob = None
|
|
148
|
-
|
|
149
|
-
setDatatypeFoldsTotal('int64', sourGrapes=True)
|
|
150
|
-
setDatatypeElephino('int16', sourGrapes=True)
|
|
151
|
-
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
152
|
-
Z0Z_setDatatypeModuleScalar('numba')
|
|
153
|
-
Z0Z_setDecoratorCallable('jit')
|
|
154
|
-
|
|
155
|
-
writeJobNumba(mapShape, algorithmSource, callableTarget, parametersNumba, pathFilenameWriteJob)
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"""I suspect this function will be relatively stable for now.
|
|
2
|
-
Managing settings and options, however, ... I've 'invented'
|
|
3
|
-
everything I am doing. I would rather benefit from humanity's
|
|
4
|
-
collective wisdom."""
|
|
5
|
-
from mapFolding.someAssemblyRequired.synthesizeNumba import *
|
|
6
|
-
|
|
7
|
-
def getFunctionDef(algorithmSource: ModuleType, *arguments, **keywordArguments) -> tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
8
|
-
pythonSource = inspect.getsource(algorithmSource)
|
|
9
|
-
astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
|
|
10
|
-
FunctionDefTarget, allImports = makeFunctionDef(astModule, *arguments, **keywordArguments)
|
|
11
|
-
return FunctionDefTarget, allImports
|
|
12
|
-
|
|
13
|
-
def makePythonSource(listFunctionDefs: list[ast.FunctionDef], listAstImports: list[ast.Import | ast.ImportFrom], additional_imports: list[str]) -> str:
|
|
14
|
-
astModule = ast.Module(body=cast(list[ast.stmt], listAstImports + listFunctionDefs), type_ignores=[])
|
|
15
|
-
ast.fix_missing_locations(astModule)
|
|
16
|
-
pythonSource = ast.unparse(astModule)
|
|
17
|
-
if not pythonSource: raise FREAKOUT
|
|
18
|
-
pythonSource = autoflake.fix_code(pythonSource, additional_imports)
|
|
19
|
-
return pythonSource
|
|
20
|
-
|
|
21
|
-
def writePythonAsModule(pythonSource: str, listCallableSynthesized: list[str], relativePathWrite: Path | None, filenameWrite: str | None, formatFilenameWrite: str | None) -> list[youOughtaKnow]:
|
|
22
|
-
pathFilename = None
|
|
23
|
-
if not relativePathWrite:
|
|
24
|
-
pathWrite = getPathSyntheticModules()
|
|
25
|
-
else:
|
|
26
|
-
pathWrite = getPathPackage() / relativePathWrite
|
|
27
|
-
|
|
28
|
-
if not formatFilenameWrite:
|
|
29
|
-
formatFilenameWrite = formatFilenameModuleDEFAULT
|
|
30
|
-
|
|
31
|
-
if not filenameWrite:
|
|
32
|
-
if len(listCallableSynthesized) == 1:
|
|
33
|
-
callableTarget = listCallableSynthesized[0]
|
|
34
|
-
else:
|
|
35
|
-
callableTarget = 'count'
|
|
36
|
-
filenameWrite = formatFilenameWrite.format(callableTarget=callableTarget)
|
|
37
|
-
else:
|
|
38
|
-
if not filenameWrite.endswith('.py'):
|
|
39
|
-
warnings.warn(f"Filename {filenameWrite=} does not end with '.py'.")
|
|
40
|
-
|
|
41
|
-
pathFilename = pathWrite / filenameWrite
|
|
42
|
-
|
|
43
|
-
pathFilename.write_text(pythonSource)
|
|
44
|
-
|
|
45
|
-
howIsThisStillAThing = getPathPackage().parent
|
|
46
|
-
dumbassPythonNamespace = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
|
|
47
|
-
ImaModule = '.'.join(dumbassPythonNamespace)
|
|
48
|
-
|
|
49
|
-
listStuffYouOughtaKnow: list[youOughtaKnow] = []
|
|
50
|
-
|
|
51
|
-
for callableTarget in listCallableSynthesized:
|
|
52
|
-
astImportFrom = ast.ImportFrom(module=ImaModule, names=[ast.alias(name=callableTarget, asname=None)], level=0)
|
|
53
|
-
stuff = youOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
|
|
54
|
-
listStuffYouOughtaKnow.append(stuff)
|
|
55
|
-
|
|
56
|
-
return listStuffYouOughtaKnow
|
|
57
|
-
|
|
58
|
-
def makeFlowNumbaOptimized(listCallablesInline: list[str], callableDispatcher: bool | None = False, algorithmSource: ModuleType | None = None, relativePathWrite: Path | None = None, filenameModuleWrite: str | None = None, formatFilenameWrite: str | None = None) -> list[youOughtaKnow]:
|
|
59
|
-
if relativePathWrite and relativePathWrite.is_absolute():
|
|
60
|
-
raise ValueError("The path to write the module must be relative to the root of the package.")
|
|
61
|
-
if not algorithmSource:
|
|
62
|
-
algorithmSource = getAlgorithmSource()
|
|
63
|
-
|
|
64
|
-
Z0Z_filenameModuleWrite = 'numbaCount.py'
|
|
65
|
-
|
|
66
|
-
listStuffYouOughtaKnow: list[youOughtaKnow] = []
|
|
67
|
-
additional_imports = ['mapFolding', 'numba', 'numpy']
|
|
68
|
-
|
|
69
|
-
listFunctionDefs: list[ast.FunctionDef] = []
|
|
70
|
-
allImportsModule = UniversalImportTracker()
|
|
71
|
-
for callableTarget in listCallablesInline:
|
|
72
|
-
parametersNumba = None
|
|
73
|
-
inlineCallables = True
|
|
74
|
-
unpackArrays = False
|
|
75
|
-
allImports = None
|
|
76
|
-
filenameWrite = None
|
|
77
|
-
match callableTarget:
|
|
78
|
-
case 'countParallel':
|
|
79
|
-
parametersNumba = parametersNumbaSuperJitParallel
|
|
80
|
-
case 'countSequential':
|
|
81
|
-
parametersNumba = parametersNumbaSuperJit
|
|
82
|
-
unpackArrays = True
|
|
83
|
-
case 'countInitialize':
|
|
84
|
-
parametersNumba = parametersNumbaDEFAULT
|
|
85
|
-
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
86
|
-
listFunctionDefs.append(FunctionDefTarget)
|
|
87
|
-
allImportsModule.update(allImports)
|
|
88
|
-
|
|
89
|
-
listAstImports = allImportsModule.makeListAst()
|
|
90
|
-
pythonSource = makePythonSource(listFunctionDefs, listAstImports, additional_imports)
|
|
91
|
-
|
|
92
|
-
filenameWrite = filenameModuleWrite or Z0Z_filenameModuleWrite
|
|
93
|
-
|
|
94
|
-
listStuff = writePythonAsModule(pythonSource, listCallablesInline, relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
95
|
-
listStuffYouOughtaKnow.extend(listStuff)
|
|
96
|
-
|
|
97
|
-
if callableDispatcher:
|
|
98
|
-
callableTarget = getAlgorithmDispatcher().__name__
|
|
99
|
-
parametersNumba = None
|
|
100
|
-
inlineCallables = False
|
|
101
|
-
unpackArrays = False
|
|
102
|
-
allImports = UniversalImportTracker()
|
|
103
|
-
filenameWrite = None
|
|
104
|
-
for stuff in listStuffYouOughtaKnow:
|
|
105
|
-
statement = stuff.astForCompetentProgrammers
|
|
106
|
-
if isinstance(statement, (ast.Import, ast.ImportFrom)):
|
|
107
|
-
allImports.addAst(statement)
|
|
108
|
-
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
109
|
-
listAstImports = allImports.makeListAst()
|
|
110
|
-
|
|
111
|
-
pythonSource = makePythonSource([FunctionDefTarget], listAstImports, additional_imports)
|
|
112
|
-
|
|
113
|
-
listStuff = writePythonAsModule(pythonSource, [callableTarget], relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
114
|
-
listStuffYouOughtaKnow.extend(listStuff)
|
|
115
|
-
|
|
116
|
-
return listStuffYouOughtaKnow
|
|
117
|
-
|
|
118
|
-
if __name__ == '__main__':
|
|
119
|
-
# Z0Z_setDatatypeModuleScalar('numba')
|
|
120
|
-
# Z0Z_setDecoratorCallable('jit')
|
|
121
|
-
listCallablesInline: list[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
122
|
-
callableDispatcher = True
|
|
123
|
-
makeFlowNumbaOptimized(listCallablesInline, callableDispatcher)
|