mapFolding 0.9.1__py3-none-any.whl → 0.9.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.
Files changed (36) hide show
  1. mapFolding/Z0Z_flowControl.py +99 -0
  2. mapFolding/__init__.py +63 -60
  3. mapFolding/basecamp.py +40 -35
  4. mapFolding/beDRY.py +72 -66
  5. mapFolding/dataBaskets.py +49 -0
  6. mapFolding/datatypes.py +21 -0
  7. mapFolding/oeis.py +57 -75
  8. mapFolding/reference/__init__.py +2 -2
  9. mapFolding/someAssemblyRequired/__init__.py +6 -4
  10. mapFolding/someAssemblyRequired/_theTypes.py +9 -1
  11. mapFolding/someAssemblyRequired/_tool_Make.py +0 -1
  12. mapFolding/someAssemblyRequired/_tool_Then.py +16 -8
  13. mapFolding/someAssemblyRequired/_toolboxAntecedents.py +111 -35
  14. mapFolding/someAssemblyRequired/_toolboxContainers.py +58 -49
  15. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +42 -42
  16. mapFolding/someAssemblyRequired/toolboxNumba.py +3 -11
  17. mapFolding/someAssemblyRequired/transformationTools.py +94 -70
  18. mapFolding/syntheticModules/numbaCount.py +9 -11
  19. mapFolding/theDao.py +19 -21
  20. mapFolding/theDaoOfMapFolding.py +142 -0
  21. mapFolding/theSSOT.py +36 -58
  22. mapFolding/toolboxFilesystem.py +29 -38
  23. {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/METADATA +4 -3
  24. mapfolding-0.9.3.dist-info/RECORD +51 -0
  25. {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/WHEEL +1 -1
  26. tests/__init__.py +2 -2
  27. tests/conftest.py +7 -7
  28. tests/test_computations.py +15 -13
  29. tests/test_other.py +0 -7
  30. tests/test_tasks.py +2 -2
  31. mapfolding-0.9.1.dist-info/RECORD +0 -47
  32. /mapFolding/reference/{lunnanNumpy.py → lunnonNumpy.py} +0 -0
  33. /mapFolding/reference/{lunnanWhile.py → lunnonWhile.py} +0 -0
  34. {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/entry_points.txt +0 -0
  35. {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/licenses/LICENSE +0 -0
  36. {mapfolding-0.9.1.dist-info → mapfolding-0.9.3.dist-info}/top_level.txt +0 -0
@@ -2,17 +2,22 @@
2
2
  AST Node Predicate and Access Utilities for Pattern Matching and Traversal
3
3
 
4
4
  This module provides utilities for accessing and matching AST nodes in a consistent way.
5
- It contains two primary classes:
5
+ It contains three primary classes:
6
6
 
7
7
  1. DOT: Provides consistent accessor methods for AST node attributes across different
8
8
  node types, simplifying the access to node properties.
9
9
 
10
- 2. ifThis: Contains predicate functions for matching AST nodes based on various criteria,
10
+ 2. be: Offers type-guard functions that verify AST node types, enabling safe type
11
+ narrowing for static type checking and improving code safety.
12
+
13
+ 3. ifThis: Contains predicate functions for matching AST nodes based on various criteria,
11
14
  enabling precise targeting of nodes for analysis or transformation.
12
15
 
13
16
  These utilities form the foundation of the pattern-matching component in the AST
14
17
  manipulation framework, working in conjunction with the NodeChanger and NodeTourist
15
- classes to enable precise and targeted code transformations.
18
+ classes to enable precise and targeted code transformations. Together, they implement
19
+ a declarative approach to AST manipulation that separates node identification (ifThis),
20
+ type verification (be), and data access (DOT).
16
21
  """
17
22
 
18
23
  from collections.abc import Callable
@@ -26,6 +31,7 @@ from mapFolding.someAssemblyRequired import (
26
31
  astClassHasDOTvalue_expr,
27
32
  astClassOptionallyHasDOTnameNotName,
28
33
  astClassHasDOTvalue_exprNone,
34
+ ImaCallToName,
29
35
  )
30
36
  from typing import Any, overload, TypeGuard
31
37
  import ast
@@ -65,9 +71,17 @@ class DOT:
65
71
  @staticmethod
66
72
  def attr(node: ast.Attribute) -> ast_Identifier:
67
73
  return node.attr
74
+
75
+ @staticmethod
76
+ @overload
77
+ def func(node: ImaCallToName) -> ast.Name:...
68
78
  @staticmethod
69
- def func(node: ast.Call) -> ast.expr:
79
+ @overload
80
+ def func(node: ast.Call) -> ast.expr:...
81
+ @staticmethod
82
+ def func(node: ast.Call | ImaCallToName) -> ast.expr | ast.Name:
70
83
  return node.func
84
+
71
85
  @staticmethod
72
86
  def id(node: ast.Name) -> ast_Identifier:
73
87
  return node.id
@@ -111,6 +125,75 @@ class DOT:
111
125
  def value(node: astClassHasDOTvalue) -> Any | ast.expr | bool | None:
112
126
  return node.value
113
127
 
128
+ class be:
129
+ """
130
+ Provide type-guard functions for safely verifying AST node types during manipulation.
131
+
132
+ The be class contains static methods that perform runtime type verification of AST nodes,
133
+ returning TypeGuard results that enable static type checkers to narrow node types in
134
+ conditional branches. These type-guards:
135
+
136
+ 1. Improve code safety by preventing operations on incompatible node types
137
+ 2. Enable IDE tooling to provide better autocompletion and error detection
138
+ 3. Document expected node types in a way that's enforced by the type system
139
+ 4. Support pattern-matching workflows where node types must be verified before access
140
+
141
+ When used with conditional statements, these type-guards allow for precise,
142
+ type-safe manipulation of AST nodes while maintaining full static type checking
143
+ capabilities, even in complex transformation scenarios.
144
+ """
145
+ @staticmethod
146
+ def AnnAssign(node: ast.AST) -> TypeGuard[ast.AnnAssign]:
147
+ return isinstance(node, ast.AnnAssign)
148
+
149
+ @staticmethod
150
+ def arg(node: ast.AST) -> TypeGuard[ast.arg]:
151
+ return isinstance(node, ast.arg)
152
+
153
+ @staticmethod
154
+ def Assign(node: ast.AST) -> TypeGuard[ast.Assign]:
155
+ return isinstance(node, ast.Assign)
156
+
157
+ @staticmethod
158
+ def Attribute(node: ast.AST) -> TypeGuard[ast.Attribute]:
159
+ return isinstance(node, ast.Attribute)
160
+
161
+ @staticmethod
162
+ def AugAssign(node: ast.AST) -> TypeGuard[ast.AugAssign]:
163
+ return isinstance(node, ast.AugAssign)
164
+
165
+ @staticmethod
166
+ def Call(node: ast.AST) -> TypeGuard[ast.Call]:
167
+ return isinstance(node, ast.Call)
168
+
169
+ @staticmethod
170
+ def ClassDef(node: ast.AST) -> TypeGuard[ast.ClassDef]:
171
+ return isinstance(node, ast.ClassDef)
172
+
173
+ @staticmethod
174
+ def FunctionDef(node: ast.AST) -> TypeGuard[ast.FunctionDef]:
175
+ return isinstance(node, ast.FunctionDef)
176
+
177
+ @staticmethod
178
+ def keyword(node: ast.AST) -> TypeGuard[ast.keyword]:
179
+ return isinstance(node, ast.keyword)
180
+
181
+ @staticmethod
182
+ def Name(node: ast.AST) -> TypeGuard[ast.Name]:
183
+ return isinstance(node, ast.Name)
184
+
185
+ @staticmethod
186
+ def Return(node: ast.AST) -> TypeGuard[ast.Return]:
187
+ return isinstance(node, ast.Return)
188
+
189
+ @staticmethod
190
+ def Starred(node: ast.AST) -> TypeGuard[ast.Starred]:
191
+ return isinstance(node, ast.Starred)
192
+
193
+ @staticmethod
194
+ def Subscript(node: ast.AST) -> TypeGuard[ast.Subscript]:
195
+ return isinstance(node, ast.Subscript)
196
+
114
197
  class ifThis:
115
198
  """
116
199
  Provide predicate functions for matching and filtering AST nodes based on various criteria.
@@ -135,41 +218,41 @@ class ifThis:
135
218
  @staticmethod
136
219
  def is_arg_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.arg] | bool]:
137
220
  """see also `isArgument_Identifier`"""
138
- return lambda node: isinstance(node, ast.arg) and ifThis._Identifier(identifier)(DOT.arg(node))
221
+ return lambda node: be.arg(node) and ifThis._Identifier(identifier)(DOT.arg(node))
139
222
  @staticmethod
140
223
  def is_keyword_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.keyword] | bool]:
