mapFolding 0.10.0__py3-none-any.whl → 0.11.0__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 +29 -27
- mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +4 -6
- mapFolding/someAssemblyRequired/__init__.py +15 -24
- mapFolding/someAssemblyRequired/_toolIfThis.py +4 -144
- mapFolding/someAssemblyRequired/_toolboxContainers.py +12 -284
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +6 -6
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +5 -5
- mapFolding/someAssemblyRequired/transformationTools.py +5 -178
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/METADATA +2 -1
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/RECORD +14 -26
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/WHEEL +1 -1
- mapFolding/someAssemblyRequired/_astTypes.py +0 -117
- mapFolding/someAssemblyRequired/_theTypes.py +0 -34
- mapFolding/someAssemblyRequired/_toolBe.py +0 -524
- mapFolding/someAssemblyRequired/_toolDOT.py +0 -493
- mapFolding/someAssemblyRequired/_toolGrab.py +0 -653
- mapFolding/someAssemblyRequired/_toolMake.py +0 -339
- mapFolding/someAssemblyRequired/_toolThen.py +0 -63
- mapFolding/someAssemblyRequired/_toolboxAST.py +0 -57
- mapFolding/someAssemblyRequired/_toolboxPython.py +0 -188
- mapFolding/toolFactory/astFactory.py +0 -493
- mapFolding/toolFactory/astFactory_annex.py +0 -63
- mapFolding/toolFactory/astFactory_docstrings.py +0 -63
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.10.0.dist-info → mapfolding-0.11.0.dist-info}/top_level.txt +0 -0
|
@@ -18,294 +18,16 @@ The containers work in conjunction with transformation tools that manipulate the
|
|
|
18
18
|
specific optimizations and transformations.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
from
|
|
22
|
-
from collections.abc import Callable
|
|
21
|
+
from astToolkit import IngredientsFunction as IngredientsFunction, IngredientsModule as IngredientsModule, LedgerOfImports as LedgerOfImports
|
|
22
|
+
from collections.abc import Callable
|
|
23
23
|
from copy import deepcopy
|
|
24
|
-
from typing import Any
|
|
25
24
|
from mapFolding.someAssemblyRequired import ast_Identifier, DOT, IfThis, Make, NodeTourist, parseLogicalPath2astModule, str_nameDOTname, Then
|
|
26
25
|
from mapFolding.theSSOT import raiseIfNoneGitHubIssueNumber3, The
|
|
27
26
|
from pathlib import Path, PurePosixPath
|
|
28
|
-
from
|
|
27
|
+
from typing import Any, cast
|
|
29
28
|
import ast
|
|
30
29
|
import dataclasses
|
|
31
30
|
|
|
32
|
-
class LedgerOfImports:
|
|
33
|
-
"""
|
|
34
|
-
Track and manage import statements for programmatically generated code.
|
|
35
|
-
|
|
36
|
-
LedgerOfImports acts as a registry for import statements, maintaining a clean separation between the logical
|
|
37
|
-
structure of imports and their textual representation. It enables:
|
|
38
|
-
|
|
39
|
-
1. Tracking regular imports and import-from statements.
|
|
40
|
-
2. Adding imports programmatically during code transformation.
|
|
41
|
-
3. Merging imports from multiple sources.
|
|
42
|
-
4. Removing unnecessary or conflicting imports.
|
|
43
|
-
5. Generating optimized AST import nodes for the final code.
|
|
44
|
-
|
|
45
|
-
This class forms the foundation of dependency management in generated code, ensuring that all required libraries are
|
|
46
|
-
available without duplication or conflict.
|
|
47
|
-
"""
|
|
48
|
-
# TODO When resolving the ledger of imports, remove self-referential imports
|
|
49
|
-
|
|
50
|
-
def __init__(self, startWith: ast.AST | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
51
|
-
self.dictionaryImportFrom: dict[str_nameDOTname, list[tuple[ast_Identifier, ast_Identifier | None]]] = defaultdict(list)
|
|
52
|
-
self.listImport: list[str_nameDOTname] = []
|
|
53
|
-
self.type_ignores = [] if type_ignores is None else list(type_ignores)
|
|
54
|
-
if startWith:
|
|
55
|
-
self.walkThis(startWith)
|
|
56
|
-
|
|
57
|
-
def addAst(self, astImport____: ast.Import | ast.ImportFrom, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
58
|
-
match astImport____:
|
|
59
|
-
case ast.Import():
|
|
60
|
-
for alias in astImport____.names:
|
|
61
|
-
self.listImport.append(alias.name)
|
|
62
|
-
case ast.ImportFrom():
|
|
63
|
-
# TODO fix the mess created by `None` means '.'. I need a `str_nameDOTname` to replace '.'
|
|
64
|
-
if astImport____.module is None:
|
|
65
|
-
astImport____.module = '.'
|
|
66
|
-
for alias in astImport____.names:
|
|
67
|
-
self.dictionaryImportFrom[astImport____.module].append((alias.name, alias.asname))
|
|
68
|
-
case _:
|
|
69
|
-
raise ValueError(f"I received {type(astImport____) = }, but I can only accept {ast.Import} and {ast.ImportFrom}.")
|
|
70
|
-
if type_ignores:
|
|
71
|
-
self.type_ignores.extend(type_ignores)
|
|
72
|
-
|
|
73
|
-
def addImport_asStr(self, moduleWithLogicalPath: str_nameDOTname, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
74
|
-
self.listImport.append(moduleWithLogicalPath)
|
|
75
|
-
if type_ignores:
|
|
76
|
-
self.type_ignores.extend(type_ignores)
|
|
77
|
-
|
|
78
|
-
def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
79
|
-
self.dictionaryImportFrom[moduleWithLogicalPath].append((name, asname))
|
|
80
|
-
if type_ignores:
|
|
81
|
-
self.type_ignores.extend(type_ignores)
|
|
82
|
-
|
|
83
|
-
def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
|
|
84
|
-
"""Remove all imports from a specific module."""
|
|
85
|
-
self.removeImportFrom(moduleWithLogicalPath, None, None)
|
|
86
|
-
|
|
87
|
-
def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
|
|
88
|
-
"""
|
|
89
|
-
name, asname Action
|
|
90
|
-
None, None : remove all matches for the module
|
|
91
|
-
ast_Identifier, ast_Identifier : remove exact matches
|
|
92
|
-
ast_Identifier, None : remove exact matches
|
|
93
|
-
None, ast_Identifier : remove all matches for asname and if entry_asname is None remove name == ast_Identifier
|
|
94
|
-
"""
|
|
95
|
-
if moduleWithLogicalPath in self.dictionaryImportFrom:
|
|
96
|
-
if name is None and asname is None:
|
|
97
|
-
# Remove all entries for the module
|
|
98
|
-
self.dictionaryImportFrom.pop(moduleWithLogicalPath)
|
|
99
|
-
else:
|
|
100
|
-
if name is None:
|
|
101
|
-
self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
|
|
102
|
-
if not (entry_asname == asname) and not (entry_asname is None and entry_name == asname)]
|
|
103
|
-
else:
|
|
104
|
-
self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
|
|
105
|
-
if not (entry_name == name and entry_asname == asname)]
|
|
106
|
-
if not self.dictionaryImportFrom[moduleWithLogicalPath]:
|
|
107
|
-
self.dictionaryImportFrom.pop(moduleWithLogicalPath)
|
|
108
|
-
|
|
109
|
-
def exportListModuleIdentifiers(self) -> list[ast_Identifier]:
|
|
110
|
-
listModuleIdentifiers: list[ast_Identifier] = list(self.dictionaryImportFrom.keys())
|
|
111
|
-
listModuleIdentifiers.extend(self.listImport)
|
|
112
|
-
return sorted(set(listModuleIdentifiers))
|
|
113
|
-
|
|
114
|
-
def makeList_ast(self) -> list[ast.ImportFrom | ast.Import]:
|
|
115
|
-
listImportFrom: list[ast.ImportFrom] = []
|
|
116
|
-
for moduleWithLogicalPath, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
|
|
117
|
-
listOfNameTuples = sorted(list(set(listOfNameTuples)), key=lambda nameTuple: nameTuple[0])
|
|
118
|
-
list_alias: list[ast.alias] = []
|
|
119
|
-
for name, asname in listOfNameTuples:
|
|
120
|
-
list_alias.append(Make.alias(name, asname))
|
|
121
|
-
if list_alias:
|
|
122
|
-
listImportFrom.append(Make.ImportFrom(moduleWithLogicalPath, list_alias))
|
|
123
|
-
list_astImport: list[ast.Import] = [Make.Import(moduleWithLogicalPath) for moduleWithLogicalPath in sorted(set(self.listImport))]
|
|
124
|
-
return listImportFrom + list_astImport
|
|
125
|
-
|
|
126
|
-
def update(self, *fromLedger: 'LedgerOfImports') -> None:
|
|
127
|
-
"""Update this ledger with imports from one or more other ledgers.
|
|
128
|
-
Parameters:
|
|
129
|
-
*fromLedger: One or more other `LedgerOfImports` objects from which to merge.
|
|
130
|
-
"""
|
|
131
|
-
updatedDictionary = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(ledger.dictionaryImportFrom for ledger in fromLedger), destroyDuplicates=True, reorderLists=True)
|
|
132
|
-
self.dictionaryImportFrom = defaultdict(list, updatedDictionary)
|
|
133
|
-
for ledger in fromLedger:
|
|
134
|
-
self.listImport.extend(ledger.listImport)
|
|
135
|
-
self.type_ignores.extend(ledger.type_ignores)
|
|
136
|
-
|
|
137
|
-
def walkThis(self, walkThis: ast.AST, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
138
|
-
for nodeBuffalo in ast.walk(walkThis):
|
|
139
|
-
if isinstance(nodeBuffalo, (ast.Import, ast.ImportFrom)):
|
|
140
|
-
self.addAst(nodeBuffalo)
|
|
141
|
-
if type_ignores:
|
|
142
|
-
self.type_ignores.extend(type_ignores)
|
|
143
|
-
|
|
144
|
-
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
145
|
-
@dataclasses.dataclass
|
|
146
|
-
class IngredientsFunction:
|
|
147
|
-
"""
|
|
148
|
-
Package a function definition with its import dependencies for code generation.
|
|
149
|
-
|
|
150
|
-
IngredientsFunction encapsulates an AST function definition along with all the imports required for that function to
|
|
151
|
-
operate correctly. This creates a modular, portable unit that can be:
|
|
152
|
-
|
|
153
|
-
1. Transformed independently (e.g., by applying Numba decorators).
|
|
154
|
-
2. Transplanted between modules while maintaining dependencies.
|
|
155
|
-
3. Combined with other functions to form complete modules.
|
|
156
|
-
4. Analyzed for optimization opportunities.
|
|
157
|
-
|
|
158
|
-
This class forms the primary unit of function manipulation in the code generation system, enabling targeted
|
|
159
|
-
transformations while preserving function dependencies.
|
|
160
|
-
|
|
161
|
-
Parameters:
|
|
162
|
-
astFunctionDef: The AST representation of the function definition
|
|
163
|
-
imports: Import statements needed by the function
|
|
164
|
-
type_ignores: Type ignore comments associated with the function
|
|
165
|
-
"""
|
|
166
|
-
astFunctionDef: ast.FunctionDef
|
|
167
|
-
imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
|
|
168
|
-
type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
|
|
169
|
-
|
|
170
|
-
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
171
|
-
@dataclasses.dataclass
|
|
172
|
-
class IngredientsModule:
|
|
173
|
-
"""
|
|
174
|
-
Assemble a complete Python module from its constituent AST components.
|
|
175
|
-
|
|
176
|
-
IngredientsModule provides a structured container for all elements needed to generate a complete Python module,
|
|
177
|
-
including:
|
|
178
|
-
|
|
179
|
-
1. Import statements aggregated from all module components.
|
|
180
|
-
2. Prologue code that runs before function definitions.
|
|
181
|
-
3. Function definitions with their dependencies.
|
|
182
|
-
4. Epilogue code that runs after function definitions.
|
|
183
|
-
5. Entry point code executed when the module runs as a script.
|
|
184
|
-
6. Type ignores and other annotations.
|
|
185
|
-
|
|
186
|
-
This class enables programmatic assembly of Python modules with a clear separation between different structural
|
|
187
|
-
elements, while maintaining the proper ordering and relationships between components.
|
|
188
|
-
|
|
189
|
-
The modular design allows transformations to be applied to specific parts of a module while preserving the overall
|
|
190
|
-
structure.
|
|
191
|
-
|
|
192
|
-
Parameters:
|
|
193
|
-
ingredientsFunction (None): One or more `IngredientsFunction` that will appended to `listIngredientsFunctions`.
|
|
194
|
-
"""
|
|
195
|
-
ingredientsFunction: dataclasses.InitVar[Sequence[IngredientsFunction] | IngredientsFunction | None] = None
|
|
196
|
-
|
|
197
|
-
# init var with an existing module? method to deconstruct an existing module?
|
|
198
|
-
|
|
199
|
-
# `body` attribute of `ast.Module`
|
|
200
|
-
"""NOTE
|
|
201
|
-
- Bare statements in `prologue` and `epilogue` are not 'protected' by `if __name__ == '__main__':` so they will be executed merely by loading the module.
|
|
202
|
-
- The dataclass has methods for modifying `prologue`, `epilogue`, and `launcher`.
|
|
203
|
-
- However, `prologue`, `epilogue`, and `launcher` are `ast.Module` (as opposed to `list[ast.stmt]`), so that you may use tools such as `ast.walk` and `ast.NodeVisitor` on the fields.
|
|
204
|
-
"""
|
|
205
|
-
imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
|
|
206
|
-
"""Modify this field using the methods in `LedgerOfImports`."""
|
|
207
|
-
prologue: ast.Module = Make.Module([],[])
|
|
208
|
-
"""Statements after the imports and before the functions in listIngredientsFunctions."""
|
|
209
|
-
listIngredientsFunctions: list[IngredientsFunction] = dataclasses.field(default_factory=list)
|
|
210
|
-
epilogue: ast.Module = Make.Module([],[])
|
|
211
|
-
"""Statements after the functions in listIngredientsFunctions and before `launcher`."""
|
|
212
|
-
launcher: ast.Module = Make.Module([],[])
|
|
213
|
-
"""`if __name__ == '__main__':`"""
|
|
214
|
-
|
|
215
|
-
# `ast.TypeIgnore` statements to supplement those in other fields; `type_ignores` is a parameter for `ast.Module` constructor
|
|
216
|
-
supplemental_type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
|
|
217
|
-
|
|
218
|
-
def __post_init__(self, ingredientsFunction: Sequence[IngredientsFunction] | IngredientsFunction | None = None) -> None:
|
|
219
|
-
if ingredientsFunction is not None:
|
|
220
|
-
if isinstance(ingredientsFunction, IngredientsFunction):
|
|
221
|
-
self.appendIngredientsFunction(ingredientsFunction)
|
|
222
|
-
else:
|
|
223
|
-
self.appendIngredientsFunction(*ingredientsFunction)
|
|
224
|
-
|
|
225
|
-
def _append_astModule(self, self_astModule: ast.Module, astModule: ast.Module | None, statement: Sequence[ast.stmt] | ast.stmt | None, type_ignores: list[ast.TypeIgnore] | None) -> None:
|
|
226
|
-
"""Append one or more statements to `prologue`."""
|
|
227
|
-
list_body: list[ast.stmt] = []
|
|
228
|
-
listTypeIgnore: list[ast.TypeIgnore] = []
|
|
229
|
-
if astModule is not None and isinstance(astModule, ast.Module): # type: ignore
|
|
230
|
-
list_body.extend(astModule.body)
|
|
231
|
-
listTypeIgnore.extend(astModule.type_ignores)
|
|
232
|
-
if type_ignores is not None:
|
|
233
|
-
listTypeIgnore.extend(type_ignores)
|
|
234
|
-
if statement is not None:
|
|
235
|
-
if isinstance(statement, Sequence):
|
|
236
|
-
list_body.extend(statement)
|
|
237
|
-
else:
|
|
238
|
-
list_body.append(statement)
|
|
239
|
-
self_astModule.body.extend(list_body)
|
|
240
|
-
self_astModule.type_ignores.extend(listTypeIgnore)
|
|
241
|
-
ast.fix_missing_locations(self_astModule)
|
|
242
|
-
|
|
243
|
-
def appendPrologue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
244
|
-
"""Append one or more statements to `prologue`."""
|
|
245
|
-
self._append_astModule(self.prologue, astModule, statement, type_ignores)
|
|
246
|
-
|
|
247
|
-
def appendEpilogue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
248
|
-
"""Append one or more statements to `epilogue`."""
|
|
249
|
-
self._append_astModule(self.epilogue, astModule, statement, type_ignores)
|
|
250
|
-
|
|
251
|
-
def appendLauncher(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
252
|
-
"""Append one or more statements to `launcher`."""
|
|
253
|
-
self._append_astModule(self.launcher, astModule, statement, type_ignores)
|
|
254
|
-
|
|
255
|
-
def appendIngredientsFunction(self, *ingredientsFunction: IngredientsFunction) -> None:
|
|
256
|
-
"""Append one or more `IngredientsFunction`."""
|
|
257
|
-
for allegedIngredientsFunction in ingredientsFunction:
|
|
258
|
-
self.listIngredientsFunctions.append(allegedIngredientsFunction)
|
|
259
|
-
|
|
260
|
-
def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
|
|
261
|
-
self.removeImportFrom(moduleWithLogicalPath, None, None)
|
|
262
|
-
"""Remove all imports from a specific module."""
|
|
263
|
-
|
|
264
|
-
def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
|
|
265
|
-
"""
|
|
266
|
-
This method modifies all `LedgerOfImports` in this `IngredientsModule` and all `IngredientsFunction` in `listIngredientsFunctions`.
|
|
267
|
-
It is not a "blacklist", so the `import from` could be added after this modification.
|
|
268
|
-
"""
|
|
269
|
-
self.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
|
|
270
|
-
for ingredientsFunction in self.listIngredientsFunctions:
|
|
271
|
-
ingredientsFunction.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
|
|
272
|
-
|
|
273
|
-
def _consolidatedLedger(self) -> LedgerOfImports:
|
|
274
|
-
"""Consolidate all ledgers of imports."""
|
|
275
|
-
sherpaLedger = LedgerOfImports()
|
|
276
|
-
listLedgers: list[LedgerOfImports] = [self.imports]
|
|
277
|
-
for ingredientsFunction in self.listIngredientsFunctions:
|
|
278
|
-
listLedgers.append(ingredientsFunction.imports)
|
|
279
|
-
sherpaLedger.update(*listLedgers)
|
|
280
|
-
return sherpaLedger
|
|
281
|
-
|
|
282
|
-
@property
|
|
283
|
-
def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
|
|
284
|
-
return self._consolidatedLedger().makeList_ast()
|
|
285
|
-
|
|
286
|
-
@property
|
|
287
|
-
def body(self) -> list[ast.stmt]:
|
|
288
|
-
list_stmt: list[ast.stmt] = []
|
|
289
|
-
list_stmt.extend(self.list_astImportImportFrom)
|
|
290
|
-
list_stmt.extend(self.prologue.body)
|
|
291
|
-
for ingredientsFunction in self.listIngredientsFunctions:
|
|
292
|
-
list_stmt.append(ingredientsFunction.astFunctionDef)
|
|
293
|
-
list_stmt.extend(self.epilogue.body)
|
|
294
|
-
list_stmt.extend(self.launcher.body)
|
|
295
|
-
# TODO `launcher`, if it exists, must start with `if __name__ == '__main__':` and be indented
|
|
296
|
-
return list_stmt
|
|
297
|
-
|
|
298
|
-
@property
|
|
299
|
-
def type_ignores(self) -> list[ast.TypeIgnore]:
|
|
300
|
-
listTypeIgnore: list[ast.TypeIgnore] = self.supplemental_type_ignores
|
|
301
|
-
listTypeIgnore.extend(self._consolidatedLedger().type_ignores)
|
|
302
|
-
listTypeIgnore.extend(self.prologue.type_ignores)
|
|
303
|
-
for ingredientsFunction in self.listIngredientsFunctions:
|
|
304
|
-
listTypeIgnore.extend(ingredientsFunction.type_ignores)
|
|
305
|
-
listTypeIgnore.extend(self.epilogue.type_ignores)
|
|
306
|
-
listTypeIgnore.extend(self.launcher.type_ignores)
|
|
307
|
-
return listTypeIgnore
|
|
308
|
-
|
|
309
31
|
# Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
|
|
310
32
|
@dataclasses.dataclass
|
|
311
33
|
class RecipeSynthesizeFlow:
|
|
@@ -531,7 +253,13 @@ class DeReConstructField2ast:
|
|
|
531
253
|
self.ast_keyword_field__field = Make.keyword(self.name, self.astName)
|
|
532
254
|
self.ast_nameDOTname = Make.Attribute(Make.Name(dataclassesDOTdataclassInstance_Identifier), self.name)
|
|
533
255
|
|
|
534
|
-
|
|
256
|
+
findThis = IfThis.isAnnAssign_targetIs(IfThis.isName_Identifier(self.name))
|
|
257
|
+
|
|
258
|
+
sherpa = NodeTourist(
|
|
259
|
+
findThis=findThis
|
|
260
|
+
, doThat=Then.extractIt(DOT.annotation)
|
|
261
|
+
).captureLastMatch(dataclassClassDef)
|
|
262
|
+
|
|
535
263
|
if sherpa is None: raise raiseIfNoneGitHubIssueNumber3
|
|
536
264
|
else: self.astAnnotation = sherpa
|
|
537
265
|
|
|
@@ -544,7 +272,7 @@ class DeReConstructField2ast:
|
|
|
544
272
|
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotationType)
|
|
545
273
|
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, 'dtype')
|
|
546
274
|
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Name('uint8'))
|
|
547
|
-
dtype_asnameName: ast.Name = self.astAnnotation
|
|
275
|
+
dtype_asnameName: ast.Name = cast(ast.Name, self.astAnnotation)
|
|
548
276
|
if dtype_asnameName.id == 'Array3D':
|
|
549
277
|
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Tuple([Make.Name('uint8'), Make.Name('uint8'), Make.Name('uint8')]))
|
|
550
278
|
ast_expr = Make.Subscript(Make.Name(annotationType), Make.Tuple([axesSubscript, Make.Subscript(Make.Name('dtype'), dtype_asnameName)]))
|
|
@@ -561,7 +289,7 @@ class DeReConstructField2ast:
|
|
|
561
289
|
elif isinstance(self.astAnnotation, ast.Subscript):
|
|
562
290
|
elementConstructor: ast_Identifier = self.metadata['elementConstructor']
|
|
563
291
|
self.ledger.addImportFrom_asStr(dataclassesDOTdataclassLogicalPathModule, elementConstructor)
|
|
564
|
-
takeTheTuple
|
|
292
|
+
takeTheTuple = deepcopy(self.astAnnotation.slice)
|
|
565
293
|
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, takeTheTuple)
|
|
566
294
|
self.Z0Z_hack = (self.astAnnAssignConstructor, elementConstructor)
|
|
567
295
|
if isinstance(self.astAnnotation, ast.Name):
|
|
@@ -15,7 +15,7 @@ from mapFolding.someAssemblyRequired import (
|
|
|
15
15
|
)
|
|
16
16
|
from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2Numba
|
|
17
17
|
from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
|
|
18
|
-
from mapFolding.someAssemblyRequired.transformationTools import
|
|
18
|
+
from mapFolding.someAssemblyRequired.transformationTools import write_astModule
|
|
19
19
|
from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
|
|
20
20
|
from mapFolding.dataBaskets import MapFoldingState
|
|
21
21
|
from pathlib import PurePosixPath
|
|
@@ -77,7 +77,7 @@ if __name__ == '__main__':
|
|
|
77
77
|
ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
|
|
78
78
|
ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
|
|
79
79
|
|
|
80
|
-
findThis = IfThis.
|
|
80
|
+
findThis = IfThis.isAugAssignAndTargetIs(IfThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
|
|
81
81
|
doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
|
|
82
82
|
countWithProgressBar = NodeChanger(findThis, doThat)
|
|
83
83
|
countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
|
|
@@ -131,19 +131,19 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
|
|
|
131
131
|
ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
|
|
132
132
|
match elementConstructor:
|
|
133
133
|
case 'scalar':
|
|
134
|
-
ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg])
|
|
134
|
+
cast(ast.Constant, cast(ast.Call, ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
|
|
135
135
|
case 'array':
|
|
136
136
|
dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
|
|
137
137
|
dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
|
|
138
|
-
ImaAnnAssign.value.args = [dataAs_astExpr]
|
|
138
|
+
cast(ast.Call, ImaAnnAssign.value).args = [dataAs_astExpr]
|
|
139
139
|
case _:
|
|
140
140
|
list_exprDOTannotation: list[ast.expr] = []
|
|
141
141
|
list_exprDOTvalue: list[ast.expr] = []
|
|
142
142
|
for dimension in job.state.mapShape:
|
|
143
143
|
list_exprDOTannotation.append(Make.Name(elementConstructor))
|
|
144
144
|
list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
|
|
145
|
-
ImaAnnAssign.annotation.slice.elts = list_exprDOTannotation
|
|
146
|
-
ImaAnnAssign.value.elts = list_exprDOTvalue
|
|
145
|
+
cast(ast.Tuple, cast(ast.Subscript, cast(ast.AnnAssign, ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
|
|
146
|
+
cast(ast.Tuple, ImaAnnAssign.value).elts = list_exprDOTvalue
|
|
147
147
|
|
|
148
148
|
ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
|
|
149
149
|
|
|
@@ -95,7 +95,7 @@ if __name__ == '__main__':
|
|
|
95
95
|
ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
|
|
96
96
|
ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
|
|
97
97
|
|
|
98
|
-
findThis = IfThis.
|
|
98
|
+
findThis = IfThis.isAugAssignAndTargetIs(IfThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
|
|
99
99
|
doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
|
|
100
100
|
countWithProgressBar = NodeChanger(findThis, doThat)
|
|
101
101
|
countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
|
|
@@ -149,19 +149,19 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
|
|
|
149
149
|
ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
|
|
150
150
|
match elementConstructor:
|
|
151
151
|
case 'scalar':
|
|
152
|
-
ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg])
|
|
152
|
+
cast(ast.Constant, cast(ast.Call, ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
|
|
153
153
|
case 'array':
|
|
154
154
|
dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
|
|
155
155
|
dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
|
|
156
|
-
ImaAnnAssign.value.args = [dataAs_astExpr]
|
|
156
|
+
cast(ast.Call, ImaAnnAssign.value).args = [dataAs_astExpr]
|
|
157
157
|
case _:
|
|
158
158
|
list_exprDOTannotation: list[ast.expr] = []
|
|
159
159
|
list_exprDOTvalue: list[ast.expr] = []
|
|
160
160
|
for dimension in job.state.mapShape:
|
|
161
161
|
list_exprDOTannotation.append(Make.Name(elementConstructor))
|
|
162
162
|
list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
|
|
163
|
-
ImaAnnAssign.annotation.slice.elts = list_exprDOTannotation
|
|
164
|
-
ImaAnnAssign.value.elts = list_exprDOTvalue
|
|
163
|
+
cast(ast.Tuple, cast(ast.Subscript, cast(ast.AnnAssign, ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
|
|
164
|
+
cast(ast.Tuple, ImaAnnAssign.value).elts = list_exprDOTvalue
|
|
165
165
|
|
|
166
166
|
ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
|
|
167
167
|
|
|
@@ -18,7 +18,7 @@ readable, maintainable implementations to highly optimized versions while preser
|
|
|
18
18
|
logical structure and correctness.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
from
|
|
21
|
+
from astToolkit.transformationTools import ( inlineFunctionDef as inlineFunctionDef, removeUnusedParameters as removeUnusedParameters, write_astModule as write_astModule, )
|
|
22
22
|
from collections.abc import Callable, Mapping
|
|
23
23
|
from copy import deepcopy
|
|
24
24
|
from mapFolding.beDRY import outfitCountFolds
|
|
@@ -27,7 +27,6 @@ from mapFolding.someAssemblyRequired import (
|
|
|
27
27
|
astModuleToIngredientsFunction,
|
|
28
28
|
Be,
|
|
29
29
|
DeReConstructField2ast,
|
|
30
|
-
DOT,
|
|
31
30
|
extractClassDef,
|
|
32
31
|
Grab,
|
|
33
32
|
IfThis,
|
|
@@ -45,102 +44,14 @@ from mapFolding.someAssemblyRequired import (
|
|
|
45
44
|
Then,
|
|
46
45
|
个,
|
|
47
46
|
)
|
|
48
|
-
from mapFolding.theSSOT import ComputationState,
|
|
49
|
-
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal
|
|
47
|
+
from mapFolding.theSSOT import ComputationState, The
|
|
48
|
+
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal
|
|
50
49
|
from os import PathLike
|
|
51
50
|
from pathlib import Path, PurePath
|
|
52
51
|
from typing import Any, Literal, overload
|
|
53
52
|
import ast
|
|
54
53
|
import dataclasses
|
|
55
54
|
import pickle
|
|
56
|
-
import python_minifier
|
|
57
|
-
|
|
58
|
-
def makeDictionaryFunctionDef(module: ast.Module) -> dict[ast_Identifier, ast.FunctionDef]:
|
|
59
|
-
"""
|
|
60
|
-
Create a dictionary mapping function names to their AST definitions.
|
|
61
|
-
|
|
62
|
-
This function creates a dictionary that maps function names to their AST function
|
|
63
|
-
definition nodes for all functions defined in the given module.
|
|
64
|
-
|
|
65
|
-
Parameters:
|
|
66
|
-
module: The AST module to extract function definitions from.
|
|
67
|
-
|
|
68
|
-
Returns:
|
|
69
|
-
A dictionary mapping function identifiers to their AST function definition nodes.
|
|
70
|
-
"""
|
|
71
|
-
dictionaryIdentifier2FunctionDef: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
72
|
-
NodeTourist(Be.FunctionDef, Then.updateKeyValueIn(DOT.name, Then.extractIt, dictionaryIdentifier2FunctionDef)).visit(module)
|
|
73
|
-
return dictionaryIdentifier2FunctionDef
|
|
74
|
-
|
|
75
|
-
def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) -> ast.FunctionDef:
|
|
76
|
-
"""
|
|
77
|
-
Inline function calls within a function definition to create a self-contained function.
|
|
78
|
-
|
|
79
|
-
This function takes a function identifier and a module, finds the function definition,
|
|
80
|
-
and then recursively inlines all function calls within that function with their
|
|
81
|
-
implementation bodies. This produces a fully inlined function that doesn't depend
|
|
82
|
-
on other function definitions from the module.
|
|
83
|
-
|
|
84
|
-
Parameters:
|
|
85
|
-
identifierToInline: The name of the function to inline.
|
|
86
|
-
module: The AST module containing the function and its dependencies.
|
|
87
|
-
|
|
88
|
-
Returns:
|
|
89
|
-
A modified function definition with all function calls inlined.
|
|
90
|
-
|
|
91
|
-
Raises:
|
|
92
|
-
ValueError: If the function to inline is not found in the module.
|
|
93
|
-
"""
|
|
94
|
-
dictionaryFunctionDef: dict[ast_Identifier, ast.FunctionDef] = makeDictionaryFunctionDef(module)
|
|
95
|
-
try:
|
|
96
|
-
FunctionDefToInline = dictionaryFunctionDef[identifierToInline]
|
|
97
|
-
except KeyError as ERRORmessage:
|
|
98
|
-
raise ValueError(f"FunctionDefToInline not found in dictionaryIdentifier2FunctionDef: {identifierToInline = }") from ERRORmessage
|
|
99
|
-
|
|
100
|
-
listIdentifiersCalledFunctions: list[ast_Identifier] = []
|
|
101
|
-
findIdentifiersToInline = NodeTourist(findThis = IfThis.isCallToName, doThat = Grab.funcDOTidAttribute(Then.appendTo(listIdentifiersCalledFunctions)))
|
|
102
|
-
findIdentifiersToInline.visit(FunctionDefToInline)
|
|
103
|
-
|
|
104
|
-
dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
105
|
-
for identifier in sorted(set(listIdentifiersCalledFunctions).intersection(dictionaryFunctionDef.keys())):
|
|
106
|
-
if NodeTourist(IfThis.matchesMeButNotAnyDescendant(IfThis.isCall_Identifier(identifier)), Then.extractIt).captureLastMatch(module) is not None:
|
|
107
|
-
dictionary4Inlining[identifier] = dictionaryFunctionDef[identifier]
|
|
108
|
-
|
|
109
|
-
keepGoing = True
|
|
110
|
-
while keepGoing:
|
|
111
|
-
keepGoing = False
|
|
112
|
-
listIdentifiersCalledFunctions.clear()
|
|
113
|
-
findIdentifiersToInline.visit(Make.Module(list(dictionary4Inlining.values())))
|
|
114
|
-
|
|
115
|
-
listIdentifiersCalledFunctions = sorted((set(listIdentifiersCalledFunctions).difference(dictionary4Inlining.keys())).intersection(dictionaryFunctionDef.keys()))
|
|
116
|
-
if len(listIdentifiersCalledFunctions) > 0:
|
|
117
|
-
keepGoing = True
|
|
118
|
-
for identifier in listIdentifiersCalledFunctions:
|
|
119
|
-
if NodeTourist(IfThis.matchesMeButNotAnyDescendant(IfThis.isCall_Identifier(identifier)), Then.extractIt).captureLastMatch(module) is not None:
|
|
120
|
-
FunctionDefTarget = dictionaryFunctionDef[identifier]
|
|
121
|
-
if len(FunctionDefTarget.body) == 1:
|
|
122
|
-
replacement = NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(FunctionDefTarget)
|
|
123
|
-
|
|
124
|
-
findThis = IfThis.isCall_Identifier(identifier)
|
|
125
|
-
doThat = Then.replaceWith(replacement)
|
|
126
|
-
inliner = NodeChanger(findThis, doThat)
|
|
127
|
-
for astFunctionDef in dictionary4Inlining.values():
|
|
128
|
-
inliner.visit(astFunctionDef)
|
|
129
|
-
else:
|
|
130
|
-
inliner = NodeChanger(IfThis.isAssignAndValueIs(IfThis.isCall_Identifier(identifier)),Then.replaceWith(FunctionDefTarget.body[0:-1]))
|
|
131
|
-
for astFunctionDef in dictionary4Inlining.values():
|
|
132
|
-
inliner.visit(astFunctionDef)
|
|
133
|
-
|
|
134
|
-
for identifier, FunctionDefTarget in dictionary4Inlining.items():
|
|
135
|
-
if len(FunctionDefTarget.body) == 1:
|
|
136
|
-
replacement = NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(FunctionDefTarget)
|
|
137
|
-
inliner = NodeChanger(IfThis.isCall_Identifier(identifier), Then.replaceWith(replacement))
|
|
138
|
-
inliner.visit(FunctionDefToInline)
|
|
139
|
-
else:
|
|
140
|
-
inliner = NodeChanger(IfThis.isAssignAndValueIs(IfThis.isCall_Identifier(identifier)),Then.replaceWith(FunctionDefTarget.body[0:-1]))
|
|
141
|
-
inliner.visit(FunctionDefToInline)
|
|
142
|
-
ast.fix_missing_locations(FunctionDefToInline)
|
|
143
|
-
return FunctionDefToInline
|
|
144
55
|
|
|
145
56
|
@overload
|
|
146
57
|
def makeInitializedComputationState(mapShape: tuple[int, ...], writeJob: Literal[True], *, pathFilename: PathLike[str] | PurePath | None = None, **keywordArguments: Any) -> Path: ...
|
|
@@ -248,91 +159,7 @@ def shatter_dataclassesDOTdataclass(logicalPathModule: str_nameDOTname, dataclas
|
|
|
248
159
|
|
|
249
160
|
return shatteredDataclass
|
|
250
161
|
|
|
251
|
-
def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any] | PurePath, packageName: ast_Identifier | None = None) -> None:
|
|
252
|
-
"""
|
|
253
|
-
Convert an IngredientsModule to Python source code and write it to a file.
|
|
254
|
-
|
|
255
|
-
This function renders an IngredientsModule into executable Python code,
|
|
256
|
-
applies code quality improvements like import organization via autoflake,
|
|
257
|
-
and writes the result to the specified file path.
|
|
258
|
-
|
|
259
|
-
The function performs several key steps:
|
|
260
|
-
1. Converts the AST module structure to a valid Python AST
|
|
261
|
-
2. Fixes location attributes in the AST for proper formatting
|
|
262
|
-
3. Converts the AST to Python source code
|
|
263
|
-
4. Optimizes imports using autoflake
|
|
264
|
-
5. Writes the final source code to the specified file location
|
|
265
|
-
|
|
266
|
-
This is typically the final step in the code generation assembly line,
|
|
267
|
-
producing optimized Python modules ready for execution.
|
|
268
|
-
|
|
269
|
-
Parameters:
|
|
270
|
-
ingredients: The IngredientsModule containing the module definition.
|
|
271
|
-
pathFilename: The file path where the module should be written.
|
|
272
|
-
packageName: Optional package name to preserve in import optimization.
|
|
273
|
-
|
|
274
|
-
Raises:
|
|
275
|
-
raiseIfNoneGitHubIssueNumber3: If the generated source code is empty.
|
|
276
|
-
"""
|
|
277
|
-
astModule = Make.Module(ingredients.body, ingredients.type_ignores)
|
|
278
|
-
ast.fix_missing_locations(astModule)
|
|
279
|
-
pythonSource: str = ast.unparse(astModule)
|
|
280
|
-
if not pythonSource: raise raiseIfNoneGitHubIssueNumber3
|
|
281
|
-
autoflake_additional_imports: list[str] = ingredients.imports.exportListModuleIdentifiers()
|
|
282
|
-
if packageName:
|
|
283
|
-
autoflake_additional_imports.append(packageName)
|
|
284
|
-
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)
|
|
285
|
-
# pythonSource = python_minifier.minify(pythonSource, remove_annotations=False, hoist_literals=False)
|
|
286
|
-
writeStringToHere(pythonSource, pathFilename)
|
|
287
|
-
|
|
288
162
|
# END of acceptable classes and functions ======================================================
|
|
289
|
-
def removeUnusedParameters(ingredientsFunction: IngredientsFunction) -> IngredientsFunction:
|
|
290
|
-
"""
|
|
291
|
-
Removes unused parameters from a function's AST definition, return statement, and annotation.
|
|
292
|
-
|
|
293
|
-
This function analyzes the Abstract Syntax Tree (AST) of a given function and removes
|
|
294
|
-
any parameters that are not referenced within the function body. It updates the
|
|
295
|
-
function signature, the return statement (if it's a tuple containing unused variables),
|
|
296
|
-
and the return type annotation accordingly.
|
|
297
|
-
|
|
298
|
-
Parameters
|
|
299
|
-
----------
|
|
300
|
-
ingredientsFunction : IngredientsFunction
|
|
301
|
-
An object containing the AST representation of a function to be processed.
|
|
302
|
-
|
|
303
|
-
Returns
|
|
304
|
-
-------
|
|
305
|
-
IngredientsFunction
|
|
306
|
-
The modified IngredientsFunction object with unused parameters and corresponding
|
|
307
|
-
return elements/annotations removed from its AST.
|
|
308
|
-
|
|
309
|
-
The modification is done in-place on the original AST nodes within the IngredientsFunction object.
|
|
310
|
-
"""
|
|
311
|
-
list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
|
|
312
|
-
list_arg_arg: list[ast_Identifier] = [ast_arg.arg for ast_arg in list_argCuzMyBrainRefusesToThink]
|
|
313
|
-
listName: list[ast.Name] = []
|
|
314
|
-
fauxFunctionDef = deepcopy(ingredientsFunction.astFunctionDef)
|
|
315
|
-
NodeChanger(Be.Return, Then.removeIt).visit(fauxFunctionDef)
|
|
316
|
-
NodeTourist(Be.Name, Then.appendTo(listName)).visit(fauxFunctionDef)
|
|
317
|
-
list_Identifiers: list[ast_Identifier] = [astName.id for astName in listName]
|
|
318
|
-
list_IdentifiersNotUsed: list[ast_Identifier] = list(set(list_arg_arg) - set(list_Identifiers))
|
|
319
|
-
for arg_Identifier in list_IdentifiersNotUsed:
|
|
320
|
-
remove_arg = NodeChanger(IfThis.is_arg_Identifier(arg_Identifier), Then.removeIt)
|
|
321
|
-
remove_arg.visit(ingredientsFunction.astFunctionDef)
|
|
322
|
-
|
|
323
|
-
list_argCuzMyBrainRefusesToThink = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
|
|
324
|
-
|
|
325
|
-
listName: list[ast.Name] = [Make.Name(ast_arg.arg) for ast_arg in list_argCuzMyBrainRefusesToThink]
|
|
326
|
-
replaceReturn = NodeChanger(Be.Return, Then.replaceWith(Make.Return(Make.Tuple(listName))))
|
|
327
|
-
replaceReturn.visit(ingredientsFunction.astFunctionDef)
|
|
328
|
-
|
|
329
|
-
list_annotation: list[ast.expr] = [ast_arg.annotation for ast_arg in list_argCuzMyBrainRefusesToThink if ast_arg.annotation is not None]
|
|
330
|
-
ingredientsFunction.astFunctionDef.returns = Make.Subscript(Make.Name('tuple'), Make.Tuple(list_annotation))
|
|
331
|
-
|
|
332
|
-
ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
|
|
333
|
-
|
|
334
|
-
return ingredientsFunction
|
|
335
|
-
|
|
336
163
|
def makeNewFlow(recipeFlow: RecipeSynthesizeFlow) -> IngredientsModule:
|
|
337
164
|
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
338
165
|
listAllIngredientsFunctions = [
|
|
@@ -374,7 +201,7 @@ def makeNewFlow(recipeFlow: RecipeSynthesizeFlow) -> IngredientsModule:
|
|
|
374
201
|
for ingredients in listAllIngredientsFunctions:
|
|
375
202
|
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
376
203
|
updateName = NodeChanger(IfThis.isName_Identifier(source_Identifier) , Grab.idAttribute(Then.replaceWith(recipe_Identifier)))
|
|
377
|
-
update_arg = NodeChanger(IfThis.isArgument_Identifier(source_Identifier), Grab.argAttribute(Then.replaceWith(recipe_Identifier)))
|
|
204
|
+
update_arg = NodeChanger(IfThis.isArgument_Identifier(source_Identifier), Grab.argAttribute(Then.replaceWith(recipe_Identifier)))
|
|
378
205
|
updateName.visit(ingredients.astFunctionDef)
|
|
379
206
|
update_arg.visit(ingredients.astFunctionDef)
|
|
380
207
|
|
|
@@ -494,7 +321,7 @@ def Z0Z_lameFindReplace(astTree: 个, mappingFindReplaceNodes: Mapping[ast.AST,
|
|
|
494
321
|
|
|
495
322
|
while keepGoing:
|
|
496
323
|
for nodeFind, nodeReplace in mappingFindReplaceNodes.items():
|
|
497
|
-
NodeChanger(IfThis.
|
|
324
|
+
NodeChanger(IfThis.unparseIs(nodeFind), Then.replaceWith(nodeReplace)).visit(newTree)
|
|
498
325
|
|
|
499
326
|
if ast.unparse(newTree) == ast.unparse(astTree):
|
|
500
327
|
keepGoing = False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mapFolding
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License: CC-BY-NC-4.0
|
|
@@ -31,6 +31,7 @@ Classifier: Typing :: Typed
|
|
|
31
31
|
Requires-Python: >=3.10
|
|
32
32
|
Description-Content-Type: text/markdown
|
|
33
33
|
License-File: LICENSE
|
|
34
|
+
Requires-Dist: astToolkit
|
|
34
35
|
Requires-Dist: autoflake
|
|
35
36
|
Requires-Dist: cytoolz
|
|
36
37
|
Requires-Dist: more_itertools
|