mapFolding 0.9.4__py3-none-any.whl → 0.9.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapFolding/__init__.py +41 -7
- mapFolding/basecamp.py +100 -9
- mapFolding/beDRY.py +7 -15
- mapFolding/dataBaskets.py +12 -0
- mapFolding/datatypes.py +4 -4
- mapFolding/oeis.py +2 -7
- mapFolding/someAssemblyRequired/RecipeJob.py +97 -3
- mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +112 -12
- mapFolding/someAssemblyRequired/__init__.py +26 -28
- mapFolding/someAssemblyRequired/_theTypes.py +13 -19
- mapFolding/someAssemblyRequired/_tool_Make.py +4 -6
- mapFolding/someAssemblyRequired/_tool_Then.py +17 -22
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +32 -15
- mapFolding/someAssemblyRequired/_toolboxContainers.py +124 -29
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +274 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +3 -2
- mapFolding/someAssemblyRequired/toolboxNumba.py +3 -27
- mapFolding/someAssemblyRequired/transformationTools.py +8 -120
- mapFolding/syntheticModules/daoOfMapFolding.py +74 -0
- mapFolding/syntheticModules/dataPacking.py +1 -1
- mapFolding/syntheticModules/theorem2Numba.py +2 -8
- mapFolding/syntheticModules/theorem2Trimmed.py +43 -0
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/METADATA +1 -1
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/RECORD +29 -27
- tests/test_computations.py +1 -1
- mapFolding/Z0Z_flowControl.py +0 -117
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/WHEEL +0 -0
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.9.4.dist-info → mapfolding-0.9.5.dist-info}/top_level.txt +0 -0
|
@@ -1,50 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Code Transformation Framework for Algorithm Optimization and Testing
|
|
3
3
|
|
|
4
|
-
This package implements a comprehensive framework for programmatically analyzing,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
functional implementations into highly-optimized variants with verified correctness.
|
|
4
|
+
This package implements a comprehensive framework for programmatically analyzing, transforming, and generating optimized
|
|
5
|
+
Python code. It serves as the algorithmic optimization engine for the mapFolding package, enabling the conversion of
|
|
6
|
+
readable, functional implementations into highly-optimized variants with verified correctness.
|
|
8
7
|
|
|
9
8
|
## Core Architecture Components
|
|
10
9
|
|
|
11
10
|
1. **AST Manipulation Tools**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
- Pattern recognition with composable predicates (ifThis)
|
|
12
|
+
- Node access with consistent interfaces (DOT)
|
|
13
|
+
- AST traversal and transformation (NodeChanger, NodeTourist)
|
|
14
|
+
- AST construction with sane defaults (Make)
|
|
15
|
+
- Node transformation operations (grab, Then)
|
|
17
16
|
|
|
18
17
|
2. **Container and Organization**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
- Import tracking and management (LedgerOfImports)
|
|
19
|
+
- Function packaging with dependencies (IngredientsFunction)
|
|
20
|
+
- Module assembly with structured components (IngredientsModule)
|
|
21
|
+
- Recipe configuration for generating optimized code (RecipeSynthesizeFlow)
|
|
22
|
+
- Dataclass decomposition for compatibility (ShatteredDataclass)
|
|
24
23
|
|
|
25
24
|
3. **Optimization assembly lines**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
- General-purpose Numba acceleration (makeNumbaFlow)
|
|
26
|
+
- Job-specific optimization for concrete parameters (makeJobNumba)
|
|
27
|
+
- Specialized component transformation (decorateCallableWithNumba)
|
|
29
28
|
|
|
30
29
|
## Integration with Testing Framework
|
|
31
30
|
|
|
32
|
-
The transformation components are extensively tested through the package's test suite,
|
|
33
|
-
|
|
34
|
-
process and the resulting optimized code:
|
|
31
|
+
The transformation components are extensively tested through the package's test suite, which provides specialized
|
|
32
|
+
fixtures and utilities for validating both the transformation process and the resulting optimized code:
|
|
35
33
|
|
|
36
|
-
- **syntheticDispatcherFixture**: Creates and tests a complete Numba-optimized module
|
|
37
|
-
|
|
34
|
+
- **syntheticDispatcherFixture**: Creates and tests a complete Numba-optimized module using RecipeSynthesizeFlow
|
|
35
|
+
configuration
|
|
38
36
|
|
|
39
37
|
- **test_writeJobNumba**: Tests the job-specific optimization process with RecipeJob
|
|
40
38
|
|
|
41
|
-
These fixtures enable users to test their own custom recipes and job configurations
|
|
42
|
-
|
|
43
|
-
extending the test suite for custom implementations.
|
|
39
|
+
These fixtures enable users to test their own custom recipes and job configurations with minimal effort. See the
|
|
40
|
+
documentation in tests/__init__.py for details on extending the test suite for custom implementations.
|
|
44
41
|
|
|
45
|
-
The framework balances multiple optimization levels - from general algorithmic
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
The framework balances multiple optimization levels - from general algorithmic improvements to parameter-specific
|
|
43
|
+
optimizations - while maintaining the ability to verify correctness at each transformation stage through the integrated
|
|
44
|
+
test suite.
|
|
48
45
|
"""
|
|
49
46
|
|
|
50
47
|
from mapFolding.someAssemblyRequired._theTypes import (
|
|
@@ -85,6 +82,7 @@ from mapFolding.someAssemblyRequired._tool_Make import Make as Make
|
|
|
85
82
|
from mapFolding.someAssemblyRequired._tool_Then import grab as grab, Then as Then
|
|
86
83
|
|
|
87
84
|
from mapFolding.someAssemblyRequired._toolboxContainers import (
|
|
85
|
+
DeReConstructField2ast as DeReConstructField2ast,
|
|
88
86
|
IngredientsFunction as IngredientsFunction,
|
|
89
87
|
IngredientsModule as IngredientsModule,
|
|
90
88
|
LedgerOfImports as LedgerOfImports,
|
|
@@ -1,28 +1,23 @@
|
|
|
1
|
-
from
|
|
1
|
+
from mapFolding import astDOTParamSpec, astDOTTryStar, astDOTtype_param, astDOTTypeAlias, astDOTTypeVar, astDOTTypeVarTuple
|
|
2
|
+
from typing import Any, TypeAlias as typing_TypeAlias, TypeVar as typing_TypeVar
|
|
2
3
|
import ast
|
|
4
|
+
|
|
3
5
|
# TODO understand typing.
|
|
4
6
|
|
|
5
7
|
stuPyd: typing_TypeAlias = str
|
|
6
|
-
if TYPE_CHECKING:
|
|
7
|
-
""" 3.12 new: ast.ParamSpec, ast.type_param, ast.TypeAlias, ast.TypeVar, ast.TypeVarTuple
|
|
8
|
-
3.11 new: ast.TryStar"""
|
|
9
|
-
astClassHasDOTbodyList_stmt: typing_TypeAlias = ast.AsyncFor | ast.AsyncWith | ast.ClassDef | ast.ExceptHandler | ast.For | ast.FunctionDef | ast.If | ast.Interactive | ast.match_case | ast.Module | ast.Try | ast.TryStar | ast.While | ast.With
|
|
10
|
-
astClassHasDOTnameNotNameAlways: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.ParamSpec | ast.TypeVar | ast.TypeVarTuple
|
|
11
|
-
astClassHasDOTvalue_expr: typing_TypeAlias = ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Starred | ast.Subscript | ast.TypeAlias | ast.YieldFrom
|
|
12
|
-
|
|
13
|
-
else:
|
|
14
|
-
astClassHasDOTbodyList_stmt = stuPyd
|
|
15
|
-
astClassHasDOTnameNotNameAlways = stuPyd
|
|
16
|
-
astClassHasDOTvalue_expr = stuPyd
|
|
17
8
|
|
|
9
|
+
# NOTE An idea to subclass antecedents to effectively TypeGuard more than just the top level of the antecedent.
|
|
18
10
|
class ImaCallToName(ast.Call):
|
|
19
11
|
func: ast.Name # pyright: ignore[reportIncompatibleVariableOverride]
|
|
20
12
|
# assert isinstance(ast.Call.func, ast.Name), "brinkmanship"
|
|
21
13
|
# func: ast.Name
|
|
22
14
|
|
|
15
|
+
# Some common attributes of ast classes.
|
|
23
16
|
astClassHasDOTbody_expr: typing_TypeAlias = ast.Expression | ast.IfExp | ast.Lambda
|
|
17
|
+
astClassHasDOTbodyList_stmt: typing_TypeAlias = ast.AsyncFor | ast.AsyncWith | ast.ClassDef | ast.ExceptHandler | ast.For | ast.FunctionDef | ast.If | ast.Interactive | ast.match_case | ast.Module | ast.Try | astDOTTryStar | ast.While | ast.With
|
|
24
18
|
astClassHasDOTbody: typing_TypeAlias = astClassHasDOTbody_expr | astClassHasDOTbodyList_stmt
|
|
25
19
|
|
|
20
|
+
astClassHasDOTnameNotNameAlways: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | astDOTParamSpec | astDOTTypeVar | astDOTTypeVarTuple
|
|
26
21
|
astClassHasDOTnameNotNameOptionally: typing_TypeAlias = ast.ExceptHandler | ast.MatchAs | ast.MatchStar
|
|
27
22
|
astClassHasDOTnameNotName: typing_TypeAlias = astClassHasDOTnameNotNameAlways | astClassHasDOTnameNotNameOptionally
|
|
28
23
|
|
|
@@ -30,9 +25,11 @@ astClassHasDOTtargetAttributeNameSubscript: typing_TypeAlias = ast.AnnAssign | a
|
|
|
30
25
|
astClassHasDOTtarget_expr: typing_TypeAlias = ast.AsyncFor | ast.comprehension | ast.For
|
|
31
26
|
astClassHasDOTtarget: typing_TypeAlias = ast.NamedExpr | astClassHasDOTtarget_expr | astClassHasDOTtargetAttributeNameSubscript
|
|
32
27
|
|
|
28
|
+
astClassHasDOTvalue_expr: typing_TypeAlias = ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Starred | ast.Subscript | astDOTTypeAlias | ast.YieldFrom
|
|
33
29
|
astClassHasDOTvalue_exprNone: typing_TypeAlias = ast.AnnAssign | ast.Return | ast.Yield
|
|
34
30
|
astClassHasDOTvalue: typing_TypeAlias = ast.Constant | ast.MatchSingleton | astClassHasDOTvalue_expr | astClassHasDOTvalue_exprNone
|
|
35
31
|
|
|
32
|
+
# Type hints through TypeAlias or type "hints" through the identifier name.
|
|
36
33
|
ast_expr_Slice: typing_TypeAlias = ast.expr
|
|
37
34
|
ast_Identifier: typing_TypeAlias = str
|
|
38
35
|
intORlist_ast_type_paramORstr_orNone: typing_TypeAlias = Any
|
|
@@ -40,10 +37,11 @@ intORstr_orNone: typing_TypeAlias = Any
|
|
|
40
37
|
list_ast_type_paramORstr_orNone: typing_TypeAlias = Any
|
|
41
38
|
str_nameDOTname: typing_TypeAlias = stuPyd
|
|
42
39
|
|
|
40
|
+
# Limited success with TypeVar.
|
|
43
41
|
个 = typing_TypeVar('个', bound = ast.AST, covariant = True)
|
|
44
42
|
NodeORattribute = typing_TypeVar('NodeORattribute', bound = ast.AST | ast_expr_Slice | ast_Identifier | str_nameDOTname | bool | Any | None, covariant = True)
|
|
45
43
|
|
|
46
|
-
#
|
|
44
|
+
# For my reference, all ast classes by subgroup:
|
|
47
45
|
Ima_ast_boolop: typing_TypeAlias = ast.boolop | ast.And | ast.Or
|
|
48
46
|
Ima_ast_cmpop: typing_TypeAlias = ast.cmpop | ast.Eq | ast.NotEq | ast.Lt | ast.LtE | ast.Gt | ast.GtE | ast.Is | ast.IsNot | ast.In | ast.NotIn
|
|
49
47
|
Ima_ast_excepthandler: typing_TypeAlias = ast.excepthandler | ast.ExceptHandler
|
|
@@ -53,11 +51,7 @@ Ima_ast_mod: typing_TypeAlias = ast.mod | ast.Expression | ast.FunctionType | as
|
|
|
53
51
|
Ima_ast_operator: typing_TypeAlias = ast.operator | ast.Add | ast.Sub | ast.Mult | ast.MatMult | ast.Div | ast.Mod | ast.Pow | ast.LShift | ast.RShift | ast.BitOr | ast.BitXor | ast.BitAnd | ast.FloorDiv
|
|
54
52
|
Ima_ast_orphan = ast.alias | ast.arg | ast.arguments | ast.comprehension | ast.keyword | ast.match_case | ast.withitem
|
|
55
53
|
iMa_ast_pattern: typing_TypeAlias = ast.pattern | ast.MatchAs | ast.MatchClass | ast.MatchMapping | ast.MatchOr | ast.MatchSequence | ast.MatchSingleton | ast.MatchStar | ast.MatchValue
|
|
54
|
+
Ima_ast_stmt: typing_TypeAlias = ast.stmt | ast.AnnAssign | ast.Assert | ast.Assign | ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.AugAssign | ast.Break | ast.ClassDef | ast.Continue | ast.Delete | ast.Expr | ast.For | ast.FunctionDef | ast.Global | ast.If | ast.Import | ast.ImportFrom | ast.Match | ast.Nonlocal | ast.Pass | ast.Raise | ast.Return | ast.Try | astDOTTryStar | astDOTTypeAlias | ast.While | ast.With
|
|
56
55
|
Ima_ast_type_ignore: typing_TypeAlias = ast.type_ignore | ast.TypeIgnore
|
|
56
|
+
Ima_ast_type_param: typing_TypeAlias = astDOTtype_param | astDOTParamSpec | astDOTTypeVar | astDOTTypeVarTuple
|
|
57
57
|
Ima_ast_unaryop: typing_TypeAlias = ast.unaryop | ast.Invert | ast.Not | ast.UAdd | ast.USub
|
|
58
|
-
if TYPE_CHECKING:
|
|
59
|
-
Ima_ast_stmt: typing_TypeAlias = ast.stmt | ast.AnnAssign | ast.Assert | ast.Assign | ast.AsyncFor | ast.AsyncFunctionDef | ast.AsyncWith | ast.AugAssign | ast.Break | ast.ClassDef | ast.Continue | ast.Delete | ast.Expr | ast.For | ast.FunctionDef | ast.Global | ast.If | ast.Import | ast.ImportFrom | ast.Match | ast.Nonlocal | ast.Pass | ast.Raise | ast.Return | ast.Try | ast.TryStar | ast.TypeAlias | ast.While | ast.With
|
|
60
|
-
Ima_ast_type_param: typing_TypeAlias = ast.type_param | ast.ParamSpec | ast.TypeVar | ast.TypeVarTuple
|
|
61
|
-
else:
|
|
62
|
-
Ima_ast_stmt = stuPyd
|
|
63
|
-
Ima_ast_type_param = stuPyd
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
2
|
AST Node Construction Utilities for Python Code Generation
|
|
3
3
|
|
|
4
|
-
This module provides the Make class with static methods for creating AST nodes
|
|
5
|
-
|
|
6
|
-
directly, making programmatic code generation more intuitive and less error-prone.
|
|
4
|
+
This module provides the Make class with static methods for creating AST nodes with sane defaults. It abstracts away the
|
|
5
|
+
complexity of constructing AST nodes directly, making programmatic code generation more intuitive and less error-prone.
|
|
7
6
|
|
|
8
|
-
The Make class serves as a factory for creating various types of AST nodes needed
|
|
9
|
-
|
|
10
|
-
a consistent pattern that maps cleanly to Python's syntax while handling the
|
|
7
|
+
The Make class serves as a factory for creating various types of AST nodes needed in code generation, transformation,
|
|
8
|
+
and analysis workflows. Each method follows a consistent pattern that maps cleanly to Python's syntax while handling the
|
|
11
9
|
details of AST node construction.
|
|
12
10
|
"""
|
|
13
11
|
|
|
@@ -1,36 +1,32 @@
|
|
|
1
1
|
"""
|
|
2
2
|
AST Node Transformation Actions for Python Code Manipulation
|
|
3
3
|
|
|
4
|
-
This module provides the Then class with static methods for generating callable
|
|
5
|
-
|
|
6
|
-
These action functions are used primarily with NodeChanger and NodeTourist to
|
|
4
|
+
This module provides the Then class with static methods for generating callable action functions that specify what to do
|
|
5
|
+
with AST nodes that match predicates. These action functions are used primarily with NodeChanger and NodeTourist to
|
|
7
6
|
transform or extract information from AST nodes.
|
|
8
7
|
|
|
9
|
-
The module also contains the grab class that provides functions for modifying
|
|
10
|
-
|
|
11
|
-
fine-grained control when transforming AST structures.
|
|
8
|
+
The module also contains the grab class that provides functions for modifying specific attributes of AST nodes while
|
|
9
|
+
preserving their structure, enabling fine-grained control when transforming AST structures.
|
|
12
10
|
|
|
13
|
-
Together, these classes provide a complete system for manipulating AST nodes
|
|
14
|
-
|
|
11
|
+
Together, these classes provide a complete system for manipulating AST nodes once they have been identified using
|
|
12
|
+
predicate functions from ifThis.
|
|
15
13
|
"""
|
|
16
14
|
|
|
17
15
|
from collections.abc import Callable, Sequence
|
|
18
16
|
from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue, ImaCallToName, NodeORattribute
|
|
19
|
-
from typing import Any
|
|
17
|
+
from typing import Any
|
|
20
18
|
import ast
|
|
21
19
|
|
|
22
20
|
class grab:
|
|
23
21
|
"""
|
|
24
22
|
Modify specific attributes of AST nodes while preserving the node structure.
|
|
25
23
|
|
|
26
|
-
The grab class provides static methods that create transformation functions to modify
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
entire node.
|
|
24
|
+
The grab class provides static methods that create transformation functions to modify specific attributes of AST
|
|
25
|
+
nodes. Unlike DOT which provides read-only access, grab allows for targeted modifications of node attributes without
|
|
26
|
+
replacing the entire node.
|
|
30
27
|
|
|
31
|
-
Each method returns a function that takes a node, applies a transformation to a
|
|
32
|
-
|
|
33
|
-
control when transforming AST structures.
|
|
28
|
+
Each method returns a function that takes a node, applies a transformation to a specific attribute of that node, and
|
|
29
|
+
returns the modified node. This enables fine-grained control when transforming AST structures.
|
|
34
30
|
"""
|
|
35
31
|
@staticmethod
|
|
36
32
|
def andDoAllOf(listOfActions: list[Callable[[NodeORattribute], NodeORattribute]]) -> Callable[[NodeORattribute], NodeORattribute]:
|
|
@@ -114,13 +110,12 @@ class Then:
|
|
|
114
110
|
"""
|
|
115
111
|
Provide action functions that specify what to do with AST nodes that match predicates.
|
|
116
112
|
|
|
117
|
-
The Then class contains static methods that generate action functions used with
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
extraction, and collection operations.
|
|
113
|
+
The Then class contains static methods that generate action functions used with NodeChanger and NodeTourist to
|
|
114
|
+
transform or extract information from AST nodes that match specific predicates. These actions include node
|
|
115
|
+
replacement, insertion, extraction, and collection operations.
|
|
121
116
|
|
|
122
|
-
When paired with predicates from the ifThis class, Then methods complete the
|
|
123
|
-
|
|
117
|
+
When paired with predicates from the ifThis class, Then methods complete the pattern-matching-and-action workflow
|
|
118
|
+
for AST manipulation.
|
|
124
119
|
"""
|
|
125
120
|
@staticmethod
|
|
126
121
|
def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST | ast_Identifier], ast.AST | ast_Identifier]:
|
|
@@ -28,12 +28,12 @@ from mapFolding.someAssemblyRequired import (
|
|
|
28
28
|
astClassHasDOTnameNotName,
|
|
29
29
|
astClassHasDOTnameNotNameAlways,
|
|
30
30
|
astClassHasDOTnameNotNameOptionally,
|
|
31
|
-
astClassHasDOTtarget_expr,
|
|
32
31
|
astClassHasDOTtarget,
|
|
32
|
+
astClassHasDOTtarget_expr,
|
|
33
33
|
astClassHasDOTtargetAttributeNameSubscript,
|
|
34
|
+
astClassHasDOTvalue,
|
|
34
35
|
astClassHasDOTvalue_expr,
|
|
35
36
|
astClassHasDOTvalue_exprNone,
|
|
36
|
-
astClassHasDOTvalue,
|
|
37
37
|
ImaCallToName,
|
|
38
38
|
)
|
|
39
39
|
from typing import Any, overload, TypeGuard
|
|
@@ -43,13 +43,12 @@ class DOT:
|
|
|
43
43
|
"""
|
|
44
44
|
Access attributes and sub-nodes of AST elements via consistent accessor methods.
|
|
45
45
|
|
|
46
|
-
The DOT class provides static methods to access specific attributes of different
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
AST structure details.
|
|
46
|
+
The DOT class provides static methods to access specific attributes of different types of AST nodes in a consistent
|
|
47
|
+
way. This simplifies attribute access across various node types and improves code readability by abstracting the
|
|
48
|
+
underlying AST structure details.
|
|
50
49
|
|
|
51
|
-
DOT is designed for safe, read-only access to node properties, unlike the grab
|
|
52
|
-
|
|
50
|
+
DOT is designed for safe, read-only access to node properties, unlike the grab class which is designed for modifying
|
|
51
|
+
node attributes.
|
|
53
52
|
"""
|
|
54
53
|
@staticmethod
|
|
55
54
|
@overload
|
|
@@ -213,6 +212,10 @@ class be:
|
|
|
213
212
|
def Name(node: ast.AST) -> TypeGuard[ast.Name]:
|
|
214
213
|
return isinstance(node, ast.Name)
|
|
215
214
|
|
|
215
|
+
@staticmethod
|
|
216
|
+
def Not(node: ast.AST) -> TypeGuard[ast.Not]:
|
|
217
|
+
return isinstance(node, ast.Not)
|
|
218
|
+
|
|
216
219
|
@staticmethod
|
|
217
220
|
def Return(node: ast.AST) -> TypeGuard[ast.Return]:
|
|
218
221
|
return isinstance(node, ast.Return)
|
|
@@ -229,6 +232,10 @@ class be:
|
|
|
229
232
|
def Tuple(node: ast.AST) -> TypeGuard[ast.Tuple]:
|
|
230
233
|
return isinstance(node, ast.Tuple)
|
|
231
234
|
|
|
235
|
+
@staticmethod
|
|
236
|
+
def UnaryOp(node: ast.AST) -> TypeGuard[ast.UnaryOp]:
|
|
237
|
+
return isinstance(node, ast.UnaryOp)
|
|
238
|
+
|
|
232
239
|
@staticmethod
|
|
233
240
|
def While(node: ast.AST) -> TypeGuard[ast.While]:
|
|
234
241
|
return isinstance(node, ast.While)
|
|
@@ -237,13 +244,12 @@ class ifThis:
|
|
|
237
244
|
"""
|
|
238
245
|
Provide predicate functions for matching and filtering AST nodes based on various criteria.
|
|
239
246
|
|
|
240
|
-
The ifThis class contains static methods that generate predicate functions used to test
|
|
241
|
-
|
|
242
|
-
|
|
247
|
+
The ifThis class contains static methods that generate predicate functions used to test whether AST nodes match
|
|
248
|
+
specific criteria. These predicates can be used with NodeChanger and NodeTourist to identify and process specific
|
|
249
|
+
patterns in the AST.
|
|
243
250
|
|
|
244
|
-
The class provides predicates for matching various node types, attributes, identifiers,
|
|
245
|
-
|
|
246
|
-
transformation.
|
|
251
|
+
The class provides predicates for matching various node types, attributes, identifiers, and structural patterns,
|
|
252
|
+
enabling precise targeting of AST elements for analysis or transformation.
|
|
247
253
|
"""
|
|
248
254
|
@staticmethod
|
|
249
255
|
def _Identifier(identifier: ast_Identifier) -> Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]:
|
|
@@ -304,7 +310,18 @@ class ifThis:
|
|
|
304
310
|
and ifThis.isConstant_value(0)(node.comparators[0]))
|
|
305
311
|
|
|
306
312
|
@staticmethod
|
|
307
|
-
def
|
|
313
|
+
def isUnaryNotAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.UnaryOp] | bool]:
|
|
314
|
+
return lambda node: (be.UnaryOp(node)
|
|
315
|
+
and be.Not(node.op)
|
|
316
|
+
and ifThis.isAttributeNamespace_Identifier(namespace, identifier)(node.operand))
|
|
317
|
+
|
|
318
|
+
@staticmethod
|
|
319
|
+
def isIfUnaryNotAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.If] | bool]:
|
|
320
|
+
return lambda node: (be.If(node)
|
|
321
|
+
and ifThis.isUnaryNotAttributeNamespace_Identifier(namespace, identifier)(node.test))
|
|
322
|
+
|
|
323
|
+
@staticmethod
|
|
324
|
+
def isIfAttributeNamespace_IdentifierGreaterThan0(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.If] | bool]:
|
|
308
325
|
return lambda node: (be.If(node)
|
|
309
326
|
and ifThis.isAttributeNamespace_IdentifierGreaterThan0(namespace, identifier)(node.test))
|
|
310
327
|
|
|
@@ -19,9 +19,11 @@ specific optimizations and transformations.
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from collections import defaultdict
|
|
22
|
-
from collections.abc import Sequence
|
|
23
|
-
from
|
|
24
|
-
from
|
|
22
|
+
from collections.abc import Callable, Sequence
|
|
23
|
+
from copy import deepcopy
|
|
24
|
+
from typing import Any
|
|
25
|
+
from mapFolding.someAssemblyRequired import ast_Identifier, DOT, ifThis, Make, NodeTourist, parseLogicalPath2astModule, str_nameDOTname, Then
|
|
26
|
+
from mapFolding.theSSOT import raiseIfNoneGitHubIssueNumber3, The
|
|
25
27
|
from pathlib import Path, PurePosixPath
|
|
26
28
|
from Z0Z_tools import updateExtendPolishDictionaryLists
|
|
27
29
|
import ast
|
|
@@ -171,22 +173,21 @@ class IngredientsModule:
|
|
|
171
173
|
"""
|
|
172
174
|
Assemble a complete Python module from its constituent AST components.
|
|
173
175
|
|
|
174
|
-
IngredientsModule provides a structured container for all elements needed to
|
|
175
|
-
|
|
176
|
+
IngredientsModule provides a structured container for all elements needed to generate a complete Python module,
|
|
177
|
+
including:
|
|
176
178
|
|
|
177
|
-
1. Import statements aggregated from all module components
|
|
178
|
-
2. Prologue code that runs before function definitions
|
|
179
|
-
3. Function definitions with their dependencies
|
|
180
|
-
4. Epilogue code that runs after function definitions
|
|
181
|
-
5. Entry point code executed when the module runs as a script
|
|
182
|
-
6. Type ignores and other annotations
|
|
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.
|
|
183
185
|
|
|
184
|
-
This class enables programmatic assembly of Python modules with a clear
|
|
185
|
-
|
|
186
|
-
proper ordering and relationships between components.
|
|
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.
|
|
187
188
|
|
|
188
|
-
The modular design allows transformations to be applied to specific parts
|
|
189
|
-
|
|
189
|
+
The modular design allows transformations to be applied to specific parts of a module while preserving the overall
|
|
190
|
+
structure.
|
|
190
191
|
|
|
191
192
|
Parameters:
|
|
192
193
|
ingredientsFunction (None): One or more `IngredientsFunction` that will appended to `listIngredientsFunctions`.
|
|
@@ -311,22 +312,20 @@ class RecipeSynthesizeFlow:
|
|
|
311
312
|
"""
|
|
312
313
|
Configure the generation of new modules, including Numba-accelerated code modules.
|
|
313
314
|
|
|
314
|
-
RecipeSynthesizeFlow defines the complete blueprint for transforming an original
|
|
315
|
-
|
|
315
|
+
RecipeSynthesizeFlow defines the complete blueprint for transforming an original Python algorithm into an optimized,
|
|
316
|
+
accelerated implementation. It specifies:
|
|
316
317
|
|
|
317
|
-
1. Source code locations and identifiers
|
|
318
|
-
2. Target code locations and identifiers
|
|
319
|
-
3. Naming conventions for generated modules and functions
|
|
320
|
-
4. File system paths for output files
|
|
321
|
-
5. Import relationships between components
|
|
318
|
+
1. Source code locations and identifiers.
|
|
319
|
+
2. Target code locations and identifiers.
|
|
320
|
+
3. Naming conventions for generated modules and functions.
|
|
321
|
+
4. File system paths for output files.
|
|
322
|
+
5. Import relationships between components.
|
|
322
323
|
|
|
323
|
-
This configuration class serves as a single source of truth for the code generation
|
|
324
|
-
|
|
325
|
-
customization of the transformation assembly line.
|
|
324
|
+
This configuration class serves as a single source of truth for the code generation process, ensuring consistency
|
|
325
|
+
across all generated artifacts while enabling customization of the transformation assembly line.
|
|
326
326
|
|
|
327
|
-
The transformation process uses this configuration to extract functions from the
|
|
328
|
-
|
|
329
|
-
properly structured optimized modules with all necessary imports.
|
|
327
|
+
The transformation process uses this configuration to extract functions from the source module, transform them
|
|
328
|
+
according to optimization rules, and output properly structured optimized modules with all necessary imports.
|
|
330
329
|
"""
|
|
331
330
|
# ========================================
|
|
332
331
|
# Source
|
|
@@ -471,3 +470,99 @@ class ShatteredDataclass:
|
|
|
471
470
|
|
|
472
471
|
signatureReturnAnnotation: ast.Subscript = dummySubscript
|
|
473
472
|
"""tuple-based return type annotation for function definitions."""
|
|
473
|
+
|
|
474
|
+
@dataclasses.dataclass
|
|
475
|
+
class DeReConstructField2ast:
|
|
476
|
+
"""
|
|
477
|
+
Transform a dataclass field into AST node representations for code generation.
|
|
478
|
+
|
|
479
|
+
This class extracts and transforms a dataclass Field object into various AST node
|
|
480
|
+
representations needed for code generation. It handles the conversion of field
|
|
481
|
+
attributes, type annotations, and metadata into AST constructs that can be used
|
|
482
|
+
to reconstruct the field in generated code.
|
|
483
|
+
|
|
484
|
+
The class is particularly important for decomposing dataclass fields (like those in
|
|
485
|
+
ComputationState) to enable their use in specialized contexts like Numba-optimized
|
|
486
|
+
functions, where the full dataclass cannot be directly used but its contents need
|
|
487
|
+
to be accessible.
|
|
488
|
+
|
|
489
|
+
Each field is processed according to its type and metadata to create appropriate
|
|
490
|
+
variable declarations, type annotations, and initialization code as AST nodes.
|
|
491
|
+
"""
|
|
492
|
+
dataclassesDOTdataclassLogicalPathModule: dataclasses.InitVar[str_nameDOTname]
|
|
493
|
+
dataclassClassDef: dataclasses.InitVar[ast.ClassDef]
|
|
494
|
+
dataclassesDOTdataclassInstance_Identifier: dataclasses.InitVar[ast_Identifier]
|
|
495
|
+
field: dataclasses.InitVar[dataclasses.Field[Any]]
|
|
496
|
+
|
|
497
|
+
ledger: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
|
|
498
|
+
|
|
499
|
+
name: ast_Identifier = dataclasses.field(init=False)
|
|
500
|
+
typeBuffalo: type[Any] | str | Any = dataclasses.field(init=False)
|
|
501
|
+
default: Any | None = dataclasses.field(init=False)
|
|
502
|
+
default_factory: Callable[..., Any] | None = dataclasses.field(init=False)
|
|
503
|
+
repr: bool = dataclasses.field(init=False)
|
|
504
|
+
hash: bool | None = dataclasses.field(init=False)
|
|
505
|
+
init: bool = dataclasses.field(init=False)
|
|
506
|
+
compare: bool = dataclasses.field(init=False)
|
|
507
|
+
metadata: dict[Any, Any] = dataclasses.field(init=False)
|
|
508
|
+
kw_only: bool = dataclasses.field(init=False)
|
|
509
|
+
|
|
510
|
+
astName: ast.Name = dataclasses.field(init=False)
|
|
511
|
+
ast_keyword_field__field: ast.keyword = dataclasses.field(init=False)
|
|
512
|
+
ast_nameDOTname: ast.Attribute = dataclasses.field(init=False)
|
|
513
|
+
astAnnotation: ast.expr = dataclasses.field(init=False)
|
|
514
|
+
ast_argAnnotated: ast.arg = dataclasses.field(init=False)
|
|
515
|
+
astAnnAssignConstructor: ast.AnnAssign|ast.Assign = dataclasses.field(init=False)
|
|
516
|
+
Z0Z_hack: tuple[ast.AnnAssign|ast.Assign, str] = dataclasses.field(init=False)
|
|
517
|
+
|
|
518
|
+
def __post_init__(self, dataclassesDOTdataclassLogicalPathModule: str_nameDOTname, dataclassClassDef: ast.ClassDef, dataclassesDOTdataclassInstance_Identifier: ast_Identifier, field: dataclasses.Field[Any]) -> None:
|
|
519
|
+
self.compare = field.compare
|
|
520
|
+
self.default = field.default if field.default is not dataclasses.MISSING else None
|
|
521
|
+
self.default_factory = field.default_factory if field.default_factory is not dataclasses.MISSING else None
|
|
522
|
+
self.hash = field.hash
|
|
523
|
+
self.init = field.init
|
|
524
|
+
self.kw_only = field.kw_only if field.kw_only is not dataclasses.MISSING else False
|
|
525
|
+
self.metadata = dict(field.metadata)
|
|
526
|
+
self.name = field.name
|
|
527
|
+
self.repr = field.repr
|
|
528
|
+
self.typeBuffalo = field.type
|
|
529
|
+
|
|
530
|
+
self.astName = Make.Name(self.name)
|
|
531
|
+
self.ast_keyword_field__field = Make.keyword(self.name, self.astName)
|
|
532
|
+
self.ast_nameDOTname = Make.Attribute(Make.Name(dataclassesDOTdataclassInstance_Identifier), self.name)
|
|
533
|
+
|
|
534
|
+
sherpa = NodeTourist(ifThis.isAnnAssign_targetIs(ifThis.isName_Identifier(self.name)), Then.extractIt(DOT.annotation)).captureLastMatch(dataclassClassDef)
|
|
535
|
+
if sherpa is None: raise raiseIfNoneGitHubIssueNumber3
|
|
536
|
+
else: self.astAnnotation = sherpa
|
|
537
|
+
|
|
538
|
+
self.ast_argAnnotated = Make.arg(self.name, self.astAnnotation)
|
|
539
|
+
|
|
540
|
+
dtype = self.metadata.get('dtype', None)
|
|
541
|
+
if dtype:
|
|
542
|
+
moduleWithLogicalPath: str_nameDOTname = 'numpy'
|
|
543
|
+
annotationType = 'ndarray'
|
|
544
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotationType)
|
|
545
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, 'dtype')
|
|
546
|
+
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Name('uint8'))
|
|
547
|
+
dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
|
|
548
|
+
if dtype_asnameName.id == 'Array3D':
|
|
549
|
+
axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Tuple([Make.Name('uint8'), Make.Name('uint8'), Make.Name('uint8')]))
|
|
550
|
+
ast_expr = Make.Subscript(Make.Name(annotationType), Make.Tuple([axesSubscript, Make.Subscript(Make.Name('dtype'), dtype_asnameName)]))
|
|
551
|
+
constructor = 'array'
|
|
552
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, constructor)
|
|
553
|
+
dtypeIdentifier: ast_Identifier = dtype.__name__
|
|
554
|
+
self.ledger.addImportFrom_asStr(moduleWithLogicalPath, dtypeIdentifier, dtype_asnameName.id)
|
|
555
|
+
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, ast_expr, Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
|
|
556
|
+
self.astAnnAssignConstructor = Make.Assign([self.astName], Make.Call(Make.Name(constructor), list_astKeywords=[Make.keyword('dtype', dtype_asnameName)]))
|
|
557
|
+
self.Z0Z_hack = (self.astAnnAssignConstructor, 'array')
|
|
558
|
+
elif isinstance(self.astAnnotation, ast.Name):
|
|
559
|
+
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, Make.Call(self.astAnnotation, [Make.Constant(-1)]))
|
|
560
|
+
self.Z0Z_hack = (self.astAnnAssignConstructor, 'scalar')
|
|
561
|
+
elif isinstance(self.astAnnotation, ast.Subscript):
|
|
562
|
+
elementConstructor: ast_Identifier = self.metadata['elementConstructor']
|
|
563
|
+
self.ledger.addImportFrom_asStr(dataclassesDOTdataclassLogicalPathModule, elementConstructor)
|
|
564
|
+
takeTheTuple: ast.Tuple = deepcopy(self.astAnnotation.slice) # type: ignore
|
|
565
|
+
self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, takeTheTuple)
|
|
566
|
+
self.Z0Z_hack = (self.astAnnAssignConstructor, elementConstructor)
|
|
567
|
+
if isinstance(self.astAnnotation, ast.Name):
|
|
568
|
+
self.ledger.addImportFrom_asStr(dataclassesDOTdataclassLogicalPathModule, self.astAnnotation.id) # pyright: ignore [reportUnknownArgumentType, reportUnknownMemberType, reportIJustCalledATypeGuardMethod_WTF]
|