141
224
  """see also `isArgument_Identifier`"""
142
- return lambda node: isinstance(node, ast.keyword) and ifThis._Identifier(identifier)(DOT.arg(node))
225
+ return lambda node: be.keyword(node) and ifThis._Identifier(identifier)(DOT.arg(node))
143
226
 
144
227
  @staticmethod
145
228
  def isAnnAssign_targetIs(targetPredicate: Callable[[ast.expr], TypeGuard[ast.expr] | bool]) -> Callable[[ast.AST], TypeGuard[ast.AnnAssign] | bool]:
146
229
  def workhorse(node: ast.AST) -> TypeGuard[ast.AnnAssign] | bool:
147
- return isinstance(node, ast.AnnAssign) and targetPredicate(DOT.target(node))
230
+ return be.AnnAssign(node) and targetPredicate(DOT.target(node))
148
231
  return workhorse
149
232
 
150
233
  @staticmethod
151
234
  def isArgument_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.arg | ast.keyword] | bool]:
152
- return lambda node: (isinstance(node, ast.arg) or isinstance(node, ast.keyword)) and ifThis._Identifier(identifier)(DOT.arg(node))
235
+ return lambda node: (be.arg(node) or be.keyword(node)) and ifThis._Identifier(identifier)(DOT.arg(node))
153
236
 
