mapFolding 0.12.1__py3-none-any.whl → 0.12.3__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 +46 -20
- mapFolding/_theSSOT.py +81 -0
- mapFolding/_theTypes.py +148 -0
- mapFolding/basecamp.py +62 -47
- mapFolding/beDRY.py +100 -73
- mapFolding/dataBaskets.py +226 -31
- mapFolding/filesystemToolkit.py +161 -107
- mapFolding/oeis.py +388 -174
- mapFolding/reference/flattened.py +1 -1
- mapFolding/someAssemblyRequired/RecipeJob.py +146 -20
- mapFolding/someAssemblyRequired/__init__.py +60 -38
- mapFolding/someAssemblyRequired/_toolIfThis.py +125 -35
- mapFolding/someAssemblyRequired/_toolkitContainers.py +125 -44
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +35 -26
- mapFolding/someAssemblyRequired/infoBooth.py +37 -2
- mapFolding/someAssemblyRequired/makeAllModules.py +785 -0
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +161 -74
- mapFolding/someAssemblyRequired/toolkitNumba.py +218 -36
- mapFolding/someAssemblyRequired/transformationTools.py +125 -58
- mapfolding-0.12.3.dist-info/METADATA +163 -0
- mapfolding-0.12.3.dist-info/RECORD +53 -0
- {mapfolding-0.12.1.dist-info → mapfolding-0.12.3.dist-info}/WHEEL +1 -1
- tests/__init__.py +28 -44
- tests/conftest.py +66 -61
- tests/test_computations.py +64 -89
- tests/test_filesystem.py +25 -1
- tests/test_oeis.py +37 -7
- tests/test_other.py +29 -2
- tests/test_tasks.py +30 -2
- mapFolding/datatypes.py +0 -18
- mapFolding/someAssemblyRequired/Z0Z_makeAllModules.py +0 -433
- mapFolding/theSSOT.py +0 -34
- mapfolding-0.12.1.dist-info/METADATA +0 -184
- mapfolding-0.12.1.dist-info/RECORD +0 -53
- {mapfolding-0.12.1.dist-info → mapfolding-0.12.3.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.12.1.dist-info → mapfolding-0.12.3.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.12.1.dist-info → mapfolding-0.12.3.dist-info}/top_level.txt +0 -0
|
@@ -1,30 +1,63 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Numba
|
|
2
|
+
Map folding AST transformation system: Numba integration and just-in-time compilation optimization.
|
|
3
3
|
|
|
4
|
-
This module provides
|
|
5
|
-
Numba-
|
|
6
|
-
|
|
4
|
+
This module provides the compilation optimization layer of the map folding AST transformation system,
|
|
5
|
+
implementing comprehensive tools for applying Numba's just-in-time compilation to functions generated
|
|
6
|
+
by the core transformation tools. Building upon the dataclass decomposition and function optimization
|
|
7
|
+
capabilities established in the operational core, this module completes the transformation process
|
|
8
|
+
by applying aggressive performance optimizations through strategic compiler configuration.
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
The integration addresses the final stage of the transformation process where decomposed, optimized
|
|
11
|
+
functions receive Numba decorators with carefully configured optimization parameters. The module
|
|
12
|
+
handles the complexities of type signature generation, import management, and decorator conflict
|
|
13
|
+
resolution that arise when converting high-level map folding algorithms into machine-optimized code.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
Two primary compilation strategies accommodate different performance and compatibility requirements:
|
|
16
|
+
aggressive optimization for production numerical computing provides maximum performance through
|
|
17
|
+
comprehensive compiler directives including nopython mode, bounds checking elimination, forced
|
|
18
|
+
function inlining, and fastmath optimizations; lightweight optimization maintains broader compatibility
|
|
19
|
+
while achieving significant performance gains through selective compiler optimizations suitable for
|
|
20
|
+
development and testing environments.
|
|
21
|
+
|
|
22
|
+
The strategic application of these optimization configurations enables map folding calculations that
|
|
23
|
+
require hours or days to complete, transforming abstract mathematical algorithms into highly efficient
|
|
24
|
+
computational modules. The compilation layer integrates seamlessly with the broader transformation
|
|
25
|
+
system to produce standalone modules optimized for specific map dimensions and computational contexts.
|
|
16
26
|
"""
|
|
17
27
|
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from astToolkit import IngredientsFunction, Make, str_nameDOTname
|
|
21
|
-
from astToolkit.transformationTools import write_astModule
|
|
22
|
-
from numba.core.compiler import CompilerBase as numbaCompilerBase
|
|
23
|
-
from typing import Any, cast, Final
|
|
28
|
+
from astToolkit import identifierDotAttribute, IngredientsFunction, Make
|
|
29
|
+
from typing import cast, Final, NotRequired, TYPE_CHECKING, TypedDict
|
|
24
30
|
import ast
|
|
25
31
|
import dataclasses
|
|
32
|
+
import warnings
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from collections.abc import Sequence
|
|
26
36
|
|
|
27
37
|
class ParametersNumba(TypedDict):
|
|
38
|
+
"""
|
|
39
|
+
Configuration parameters for Numba compilation decorators.
|
|
40
|
+
|
|
41
|
+
This TypedDict defines all possible configuration options that can be passed to Numba's
|
|
42
|
+
`@jit` decorator to control compilation behavior. The parameters enable fine-tuned control
|
|
43
|
+
over optimization strategies, debugging features, and runtime behavior.
|
|
44
|
+
|
|
45
|
+
Key compilation modes:
|
|
46
|
+
nopython: Forces compilation without Python fallback for maximum performance
|
|
47
|
+
cache: Enables compilation result caching to disk for faster subsequent runs
|
|
48
|
+
fastmath: Allows aggressive mathematical optimizations at cost of IEEE compliance
|
|
49
|
+
parallel: Enables automatic parallelization of supported operations
|
|
50
|
+
|
|
51
|
+
Debug and development options:
|
|
52
|
+
debug: Enables debug information generation
|
|
53
|
+
boundscheck: Controls array bounds checking (disabled for performance in production)
|
|
54
|
+
error_model: Defines how numerical errors are handled ('numpy' vs 'python')
|
|
55
|
+
|
|
56
|
+
Only `cache`, `error_model`, and `fastmath` are required fields. All other fields are
|
|
57
|
+
optional via `NotRequired`, allowing flexible configuration while requiring explicit
|
|
58
|
+
decisions on critical performance and correctness parameters.
|
|
59
|
+
"""
|
|
60
|
+
|
|
28
61
|
_dbg_extend_lifetimes: NotRequired[bool]
|
|
29
62
|
_dbg_optnone: NotRequired[bool]
|
|
30
63
|
_nrt: NotRequired[bool]
|
|
@@ -36,7 +69,7 @@ class ParametersNumba(TypedDict):
|
|
|
36
69
|
forceinline: NotRequired[bool]
|
|
37
70
|
forceobj: NotRequired[bool]
|
|
38
71
|
inline: NotRequired[str]
|
|
39
|
-
locals: NotRequired[dict[str, Any]]
|
|
72
|
+
# locals: NotRequired[dict[str, Any]]
|
|
40
73
|
looplift: NotRequired[bool]
|
|
41
74
|
no_cfunc_wrapper: NotRequired[bool]
|
|
42
75
|
no_cpython_wrapper: NotRequired[bool]
|
|
@@ -44,35 +77,154 @@ class ParametersNumba(TypedDict):
|
|
|
44
77
|
nogil: NotRequired[bool]
|
|
45
78
|
nopython: NotRequired[bool]
|
|
46
79
|
parallel: NotRequired[bool]
|
|
47
|
-
pipeline_class: NotRequired[type[numbaCompilerBase]]
|
|
48
|
-
signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
|
|
80
|
+
# pipeline_class: NotRequired[type[numbaCompilerBase]]
|
|
81
|
+
# signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
|
|
49
82
|
target: NotRequired[str]
|
|
50
83
|
|
|
51
|
-
parametersNumbaDefault: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': False, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False
|
|
52
|
-
"""
|
|
84
|
+
parametersNumbaDefault: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': False, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False }
|
|
85
|
+
"""
|
|
86
|
+
Comprehensive Numba configuration for maximum performance optimization.
|
|
87
|
+
|
|
88
|
+
This configuration provides aggressive optimization settings suitable for production
|
|
89
|
+
numerical computing code. Key characteristics:
|
|
90
|
+
Enables nopython mode for full compilation without Python fallback
|
|
91
|
+
Disables bounds checking for maximum array access performance
|
|
92
|
+
Forces function inlining with 'always' policy for reduced call overhead
|
|
93
|
+
Uses numpy error model for consistent numerical behavior
|
|
94
|
+
Enables fastmath for aggressive floating-point optimizations
|
|
95
|
+
Disables loop lifting to prevent unexpected performance penalties
|
|
96
|
+
|
|
97
|
+
The configuration prioritizes execution speed over compatibility, producing highly
|
|
98
|
+
optimized machine code at the cost of reduced interoperability with uncompiled
|
|
99
|
+
Python functions.
|
|
100
|
+
"""
|
|
101
|
+
|
|
53
102
|
parametersNumbaLight: Final[ParametersNumba] = {'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True}
|
|
103
|
+
"""
|
|
104
|
+
Minimal Numba configuration for basic optimization with maximum compatibility.
|
|
105
|
+
|
|
106
|
+
This lightweight configuration provides essential optimizations while maintaining
|
|
107
|
+
broad compatibility with existing Python code. Suitable for:
|
|
108
|
+
Development and debugging phases
|
|
109
|
+
Code that needs to interoperate with non-Numba functions
|
|
110
|
+
Situations where full nopython mode causes compilation issues
|
|
111
|
+
|
|
112
|
+
Key features:
|
|
113
|
+
Enables compilation caching for faster subsequent runs
|
|
114
|
+
Uses numpy error model for consistent mathematical behavior
|
|
115
|
+
Enables fastmath and function inlining for performance gains
|
|
116
|
+
Allows Python object mode fallback when needed
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
Z0Z_numbaDataTypeModule: identifierDotAttribute = 'numba'
|
|
120
|
+
"""
|
|
121
|
+
Module identifier for Numba imports and type annotations.
|
|
122
|
+
|
|
123
|
+
This constant specifies the module path used when importing Numba-specific types and decorators
|
|
124
|
+
in generated code. It serves as the single source of truth for the Numba module reference,
|
|
125
|
+
enabling consistent import statements across all generated functions.
|
|
126
|
+
"""
|
|
54
127
|
|
|
55
|
-
Z0Z_numbaDataTypeModule: str_nameDOTname = 'numba'
|
|
56
128
|
Z0Z_decoratorCallable: str = 'jit'
|
|
129
|
+
"""
|
|
130
|
+
The Numba decorator function name used for just-in-time compilation.
|
|
131
|
+
|
|
132
|
+
This constant identifies the specific Numba decorator applied to functions for compilation.
|
|
133
|
+
While Numba offers multiple decorators (`@jit`, `@njit`, `@vectorize`), this toolkit focuses
|
|
134
|
+
on the general-purpose `@jit` decorator with configurable parameters for flexibility.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, parametersNumba: ParametersNumba | None = None) -> IngredientsFunction: # noqa: C901
|
|
138
|
+
"""Transform a Python function into a Numba-accelerated version with appropriate decorators.
|
|
139
|
+
|
|
140
|
+
(AI generated docstring)
|
|
57
141
|
|
|
58
|
-
|
|
142
|
+
This function applies Numba's `@jit` decorator to an existing function definition within
|
|
143
|
+
an `IngredientsFunction` container. It handles the complete transformation pipeline
|
|
144
|
+
including removing any existing decorators that might conflict with Numba, constructing
|
|
145
|
+
type signatures for Numba compilation when possible, applying the `@jit` decorator with
|
|
146
|
+
specified or default parameters, and updating import requirements to include necessary
|
|
147
|
+
Numba modules.
|
|
148
|
+
|
|
149
|
+
The transformation preserves function semantics while enabling significant performance
|
|
150
|
+
improvements through just-in-time compilation. Type inference is attempted for
|
|
151
|
+
function parameters and return values to enable optimized compilation paths.
|
|
152
|
+
|
|
153
|
+
Parameters
|
|
154
|
+
----------
|
|
155
|
+
ingredientsFunction : IngredientsFunction
|
|
156
|
+
Container holding the function definition and associated metadata.
|
|
157
|
+
parametersNumba : ParametersNumba | None = None
|
|
158
|
+
Optional Numba configuration; uses `parametersNumbaDefault` if `None`.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
ingredientsFunction : IngredientsFunction
|
|
163
|
+
Modified `IngredientsFunction` with Numba decorator applied and imports updated.
|
|
164
|
+
|
|
165
|
+
"""
|
|
59
166
|
def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
|
|
60
|
-
|
|
167
|
+
"""Remove existing decorators from function definition to prevent conflicts with Numba.
|
|
168
|
+
|
|
169
|
+
(AI generated docstring)
|
|
170
|
+
|
|
171
|
+
Numba compilation can be incompatible with certain Python decorators, so this
|
|
172
|
+
function strips all existing decorators from a function definition before
|
|
173
|
+
applying the Numba `@jit` decorator. Removed decorators are logged as warnings
|
|
174
|
+
for debugging purposes.
|
|
175
|
+
|
|
176
|
+
TODO: Implement more sophisticated decorator handling that can preserve
|
|
177
|
+
compatible decorators and intelligently handle decorator composition.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
astCallable : ast.FunctionDef
|
|
182
|
+
Function definition AST node to process.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
astCallable : ast.FunctionDef
|
|
187
|
+
Function definition with decorator list cleared.
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
# TODO more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
|
|
61
191
|
for decoratorItem in astCallable.decorator_list.copy():
|
|
62
|
-
import warnings
|
|
63
192
|
astCallable.decorator_list.remove(decoratorItem)
|
|
64
|
-
warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}")
|
|
193
|
+
warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}", stacklevel=2)
|
|
65
194
|
return astCallable
|
|
66
195
|
|
|
67
196
|
def makeSpecialSignatureForNumba(signatureElement: ast.arg) -> ast.Subscript | ast.Name | None: # pyright: ignore[reportUnusedFunction]
|
|
197
|
+
"""Generate Numba-compatible type signatures for function parameters.
|
|
198
|
+
|
|
199
|
+
(AI generated docstring)
|
|
200
|
+
|
|
201
|
+
This function analyzes function parameter type annotations and converts them into
|
|
202
|
+
Numba-compatible type signature expressions. It handles various annotation patterns
|
|
203
|
+
including array types with shape and dtype information, scalar types with simple
|
|
204
|
+
name annotations, and complex subscripted types requiring special handling.
|
|
205
|
+
|
|
206
|
+
The generated signatures enable Numba to perform more efficient compilation by
|
|
207
|
+
providing explicit type information rather than relying solely on type inference.
|
|
208
|
+
|
|
209
|
+
Parameters
|
|
210
|
+
----------
|
|
211
|
+
signatureElement : ast.arg
|
|
212
|
+
Function parameter with type annotation to convert.
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
ast.Subscript | ast.Name | None
|
|
217
|
+
Numba-compatible type signature AST node, or None if conversion not possible.
|
|
218
|
+
|
|
219
|
+
"""
|
|
68
220
|
if isinstance(signatureElement.annotation, ast.Subscript) and isinstance(signatureElement.annotation.slice, ast.Tuple):
|
|
69
221
|
annotationShape: ast.expr = signatureElement.annotation.slice.elts[0]
|
|
70
222
|
if isinstance(annotationShape, ast.Subscript) and isinstance(annotationShape.slice, ast.Tuple):
|
|
71
223
|
shapeAsListSlices: list[ast.Slice] = [ast.Slice() for _axis in range(len(annotationShape.slice.elts))]
|
|
72
|
-
shapeAsListSlices[-1] =
|
|
73
|
-
shapeAST: ast.Slice | ast.Tuple =
|
|
224
|
+
shapeAsListSlices[-1] = Make.Slice(step=Make.Constant(1))
|
|
225
|
+
shapeAST: ast.Slice | ast.Tuple = Make.Tuple(list(shapeAsListSlices))
|
|
74
226
|
else:
|
|
75
|
-
shapeAST =
|
|
227
|
+
shapeAST = Make.Slice(step=Make.Constant(1))
|
|
76
228
|
|
|
77
229
|
annotationDtype: ast.expr = signatureElement.annotation.slice.elts[1]
|
|
78
230
|
if (isinstance(annotationDtype, ast.Subscript) and isinstance(annotationDtype.slice, ast.Attribute)):
|
|
@@ -84,9 +236,9 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
|
|
|
84
236
|
Z0Z_hacky_dtype: str = ndarrayName
|
|
85
237
|
datatype_attr = datatypeAST or Z0Z_hacky_dtype
|
|
86
238
|
ingredientsFunction.imports.addImportFrom_asStr(datatypeModuleDecorator, datatype_attr)
|
|
87
|
-
datatypeNumba =
|
|
239
|
+
datatypeNumba = Make.Name(datatype_attr)
|
|
88
240
|
|
|
89
|
-
return
|
|
241
|
+
return Make.Subscript(datatypeNumba, slice=shapeAST)
|
|
90
242
|
|
|
91
243
|
elif isinstance(signatureElement.annotation, ast.Name):
|
|
92
244
|
return signatureElement.annotation
|
|
@@ -105,15 +257,16 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
|
|
|
105
257
|
|
|
106
258
|
if ingredientsFunction.astFunctionDef.returns and isinstance(ingredientsFunction.astFunctionDef.returns, ast.Name):
|
|
107
259
|
theReturn: ast.Name = ingredientsFunction.astFunctionDef.returns
|
|
108
|
-
list_argsDecorator = [cast(ast.expr,
|
|
109
|
-
,
|
|
260
|
+
list_argsDecorator = [cast("ast.expr", Make.Call(Make.Name(theReturn.id)
|
|
261
|
+
, list_arg4signature_or_function if list_arg4signature_or_function else [], [] ) )]
|
|
110
262
|
elif list_arg4signature_or_function:
|
|
111
|
-
list_argsDecorator = [cast(ast.expr,
|
|
263
|
+
list_argsDecorator = [cast("ast.expr", Make.Tuple(list_arg4signature_or_function))]
|
|
112
264
|
|
|
113
265
|
ingredientsFunction.astFunctionDef = Z0Z_UnhandledDecorators(ingredientsFunction.astFunctionDef)
|
|
114
266
|
if parametersNumba is None:
|
|
115
267
|
parametersNumba = parametersNumbaDefault
|
|
116
|
-
|
|
268
|
+
|
|
269
|
+
listDecoratorKeywords: list[ast.keyword] = [Make.keyword(parameterName, Make.Constant(parameterValue)) for parameterName, parameterValue in parametersNumba.items()] # pyright: ignore[reportArgumentType]
|
|
117
270
|
|
|
118
271
|
decoratorModule = Z0Z_numbaDataTypeModule
|
|
119
272
|
decoratorCallable = Z0Z_decoratorCallable
|
|
@@ -127,6 +280,35 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
|
|
|
127
280
|
|
|
128
281
|
@dataclasses.dataclass
|
|
129
282
|
class SpicesJobNumba:
|
|
283
|
+
"""Configuration container for Numba-specific job processing options.
|
|
284
|
+
|
|
285
|
+
(AI generated docstring)
|
|
286
|
+
|
|
287
|
+
This dataclass encapsulates configuration settings that control how Numba
|
|
288
|
+
compilation and execution is applied to job processing functions. It provides
|
|
289
|
+
a centralized way to manage Numba-specific settings that affect both
|
|
290
|
+
compilation behavior and runtime features like progress reporting.
|
|
291
|
+
|
|
292
|
+
The class serves as a bridge between the generic job processing system and
|
|
293
|
+
Numba's specialized requirements, enabling consistent application of
|
|
294
|
+
optimization settings across different computational contexts.
|
|
295
|
+
|
|
296
|
+
Attributes
|
|
297
|
+
----------
|
|
298
|
+
useNumbaProgressBar : bool
|
|
299
|
+
Enable progress bar display for long-running computations.
|
|
300
|
+
numbaProgressBarIdentifier : str
|
|
301
|
+
Progress bar implementation identifier.
|
|
302
|
+
parametersNumba : ParametersNumba
|
|
303
|
+
Numba compilation parameters with sensible defaults.
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
|
|
130
307
|
useNumbaProgressBar: bool = True
|
|
308
|
+
"""Enable progress bar display for Numba-compiled functions with long execution times."""
|
|
309
|
+
|
|
131
310
|
numbaProgressBarIdentifier: str = 'ProgressBarGroupsOfFolds'
|
|
311
|
+
"""Identifier for the progress bar implementation used in Numba-compiled code."""
|
|
312
|
+
|
|
132
313
|
parametersNumba: ParametersNumba = dataclasses.field(default_factory=ParametersNumba) # pyright: ignore[reportArgumentType, reportCallIssue, reportUnknownVariableType]
|
|
314
|
+
"""Numba compilation parameters; defaults to empty dict allowing decorator defaults."""
|
|
@@ -1,47 +1,43 @@
|
|
|
1
1
|
"""
|
|
2
|
-
AST
|
|
3
|
-
|
|
4
|
-
This module
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
Map folding AST transformation system: Core dataclass decomposition and function optimization tools.
|
|
3
|
+
|
|
4
|
+
This module implements the essential transformation capabilities that form the operational core of
|
|
5
|
+
the map folding AST transformation system. Working with the pattern recognition foundation and
|
|
6
|
+
decomposition containers established in the foundational layers, these tools execute the critical
|
|
7
|
+
transformations that convert dataclass-based functions into optimized implementations suitable
|
|
8
|
+
for Numba just-in-time compilation.
|
|
9
|
+
|
|
10
|
+
The transformation process addresses the fundamental incompatibility between dataclass-dependent
|
|
11
|
+
map folding algorithms and Numba's compilation requirements. While dataclass instances provide
|
|
12
|
+
clean, maintainable interfaces for complex mathematical state, Numba cannot directly process
|
|
13
|
+
these objects but excels at optimizing operations on primitive values and tuples. The tools
|
|
14
|
+
bridge this architectural gap through systematic function signature transformation and calling
|
|
15
|
+
convention adaptation.
|
|
16
|
+
|
|
17
|
+
The three-stage transformation pattern implemented here follows a precise sequence: dataclass
|
|
18
|
+
decomposition breaks down dataclass definitions into constituent AST components while extracting
|
|
19
|
+
field definitions and type annotations; function transformation converts functions accepting
|
|
20
|
+
dataclass parameters to functions accepting individual field parameters with updated signatures
|
|
21
|
+
and return types; caller adaptation modifies calling code to unpack dataclass instances, invoke
|
|
22
|
+
transformed functions, and repack results back into dataclass instances.
|
|
23
|
+
|
|
24
|
+
This approach enables seamless integration between high-level dataclass-based interfaces and
|
|
25
|
+
low-level optimized implementations, maintaining code clarity while achieving performance gains
|
|
26
|
+
through specialized compilation paths essential for computationally intensive map folding research.
|
|
19
27
|
"""
|
|
20
28
|
|
|
21
|
-
from astToolkit import
|
|
22
|
-
|
|
23
|
-
DeReConstructField2ast,
|
|
24
|
-
IfThis,
|
|
25
|
-
ShatteredDataclass,
|
|
26
|
-
)
|
|
27
|
-
from astToolkit import(
|
|
28
|
-
Be,
|
|
29
|
-
extractClassDef,
|
|
30
|
-
IngredientsFunction,
|
|
31
|
-
Make,
|
|
32
|
-
NodeChanger,
|
|
33
|
-
parseLogicalPath2astModule,
|
|
34
|
-
str_nameDOTname,
|
|
35
|
-
Then,
|
|
36
|
-
)
|
|
29
|
+
from astToolkit import (
|
|
30
|
+
Be, extractClassDef, identifierDotAttribute, IngredientsFunction, Make, NodeChanger, parseLogicalPath2astModule, Then)
|
|
37
31
|
from astToolkit.transformationTools import unparseFindReplace
|
|
38
|
-
from
|
|
32
|
+
from hunterMakesPy import importLogicalPath2Identifier
|
|
33
|
+
from mapFolding.someAssemblyRequired import DeReConstructField2ast, IfThis, ShatteredDataclass
|
|
39
34
|
import ast
|
|
40
35
|
import dataclasses
|
|
41
36
|
|
|
42
|
-
def shatter_dataclassesDOTdataclass(logicalPathModule:
|
|
43
|
-
"""
|
|
44
|
-
|
|
37
|
+
def shatter_dataclassesDOTdataclass(logicalPathModule: identifierDotAttribute, dataclassIdentifier: str, instanceIdentifier: str) -> ShatteredDataclass:
|
|
38
|
+
"""Decompose a dataclass definition into AST components for manipulation and code generation.
|
|
39
|
+
|
|
40
|
+
(AI generated docstring)
|
|
45
41
|
|
|
46
42
|
This function breaks down a complete dataclass (like ComputationState) into its constituent
|
|
47
43
|
parts as AST nodes, enabling fine-grained manipulation of its fields for code generation.
|
|
@@ -57,35 +53,44 @@ def shatter_dataclassesDOTdataclass(logicalPathModule: str_nameDOTname, dataclas
|
|
|
57
53
|
where dataclass instances can't be directly used but their fields need to be individually
|
|
58
54
|
manipulated and passed to computational functions.
|
|
59
55
|
|
|
60
|
-
Parameters
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
logicalPathModule : identifierDotAttribute
|
|
59
|
+
The fully qualified module path containing the dataclass definition.
|
|
60
|
+
dataclassIdentifier : str
|
|
61
|
+
The name of the dataclass to decompose.
|
|
62
|
+
instanceIdentifier : str
|
|
63
|
+
The variable name to use for the dataclass instance in generated code.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
ShatteredDataclass
|
|
68
|
+
A ShatteredDataclass containing AST representations of all dataclass components,
|
|
69
|
+
with imports, field definitions, annotations, and repackaging code.
|
|
70
|
+
|
|
71
|
+
Raises
|
|
72
|
+
------
|
|
73
|
+
ValueError
|
|
74
|
+
If the dataclass cannot be found in the specified module or if no counting variable is identified in the dataclass.
|
|
68
75
|
|
|
69
|
-
Raises:
|
|
70
|
-
ValueError: If the dataclass cannot be found in the specified module or if no counting variable is identified in the dataclass.
|
|
71
76
|
"""
|
|
72
77
|
Official_fieldOrder: list[str] = []
|
|
73
78
|
dictionaryDeReConstruction: dict[str, DeReConstructField2ast] = {}
|
|
74
79
|
|
|
75
|
-
dataclassClassDef = extractClassDef(parseLogicalPath2astModule(logicalPathModule), dataclassIdentifier)
|
|
76
|
-
if not
|
|
80
|
+
dataclassClassDef: ast.ClassDef | None = extractClassDef(parseLogicalPath2astModule(logicalPathModule), dataclassIdentifier)
|
|
81
|
+
if not dataclassClassDef:
|
|
82
|
+
message = f"I could not find `{dataclassIdentifier = }` in `{logicalPathModule = }`."
|
|
83
|
+
raise ValueError(message)
|
|
77
84
|
|
|
78
85
|
countingVariable = None
|
|
79
|
-
for aField in dataclasses.fields(
|
|
86
|
+
for aField in dataclasses.fields(importLogicalPath2Identifier(logicalPathModule, dataclassIdentifier)): # pyright: ignore [reportArgumentType]
|
|
80
87
|
Official_fieldOrder.append(aField.name)
|
|
81
88
|
dictionaryDeReConstruction[aField.name] = DeReConstructField2ast(logicalPathModule, dataclassClassDef, instanceIdentifier, aField)
|
|
82
89
|
if aField.metadata.get('theCountingIdentifier', False):
|
|
83
90
|
countingVariable = dictionaryDeReConstruction[aField.name].name
|
|
84
|
-
|
|
85
91
|
if countingVariable is None:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
raise Exception
|
|
92
|
+
message = f"I could not find the counting variable in `{dataclassIdentifier = }` in `{logicalPathModule = }`."
|
|
93
|
+
raise ValueError(message)
|
|
89
94
|
|
|
90
95
|
shatteredDataclass = ShatteredDataclass(
|
|
91
96
|
countingVariableAnnotation=dictionaryDeReConstruction[countingVariable].astAnnotation,
|
|
@@ -109,7 +114,36 @@ def shatter_dataclassesDOTdataclass(logicalPathModule: str_nameDOTname, dataclas
|
|
|
109
114
|
return shatteredDataclass
|
|
110
115
|
|
|
111
116
|
def removeDataclassFromFunction(ingredientsTarget: IngredientsFunction, shatteredDataclass: ShatteredDataclass) -> IngredientsFunction:
|
|
112
|
-
|
|
117
|
+
"""Transform a function that operates on dataclass instances to work with individual field parameters.
|
|
118
|
+
|
|
119
|
+
(AI generated docstring)
|
|
120
|
+
|
|
121
|
+
This function performs the core transformation required for Numba compatibility by removing dataclass
|
|
122
|
+
dependencies from function signatures and implementations. It modifies the target function to:
|
|
123
|
+
|
|
124
|
+
1. Replace the single dataclass parameter with individual field parameters.
|
|
125
|
+
2. Update the return type annotation to return a tuple of field values.
|
|
126
|
+
3. Transform return statements to return the tuple of fields.
|
|
127
|
+
4. Replace all dataclass attribute access with direct field variable access.
|
|
128
|
+
|
|
129
|
+
This transformation is essential for creating Numba-compatible functions from dataclass-based
|
|
130
|
+
implementations, as Numba cannot handle dataclass instances directly but can efficiently
|
|
131
|
+
process individual primitive values and tuples.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
ingredientsTarget : IngredientsFunction
|
|
136
|
+
The function definition and its dependencies to be transformed.
|
|
137
|
+
shatteredDataclass : ShatteredDataclass
|
|
138
|
+
The decomposed dataclass components providing AST mappings and transformations.
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
IngredientsFunction
|
|
143
|
+
The modified function ingredients with dataclass dependencies removed.
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
ingredientsTarget.astFunctionDef.args = Make.arguments(list_arg=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
113
147
|
ingredientsTarget.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
|
|
114
148
|
changeReturnCallable = NodeChanger(Be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
|
|
115
149
|
changeReturnCallable.visit(ingredientsTarget.astFunctionDef)
|
|
@@ -117,10 +151,43 @@ def removeDataclassFromFunction(ingredientsTarget: IngredientsFunction, shattere
|
|
|
117
151
|
return ingredientsTarget
|
|
118
152
|
|
|
119
153
|
def unpackDataclassCallFunctionRepackDataclass(ingredientsCaller: IngredientsFunction, targetCallableIdentifier: str, shatteredDataclass: ShatteredDataclass) -> IngredientsFunction:
|
|
154
|
+
"""Transform a caller function to interface with a dataclass-free target function.
|
|
155
|
+
|
|
156
|
+
(AI generated docstring)
|
|
157
|
+
|
|
158
|
+
This function complements `removeDataclassFromFunction` by modifying calling code to work with
|
|
159
|
+
the transformed target function. It implements the unpacking and repacking pattern required
|
|
160
|
+
when a dataclass-based caller needs to invoke a function that has been converted to accept
|
|
161
|
+
individual field parameters instead of dataclass instances.
|
|
162
|
+
|
|
163
|
+
The transformation creates a three-step pattern around the target function call:
|
|
164
|
+
1. Unpack the dataclass instance into individual field variables.
|
|
165
|
+
2. Call the target function with the unpacked field values.
|
|
166
|
+
3. Repack the returned field values back into a dataclass instance.
|
|
167
|
+
|
|
168
|
+
This enables seamless integration between dataclass-based high-level code and optimized
|
|
169
|
+
field-based implementations, maintaining the original interface while enabling performance
|
|
170
|
+
optimizations in the target function.
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
ingredientsCaller : IngredientsFunction
|
|
175
|
+
The calling function definition and its dependencies to be transformed.
|
|
176
|
+
targetCallableIdentifier : str
|
|
177
|
+
The name of the target function being called.
|
|
178
|
+
shatteredDataclass : ShatteredDataclass
|
|
179
|
+
The decomposed dataclass components providing unpacking and repacking logic.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
IngredientsFunction
|
|
184
|
+
The modified caller function with appropriate unpacking and repacking around the target call.
|
|
185
|
+
|
|
186
|
+
"""
|
|
120
187
|
astCallTargetCallable = Make.Call(Make.Name(targetCallableIdentifier), shatteredDataclass.listName4Parameters)
|
|
121
|
-
replaceAssignTargetCallable = NodeChanger(
|
|
122
|
-
unpack4targetCallable = NodeChanger(
|
|
123
|
-
repack4targetCallable = NodeChanger(
|
|
188
|
+
replaceAssignTargetCallable = NodeChanger(Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier)), Then.replaceWith(Make.Assign([shatteredDataclass.fragments4AssignmentOrParameters], value=astCallTargetCallable)))
|
|
189
|
+
unpack4targetCallable = NodeChanger(Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier)), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
190
|
+
repack4targetCallable = NodeChanger(Be.Assign.valueIs(IfThis.isCallIdentifier(targetCallableIdentifier)), Then.insertThisBelow([shatteredDataclass.repack]))
|
|
124
191
|
replaceAssignTargetCallable.visit(ingredientsCaller.astFunctionDef)
|
|
125
192
|
unpack4targetCallable.visit(ingredientsCaller.astFunctionDef)
|
|
126
193
|
repack4targetCallable.visit(ingredientsCaller.astFunctionDef)
|