mapFolding 0.9.0__py3-none-any.whl → 0.9.2__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 +49 -48
- mapFolding/basecamp.py +40 -35
- mapFolding/beDRY.py +75 -69
- mapFolding/oeis.py +74 -85
- mapFolding/reference/__init__.py +2 -2
- mapFolding/someAssemblyRequired/RecipeJob.py +103 -0
- mapFolding/someAssemblyRequired/__init__.py +31 -29
- mapFolding/someAssemblyRequired/_theTypes.py +9 -1
- mapFolding/someAssemblyRequired/_tool_Make.py +1 -2
- mapFolding/someAssemblyRequired/_tool_Then.py +16 -8
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +111 -23
- mapFolding/someAssemblyRequired/_toolboxContainers.py +27 -28
- mapFolding/someAssemblyRequired/_toolboxPython.py +3 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +83 -51
- mapFolding/someAssemblyRequired/toolboxNumba.py +19 -220
- mapFolding/someAssemblyRequired/transformationTools.py +183 -12
- mapFolding/syntheticModules/{numbaCount_doTheNeedful.py → numbaCount.py} +13 -12
- mapFolding/theDao.py +37 -36
- mapFolding/theSSOT.py +29 -33
- mapFolding/toolboxFilesystem.py +29 -38
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/METADATA +2 -1
- mapfolding-0.9.2.dist-info/RECORD +47 -0
- tests/test_computations.py +2 -1
- tests/test_other.py +0 -7
- mapfolding-0.9.0.dist-info/RECORD +0 -46
- /mapFolding/reference/{lunnanNumpy.py → lunnonNumpy.py} +0 -0
- /mapFolding/reference/{lunnanWhile.py → lunnonWhile.py} +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/WHEEL +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/top_level.txt +0 -0
|
@@ -16,13 +16,10 @@ performance improvements while preserving code semantics and correctness.
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
from collections.abc import Callable, Sequence
|
|
19
|
-
from mapFolding.someAssemblyRequired import
|
|
20
|
-
from mapFolding.someAssemblyRequired.transformationTools import
|
|
21
|
-
from mapFolding.theSSOT import ComputationState, DatatypeFoldsTotal as TheDatatypeFoldsTotal, DatatypeElephino as TheDatatypeElephino, DatatypeLeavesTotal as TheDatatypeLeavesTotal
|
|
22
|
-
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, getPathRootJobDEFAULT
|
|
19
|
+
from mapFolding.someAssemblyRequired import ast_Identifier, be, IngredientsFunction, Make, NodeTourist, RecipeSynthesizeFlow, str_nameDOTname, Then
|
|
20
|
+
from mapFolding.someAssemblyRequired.transformationTools import makeNewFlow, write_astModule
|
|
23
21
|
from numba.core.compiler import CompilerBase as numbaCompilerBase
|
|
24
|
-
from
|
|
25
|
-
from typing import Any, cast, Final, TYPE_CHECKING, TypeAlias, TypeGuard
|
|
22
|
+
from typing import Any, cast, Final, TYPE_CHECKING, TypeGuard
|
|
26
23
|
import ast
|
|
27
24
|
import dataclasses
|
|
28
25
|
|
|
@@ -48,17 +45,17 @@ class ParametersNumba(TypedDict):
|
|
|
48
45
|
debug: NotRequired[bool]
|
|
49
46
|
error_model: str
|
|
50
47
|
fastmath: bool
|
|
51
|
-
forceinline: bool
|
|
48
|
+
forceinline: NotRequired[bool]
|
|
52
49
|
forceobj: NotRequired[bool]
|
|
53
|
-
inline: str
|
|
50
|
+
inline: NotRequired[str]
|
|
54
51
|
locals: NotRequired[dict[str, Any]]
|
|
55
|
-
looplift: bool
|
|
56
|
-
no_cfunc_wrapper: bool
|
|
57
|
-
no_cpython_wrapper: bool
|
|
52
|
+
looplift: NotRequired[bool]
|
|
53
|
+
no_cfunc_wrapper: NotRequired[bool]
|
|
54
|
+
no_cpython_wrapper: NotRequired[bool]
|
|
58
55
|
no_rewrites: NotRequired[bool]
|
|
59
56
|
nogil: NotRequired[bool]
|
|
60
|
-
nopython: bool
|
|
61
|
-
parallel: bool
|
|
57
|
+
nopython: NotRequired[bool]
|
|
58
|
+
parallel: NotRequired[bool]
|
|
62
59
|
pipeline_class: NotRequired[type[numbaCompilerBase]]
|
|
63
60
|
signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
|
|
64
61
|
target: NotRequired[str]
|
|
@@ -74,6 +71,7 @@ parametersNumbaSuperJit: Final[ParametersNumba] = { **parametersNumbaDefault, 'n
|
|
|
74
71
|
parametersNumbaSuperJitParallel: Final[ParametersNumba] = { **parametersNumbaSuperJit, '_nrt': True, 'parallel': True, }
|
|
75
72
|
"""Speed, no helmet, concurrency, no talking to non-jitted functions."""
|
|
76
73
|
parametersNumbaMinimum: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': True, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': False, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': False, 'forceobj': True, 'parallel': False, }
|
|
74
|
+
parametersNumbaLight: Final[ParametersNumba] = {'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True}
|
|
77
75
|
|
|
78
76
|
Z0Z_numbaDataTypeModule: str_nameDOTname = 'numba'
|
|
79
77
|
Z0Z_decoratorCallable: ast_Identifier = 'jit'
|
|
@@ -121,10 +119,10 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
|
|
|
121
119
|
list_arg4signature_or_function: list[ast.expr] = []
|
|
122
120
|
for parameter in ingredientsFunction.astFunctionDef.args.args:
|
|
123
121
|
# For now, let Numba infer them.
|
|
122
|
+
signatureElement: ast.Subscript | ast.Name | None = makeSpecialSignatureForNumba(parameter)
|
|
123
|
+
if signatureElement:
|
|
124
|
+
list_arg4signature_or_function.append(signatureElement)
|
|
124
125
|
continue
|
|
125
|
-
# signatureElement: ast.Subscript | ast.Name | None = makeSpecialSignatureForNumba(parameter)
|
|
126
|
-
# if signatureElement:
|
|
127
|
-
# list_arg4signature_or_function.append(signatureElement)
|
|
128
126
|
|
|
129
127
|
if ingredientsFunction.astFunctionDef.returns and isinstance(ingredientsFunction.astFunctionDef.returns, ast.Name):
|
|
130
128
|
theReturn: ast.Name = ingredientsFunction.astFunctionDef.returns
|
|
@@ -153,111 +151,9 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
|
|
|
153
151
|
class SpicesJobNumba:
|
|
154
152
|
useNumbaProgressBar: bool = True
|
|
155
153
|
numbaProgressBarIdentifier: ast_Identifier = 'ProgressBarGroupsOfFolds'
|
|
156
|
-
parametersNumba =
|
|
154
|
+
parametersNumba: ParametersNumba = dataclasses.field(default_factory=ParametersNumba) # type: ignore
|
|
157
155
|
|
|
158
156
|
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
159
|
-
@dataclasses.dataclass
|
|
160
|
-
class RecipeJob:
|
|
161
|
-
state: ComputationState
|
|
162
|
-
# TODO create function to calculate `foldsTotalEstimated`
|
|
163
|
-
foldsTotalEstimated: int = 0
|
|
164
|
-
shatteredDataclass: ShatteredDataclass = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
165
|
-
|
|
166
|
-
# ========================================
|
|
167
|
-
# Source
|
|
168
|
-
source_astModule = parsePathFilename2astModule(theNumbaFlow.pathFilenameSequential)
|
|
169
|
-
sourceCountCallable: ast_Identifier = theNumbaFlow.callableSequential
|
|
170
|
-
|
|
171
|
-
sourceLogicalPathModuleDataclass: str_nameDOTname = theNumbaFlow.logicalPathModuleDataclass
|
|
172
|
-
sourceDataclassIdentifier: ast_Identifier = theNumbaFlow.dataclassIdentifier
|
|
173
|
-
sourceDataclassInstance: ast_Identifier = theNumbaFlow.dataclassInstance
|
|
174
|
-
|
|
175
|
-
sourcePathPackage: PurePosixPath | None = theNumbaFlow.pathPackage
|
|
176
|
-
sourcePackageIdentifier: ast_Identifier | None = theNumbaFlow.packageIdentifier
|
|
177
|
-
|
|
178
|
-
# ========================================
|
|
179
|
-
# Filesystem (names of physical objects)
|
|
180
|
-
pathPackage: PurePosixPath | None = None
|
|
181
|
-
pathModule: PurePosixPath | None = PurePosixPath(getPathRootJobDEFAULT())
|
|
182
|
-
""" `pathModule` will override `pathPackage` and `logicalPathRoot`."""
|
|
183
|
-
fileExtension: str = theNumbaFlow.fileExtension
|
|
184
|
-
pathFilenameFoldsTotal: PurePosixPath = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
185
|
-
|
|
186
|
-
# ========================================
|
|
187
|
-
# Logical identifiers (as opposed to physical identifiers)
|
|
188
|
-
packageIdentifier: ast_Identifier | None = None
|
|
189
|
-
logicalPathRoot: str_nameDOTname | None = None
|
|
190
|
-
""" `logicalPathRoot` likely corresponds to a physical filesystem directory."""
|
|
191
|
-
moduleIdentifier: ast_Identifier = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
192
|
-
countCallable: ast_Identifier = sourceCountCallable
|
|
193
|
-
dataclassIdentifier: ast_Identifier | None = sourceDataclassIdentifier
|
|
194
|
-
dataclassInstance: ast_Identifier | None = sourceDataclassInstance
|
|
195
|
-
logicalPathModuleDataclass: str_nameDOTname | None = sourceLogicalPathModuleDataclass
|
|
196
|
-
|
|
197
|
-
# ========================================
|
|
198
|
-
# Datatypes
|
|
199
|
-
DatatypeFoldsTotal: TypeAlias = TheDatatypeFoldsTotal
|
|
200
|
-
DatatypeElephino: TypeAlias = TheDatatypeElephino
|
|
201
|
-
DatatypeLeavesTotal: TypeAlias = TheDatatypeLeavesTotal
|
|
202
|
-
|
|
203
|
-
def _makePathFilename(self,
|
|
204
|
-
pathRoot: PurePosixPath | None = None,
|
|
205
|
-
logicalPathINFIX: str_nameDOTname | None = None,
|
|
206
|
-
filenameStem: str | None = None,
|
|
207
|
-
fileExtension: str | None = None,
|
|
208
|
-
) -> PurePosixPath:
|
|
209
|
-
if pathRoot is None:
|
|
210
|
-
pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
|
|
211
|
-
if logicalPathINFIX:
|
|
212
|
-
whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
|
|
213
|
-
pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
|
|
214
|
-
if filenameStem is None:
|
|
215
|
-
filenameStem = self.moduleIdentifier
|
|
216
|
-
if fileExtension is None:
|
|
217
|
-
fileExtension = self.fileExtension
|
|
218
|
-
filename: str = filenameStem + fileExtension
|
|
219
|
-
return pathRoot.joinpath(filename)
|
|
220
|
-
|
|
221
|
-
@property
|
|
222
|
-
def pathFilenameModule(self) -> PurePosixPath:
|
|
223
|
-
if self.pathModule is None:
|
|
224
|
-
return self._makePathFilename()
|
|
225
|
-
else:
|
|
226
|
-
return self._makePathFilename(pathRoot=self.pathModule, logicalPathINFIX=None)
|
|
227
|
-
|
|
228
|
-
def __post_init__(self):
|
|
229
|
-
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(self.state.mapShape))
|
|
230
|
-
|
|
231
|
-
if self.moduleIdentifier is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
232
|
-
self.moduleIdentifier = pathFilenameFoldsTotal.stem
|
|
233
|
-
|
|
234
|
-
if self.pathFilenameFoldsTotal is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
235
|
-
self.pathFilenameFoldsTotal = pathFilenameFoldsTotal
|
|
236
|
-
|
|
237
|
-
if self.shatteredDataclass is None and self.logicalPathModuleDataclass and self.dataclassIdentifier and self.dataclassInstance: # pyright: ignore[reportUnnecessaryComparison]
|
|
238
|
-
self.shatteredDataclass = shatter_dataclassesDOTdataclass(self.logicalPathModuleDataclass, self.dataclassIdentifier, self.dataclassInstance)
|
|
239
|
-
|
|
240
|
-
# ========================================
|
|
241
|
-
# Fields you probably don't need =================================
|
|
242
|
-
# Dispatcher =================================
|
|
243
|
-
sourceDispatcherCallable: ast_Identifier = theNumbaFlow.callableDispatcher
|
|
244
|
-
dispatcherCallable: ast_Identifier = sourceDispatcherCallable
|
|
245
|
-
# Parallel counting =================================
|
|
246
|
-
sourceDataclassInstanceTaskDistribution: ast_Identifier = theNumbaFlow.dataclassInstanceTaskDistribution
|
|
247
|
-
sourceConcurrencyManagerNamespace: ast_Identifier = theNumbaFlow.concurrencyManagerNamespace
|
|
248
|
-
sourceConcurrencyManagerIdentifier: ast_Identifier = theNumbaFlow.concurrencyManagerIdentifier
|
|
249
|
-
dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
|
|
250
|
-
concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
|
|
251
|
-
concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
|
|
252
|
-
|
|
253
|
-
class be:
|
|
254
|
-
@staticmethod
|
|
255
|
-
def Call(node: ast.AST) -> TypeGuard[ast.Call]:
|
|
256
|
-
return isinstance(node, ast.Call)
|
|
257
|
-
@staticmethod
|
|
258
|
-
def Return(node: ast.AST) -> TypeGuard[ast.Return]:
|
|
259
|
-
return isinstance(node, ast.Return)
|
|
260
|
-
|
|
261
157
|
def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
|
|
262
158
|
"""
|
|
263
159
|
Transform standard Python algorithm code into optimized Numba implementations.
|
|
@@ -283,109 +179,12 @@ def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
|
|
|
283
179
|
transformation process, including source and target locations,
|
|
284
180
|
function and variable names, and output paths.
|
|
285
181
|
"""
|
|
286
|
-
# TODO a tool to automatically remove unused variables from the ArgumentsSpecification (return, and returns) _might_ be nice.
|
|
287
|
-
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
288
|
-
|
|
289
|
-
listAllIngredientsFunctions = [
|
|
290
|
-
(ingredientsInitialize := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableInitialize)),
|
|
291
|
-
(ingredientsParallel := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableParallel)),
|
|
292
|
-
(ingredientsSequential := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableSequential)),
|
|
293
|
-
(ingredientsDispatcher := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableDispatcher)),
|
|
294
|
-
]
|
|
295
|
-
|
|
296
|
-
# Inline functions ========================================================
|
|
297
|
-
# NOTE Replacements statements are based on the identifiers in the _source_, so operate on the source identifiers.
|
|
298
|
-
ingredientsInitialize.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableInitialize, numbaFlow.source_astModule)
|
|
299
|
-
ingredientsParallel.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableParallel, numbaFlow.source_astModule)
|
|
300
|
-
ingredientsSequential.astFunctionDef = inlineFunctionDef(numbaFlow.sourceCallableSequential, numbaFlow.source_astModule)
|
|
301
|
-
|
|
302
|
-
# assignRecipeIdentifiersToCallable. =============================
|
|
303
|
-
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
304
|
-
# How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
|
|
305
|
-
# NOTE reminder: you are updating these `ast.Name` here (and not in a more general search) because this is a
|
|
306
|
-
# narrow search for `ast.Call` so you won't accidentally replace unrelated `ast.Name`.
|
|
307
|
-
listFindReplace = [(numbaFlow.sourceCallableDispatcher, numbaFlow.callableDispatcher),
|
|
308
|
-
(numbaFlow.sourceCallableInitialize, numbaFlow.callableInitialize),
|
|
309
|
-
(numbaFlow.sourceCallableParallel, numbaFlow.callableParallel),
|
|
310
|
-
(numbaFlow.sourceCallableSequential, numbaFlow.callableSequential),]
|
|
311
|
-
for ingredients in listAllIngredientsFunctions:
|
|
312
|
-
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
313
|
-
updateCallName = NodeChanger(ifThis.isCall_Identifier(source_Identifier), grab.funcAttribute(Then.replaceWith(Make.Name(recipe_Identifier))))
|
|
314
|
-
updateCallName.visit(ingredients.astFunctionDef)
|
|
315
|
-
|
|
316
|
-
ingredientsDispatcher.astFunctionDef.name = numbaFlow.callableDispatcher
|
|
317
|
-
ingredientsInitialize.astFunctionDef.name = numbaFlow.callableInitialize
|
|
318
|
-
ingredientsParallel.astFunctionDef.name = numbaFlow.callableParallel
|
|
319
|
-
ingredientsSequential.astFunctionDef.name = numbaFlow.callableSequential
|
|
320
|
-
|
|
321
|
-
# Assign identifiers per the recipe. ==============================
|
|
322
|
-
listFindReplace = [(numbaFlow.sourceDataclassInstance, numbaFlow.dataclassInstance),
|
|
323
|
-
(numbaFlow.sourceDataclassInstanceTaskDistribution, numbaFlow.dataclassInstanceTaskDistribution),
|
|
324
|
-
(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.concurrencyManagerNamespace),]
|
|
325
|
-
for ingredients in listAllIngredientsFunctions:
|
|
326
|
-
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
327
|
-
updateName = NodeChanger(ifThis.isName_Identifier(source_Identifier) , grab.idAttribute(Then.replaceWith(recipe_Identifier)))
|
|
328
|
-
update_arg = NodeChanger(ifThis.isArgument_Identifier(source_Identifier), grab.argAttribute(Then.replaceWith(recipe_Identifier)))
|
|
329
|
-
updateName.visit(ingredients.astFunctionDef)
|
|
330
|
-
update_arg.visit(ingredients.astFunctionDef)
|
|
331
|
-
|
|
332
|
-
updateConcurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.sourceConcurrencyManagerIdentifier)
|
|
333
|
-
, grab.funcAttribute(Then.replaceWith(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier))))
|
|
334
|
-
updateConcurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
335
|
-
|
|
336
|
-
# shatter Dataclass =======================================================
|
|
337
|
-
instance_Identifier = numbaFlow.dataclassInstance
|
|
338
|
-
getTheOtherRecord_damn = numbaFlow.dataclassInstanceTaskDistribution
|
|
339
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(numbaFlow.logicalPathModuleDataclass, numbaFlow.sourceDataclassIdentifier, instance_Identifier)
|
|
340
|
-
ingredientsDispatcher.imports.update(shatteredDataclass.ledger)
|
|
341
|
-
|
|
342
|
-
# How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
|
|
343
|
-
# Change callable parameters and Call to the callable at the same time ====
|
|
344
|
-
# sequentialCallable =========================================================
|
|
345
|
-
ingredientsSequential.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
346
|
-
astCallSequentialCallable = Make.Call(Make.Name(numbaFlow.callableSequential), shatteredDataclass.listName4Parameters)
|
|
347
|
-
changeReturnSequentialCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
|
|
348
|
-
ingredientsSequential.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
|
|
349
|
-
replaceAssignSequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.replaceWith(Make.Assign(listTargets=[shatteredDataclass.fragments4AssignmentOrParameters], value=astCallSequentialCallable)))
|
|
350
|
-
|
|
351
|
-
unpack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
352
|
-
repack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(numbaFlow.callableSequential)), Then.insertThisBelow([shatteredDataclass.repack]))
|
|
353
|
-
|
|
354
|
-
changeReturnSequentialCallable.visit(ingredientsSequential.astFunctionDef)
|
|
355
|
-
replaceAssignSequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
356
|
-
unpack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
357
|
-
repack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
358
|
-
|
|
359
|
-
ingredientsSequential.astFunctionDef = Z0Z_lameFindReplace(ingredientsSequential.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
360
|
-
|
|
361
|
-
# parallelCallable =========================================================
|
|
362
|
-
ingredientsParallel.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
363
|
-
replaceCall2concurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier), Then.replaceWith(Make.Call(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier), listArguments=[Make.Name(numbaFlow.callableParallel)] + shatteredDataclass.listName4Parameters)))
|
|
364
|
-
|
|
365
|
-
# NOTE I am dissatisfied with this logic for many reasons, including that it requires separate NodeCollector and NodeReplacer instances.
|
|
366
|
-
astCallConcurrencyResult: list[ast.Call] = []
|
|
367
|
-
get_astCallConcurrencyResult = NodeTourist(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), getIt(astCallConcurrencyResult))
|
|
368
|
-
get_astCallConcurrencyResult.visit(ingredientsDispatcher.astFunctionDef)
|
|
369
|
-
replaceAssignParallelCallable = NodeChanger(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), grab.valueAttribute(Then.replaceWith(astCallConcurrencyResult[0])))
|
|
370
|
-
replaceAssignParallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
371
|
-
changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.countingVariableName)))
|
|
372
|
-
ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
|
|
373
|
-
|
|
374
|
-
unpack4parallelCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
375
|
-
|
|
376
|
-
unpack4parallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
377
|
-
replaceCall2concurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
378
|
-
changeReturnParallelCallable.visit(ingredientsParallel.astFunctionDef)
|
|
379
|
-
|
|
380
|
-
ingredientsParallel.astFunctionDef = Z0Z_lameFindReplace(ingredientsParallel.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
381
182
|
|
|
382
|
-
|
|
383
|
-
ingredientsParallel = decorateCallableWithNumba(ingredientsParallel)
|
|
384
|
-
ingredientsSequential = decorateCallableWithNumba(ingredientsSequential)
|
|
183
|
+
ingredientsModuleNumbaUnified = makeNewFlow(numbaFlow)
|
|
385
184
|
|
|
386
|
-
#
|
|
387
|
-
ingredientsModuleNumbaUnified =
|
|
388
|
-
ingredientsModuleNumbaUnified.
|
|
185
|
+
# numba decorators =========================================
|
|
186
|
+
ingredientsModuleNumbaUnified.listIngredientsFunctions[1] = decorateCallableWithNumba(ingredientsModuleNumbaUnified.listIngredientsFunctions[1])
|
|
187
|
+
ingredientsModuleNumbaUnified.listIngredientsFunctions[2] = decorateCallableWithNumba(ingredientsModuleNumbaUnified.listIngredientsFunctions[2])
|
|
389
188
|
|
|
390
189
|
write_astModule(ingredientsModuleNumbaUnified, numbaFlow.pathFilenameDispatcher, numbaFlow.packageIdentifier)
|
|
391
190
|
|
|
@@ -25,7 +25,9 @@ from mapFolding.beDRY import outfitCountFolds
|
|
|
25
25
|
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, writeStringToHere
|
|
26
26
|
from mapFolding.someAssemblyRequired import (
|
|
27
27
|
ast_Identifier,
|
|
28
|
+
be,
|
|
28
29
|
DOT,
|
|
30
|
+
grab,
|
|
29
31
|
ifThis,
|
|
30
32
|
importLogicalPath2Callable,
|
|
31
33
|
IngredientsFunction,
|
|
@@ -35,6 +37,7 @@ from mapFolding.someAssemblyRequired import (
|
|
|
35
37
|
NodeChanger,
|
|
36
38
|
NodeTourist,
|
|
37
39
|
parseLogicalPath2astModule,
|
|
40
|
+
RecipeSynthesizeFlow,
|
|
38
41
|
ShatteredDataclass,
|
|
39
42
|
str_nameDOTname,
|
|
40
43
|
Then,
|
|
@@ -47,6 +50,7 @@ from typing import Any, Literal, overload
|
|
|
47
50
|
import ast
|
|
48
51
|
import dataclasses
|
|
49
52
|
import pickle
|
|
53
|
+
import python_minifier
|
|
50
54
|
|
|
51
55
|
def astModuleToIngredientsFunction(astModule: ast.AST, identifierFunctionDef: ast_Identifier) -> IngredientsFunction:
|
|
52
56
|
"""
|
|
@@ -97,7 +101,7 @@ def extractFunctionDef(module: ast.AST, identifier: ast_Identifier) -> ast.Funct
|
|
|
97
101
|
identifier: The name of the function to find.
|
|
98
102
|
|
|
99
103
|
Returns:
|
|
100
|
-
The matching function definition AST node, or None if not found.
|
|
104
|
+
astFunctionDef: The matching function definition AST node, or None if not found.
|
|
101
105
|
"""
|
|
102
106
|
return NodeTourist(ifThis.isFunctionDef_Identifier(identifier), Then.extractIt).captureLastMatch(module)
|
|
103
107
|
|
|
@@ -115,7 +119,7 @@ def makeDictionaryFunctionDef(module: ast.Module) -> dict[ast_Identifier, ast.Fu
|
|
|
115
119
|
A dictionary mapping function identifiers to their AST function definition nodes.
|
|
116
120
|
"""
|
|
117
121
|
dictionaryIdentifier2FunctionDef: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
118
|
-
NodeTourist(
|
|
122
|
+
NodeTourist(be.FunctionDef, Then.updateKeyValueIn(DOT.name, Then.extractIt, dictionaryIdentifier2FunctionDef)).visit(module)
|
|
119
123
|
return dictionaryIdentifier2FunctionDef
|
|
120
124
|
|
|
121
125
|
def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) -> ast.FunctionDef:
|
|
@@ -144,7 +148,7 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
144
148
|
raise ValueError(f"FunctionDefToInline not found in dictionaryIdentifier2FunctionDef: {identifierToInline = }") from ERRORmessage
|
|
145
149
|
|
|
146
150
|
listIdentifiersCalledFunctions: list[ast_Identifier] = []
|
|
147
|
-
findIdentifiersToInline = NodeTourist(ifThis.isCallToName,
|
|
151
|
+
findIdentifiersToInline = NodeTourist(findThis = ifThis.isCallToName, doThat = grab.funcDOTidAttribute(Then.appendTo(listIdentifiersCalledFunctions)))
|
|
148
152
|
findIdentifiersToInline.visit(FunctionDefToInline)
|
|
149
153
|
|
|
150
154
|
dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
@@ -165,7 +169,8 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
165
169
|
if NodeTourist(ifThis.matchesMeButNotAnyDescendant(ifThis.isCall_Identifier(identifier)), Then.extractIt).captureLastMatch(module) is not None:
|
|
166
170
|
FunctionDefTarget = dictionaryFunctionDef[identifier]
|
|
167
171
|
if len(FunctionDefTarget.body) == 1:
|
|
168
|
-
|
|
172
|
+
replacement = NodeTourist(be.Return, Then.extractIt(DOT.value)).captureLastMatch(FunctionDefTarget)
|
|
173
|
+
inliner = NodeChanger(ifThis.isCall_Identifier(identifier), Then.replaceWith(replacement))
|
|
169
174
|
for astFunctionDef in dictionary4Inlining.values():
|
|
170
175
|
inliner.visit(astFunctionDef)
|
|
171
176
|
else:
|
|
@@ -175,7 +180,8 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
175
180
|
|
|
176
181
|
for identifier, FunctionDefTarget in dictionary4Inlining.items():
|
|
177
182
|
if len(FunctionDefTarget.body) == 1:
|
|
178
|
-
|
|
183
|
+
replacement = NodeTourist(be.Return, Then.extractIt(DOT.value)).captureLastMatch(FunctionDefTarget)
|
|
184
|
+
inliner = NodeChanger(ifThis.isCall_Identifier(identifier), Then.replaceWith(replacement))
|
|
179
185
|
inliner.visit(FunctionDefToInline)
|
|
180
186
|
else:
|
|
181
187
|
inliner = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(identifier)),Then.replaceWith(FunctionDefTarget.body[0:-1]))
|
|
@@ -263,8 +269,8 @@ class DeReConstructField2ast:
|
|
|
263
269
|
ast_nameDOTname: ast.Attribute = dataclasses.field(init=False)
|
|
264
270
|
astAnnotation: ast.expr = dataclasses.field(init=False)
|
|
265
271
|
ast_argAnnotated: ast.arg = dataclasses.field(init=False)
|
|
266
|
-
astAnnAssignConstructor: ast.AnnAssign = dataclasses.field(init=False)
|
|
267
|
-
Z0Z_hack: tuple[ast.AnnAssign, str] = dataclasses.field(init=False)
|
|
272
|
+
astAnnAssignConstructor: ast.AnnAssign|ast.Assign = dataclasses.field(init=False)
|
|
273
|
+
Z0Z_hack: tuple[ast.AnnAssign|ast.Assign, str] = dataclasses.field(init=False)
|
|
268
274
|
|
|
269
275
|
def __post_init__(self, dataclassesDOTdataclassLogicalPathModule: str_nameDOTname, dataclassClassDef: ast.ClassDef, dataclassesDOTdataclassInstance_Identifier: ast_Identifier, field: dataclasses.Field[Any]) -> None:
|
|
270
276
|
self.compare = field.compare
|
|
@@ -282,23 +288,47 @@ class DeReConstructField2ast:
|
|
|
282
288
|
self.ast_keyword_field__field = Make.keyword(self.name, self.astName)
|
|
283
289
|
self.ast_nameDOTname = Make.Attribute(Make.Name(dataclassesDOTdataclassInstance_Identifier), self.name)
|
|
284
290
|
|
|
285
|
-
sherpa = NodeTourist(ifThis.isAnnAssign_targetIs(ifThis.isName_Identifier(self.name)), Then.extractIt(DOT.annotation)).captureLastMatch(dataclassClassDef)
|
|
291
|
+
sherpa = NodeTourist(ifThis.isAnnAssign_targetIs(ifThis.isName_Identifier(self.name)), Then.extractIt(DOT.annotation)).captureLastMatch(dataclassClassDef)
|
|
286
292
|
if sherpa is None: raise raiseIfNoneGitHubIssueNumber3
|
|
287
293
|
else: self.astAnnotation = sherpa
|
|
288
294
|
|
|
289
295
|
self.ast_argAnnotated = Make.arg(self.name, self.astAnnotation)
|
|
296
|
+
"""
|
|
297
|
+
from ast import Module, Expr, Subscript, Name, Tuple, Load
|
|
298
|
+
Subscript(
|
|
299
|
+
value=Name(id='ndarray', ctx=Load()),
|
|
300
|
+
slice=Tuple(
|
|
301
|
+
elts=[
|
|
302
|
+
Subscript(
|
|
303
|
+
value=Name(id='tuple', ctx=Load()),
|
|
304
|
+
slice=Name(id='int', ctx=Load()),
|
|
305
|
+
ctx=Load()),
|
|
306
|
+
Subscript(
|
|
307
|
+
value=Name(id='dtype', ctx=Load()),
|
|
308
|
+
slice=Name(id='NumPyLeavesTotal', ctx=Load()),
|
|
309
|
+
ctx=Load())],
|
|
310
|
+
ctx=Load()),
|
|
311
|
+
ctx=Load()
|
|
312
|
+
)
|
|
290
313
|
|
|
314
|
+
"""
|
|
291
315
|
dtype = self.metadata.get('dtype', None)
|
|
292
316
|
if dtype:
|
|
293
317
|
moduleWithLogicalPath: str_nameDOTname = 'numpy'
|
|
294
|
-
|
|
295
|
-
self.ledger.addImportFrom_asStr(moduleWithLogicalPath,
|
|
318
|
+
annotationType = 'ndarray'
|
|
319
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotationType)
|
|
320
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, 'dtype')
|
|
321
|
+
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Name('uint8'))
|
|
322
|
+
dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
|
|
323
|
+
if dtype_asnameName.id == 'Array3D':
|
|
324
|
+
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Tuple([Make.Name('uint8'), Make.Name('uint8'), Make.Name('uint8')]))
|
|
325
|
+
ast_expr = Make.Subscript(Make.Name(annotationType), Make.Tuple([axesSubscript, Make.Subscript(Make.Name('dtype'), dtype_asnameName)]))
|
|
296
326
|
constructor = 'array'
|
|
297
327
|
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, constructor)
|
|
298
328
|
dtypeIdentifier: ast_Identifier = dtype.__name__
|
|
299
|
-
dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
|
|
300
329
|
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, dtypeIdentifier, dtype_asnameName.id)
|
|
301
|
-
self.astAnnAssignConstructor = Make.AnnAssign(self.astName,
|
|
330
|
+
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, ast_expr, Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
|
|
331
|
+
self.astAnnAssignConstructor = Make.Assign([self.astName], Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
|
|
302
332
|
self.Z0Z_hack = (self.astAnnAssignConstructor, 'array')
|
|
303
333
|
elif isinstance(self.astAnnotation, ast.Name):
|
|
304
334
|
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, Make.Call(self.astAnnotation, [Make.Constant(-1)]))
|
|
@@ -413,9 +443,150 @@ def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any]
|
|
|
413
443
|
if packageName:
|
|
414
444
|
autoflake_additional_imports.append(packageName)
|
|
415
445
|
pythonSource = autoflake_fix_code(pythonSource, autoflake_additional_imports, expand_star_imports=False, remove_all_unused_imports=True, remove_duplicate_keys = False, remove_unused_variables = False)
|
|
446
|
+
# pythonSource = python_minifier.minify(pythonSource, remove_annotations=False, hoist_literals=False)
|
|
416
447
|
writeStringToHere(pythonSource, pathFilename)
|
|
417
448
|
|
|
418
449
|
# END of acceptable classes and functions ======================================================
|
|
450
|
+
def removeUnusedParameters(ingredientsFunction: IngredientsFunction) -> IngredientsFunction:
|
|
451
|
+
list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
|
|
452
|
+
list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
|
|
453
|
+
listName: list[ast.Name] = []
|
|
454
|
+
fauxFunctionDef = deepcopy(ingredientsFunction.astFunctionDef)
|
|
455
|
+
NodeChanger(be.Return, Then.removeIt).visit(fauxFunctionDef)
|
|
456
|
+
NodeTourist(be.Name, Then.appendTo(listName)).visit(fauxFunctionDef)
|
|
457
|
+
list_Identifiers: list[ast_Identifier] = [astName.id for astName in listName]
|
|
458
|
+
list_IdentifiersNotUsed: list[ast_Identifier] = list(set(list_arg_arg) - set(list_Identifiers))
|
|
459
|
+
for arg_Identifier in list_IdentifiersNotUsed:
|
|
460
|
+
remove_arg = NodeChanger(ifThis.is_arg_Identifier(arg_Identifier), Then.removeIt)
|
|
461
|
+
remove_arg.visit(ingredientsFunction.astFunctionDef)
|
|
462
|
+
return ingredientsFunction
|
|
463
|
+
|
|
464
|
+
def makeNewFlow(recipeFlow: RecipeSynthesizeFlow) -> IngredientsModule:
|
|
465
|
+
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
466
|
+
listAllIngredientsFunctions = [
|
|
467
|
+
(ingredientsInitialize := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableInitialize)),
|
|
468
|
+
(ingredientsParallel := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableParallel)),
|
|
469
|
+
(ingredientsSequential := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableSequential)),
|
|
470
|
+
(ingredientsDispatcher := astModuleToIngredientsFunction(recipeFlow.source_astModule, recipeFlow.sourceCallableDispatcher)),
|
|
471
|
+
]
|
|
472
|
+
|
|
473
|
+
# Inline functions ========================================================
|
|
474
|
+
# NOTE Replacements statements are based on the identifiers in the _source_, so operate on the source identifiers.
|
|
475
|
+
ingredientsInitialize.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableInitialize, recipeFlow.source_astModule)
|
|
476
|
+
ingredientsParallel.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableParallel, recipeFlow.source_astModule)
|
|
477
|
+
ingredientsSequential.astFunctionDef = inlineFunctionDef(recipeFlow.sourceCallableSequential, recipeFlow.source_astModule)
|
|
478
|
+
|
|
479
|
+
# assignRecipeIdentifiersToCallable. =============================
|
|
480
|
+
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
481
|
+
# How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
|
|
482
|
+
# NOTE reminder: you are updating these `ast.Name` here (and not in a more general search) because this is a
|
|
483
|
+
# narrow search for `ast.Call` so you won't accidentally replace unrelated `ast.Name`.
|
|
484
|
+
listFindReplace = [(recipeFlow.sourceCallableDispatcher, recipeFlow.callableDispatcher),
|
|
485
|
+
(recipeFlow.sourceCallableInitialize, recipeFlow.callableInitialize),
|
|
486
|
+
(recipeFlow.sourceCallableParallel, recipeFlow.callableParallel),
|
|
487
|
+
(recipeFlow.sourceCallableSequential, recipeFlow.callableSequential),]
|
|
488
|
+
for ingredients in listAllIngredientsFunctions:
|
|
489
|
+
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
490
|
+
updateCallName = NodeChanger(ifThis.isCall_Identifier(source_Identifier), grab.funcAttribute(Then.replaceWith(Make.Name(recipe_Identifier))))
|
|
491
|
+
updateCallName.visit(ingredients.astFunctionDef)
|
|
492
|
+
|
|
493
|
+
ingredientsDispatcher.astFunctionDef.name = recipeFlow.callableDispatcher
|
|
494
|
+
ingredientsInitialize.astFunctionDef.name = recipeFlow.callableInitialize
|
|
495
|
+
ingredientsParallel.astFunctionDef.name = recipeFlow.callableParallel
|
|
496
|
+
ingredientsSequential.astFunctionDef.name = recipeFlow.callableSequential
|
|
497
|
+
|
|
498
|
+
# Assign identifiers per the recipe. ==============================
|
|
499
|
+
listFindReplace = [(recipeFlow.sourceDataclassInstance, recipeFlow.dataclassInstance),
|
|
500
|
+
(recipeFlow.sourceDataclassInstanceTaskDistribution, recipeFlow.dataclassInstanceTaskDistribution),
|
|
501
|
+
(recipeFlow.sourceConcurrencyManagerNamespace, recipeFlow.concurrencyManagerNamespace),]
|
|
502
|
+
for ingredients in listAllIngredientsFunctions:
|
|
503
|
+
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
504
|
+
updateName = NodeChanger(ifThis.isName_Identifier(source_Identifier) , grab.idAttribute(Then.replaceWith(recipe_Identifier)))
|
|
505
|
+
update_arg = NodeChanger(ifThis.isArgument_Identifier(source_Identifier), grab.argAttribute(Then.replaceWith(recipe_Identifier))) # type: ignore
|
|
506
|
+
updateName.visit(ingredients.astFunctionDef)
|
|
507
|
+
update_arg.visit(ingredients.astFunctionDef)
|
|
508
|
+
|
|
509
|
+
updateConcurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.sourceConcurrencyManagerNamespace, recipeFlow.sourceConcurrencyManagerIdentifier)
|
|
510
|
+
, grab.funcAttribute(Then.replaceWith(Make.Attribute(Make.Name(recipeFlow.concurrencyManagerNamespace), recipeFlow.concurrencyManagerIdentifier))))
|
|
511
|
+
updateConcurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
512
|
+
|
|
513
|
+
# shatter Dataclass =======================================================
|
|
514
|
+
instance_Identifier = recipeFlow.dataclassInstance
|
|
515
|
+
getTheOtherRecord_damn = recipeFlow.dataclassInstanceTaskDistribution
|
|
516
|
+
shatteredDataclass = shatter_dataclassesDOTdataclass(recipeFlow.logicalPathModuleDataclass, recipeFlow.sourceDataclassIdentifier, instance_Identifier)
|
|
517
|
+
ingredientsDispatcher.imports.update(shatteredDataclass.ledger)
|
|
518
|
+
|
|
519
|
+
# How can I use dataclass settings as the SSOT for specific actions? https://github.com/hunterhogan/mapFolding/issues/16
|
|
520
|
+
# Change callable parameters and Call to the callable at the same time ====
|
|
521
|
+
# sequentialCallable =========================================================
|
|
522
|
+
if recipeFlow.removeDataclassSequential:
|
|
523
|
+
ingredientsSequential = removeDataclassFromFunction(ingredientsSequential, shatteredDataclass)
|
|
524
|
+
ingredientsDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsDispatcher, recipeFlow.callableSequential, shatteredDataclass)
|
|
525
|
+
|
|
526
|
+
if recipeFlow.removeDataclassInitialize:
|
|
527
|
+
ingredientsInitialize = removeDataclassFromFunction(ingredientsInitialize, shatteredDataclass)
|
|
528
|
+
ingredientsDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsDispatcher, recipeFlow.callableInitialize, shatteredDataclass)
|
|
529
|
+
|
|
530
|
+
# parallelCallable =========================================================
|
|
531
|
+
if recipeFlow.removeDataclassParallel:
|
|
532
|
+
ingredientsParallel.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
533
|
+
|
|
534
|
+
ingredientsParallel.astFunctionDef = Z0Z_lameFindReplace(ingredientsParallel.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
535
|
+
|
|
536
|
+
ingredientsParallel = removeUnusedParameters(ingredientsParallel)
|
|
537
|
+
|
|
538
|
+
list_argCuzMyBrainRefusesToThink = ingredientsParallel.astFunctionDef.args.args + ingredientsParallel.astFunctionDef.args.posonlyargs + ingredientsParallel.astFunctionDef.args.kwonlyargs
|
|
539
|
+
list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
|
|
540
|
+
|
|
541
|
+
listParameters = [parameter for parameter in shatteredDataclass.listName4Parameters if parameter.id in list_arg_arg]
|
|
542
|
+
|
|
543
|
+
replaceCall2concurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.concurrencyManagerNamespace, recipeFlow.concurrencyManagerIdentifier), Then.replaceWith(Make.Call(Make.Attribute(Make.Name(recipeFlow.concurrencyManagerNamespace), recipeFlow.concurrencyManagerIdentifier), listArguments=[Make.Name(recipeFlow.callableParallel)] + listParameters)))
|
|
544
|
+
|
|
545
|
+
# NOTE I am dissatisfied with this logic for many reasons, including that it requires separate NodeCollector and NodeReplacer instances.
|
|
546
|
+
astCallConcurrencyResult: list[ast.Call] = []
|
|
547
|
+
get_astCallConcurrencyResult = NodeTourist(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), getIt(astCallConcurrencyResult))
|
|
548
|
+
get_astCallConcurrencyResult.visit(ingredientsDispatcher.astFunctionDef)
|
|
549
|
+
replaceAssignParallelCallable = NodeChanger(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), grab.valueAttribute(Then.replaceWith(astCallConcurrencyResult[0])))
|
|
550
|
+
replaceAssignParallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
551
|
+
changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.countingVariableName)))
|
|
552
|
+
ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
|
|
553
|
+
|
|
554
|
+
unpack4parallelCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(recipeFlow.concurrencyManagerNamespace, recipeFlow.concurrencyManagerIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
555
|
+
|
|
556
|
+
unpack4parallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
557
|
+
replaceCall2concurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
558
|
+
changeReturnParallelCallable.visit(ingredientsParallel.astFunctionDef)
|
|
559
|
+
|
|
560
|
+
# Module-level transformations ===========================================================
|
|
561
|
+
ingredientsModuleNumbaUnified = IngredientsModule(ingredientsFunction=listAllIngredientsFunctions, imports=LedgerOfImports(recipeFlow.source_astModule))
|
|
562
|
+
ingredientsModuleNumbaUnified.removeImportFromModule('numpy')
|
|
563
|
+
|
|
564
|
+
return ingredientsModuleNumbaUnified
|
|
565
|
+
|
|
566
|
+
def removeDataclassFromFunction(ingredientsTarget: IngredientsFunction, shatteredDataclass: ShatteredDataclass) -> IngredientsFunction:
|
|
567
|
+
ingredientsTarget.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
568
|
+
ingredientsTarget.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
|
|
569
|
+
changeReturnCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
|
|
570
|
+
changeReturnCallable.visit(ingredientsTarget.astFunctionDef)
|
|
571
|
+
ingredientsTarget.astFunctionDef = Z0Z_lameFindReplace(ingredientsTarget.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
572
|
+
return ingredientsTarget
|
|
573
|
+
|
|
574
|
+
def unpackDataclassCallFunctionRepackDataclass(ingredientsCaller: IngredientsFunction, targetCallableIdentifier: ast_Identifier, shatteredDataclass: ShatteredDataclass) -> IngredientsFunction:
|
|
575
|
+
astCallTargetCallable = Make.Call(Make.Name(targetCallableIdentifier), shatteredDataclass.listName4Parameters)
|
|
576
|
+
replaceAssignTargetCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(targetCallableIdentifier)), Then.replaceWith(Make.Assign(listTargets=[shatteredDataclass.fragments4AssignmentOrParameters], value=astCallTargetCallable)))
|
|
577
|
+
unpack4targetCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(targetCallableIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
578
|
+
repack4targetCallable = NodeChanger(ifThis.isAssignAndValueIs(ifThis.isCall_Identifier(targetCallableIdentifier)), Then.insertThisBelow([shatteredDataclass.repack]))
|
|
579
|
+
replaceAssignTargetCallable.visit(ingredientsCaller.astFunctionDef)
|
|
580
|
+
unpack4targetCallable.visit(ingredientsCaller.astFunctionDef)
|
|
581
|
+
repack4targetCallable.visit(ingredientsCaller.astFunctionDef)
|
|
582
|
+
return ingredientsCaller
|
|
583
|
+
|
|
584
|
+
def getIt(astCallConcurrencyResult: list[ast.Call]) -> Callable[[ast.AST], ast.AST]:
|
|
585
|
+
def workhorse(node: ast.AST) -> ast.AST:
|
|
586
|
+
NodeTourist(be.Call, Then.appendTo(astCallConcurrencyResult)).visit(node)
|
|
587
|
+
return node
|
|
588
|
+
return workhorse
|
|
589
|
+
|
|
419
590
|
dictionaryEstimates: dict[tuple[int, ...], int] = {
|
|
420
591
|
(2,2,2,2,2,2,2,2): 798148657152000,
|
|
421
592
|
(2,21): 776374224866624,
|