154
237
  @staticmethod
155
238
  def isAssignAndTargets0Is(targets0Predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[ast.AnnAssign] | bool]:
156
239
  """node is Assign and node.targets[0] matches `targets0Predicate`."""
157
- return lambda node: isinstance(node, ast.Assign) and targets0Predicate(node.targets[0])
240
+ return lambda node: be.Assign(node) and targets0Predicate(node.targets[0])
158
241
  @staticmethod
159
242
  def isAssignAndValueIs(valuePredicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[ast.Assign] | bool]:
160
243
  """node is ast.Assign and node.value matches `valuePredicate`. """
161
- return lambda node: isinstance(node, ast.Assign) and valuePredicate(DOT.value(node))
244
+ return lambda node: be.Assign(node) and valuePredicate(DOT.value(node))
162
245
 
163
246
  @staticmethod
164
247
  def isAttribute_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Attribute] | bool]:
165
248
  """node is `ast.Attribute` and the top-level `ast.Name` is `identifier`"""
166
249
  def workhorse(node: ast.AST) -> TypeGuard[ast.Attribute]:
167
- return isinstance(node, ast.Attribute) and ifThis._nested_Identifier(identifier)(DOT.value(node))
250
+ return be.Attribute(node) and ifThis._nested_Identifier(identifier)(DOT.value(node))
168
251
  return workhorse
169
252
  @staticmethod
170
253
  def isAttributeName(node: ast.AST) -> TypeGuard[ast.Attribute]:
171
254
  """ Displayed as Name.attribute."""
172
- return isinstance(node, ast.Attribute) and isinstance(DOT.value(node), ast.Name)
255
+ return be.Attribute(node) and be.Name(DOT.value(node))
173
256
  @staticmethod
174
257
  def isAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Attribute] | bool]:
175
258
  return lambda node: ifThis.isAttributeName(node) and ifThis.isName_Identifier(namespace)(DOT.value(node)) and ifThis._Identifier(identifier)(DOT.attr(node))
@@ -177,42 +260,47 @@ class ifThis:
177
260
  @staticmethod
178
261
  def isAugAssign_targetIs(targetPredicate: Callable[[ast.expr], TypeGuard[ast.expr] | bool]) -> Callable[[ast.AST], TypeGuard[ast.AugAssign] | bool]:
179
262
  def workhorse(node: ast.AST) -> TypeGuard[ast.AugAssign] | bool:
180
- return isinstance(node, ast.AugAssign) and targetPredicate(DOT.target(node))
263
+ return be.AugAssign(node) and targetPredicate(DOT.target(node))
181
264
  return workhorse
182
265
 
183
266
  @staticmethod
184
- def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Call] | bool]:
185
- return lambda node: isinstance(node, ast.Call) and ifThis.isName_Identifier(identifier)(DOT.func(node))
267
+ def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ImaCallToName] | bool]:
268
+ def workhorse(node: ast.AST) -> TypeGuard[ImaCallToName] | bool:
269
+ return ifThis.isCallToName(node) and ifThis._Identifier(identifier)(DOT.id(DOT.func(node)))
270
+ return workhorse
271
+
186
272
  @staticmethod
187
273
  def isCallAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Call] | bool]:
188
- return lambda node: isinstance(node, ast.Call) and ifThis.isAttributeNamespace_Identifier(namespace, identifier)(DOT.func(node))
274
+ def workhorse(node: ast.AST) -> TypeGuard[ast.Call] | bool:
275
+ return be.Call(node) and ifThis.isAttributeNamespace_Identifier(namespace, identifier)(DOT.func(node))
276
+ return workhorse
189
277
  @staticmethod
190
- def isCallToName(node: ast.AST) -> TypeGuard[ast.Call]:
191
- return isinstance(node, ast.Call) and isinstance(DOT.func(node), ast.Name)
278
+ def isCallToName(node: ast.AST) -> TypeGuard[ImaCallToName]:
279
+ return be.Call(node) and be.Name(DOT.func(node))
192
280
 
193
281
  @staticmethod
