mapFolding 0.8.2__py3-none-any.whl → 0.8.4__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 +6 -2
- mapFolding/basecamp.py +11 -5
- mapFolding/filesystem.py +134 -109
- mapFolding/oeis.py +1 -1
- mapFolding/reference/__init__.py +7 -0
- mapFolding/reference/jobsCompleted/[2x19]/p2x19.py +197 -0
- mapFolding/reference/jobsCompleted/__init__.py +50 -0
- mapFolding/reference/jobsCompleted/p2x19/p2x19.py +29 -0
- mapFolding/someAssemblyRequired/__init__.py +37 -18
- mapFolding/someAssemblyRequired/_theTypes.py +35 -0
- mapFolding/someAssemblyRequired/_tool_Make.py +92 -0
- mapFolding/someAssemblyRequired/_tool_Then.py +65 -0
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +326 -0
- mapFolding/someAssemblyRequired/_toolboxContainers.py +306 -0
- mapFolding/someAssemblyRequired/_toolboxPython.py +76 -0
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +20 -1
- mapFolding/someAssemblyRequired/ingredientsNumba.py +17 -24
- mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +112 -149
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +247 -0
- mapFolding/someAssemblyRequired/transformDataStructures.py +167 -100
- mapFolding/someAssemblyRequired/transformationTools.py +63 -678
- mapFolding/syntheticModules/__init__.py +1 -0
- mapFolding/syntheticModules/numbaCount_doTheNeedful.py +36 -33
- mapFolding/theDao.py +13 -11
- mapFolding/theSSOT.py +69 -119
- {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/METADATA +4 -2
- mapfolding-0.8.4.dist-info/RECORD +49 -0
- {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/WHEEL +1 -1
- tests/conftest.py +34 -29
- tests/test_computations.py +40 -31
- tests/test_filesystem.py +3 -3
- tests/test_other.py +4 -3
- mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +0 -413
- mapfolding-0.8.2.dist-info/RECORD +0 -39
- {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -22,172 +22,135 @@ to generate a fresh optimized implementation.
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
from mapFolding.someAssemblyRequired import (
|
|
25
|
-
|
|
25
|
+
be,
|
|
26
26
|
ifThis,
|
|
27
|
-
|
|
27
|
+
Make,
|
|
28
|
+
NodeChanger,
|
|
29
|
+
NodeTourist,
|
|
30
|
+
Then,
|
|
31
|
+
Z0Z_inlineThisFunctionWithTheseValues,
|
|
32
|
+
Z0Z_lameFindReplace,
|
|
33
|
+
Z0Z_makeDictionaryReplacementStatements,
|
|
34
|
+
又,
|
|
35
|
+
)
|
|
36
|
+
from mapFolding.someAssemblyRequired._toolboxContainers import (
|
|
37
|
+
astModuleToIngredientsFunction,
|
|
28
38
|
IngredientsModule,
|
|
29
39
|
LedgerOfImports,
|
|
30
|
-
Make,
|
|
31
|
-
makeDictionaryReplacementStatements,
|
|
32
|
-
NodeCollector,
|
|
33
|
-
NodeReplacer,
|
|
34
40
|
RecipeSynthesizeFlow,
|
|
35
|
-
Then,
|
|
36
|
-
write_astModule,
|
|
37
|
-
Z0Z_replaceMatchingASTnodes,
|
|
38
|
-
inlineThisFunctionWithTheseValues,
|
|
39
41
|
)
|
|
40
42
|
from mapFolding.someAssemblyRequired.ingredientsNumba import decorateCallableWithNumba
|
|
41
43
|
from mapFolding.someAssemblyRequired.transformDataStructures import shatter_dataclassesDOTdataclass
|
|
42
|
-
from mapFolding.
|
|
44
|
+
from mapFolding.someAssemblyRequired.transformationTools import write_astModule
|
|
43
45
|
import ast
|
|
44
46
|
|
|
45
|
-
def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
def makeNumbaFlow(numbaFlow: RecipeSynthesizeFlow) -> None:
|
|
48
|
+
# TODO a tool to automatically remove unused variables from the ArgumentsSpecification (return, and returns) _might_ be nice.
|
|
49
|
+
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
listAllIngredientsFunctions = [
|
|
52
|
+
(ingredientsInitialize := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableInitialize)),
|
|
53
|
+
(ingredientsParallel := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableParallel)),
|
|
54
|
+
(ingredientsSequential := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableSequential)),
|
|
55
|
+
(ingredientsDispatcher := astModuleToIngredientsFunction(numbaFlow.source_astModule, numbaFlow.sourceCallableDispatcher)),
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# Inline functions ========================================================
|
|
59
|
+
dictionaryReplacementStatements = Z0Z_makeDictionaryReplacementStatements(numbaFlow.source_astModule)
|
|
60
|
+
# NOTE Replacements statements are based on the identifiers in the _source_, so operate on the source identifiers.
|
|
61
|
+
ingredientsInitialize.astFunctionDef = Z0Z_inlineThisFunctionWithTheseValues(ingredientsInitialize.astFunctionDef, dictionaryReplacementStatements)
|
|
62
|
+
ingredientsParallel.astFunctionDef = Z0Z_inlineThisFunctionWithTheseValues(ingredientsParallel.astFunctionDef, dictionaryReplacementStatements)
|
|
63
|
+
ingredientsSequential.astFunctionDef = Z0Z_inlineThisFunctionWithTheseValues(ingredientsSequential.astFunctionDef, dictionaryReplacementStatements)
|
|
64
|
+
|
|
65
|
+
# assignRecipeIdentifiersToCallable. =============================
|
|
66
|
+
# TODO How can I use `RecipeSynthesizeFlow` as the SSOT for the pairs of items that may need to be replaced?
|
|
67
|
+
# NOTE reminder: you are updating these `ast.Name` here (and not in a more general search) because this is a
|
|
68
|
+
# narrow search for `ast.Call` so you won't accidentally replace unrelated `ast.Name`.
|
|
69
|
+
listFindReplace = [(numbaFlow.sourceCallableDispatcher, numbaFlow.callableDispatcher),
|
|
70
|
+
(numbaFlow.sourceCallableInitialize, numbaFlow.callableInitialize),
|
|
71
|
+
(numbaFlow.sourceCallableParallel, numbaFlow.callableParallel),
|
|
72
|
+
(numbaFlow.sourceCallableSequential, numbaFlow.callableSequential),]
|
|
73
|
+
for ingredients in listAllIngredientsFunctions:
|
|
74
|
+
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
75
|
+
updateCallName = NodeChanger(ifThis.isCall_Identifier(source_Identifier), Then.DOTfunc(Then.replaceWith(Make.Name(recipe_Identifier))))
|
|
76
|
+
updateCallName.visit(ingredients.astFunctionDef)
|
|
77
|
+
|
|
78
|
+
ingredientsDispatcher.astFunctionDef.name = numbaFlow.callableDispatcher
|
|
79
|
+
ingredientsInitialize.astFunctionDef.name = numbaFlow.callableInitialize
|
|
80
|
+
ingredientsParallel.astFunctionDef.name = numbaFlow.callableParallel
|
|
81
|
+
ingredientsSequential.astFunctionDef.name = numbaFlow.callableSequential
|
|
82
|
+
|
|
83
|
+
# Assign identifiers per the recipe. ==============================
|
|
84
|
+
listFindReplace = [(numbaFlow.sourceDataclassInstance, numbaFlow.dataclassInstance),
|
|
85
|
+
(numbaFlow.sourceDataclassInstanceTaskDistribution, numbaFlow.dataclassInstanceTaskDistribution),
|
|
86
|
+
(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.concurrencyManagerNamespace),]
|
|
87
|
+
for ingredients in listAllIngredientsFunctions:
|
|
88
|
+
for source_Identifier, recipe_Identifier in listFindReplace:
|
|
89
|
+
updateName = NodeChanger(ifThis.isName_Identifier(source_Identifier), Then.DOTid(Then.replaceWith(recipe_Identifier)))
|
|
90
|
+
update_arg = NodeChanger(ifThis.isArgument_Identifier(source_Identifier), Then.DOTarg(Then.replaceWith(recipe_Identifier)))
|
|
91
|
+
updateName.visit(ingredients.astFunctionDef)
|
|
92
|
+
update_arg.visit(ingredients.astFunctionDef)
|
|
93
|
+
|
|
94
|
+
updateConcurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.sourceConcurrencyManagerIdentifier)
|
|
95
|
+
, Then.DOTfunc(Then.replaceWith(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier))))
|
|
96
|
+
updateConcurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
97
|
+
|
|
98
|
+
# shatter Dataclass =======================================================
|
|
99
|
+
instance_Identifier = numbaFlow.dataclassInstance
|
|
100
|
+
getTheOtherRecord_damn = numbaFlow.dataclassInstanceTaskDistribution
|
|
101
|
+
shatteredDataclass = shatter_dataclassesDOTdataclass(numbaFlow.logicalPathModuleDataclass, numbaFlow.sourceDataclassIdentifier, instance_Identifier)
|
|
102
|
+
ingredientsDispatcher.imports.update(shatteredDataclass.ledger)
|
|
103
|
+
|
|
104
|
+
# Change callable parameters and Call to the callable at the same time ====
|
|
105
|
+
# TODO How can I use ast and/or other tools to ensure that when I change a callable, I also change the statements that call the callable?
|
|
106
|
+
# Asked differently, how do I integrate separate statements into a "subroutine", and that subroutine is "atomic/indivisible"?
|
|
107
|
+
# sequentialCallable =========================================================
|
|
108
|
+
ingredientsSequential.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
109
|
+
astCallSequentialCallable = Make.Call(Make.Name(numbaFlow.callableSequential), shatteredDataclass.listName4Parameters)
|
|
110
|
+
changeReturnSequentialCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.fragments4AssignmentOrParameters)))
|
|
111
|
+
ingredientsSequential.astFunctionDef.returns = shatteredDataclass.signatureReturnAnnotation
|
|
112
|
+
replaceAssignSequentialCallable = NodeChanger(ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.callableSequential), Then.replaceWith(Make.Assign(listTargets=[shatteredDataclass.fragments4AssignmentOrParameters], value=astCallSequentialCallable)))
|
|
113
|
+
|
|
114
|
+
unpack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.callableSequential), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
115
|
+
repack4sequentialCallable = NodeChanger(ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.callableSequential), Then.insertThisBelow([shatteredDataclass.repack]))
|
|
116
|
+
|
|
117
|
+
changeReturnSequentialCallable.visit(ingredientsSequential.astFunctionDef)
|
|
118
|
+
replaceAssignSequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
119
|
+
unpack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
120
|
+
repack4sequentialCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
121
|
+
|
|
122
|
+
ingredientsSequential.astFunctionDef = Z0Z_lameFindReplace(ingredientsSequential.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
123
|
+
|
|
124
|
+
# parallelCallable =========================================================
|
|
125
|
+
ingredientsParallel.astFunctionDef.args = Make.argumentsSpecification(args=shatteredDataclass.list_argAnnotated4ArgumentsSpecification)
|
|
126
|
+
replaceCall2concurrencyManager = NodeChanger(ifThis.isCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier), Then.replaceWith(Make.Call(Make.Attribute(Make.Name(numbaFlow.concurrencyManagerNamespace), numbaFlow.concurrencyManagerIdentifier), listArguments=[Make.Name(numbaFlow.callableParallel)] + shatteredDataclass.listName4Parameters)))
|
|
127
|
+
|
|
128
|
+
# NOTE I am dissatisfied with this logic for many reasons, including that it requires separate NodeCollector and NodeReplacer instances.
|
|
129
|
+
astCallConcurrencyResult: list[ast.Call] = []
|
|
130
|
+
get_astCallConcurrencyResult: NodeTourist = NodeTourist(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), lambda node: NodeTourist(be.Call, Then.appendTo(astCallConcurrencyResult)).visit(node)) # pyright: ignore[reportUnknownArgumentType, reportUnknownLambdaType]
|
|
131
|
+
get_astCallConcurrencyResult.visit(ingredientsDispatcher.astFunctionDef)
|
|
132
|
+
replaceAssignParallelCallable = NodeChanger(ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(getTheOtherRecord_damn)), Then.DOTvalue(Then.replaceWith(astCallConcurrencyResult[0])))
|
|
133
|
+
replaceAssignParallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
134
|
+
changeReturnParallelCallable = NodeChanger(be.Return, Then.replaceWith(Make.Return(shatteredDataclass.countingVariableName)))
|
|
135
|
+
ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
|
|
54
136
|
|
|
55
|
-
|
|
56
|
-
are transformed, for example, the statement in `sourceDispatcherCallable` that calls `sourceSequentialCallable` should be
|
|
57
|
-
transformed at the same time: literally in the same function-or-NodeReplacer-or-subroutine. That would help
|
|
58
|
-
avoid bugs.
|
|
137
|
+
unpack4parallelCallable = NodeChanger(ifThis.isAssignAndValueIsCallAttributeNamespace_Identifier(numbaFlow.concurrencyManagerNamespace, numbaFlow.concurrencyManagerIdentifier), Then.insertThisAbove(shatteredDataclass.listUnpack))
|
|
59
138
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
139
|
+
unpack4parallelCallable.visit(ingredientsDispatcher.astFunctionDef)
|
|
140
|
+
replaceCall2concurrencyManager.visit(ingredientsDispatcher.astFunctionDef)
|
|
141
|
+
changeReturnParallelCallable.visit(ingredientsParallel.astFunctionDef)
|
|
63
142
|
|
|
64
|
-
|
|
65
|
-
"""
|
|
66
|
-
dictionaryReplacementStatements = makeDictionaryReplacementStatements(numbaFlow.source_astModule)
|
|
67
|
-
# TODO remember that `sequentialCallable` and `sourceSequentialCallable` are two different values.
|
|
68
|
-
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
143
|
+
ingredientsParallel.astFunctionDef = Z0Z_lameFindReplace(ingredientsParallel.astFunctionDef, shatteredDataclass.map_stateDOTfield2Name)
|
|
69
144
|
|
|
70
|
-
#
|
|
71
|
-
sourcePython = numbaFlow.sourceDispatcherCallable
|
|
72
|
-
astFunctionDef = extractFunctionDef(sourcePython, numbaFlow.source_astModule)
|
|
73
|
-
if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
|
|
74
|
-
ingredientsDispatcher = IngredientsFunction(astFunctionDef, LedgerOfImports(numbaFlow.source_astModule))
|
|
75
|
-
|
|
76
|
-
# sourceParallelCallable
|
|
77
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(numbaFlow.logicalPathModuleDataclass, numbaFlow.sourceDataclassIdentifier, numbaFlow.sourceDataclassInstanceTaskDistribution)
|
|
78
|
-
ingredientsDispatcher.imports.update(shatteredDataclass.ledgerDataclassANDFragments)
|
|
79
|
-
|
|
80
|
-
NodeReplacer(
|
|
81
|
-
findThis = ifThis.isAssignAndValueIsCallNamespace_Identifier(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.sourceConcurrencyManagerIdentifier)
|
|
82
|
-
, doThat = Then.insertThisAbove(shatteredDataclass.listAnnAssign4DataclassUnpack)
|
|
83
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
84
|
-
NodeReplacer(
|
|
85
|
-
findThis = ifThis.isCallNamespace_Identifier(numbaFlow.sourceConcurrencyManagerNamespace, numbaFlow.sourceConcurrencyManagerIdentifier)
|
|
86
|
-
, doThat = Then.replaceWith(Make.astCall(Make.astAttribute(Make.astName(numbaFlow.sourceConcurrencyManagerNamespace), numbaFlow.sourceConcurrencyManagerIdentifier)
|
|
87
|
-
, listArguments=[Make.astName(numbaFlow.parallelCallable)] + shatteredDataclass.listNameDataclassFragments4Parameters))
|
|
88
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
89
|
-
|
|
90
|
-
CapturedAssign: list[ast.AST] = []
|
|
91
|
-
CapturedCall: list[ast.Call] = []
|
|
92
|
-
findThis = ifThis.isCall
|
|
93
|
-
doThat = [Then.appendTo(CapturedCall)]
|
|
94
|
-
capture = NodeCollector(findThis, doThat)
|
|
95
|
-
|
|
96
|
-
NodeCollector(
|
|
97
|
-
findThis = ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(numbaFlow.sourceDataclassInstance))
|
|
98
|
-
, doThat = [Then.appendTo(CapturedAssign)
|
|
99
|
-
, lambda node: capture.visit(node)]
|
|
100
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
101
|
-
|
|
102
|
-
newAssign = CapturedAssign[0]
|
|
103
|
-
NodeReplacer(
|
|
104
|
-
findThis = lambda node: ifThis.isSubscript(node) and ifThis.isAttribute(node.value) and ifThis.isCall(node.value.value)
|
|
105
|
-
, doThat = Then.replaceWith(CapturedCall[0])
|
|
106
|
-
).visit(newAssign)
|
|
107
|
-
|
|
108
|
-
NodeReplacer(
|
|
109
|
-
findThis = ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier(numbaFlow.sourceDataclassInstance))
|
|
110
|
-
, doThat = Then.replaceWith(newAssign)
|
|
111
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
112
|
-
|
|
113
|
-
# sourceSequentialCallable
|
|
114
|
-
shatteredDataclass = shatter_dataclassesDOTdataclass(numbaFlow.logicalPathModuleDataclass, numbaFlow.sourceDataclassIdentifier, numbaFlow.sourceDataclassInstance)
|
|
115
|
-
|
|
116
|
-
ingredientsDispatcher.imports.update(shatteredDataclass.ledgerDataclassANDFragments)
|
|
117
|
-
|
|
118
|
-
NodeReplacer(
|
|
119
|
-
findThis = ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.sourceSequentialCallable)
|
|
120
|
-
, doThat = Then.insertThisAbove(shatteredDataclass.listAnnAssign4DataclassUnpack)
|
|
121
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
122
|
-
NodeReplacer(
|
|
123
|
-
findThis = ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.sourceSequentialCallable)
|
|
124
|
-
, doThat = Then.insertThisBelow([shatteredDataclass.astAssignDataclassRepack])
|
|
125
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
126
|
-
NodeReplacer(
|
|
127
|
-
findThis = ifThis.isAssignAndValueIsCall_Identifier(numbaFlow.sourceSequentialCallable)
|
|
128
|
-
, doThat = Then.replaceWith(Make.astAssign(listTargets=[shatteredDataclass.astTuple4AssignTargetsToFragments], value=Make.astCall(Make.astName(numbaFlow.sequentialCallable), shatteredDataclass.listNameDataclassFragments4Parameters)))
|
|
129
|
-
).visit(ingredientsDispatcher.astFunctionDef)
|
|
130
|
-
|
|
131
|
-
ingredientsDispatcher.astFunctionDef.name = numbaFlow.dispatcherCallable
|
|
132
|
-
|
|
133
|
-
# ===========================================================
|
|
134
|
-
sourcePython = numbaFlow.sourceInitializeCallable
|
|
135
|
-
astFunctionDef = extractFunctionDef(sourcePython, numbaFlow.source_astModule)
|
|
136
|
-
if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
|
|
137
|
-
astFunctionDef = inlineThisFunctionWithTheseValues(astFunctionDef, dictionaryReplacementStatements)
|
|
138
|
-
ingredientsInitialize = IngredientsFunction(astFunctionDef, LedgerOfImports(numbaFlow.source_astModule))
|
|
139
|
-
|
|
140
|
-
# ===========================================================
|
|
141
|
-
sourcePython = numbaFlow.sourceParallelCallable
|
|
142
|
-
astFunctionDef = extractFunctionDef(sourcePython, numbaFlow.source_astModule)
|
|
143
|
-
if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
|
|
144
|
-
astFunctionDef = inlineThisFunctionWithTheseValues(astFunctionDef, dictionaryReplacementStatements)
|
|
145
|
-
ingredientsParallel = IngredientsFunction(astFunctionDef, LedgerOfImports(numbaFlow.source_astModule))
|
|
146
|
-
ingredientsParallel.astFunctionDef.name = numbaFlow.parallelCallable
|
|
147
|
-
ingredientsParallel.astFunctionDef.args = Make.astArgumentsSpecification(args=shatteredDataclass.list_ast_argAnnotated4ArgumentsSpecification)
|
|
148
|
-
NodeReplacer(
|
|
149
|
-
findThis = ifThis.isReturn
|
|
150
|
-
, doThat = Then.replaceWith(Make.astReturn(shatteredDataclass.astTuple4AssignTargetsToFragments))
|
|
151
|
-
).visit(ingredientsParallel.astFunctionDef)
|
|
152
|
-
|
|
153
|
-
NodeReplacer(
|
|
154
|
-
findThis = ifThis.isReturn
|
|
155
|
-
, doThat = Then.replaceWith(Make.astReturn(shatteredDataclass.countingVariableName))
|
|
156
|
-
).visit(ingredientsParallel.astFunctionDef)
|
|
157
|
-
ingredientsParallel.astFunctionDef.returns = shatteredDataclass.countingVariableAnnotation
|
|
158
|
-
replacementMap = {statement.value: statement.target for statement in shatteredDataclass.listAnnAssign4DataclassUnpack}
|
|
159
|
-
ingredientsParallel.astFunctionDef = Z0Z_replaceMatchingASTnodes(ingredientsParallel.astFunctionDef, replacementMap) # type: ignore
|
|
145
|
+
# numba decorators =========================================
|
|
160
146
|
ingredientsParallel = decorateCallableWithNumba(ingredientsParallel)
|
|
161
|
-
|
|
162
|
-
# ===========================================================
|
|
163
|
-
sourcePython = numbaFlow.sourceSequentialCallable
|
|
164
|
-
astFunctionDef = extractFunctionDef(sourcePython, numbaFlow.source_astModule)
|
|
165
|
-
if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
|
|
166
|
-
astFunctionDef = inlineThisFunctionWithTheseValues(astFunctionDef, dictionaryReplacementStatements)
|
|
167
|
-
ingredientsSequential = IngredientsFunction(astFunctionDef, LedgerOfImports(numbaFlow.source_astModule))
|
|
168
|
-
ingredientsSequential.astFunctionDef.name = numbaFlow.sequentialCallable
|
|
169
|
-
ingredientsSequential.astFunctionDef.args = Make.astArgumentsSpecification(args=shatteredDataclass.list_ast_argAnnotated4ArgumentsSpecification)
|
|
170
|
-
NodeReplacer(
|
|
171
|
-
findThis = ifThis.isReturn
|
|
172
|
-
, doThat = Then.replaceWith(Make.astReturn(shatteredDataclass.astTuple4AssignTargetsToFragments))
|
|
173
|
-
).visit(ingredientsSequential.astFunctionDef)
|
|
174
|
-
NodeReplacer(
|
|
175
|
-
findThis = ifThis.isReturn
|
|
176
|
-
, doThat = Then.replaceWith(Make.astReturn(shatteredDataclass.astTuple4AssignTargetsToFragments))
|
|
177
|
-
).visit(ingredientsSequential.astFunctionDef)
|
|
178
|
-
ingredientsSequential.astFunctionDef.returns = shatteredDataclass.astSubscriptPrimitiveTupleAnnotations4FunctionDef_returns
|
|
179
|
-
replacementMap = {statement.value: statement.target for statement in shatteredDataclass.listAnnAssign4DataclassUnpack}
|
|
180
|
-
ingredientsSequential.astFunctionDef = Z0Z_replaceMatchingASTnodes(ingredientsSequential.astFunctionDef, replacementMap) # type: ignore
|
|
181
147
|
ingredientsSequential = decorateCallableWithNumba(ingredientsSequential)
|
|
182
148
|
|
|
183
|
-
# ===========================================================
|
|
184
|
-
ingredientsModuleNumbaUnified = IngredientsModule(
|
|
185
|
-
ingredientsFunction=[ingredientsInitialize,
|
|
186
|
-
ingredientsParallel,
|
|
187
|
-
ingredientsSequential,
|
|
188
|
-
ingredientsDispatcher], imports=LedgerOfImports(numbaFlow.source_astModule))
|
|
149
|
+
# Module-level transformations ===========================================================
|
|
150
|
+
ingredientsModuleNumbaUnified = IngredientsModule(ingredientsFunction=listAllIngredientsFunctions, imports=LedgerOfImports(numbaFlow.source_astModule))
|
|
189
151
|
|
|
190
|
-
write_astModule(ingredientsModuleNumbaUnified, numbaFlow.pathFilenameDispatcher, numbaFlow.
|
|
152
|
+
write_astModule(ingredientsModuleNumbaUnified, numbaFlow.pathFilenameDispatcher, numbaFlow.packageIdentifier)
|
|
191
153
|
|
|
154
|
+
theNumbaFlow: RecipeSynthesizeFlow = RecipeSynthesizeFlow()
|
|
192
155
|
if __name__ == '__main__':
|
|
193
|
-
makeNumbaFlow()
|
|
156
|
+
makeNumbaFlow(theNumbaFlow)
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""Synthesize one file to compute `foldsTotal` of `mapShape`."""
|
|
2
|
+
from mapFolding.someAssemblyRequired import ast_Identifier, be, ifThis, Make, NodeChanger, NodeTourist, parsePathFilename2astModule, str_nameDOTname, Then, write_astModule, 又
|
|
3
|
+
from mapFolding.someAssemblyRequired.ingredientsNumba import decorateCallableWithNumba, ParametersNumba, parametersNumbaDefault
|
|
4
|
+
from mapFolding.someAssemblyRequired.synthesizeNumbaFlow import theNumbaFlow
|
|
5
|
+
from mapFolding.someAssemblyRequired.transformDataStructures import makeInitializedComputationState, shatter_dataclassesDOTdataclass, ShatteredDataclass
|
|
6
|
+
from mapFolding.someAssemblyRequired._toolboxContainers import astModuleToIngredientsFunction, IngredientsFunction, IngredientsModule, LedgerOfImports
|
|
7
|
+
from mapFolding.filesystem import getFilenameFoldsTotal, getPathFilenameFoldsTotal, getPathRootJobDEFAULT
|
|
8
|
+
from mapFolding.theSSOT import ComputationState, The
|
|
9
|
+
from pathlib import Path, PurePosixPath
|
|
10
|
+
from typing import cast
|
|
11
|
+
from Z0Z_tools import autoDecodingRLE
|
|
12
|
+
import ast
|
|
13
|
+
import dataclasses
|
|
14
|
+
|
|
15
|
+
list_IdentifiersNotUsedAllHARDCODED = ['concurrencyLimit', 'foldsTotal', 'mapShape',]
|
|
16
|
+
list_IdentifiersNotUsedParallelSequentialHARDCODED = ['indexLeaf']
|
|
17
|
+
list_IdentifiersNotUsedSequentialHARDCODED = ['foldGroups', 'taskDivisions', 'taskIndex',]
|
|
18
|
+
|
|
19
|
+
list_IdentifiersReplacedHARDCODED = ['groupsOfFolds',]
|
|
20
|
+
|
|
21
|
+
list_IdentifiersStaticValuesHARDCODED = ['dimensionsTotal', 'leavesTotal',]
|
|
22
|
+
|
|
23
|
+
list_IdentifiersNotUsedHARDCODED = list_IdentifiersStaticValuesHARDCODED + list_IdentifiersReplacedHARDCODED + list_IdentifiersNotUsedAllHARDCODED + list_IdentifiersNotUsedParallelSequentialHARDCODED + list_IdentifiersNotUsedSequentialHARDCODED
|
|
24
|
+
|
|
25
|
+
@dataclasses.dataclass
|
|
26
|
+
class Z0Z_RecipeJob:
|
|
27
|
+
state: ComputationState
|
|
28
|
+
# TODO create function to calculate `foldsTotalEstimated`
|
|
29
|
+
foldsTotalEstimated: int = 0
|
|
30
|
+
useNumbaProgressBar: bool = True
|
|
31
|
+
numbaProgressBarIdentifier: ast_Identifier = 'ProgressBarGroupsOfFolds'
|
|
32
|
+
shatteredDataclass: ShatteredDataclass = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
|
|
33
|
+
|
|
34
|
+
# ========================================
|
|
35
|
+
# Source
|
|
36
|
+
source_astModule = parsePathFilename2astModule(theNumbaFlow.pathFilenameSequential)
|
|
37
|
+
sourceCountCallable: ast_Identifier = theNumbaFlow.callableSequential
|
|
38
|
+
|
|
39
|
+
sourceLogicalPathModuleDataclass: str_nameDOTname = theNumbaFlow.logicalPathModuleDataclass
|
|
40
|
+
sourceDataclassIdentifier: ast_Identifier = theNumbaFlow.dataclassIdentifier
|
|
41
|
+
sourceDataclassInstance: ast_Identifier = theNumbaFlow.dataclassInstance
|
|
42
|
+
|
|
43
|
+
sourcePathPackage: PurePosixPath | None = theNumbaFlow.pathPackage
|
|
44
|
+
sourcePackageIdentifier: ast_Identifier | None = theNumbaFlow.packageIdentifier
|
|
45
|
+
|
|
46
|
+
# ========================================
|
|
47
|
+
# Filesystem (names of physical objects)
|
|
48
|
+
pathPackage: PurePosixPath | None = None
|
|
49
|
+
pathModule: PurePosixPath | None = PurePosixPath(getPathRootJobDEFAULT())
|
|
50
|
+
""" `pathModule` will override `pathPackage` and `logicalPathRoot`."""
|
|
51
|
+
fileExtension: str = theNumbaFlow.fileExtension
|
|
52
|
+
pathFilenameFoldsTotal: PurePosixPath = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
|
|
53
|
+
|
|
54
|
+
# ========================================
|
|
55
|
+
# Logical identifiers (as opposed to physical identifiers)
|
|
56
|
+
# ========================================
|
|
57
|
+
packageIdentifier: ast_Identifier | None = None
|
|
58
|
+
logicalPathRoot: str_nameDOTname | None = None
|
|
59
|
+
""" `logicalPathRoot` likely corresponds to a physical filesystem directory."""
|
|
60
|
+
moduleIdentifier: ast_Identifier = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
|
|
61
|
+
countCallable: ast_Identifier = sourceCountCallable
|
|
62
|
+
dataclassIdentifier: ast_Identifier | None = sourceDataclassIdentifier
|
|
63
|
+
dataclassInstance: ast_Identifier | None = sourceDataclassInstance
|
|
64
|
+
logicalPathModuleDataclass: str_nameDOTname | None = sourceLogicalPathModuleDataclass
|
|
65
|
+
|
|
66
|
+
def _makePathFilename(self,
|
|
67
|
+
pathRoot: PurePosixPath | None = None,
|
|
68
|
+
logicalPathINFIX: str_nameDOTname | None = None,
|
|
69
|
+
filenameStem: str | None = None,
|
|
70
|
+
fileExtension: str | None = None,
|
|
71
|
+
) -> PurePosixPath:
|
|
72
|
+
if pathRoot is None:
|
|
73
|
+
pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
|
|
74
|
+
if logicalPathINFIX:
|
|
75
|
+
whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
|
|
76
|
+
pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
|
|
77
|
+
if filenameStem is None:
|
|
78
|
+
filenameStem = self.moduleIdentifier
|
|
79
|
+
if fileExtension is None:
|
|
80
|
+
fileExtension = self.fileExtension
|
|
81
|
+
filename: str = filenameStem + fileExtension
|
|
82
|
+
return pathRoot.joinpath(filename)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def pathFilenameModule(self) -> PurePosixPath:
|
|
86
|
+
if self.pathModule is None:
|
|
87
|
+
return self._makePathFilename()
|
|
88
|
+
else:
|
|
89
|
+
return self._makePathFilename(pathRoot=self.pathModule, logicalPathINFIX=None)
|
|
90
|
+
|
|
91
|
+
def __post_init__(self):
|
|
92
|
+
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(self.state.mapShape))
|
|
93
|
+
|
|
94
|
+
if self.moduleIdentifier is None:
|
|
95
|
+
self.moduleIdentifier = pathFilenameFoldsTotal.stem
|
|
96
|
+
|
|
97
|
+
if self.pathFilenameFoldsTotal is None:
|
|
98
|
+
self.pathFilenameFoldsTotal = pathFilenameFoldsTotal
|
|
99
|
+
|
|
100
|
+
if self.shatteredDataclass is None and self.logicalPathModuleDataclass and self.dataclassIdentifier and self.dataclassInstance:
|
|
101
|
+
self.shatteredDataclass = shatter_dataclassesDOTdataclass(self.logicalPathModuleDataclass, self.dataclassIdentifier, self.dataclassInstance)
|
|
102
|
+
|
|
103
|
+
# ========================================
|
|
104
|
+
# Fields you probably don't need =================================
|
|
105
|
+
# Dispatcher =================================
|
|
106
|
+
sourceDispatcherCallable: ast_Identifier = theNumbaFlow.callableDispatcher
|
|
107
|
+
dispatcherCallable: ast_Identifier = sourceDispatcherCallable
|
|
108
|
+
# Parallel counting =================================
|
|
109
|
+
sourceDataclassInstanceTaskDistribution: ast_Identifier = theNumbaFlow.dataclassInstanceTaskDistribution
|
|
110
|
+
sourceConcurrencyManagerNamespace: ast_Identifier = theNumbaFlow.concurrencyManagerNamespace
|
|
111
|
+
sourceConcurrencyManagerIdentifier: ast_Identifier = theNumbaFlow.concurrencyManagerIdentifier
|
|
112
|
+
dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
|
|
113
|
+
concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
|
|
114
|
+
concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
|
|
115
|
+
|
|
116
|
+
def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: Z0Z_RecipeJob) -> IngredientsModule:
|
|
117
|
+
|
|
118
|
+
linesLaunch: str = f"""
|
|
119
|
+
if __name__ == '__main__':
|
|
120
|
+
with ProgressBar(total={job.foldsTotalEstimated}, update_interval=2) as statusUpdate:
|
|
121
|
+
{job.countCallable}(statusUpdate)
|
|
122
|
+
foldsTotal = statusUpdate.n * {job.state.leavesTotal}
|
|
123
|
+
print('map {job.state.mapShape} =', foldsTotal)
|
|
124
|
+
writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
|
|
125
|
+
writeStream.write(str(foldsTotal))
|
|
126
|
+
writeStream.close()
|
|
127
|
+
"""
|
|
128
|
+
numba_progressPythonClass: ast_Identifier = 'ProgressBar'
|
|
129
|
+
numba_progressNumbaType: ast_Identifier = 'ProgressBarType'
|
|
130
|
+
ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressPythonClass)
|
|
131
|
+
ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressNumbaType)
|
|
132
|
+
|
|
133
|
+
ast_argNumbaProgress = ast.arg(arg=job.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
|
|
134
|
+
ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
|
|
135
|
+
|
|
136
|
+
findThis = ifThis.isAugAssign_targetIs(ifThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
|
|
137
|
+
doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(job.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
|
|
138
|
+
countWithProgressBar = NodeChanger(findThis, doThat)
|
|
139
|
+
countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
|
|
140
|
+
|
|
141
|
+
ingredientsModule.appendLauncher(ast.parse(linesLaunch))
|
|
142
|
+
|
|
143
|
+
return ingredientsModule
|
|
144
|
+
|
|
145
|
+
def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: Z0Z_RecipeJob) -> IngredientsFunction:
|
|
146
|
+
ingredientsFunction.imports.update(job.shatteredDataclass.ledger)
|
|
147
|
+
|
|
148
|
+
list_IdentifiersNotUsed = list_IdentifiersNotUsedHARDCODED
|
|
149
|
+
|
|
150
|
+
list_argCauseMyBrainRefusesToDoThisTheRightWay = ingredientsFunction.astFunctionDef.args.args + ingredientsFunction.astFunctionDef.args.posonlyargs + ingredientsFunction.astFunctionDef.args.kwonlyargs
|
|
151
|
+
for ast_arg in list_argCauseMyBrainRefusesToDoThisTheRightWay:
|
|
152
|
+
if ast_arg.arg in job.shatteredDataclass.field2AnnAssign:
|
|
153
|
+
if ast_arg.arg in list_IdentifiersNotUsed:
|
|
154
|
+
pass
|
|
155
|
+
else:
|
|
156
|
+
ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
|
|
157
|
+
match elementConstructor:
|
|
158
|
+
case 'scalar':
|
|
159
|
+
ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg]) # type: ignore
|
|
160
|
+
case 'array':
|
|
161
|
+
# print(ast.dump(ImaAnnAssign))
|
|
162
|
+
dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], addSpaces=True)
|
|
163
|
+
dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
|
|
164
|
+
ImaAnnAssign.value.args = [dataAs_astExpr] # type: ignore
|
|
165
|
+
case _:
|
|
166
|
+
list_exprDOTannotation: list[ast.expr] = []
|
|
167
|
+
list_exprDOTvalue: list[ast.expr] = []
|
|
168
|
+
for dimension in job.state.mapShape:
|
|
169
|
+
list_exprDOTannotation.append(Make.Name(elementConstructor))
|
|
170
|
+
list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
|
|
171
|
+
ImaAnnAssign.annotation.slice.elts = list_exprDOTannotation # type: ignore
|
|
172
|
+
ImaAnnAssign.value.elts = list_exprDOTvalue # type: ignore
|
|
173
|
+
|
|
174
|
+
ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
|
|
175
|
+
|
|
176
|
+
findThis = ifThis.is_arg_Identifier(ast_arg.arg)
|
|
177
|
+
remove_arg = NodeChanger(findThis, Then.removeIt)
|
|
178
|
+
remove_arg.visit(ingredientsFunction.astFunctionDef)
|
|
179
|
+
|
|
180
|
+
ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
|
|
181
|
+
return ingredientsFunction
|
|
182
|
+
|
|
183
|
+
def makeJobNumba(job: Z0Z_RecipeJob, parametersNumba: ParametersNumba = parametersNumbaDefault):
|
|
184
|
+
# get the raw ingredients: data and the algorithm
|
|
185
|
+
ingredientsCount: IngredientsFunction = astModuleToIngredientsFunction(job.source_astModule, job.countCallable)
|
|
186
|
+
|
|
187
|
+
# Change the return so you can dynamically determine which variables are not used
|
|
188
|
+
removeReturnStatement = NodeChanger(be.Return, Then.removeIt)
|
|
189
|
+
removeReturnStatement.visit(ingredientsCount.astFunctionDef)
|
|
190
|
+
ingredientsCount.astFunctionDef.returns = Make.Constant(value=None)
|
|
191
|
+
|
|
192
|
+
# Remove `foldGroups` and any other unused statements, so you can dynamically determine which variables are not used
|
|
193
|
+
findThis = ifThis.isAssignAndTargets0Is(ifThis.isSubscript_Identifier('foldGroups'))
|
|
194
|
+
doThat = Then.removeIt
|
|
195
|
+
remove_foldGroups = NodeChanger(findThis, doThat)
|
|
196
|
+
remove_foldGroups.visit(ingredientsCount.astFunctionDef)
|
|
197
|
+
|
|
198
|
+
# replace identifiers with static values with their values, so you can dynamically determine which variables are not used
|
|
199
|
+
list_IdentifiersStaticValues = list_IdentifiersStaticValuesHARDCODED
|
|
200
|
+
for identifier in list_IdentifiersStaticValues:
|
|
201
|
+
findThis = ifThis.isName_Identifier(identifier)
|
|
202
|
+
doThat = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
|
|
203
|
+
NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef)
|
|
204
|
+
|
|
205
|
+
# This launcher eliminates the use of one identifier, so run it now and you can dynamically determine which variables are not used
|
|
206
|
+
ingredientsModule = IngredientsModule()
|
|
207
|
+
ingredientsModule = addLauncherNumbaProgress(ingredientsModule, ingredientsCount, job)
|
|
208
|
+
parametersNumba['nogil'] = True
|
|
209
|
+
|
|
210
|
+
ingredientsCount = move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsCount, job)
|
|
211
|
+
|
|
212
|
+
ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
|
|
213
|
+
# TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
|
|
214
|
+
ingredientsCount = decorateCallableWithNumba(ingredientsCount, parametersNumba)
|
|
215
|
+
|
|
216
|
+
ingredientsModule.appendIngredientsFunction(ingredientsCount)
|
|
217
|
+
|
|
218
|
+
# add imports, make str, remove unused imports
|
|
219
|
+
# put on disk
|
|
220
|
+
write_astModule(ingredientsModule, job.pathFilenameModule, job.packageIdentifier)
|
|
221
|
+
|
|
222
|
+
"""
|
|
223
|
+
Overview
|
|
224
|
+
- the code starts life in theDao.py, which has many optimizations;
|
|
225
|
+
- `makeNumbaOptimizedFlow` increase optimization especially by using numba;
|
|
226
|
+
- `makeJobNumba` increases optimization especially by limiting its capabilities to just one set of parameters
|
|
227
|
+
- the synthesized module must run well as a standalone interpreted-Python script
|
|
228
|
+
- the next major optimization step will (probably) be to use the module synthesized by `makeJobNumba` to compile a standalone executable
|
|
229
|
+
- Nevertheless, at each major optimization step, the code is constantly being improved and optimized, so everything must be well organized (read: semantic) and able to handle a range of arbitrary upstream and not disrupt downstream transformations
|
|
230
|
+
|
|
231
|
+
Necessary
|
|
232
|
+
- Move the function's parameters to the function body,
|
|
233
|
+
- initialize identifiers with their state types and values,
|
|
234
|
+
|
|
235
|
+
Optimizations
|
|
236
|
+
- replace static-valued identifiers with their values
|
|
237
|
+
- narrowly focused imports
|
|
238
|
+
|
|
239
|
+
Minutia
|
|
240
|
+
- do not use `with` statement inside numba jitted code, except to use numba's obj mode
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
if __name__ == '__main__':
|
|
244
|
+
mapShape = (6,6)
|
|
245
|
+
state = makeInitializedComputationState(mapShape)
|
|
246
|
+
aJob = Z0Z_RecipeJob(state)
|
|
247
|
+
makeJobNumba(aJob)
|