194
282
  def isClassDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.ClassDef] | bool]:
195
- return lambda node: isinstance(node, ast.ClassDef) and ifThis._Identifier(identifier)(DOT.name(node))
283
+ return lambda node: be.ClassDef(node) and ifThis._Identifier(identifier)(DOT.name(node))
196
284
 
197
285
  @staticmethod
198
286
  def isFunctionDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.FunctionDef] | bool]:
199
- return lambda node: isinstance(node, ast.FunctionDef) and ifThis._Identifier(identifier)(DOT.name(node))
287
+ return lambda node: be.FunctionDef(node) and ifThis._Identifier(identifier)(DOT.name(node))
200
288
 
201
289
  @staticmethod
202
290
  def isName_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Name] | bool]:
203
- return lambda node: isinstance(node, ast.Name) and ifThis._Identifier(identifier)(DOT.id(node))
291
+ return lambda node: be.Name(node) and ifThis._Identifier(identifier)(DOT.id(node))
204
292
 
205
293
  @staticmethod
206
294
  def isStarred_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Starred] | bool]:
207
295
  """node is `ast.Starred` and the top-level `ast.Name` is `identifier`"""
208
296
  def workhorse(node: ast.AST) -> TypeGuard[ast.Starred]:
209
- return isinstance(node, ast.Starred) and ifThis._nested_Identifier(identifier)(DOT.value(node))
297
+ return be.Starred(node) and ifThis._nested_Identifier(identifier)(DOT.value(node))
210
298
  return workhorse
211
299
  @staticmethod
212
300
  def isSubscript_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Subscript] | bool]:
213
301
  """node is `ast.Subscript` and the top-level `ast.Name` is `identifier`"""
214
302
  def workhorse(node: ast.AST) -> TypeGuard[ast.Subscript]:
215
- return isinstance(node, ast.Subscript) and ifThis._nested_Identifier(identifier)(DOT.value(node))
303
+ return be.Subscript(node) and ifThis._nested_Identifier(identifier)(DOT.value(node))
216
304
  return workhorse
217
305
 
218
306
  @staticmethod
@@ -231,15 +319,3 @@ class ifThis:
231
319
  def Z0Z_unparseIs(astAST: ast.AST) -> Callable[[ast.AST], bool]:
232
320
  def workhorse(node: ast.AST) -> bool: return ast.unparse(node) == ast.unparse(astAST)
233
321
  return workhorse
234
-
235
-
236
- class be:
237
- @staticmethod
238
- def Call(node: ast.AST) -> TypeGuard[ast.Call]:
239
- return isinstance(node, ast.Call)
240
- @staticmethod
241
- def Name(node: ast.AST) -> TypeGuard[ast.Name]:
242
- return isinstance(node, ast.Name)
243
- @staticmethod
244
- def Return(node: ast.AST) -> TypeGuard[ast.Return]:
245
- return isinstance(node, ast.Return)
@@ -1,23 +1,21 @@
1
1
  """
2
2
  AST Container Classes for Python Code Generation and Transformation
3
3
 
4
- This module provides specialized container classes that organize AST nodes, imports,
5
- and program structure for code generation and transformation. These classes form
6
- the organizational backbone of the code generation system, enabling:
7
-
8
- 1. Tracking and managing imports with LedgerOfImports
9
- 2. Packaging function definitions with their dependencies via IngredientsFunction
10
- 3. Structuring complete modules with IngredientsModule
11
- 4. Configuring code synthesis with RecipeSynthesizeFlow
12
- 5. Organizing decomposed dataclass representations with ShatteredDataclass
13
-
14
- Together, these container classes implement a component-based architecture for
15
- programmatic generation of high-performance code. They maintain a clean separation
16
- between structure and content, allowing transformations to be applied systematically
17
- while preserving relationships between code elements.
18
-
19
- The containers work in conjunction with transformation tools that manipulate the
20
- contained AST nodes to implement specific optimizations and transformations.
4
+ This module provides specialized container classes that organize AST nodes, imports, and program structure for code
5
+ generation and transformation. These classes form the organizational backbone of the code generation system, enabling:
6
+
7
+ 1. Tracking and managing imports with LedgerOfImports.
8
+ 2. Packaging function definitions with their dependencies via IngredientsFunction.
9
+ 3. Structuring complete modules with IngredientsModule.
10
+ 4. Configuring code synthesis with RecipeSynthesizeFlow.
11
+ 5. Organizing decomposed dataclass representations with ShatteredDataclass.
12
+
13
+ Together, these container classes implement a component-based architecture for programmatic generation of
14
+ high-performance code. They maintain a clean separation between structure and content, allowing transformations to be
15
+ applied systematically while preserving relationships between code elements.
16
+
17
+ The containers work in conjunction with transformation tools that manipulate the contained AST nodes to implement
18
+ specific optimizations and transformations.
21
19
  """
22
20
 
23
21
  from collections import defaultdict
@@ -33,30 +31,31 @@ class LedgerOfImports:
33
31
  """
34
32
  Track and manage import statements for programmatically generated code.
35
33
 
36
- LedgerOfImports acts as a registry for import statements, maintaining a clean
37
- separation between the logical structure of imports and their textual representation.
34
+ LedgerOfImports acts as a registry for import statements, maintaining a clean separation between the logical
35
+ structure of imports and their textual representation.
38
36
  It enables:
39
37
 
40
- 1. Tracking regular imports and import-from statements
41
- 2. Adding imports programmatically during code transformation
42
- 3. Merging imports from multiple sources
43
- 4. Removing unnecessary or conflicting imports
44
- 5. Generating optimized AST import nodes for the final code
38
+ 1. Tracking regular imports and import-from statements.
39
+ 2. Adding imports programmatically during code transformation.
40
+ 3. Merging imports from multiple sources.
41
+ 4. Removing unnecessary or conflicting imports.
42
+ 5. Generating optimized AST import nodes for the final code.
45
43
 
46
- This class forms the foundation of dependency management in generated code,
47
- ensuring that all required libraries are available without duplication or
48
- conflict.
44
+ This class forms the foundation of dependency management in generated code, ensuring that all required libraries are
45
+ available without duplication or conflict.
49
46
  """
50
47
  # TODO When resolving the ledger of imports, remove self-referential imports
51
- # TODO add TypeIgnore tracking to the ledger of imports
52
48
 
53
- def __init__(self, startWith: ast.AST | None = None) -> None:
49
+ type_ignores: list[ast.TypeIgnore]
50
+
51
+ def __init__(self, startWith: ast.AST | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
54
52
  self.dictionaryImportFrom: dict[str_nameDOTname, list[tuple[ast_Identifier, ast_Identifier | None]]] = defaultdict(list)
55
53
  self.listImport: list[str_nameDOTname] = []
54
+ self.type_ignores = [] if type_ignores is None else list(type_ignores)
56
55
  if startWith:
57
56
  self.walkThis(startWith)
58
57
 
59
- def addAst(self, astImport____: ast.Import | ast.ImportFrom) -> None:
58
+ def addAst(self, astImport____: ast.Import | ast.ImportFrom, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
60
59
  match astImport____:
61
60
  case ast.Import():
62
61
  for alias in astImport____.names:
@@ -69,14 +68,20 @@ class LedgerOfImports:
69
68
  self.dictionaryImportFrom[astImport____.module].append((alias.name, alias.asname))
70
69
  case _:
71
70
  raise ValueError(f"I received {type(astImport____) = }, but I can only accept {ast.Import} and {ast.ImportFrom}.")
71
+ if type_ignores:
72
+ self.type_ignores.extend(type_ignores)
72
73
 
73
- def addImport_asStr(self, moduleWithLogicalPath: str_nameDOTname) -> None:
74
+ def addImport_asStr(self, moduleWithLogicalPath: str_nameDOTname, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
74
75
  self.listImport.append(moduleWithLogicalPath)
76
+ if type_ignores:
77
+ self.type_ignores.extend(type_ignores)
75
78
 
76
- def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None) -> None:
79
+ def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
77
80
  if moduleWithLogicalPath not in self.dictionaryImportFrom:
78
81
  self.dictionaryImportFrom[moduleWithLogicalPath] = []
79
82
  self.dictionaryImportFrom[moduleWithLogicalPath].append((name, asname))
83
+ if type_ignores:
84
+ self.type_ignores.extend(type_ignores)
80
85
 
81
86
  def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
82
87
  """Remove all imports from a specific module."""
@@ -129,11 +134,14 @@ class LedgerOfImports:
129
134
  self.dictionaryImportFrom = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(ledger.dictionaryImportFrom for ledger in fromLedger), destroyDuplicates=True, reorderLists=True)
130
135
  for ledger in fromLedger:
131
136
  self.listImport.extend(ledger.listImport)
137
+ self.type_ignores.extend(ledger.type_ignores)
132
138
 
133
- def walkThis(self, walkThis: ast.AST) -> None:
139
+ def walkThis(self, walkThis: ast.AST, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
134
140
  for nodeBuffalo in ast.walk(walkThis):
135
141
  if isinstance(nodeBuffalo, (ast.Import, ast.ImportFrom)):
136
142
  self.addAst(nodeBuffalo)
143
+ if type_ignores:
144
+ self.type_ignores.extend(type_ignores)
137
145
 
138
146
  # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
139
147
  @dataclasses.dataclass
@@ -141,17 +149,16 @@ class IngredientsFunction:
141
149
  """
142
150
  Package a function definition with its import dependencies for code generation.
143
151
 
144
- IngredientsFunction encapsulates an AST function definition along with all the
145
- imports required for that function to operate correctly. This creates a modular,
146
- portable unit that can be:
152
+ IngredientsFunction encapsulates an AST function definition along with all the imports required for that function to
153
+ operate correctly. This creates a modular, portable unit that can be:
147
154
 
148
- 1. Transformed independently (e.g., by applying Numba decorators)
149
- 2. Transplanted between modules while maintaining dependencies
150
- 3. Combined with other functions to form complete modules
151
- 4. Analyzed for optimization opportunities
155
+ 1. Transformed independently (e.g., by applying Numba decorators).
156
+ 2. Transplanted between modules while maintaining dependencies.
157
+ 3. Combined with other functions to form complete modules.
158
+ 4. Analyzed for optimization opportunities.
152
159
 
153
- This class forms the primary unit of function manipulation in the code generation
154
- system, enabling targeted transformations while preserving function dependencies.
160
+ This class forms the primary unit of function manipulation in the code generation system, enabling targeted
161
+ transformations while preserving function dependencies.
155
162
 
156
163
  Parameters:
157
164
  astFunctionDef: The AST representation of the function definition
@@ -251,7 +258,6 @@ class IngredientsModule:
251
258
  def appendIngredientsFunction(self, *ingredientsFunction: IngredientsFunction) -> None:
252
259
  """Append one or more `IngredientsFunction`."""
253
260
  for allegedIngredientsFunction in ingredientsFunction:
254
- assert isinstance(allegedIngredientsFunction, IngredientsFunction), ValueError(f"I received `{type(allegedIngredientsFunction) = }`, but I can only accept `{IngredientsFunction}`.")
255
261
  self.listIngredientsFunctions.append(allegedIngredientsFunction)
256
262
 
257
263
  def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
@@ -267,15 +273,18 @@ class IngredientsModule:
267
273
  for ingredientsFunction in self.listIngredientsFunctions:
268
274
  ingredientsFunction.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
269
275
 
270
- @property
271
- def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
272
- """List of `ast.Import` and `ast.ImportFrom` statements."""
276
+ def _consolidatedLedger(self) -> LedgerOfImports:
277
+ """Consolidate all ledgers of imports."""
273
278
  sherpaLedger = LedgerOfImports()
274
279
  listLedgers: list[LedgerOfImports] = [self.imports]
275
280
  for ingredientsFunction in self.listIngredientsFunctions:
276
281
  listLedgers.append(ingredientsFunction.imports)
277
282
  sherpaLedger.update(*listLedgers)
278
- return sherpaLedger.makeList_ast()
283
+ return sherpaLedger
284
+
285
+ @property
286
+ def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
287
+ return self._consolidatedLedger().makeList_ast()
279
288
 
280
289
  @property
281
290
  def body(self) -> list[ast.stmt]:
@@ -292,7 +301,7 @@ class IngredientsModule:
292
301
  @property
293
302
  def type_ignores(self) -> list[ast.TypeIgnore]:
294
303
  listTypeIgnore: list[ast.TypeIgnore] = self.supplemental_type_ignores
295
- # listTypeIgnore.extend(self.imports.makeListAst())
304
+ listTypeIgnore.extend(self._consolidatedLedger().type_ignores)
296
305
  listTypeIgnore.extend(self.prologue.type_ignores)
297
306
  for ingredientsFunction in self.listIngredientsFunctions:
298
307
  listTypeIgnore.extend(ingredientsFunction.type_ignores)
@@ -317,7 +326,7 @@ class RecipeSynthesizeFlow:
317
326
 
318
327
  This configuration class serves as a single source of truth for the code generation
319
328
  process, ensuring consistency across all generated artifacts while enabling
320
- customization of the transformation pipeline.
329
+ customization of the transformation assembly line.
321
330
 
322
331
  The transformation process uses this configuration to extract functions from the
323
332
  source module, transform them according to optimization rules, and output
@@ -6,7 +6,7 @@ for specific map folding calculation jobs. Unlike the general-purpose transforma
6
6
  in toolboxNumba.py, this module creates standalone Python modules optimized for a
7
7
  single map shape with statically-encoded parameters.
8
8
 
9
- The code generation pipeline focuses on:
9
+ The code generation assembly line focuses on:
10
10
 
11
11
  1. Converting function parameters to initialized variables with concrete values.
12
12
  2. Replacing dynamic computations with statically-known values.
@@ -18,7 +18,7 @@ This creates extremely fast, specialized implementations that can be run directl
18
18
  as Python scripts or further compiled into standalone executables.
19
19
  """
20
20
 
21
- from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal
21
+ from mapFolding import getPathFilenameFoldsTotal, raiseIfNoneGitHubIssueNumber3, The
22
22
  from mapFolding.someAssemblyRequired import (
23
23
  ast_Identifier,
24
24
  be,
@@ -29,15 +29,15 @@ from mapFolding.someAssemblyRequired import (
29
29
  Make,
30
30
  NodeChanger,
31
31
  NodeTourist,
32
+ str_nameDOTname,
32
33
  Then,
33
34
  )
34
- from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
35
- from mapFolding.someAssemblyRequired.transformationTools import extractFunctionDef, write_astModule, makeInitializedComputationState
36
35
  from mapFolding.someAssemblyRequired.RecipeJob import RecipeJob
37
- from mapFolding import The, raiseIfNoneGitHubIssueNumber3, getFoldsTotalKnown
38
- from typing import cast
39
- from Z0Z_tools import autoDecodingRLE
36
+ from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
37
+ from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, extractFunctionDef, write_astModule, makeInitializedComputationState
40
38
  from pathlib import PurePosixPath
39
+ from typing import cast, NamedTuple
40
+ from Z0Z_tools import autoDecodingRLE
41
41
  import ast
42
42
  """Synthesize one file to compute `foldsTotal` of `mapShape`."""
43
43
 
@@ -150,7 +150,7 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
150
150
  case 'scalar':
151
151
  ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg]) # type: ignore
152
152
  case 'array':
153
- dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], addSpaces=True)
153
+ dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
154
154
  dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
155
155
  ImaAnnAssign.value.args = [dataAs_astExpr] # type: ignore
156
156
  case _:
@@ -175,7 +175,7 @@ def makeJobNumba(job: RecipeJob, spices: SpicesJobNumba) -> None:
175
175
  """
176
176
  Generate a highly-optimized, single-purpose Numba module for a specific map shape.
177
177
 
178
- This function implements the complete transformation pipeline for creating a
178
+ This function implements the complete transformation assembly line for creating a
179
179
  standalone, specialized implementation for calculating map folding solutions for
180
180
  a specific shape. The process includes:
181
181
 
@@ -228,9 +228,9 @@ if __name__ == '__main__':
228
228
  writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
229
229
  writeStream.write(str(foldsTotal))
230
230
  writeStream.close()
231
- from mapFolding.oeis import getFoldsTotalKnown
232
- print(foldsTotal == getFoldsTotalKnown({job.state.mapShape}))
233
231
  """
232
+ # from mapFolding.oeis import getFoldsTotalKnown
233
+ # print(foldsTotal == getFoldsTotalKnown({job.state.mapShape}))
234
234
  ingredientsModule.appendLauncher(ast.parse(linesLaunch))
235
235
  changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(job.shatteredDataclass.countingVariableName)))
236
236
  changeReturnParallelCallable.visit(ingredientsCount.astFunctionDef)
@@ -238,38 +238,37 @@ if __name__ == '__main__':
238
238
 
239
239
  ingredientsCount = move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsCount, job)
240
240
 
241
- Z0Z_Identifier = 'DatatypeLeavesTotal'
242
- Z0Z_type = 'uint8'
243
- ingredientsModule.imports.addImportFrom_asStr('numba', Z0Z_type)
244
- Z0Z_statement = Make.Assign([Make.Name(Z0Z_Identifier, ast.Store())], Make.Name(Z0Z_type))
245
- ingredientsModule.appendPrologue(statement=Z0Z_statement)
241
+ class DatatypeConfig(NamedTuple):
242
+ Z0Z_module: str_nameDOTname
243
+ fml: ast_Identifier
244
+ Z0Z_type_name: ast_Identifier
245
+ Z0Z_asname: ast_Identifier | None = None
246
+
247
+ listDatatypeConfigs = [
248
+ DatatypeConfig(fml='DatatypeLeavesTotal', Z0Z_module='numba', Z0Z_type_name='uint8'),
249
+ DatatypeConfig(fml='DatatypeElephino', Z0Z_module='numba', Z0Z_type_name='uint16'),
250
+ DatatypeConfig(fml='DatatypeFoldsTotal', Z0Z_module='numba', Z0Z_type_name='uint64'),
251
+ ]
252
+
253
+ for datatypeConfig in listDatatypeConfigs:
254
+ ingredientsModule.imports.addImportFrom_asStr(datatypeConfig.Z0Z_module, datatypeConfig.Z0Z_type_name)
255
+ statement = Make.Assign(
256
+ [Make.Name(datatypeConfig.fml, ast.Store())],
257
+ Make.Name(datatypeConfig.Z0Z_type_name)
258
+ )
259
+ ingredientsModule.appendPrologue(statement=statement)
246
260
 
247
- Z0Z_Identifier = 'DatatypeElephino'
248
- Z0Z_type = 'uint8'
249
- ingredientsModule.imports.addImportFrom_asStr('numba', Z0Z_type)
250
- Z0Z_statement = Make.Assign([Make.Name(Z0Z_Identifier, ast.Store())], Make.Name(Z0Z_type))
251
- ingredientsModule.appendPrologue(statement=Z0Z_statement)
261
+ ingredientsCount.imports.removeImportFromModule('mapFolding.theSSOT')
252
262
 
253
- Z0Z_Identifier = 'DatatypeFoldsTotal'
254
- Z0Z_type = 'int64'
255
- ingredientsModule.imports.addImportFrom_asStr('numba', Z0Z_type)
256
- Z0Z_statement = Make.Assign([Make.Name(Z0Z_Identifier, ast.Store())], Make.Name(Z0Z_type))
257
- ingredientsModule.appendPrologue(statement=Z0Z_statement)
263
+ listNumPyTypeConfigs = [
264
+ DatatypeConfig(fml='Array1DLeavesTotal', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array1DLeavesTotal'),
265
+ DatatypeConfig(fml='Array1DElephino', Z0Z_module='numpy', Z0Z_type_name='uint16', Z0Z_asname='Array1DElephino'),
266
+ DatatypeConfig(fml='Array3D', Z0Z_module='numpy', Z0Z_type_name='uint8', Z0Z_asname='Array3D'),
267
+ ]
258
268
 
259
- ingredientsCount.imports.removeImportFromModule('mapFolding.theSSOT')
260
- Z0Z_module = 'numpy'
261
- Z0Z_asname = 'Array1DLeavesTotal'
262
- ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
263
- Z0Z_type_name = 'uint8'
264
- ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
265
- Z0Z_asname = 'Array1DElephino'
266
- ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
267
- Z0Z_type_name = 'uint8'
268
- ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
269
- Z0Z_asname = 'Array3D'
270
- ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
271
- Z0Z_type_name = 'uint8'
272
- ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
269
+ for typeConfig in listNumPyTypeConfigs:
270
+ ingredientsCount.imports.removeImportFrom(typeConfig.Z0Z_module, None, typeConfig.fml)
271
+ ingredientsCount.imports.addImportFrom_asStr(typeConfig.Z0Z_module, typeConfig.Z0Z_type_name, typeConfig.Z0Z_asname)
273
272
 
274
273
  ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
275
274
  # TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
@@ -300,9 +299,10 @@ if __name__ == '__main__':
300
299
  """
301
300
 
302
301
  if __name__ == '__main__':
303
- mapShape = (1,24)
302
+ mapShape = (2,21)
304
303
  state = makeInitializedComputationState(mapShape)
305
- foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
304
+ # foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
305
+ foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
306
306
  pathModule = PurePosixPath(The.pathPackage, 'jobs')
307
307
  pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
308
308
  aJob = RecipeJob(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
@@ -16,8 +16,8 @@ performance improvements while preserving code semantics and correctness.
16
16
  """
17
17
 
18
18
  from collections.abc import Callable, Sequence
19
- from mapFolding.someAssemblyRequired import Make, NodeTourist, RecipeSynthesizeFlow, Then, ast_Identifier, str_nameDOTname, IngredientsFunction
20
- from mapFolding.someAssemblyRequired.transformationTools import ( makeNewFlow, write_astModule, )
19
+ from mapFolding.someAssemblyRequired import ast_Identifier, be, IngredientsFunction, Make, NodeTourist, RecipeSynthesizeFlow, str_nameDOTname, Then
20
+ from mapFolding.someAssemblyRequired.transformationTools import makeNewFlow, write_astModule
21
21
  from numba.core.compiler import CompilerBase as numbaCompilerBase
22
22
  from typing import Any, cast, Final, TYPE_CHECKING, TypeGuard
23
23
  import ast
@@ -154,19 +154,11 @@ class SpicesJobNumba:
154
154
  parametersNumba: ParametersNumba = dataclasses.field(default_factory=ParametersNumba) # type: ignore
155
155
 
156
156
  # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
157
- class be:
158
- @staticmethod
159
- def Call(node: ast.AST) -> TypeGuard[ast.Call]:
160
- return isinstance(node, ast.Call)
161
- @staticmethod
162
- def Return(node: ast.AST) -> TypeGuard[ast.Return]:
163
- return isinstance(node, ast.Return)
164
-
165
157
  def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
166
158
  """
167
159
  Transform standard Python algorithm code into optimized Numba implementations.
168
160
 
169
- This function implements the complete transformation pipeline that converts
161
+ This function implements the complete transformation assembly line that converts
170
162
  a conventional Python implementation into a high-performance Numba-accelerated
171
163
  version. The process includes:
172
164