mapFolding 0.4.1__py3-none-any.whl → 0.4.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapFolding/__init__.py +2 -1
- mapFolding/basecamp.py +1 -1
- mapFolding/beDRY.py +120 -113
- mapFolding/oeis.py +18 -17
- mapFolding/someAssemblyRequired/synthesizeNumba.py +41 -48
- mapFolding/someAssemblyRequired/synthesizeNumbaGeneralized.py +83 -12
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +12 -23
- mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +82 -30
- mapFolding/syntheticModules/numbaCount.py +158 -0
- mapFolding/syntheticModules/numba_doTheNeedful.py +5 -12
- mapFolding/theDao.py +76 -73
- mapFolding/theSSOT.py +50 -189
- mapFolding/theSSOTdatatypes.py +168 -0
- {mapFolding-0.4.1.dist-info → mapFolding-0.4.3.dist-info}/METADATA +1 -1
- mapFolding-0.4.3.dist-info/RECORD +40 -0
- tests/conftest.py +30 -31
- tests/test_computations.py +27 -63
- tests/test_oeis.py +7 -10
- mapFolding/syntheticModules/numba_countInitialize.py +0 -52
- mapFolding/syntheticModules/numba_countParallel.py +0 -65
- mapFolding/syntheticModules/numba_countSequential.py +0 -67
- mapFolding/theSSOTnumba.py +0 -132
- mapFolding-0.4.1.dist-info/RECORD +0 -42
- {mapFolding-0.4.1.dist-info → mapFolding-0.4.3.dist-info}/LICENSE +0 -0
- {mapFolding-0.4.1.dist-info → mapFolding-0.4.3.dist-info}/WHEEL +0 -0
- {mapFolding-0.4.1.dist-info → mapFolding-0.4.3.dist-info}/entry_points.txt +0 -0
- {mapFolding-0.4.1.dist-info → mapFolding-0.4.3.dist-info}/top_level.txt +0 -0
|
@@ -9,10 +9,11 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
|
|
|
9
9
|
# NOTE hack
|
|
10
10
|
constructorName = constructorName.replace('ndarray', 'array')
|
|
11
11
|
argData_dtype: numpy.dtype = arrayTarget.dtype
|
|
12
|
-
|
|
12
|
+
datatypeName = argData_dtype.name
|
|
13
|
+
dtypeAsName = f"{moduleConstructor}_{datatypeName}"
|
|
13
14
|
|
|
14
15
|
allImports.addImportFromStr(moduleConstructor, constructorName)
|
|
15
|
-
allImports.addImportFromStr(moduleConstructor,
|
|
16
|
+
allImports.addImportFromStr(moduleConstructor, datatypeName, dtypeAsName)
|
|
16
17
|
|
|
17
18
|
def insertAssign(assignee: str, arraySlice: numpy.ndarray) -> None:
|
|
18
19
|
nonlocal FunctionDefTarget
|
|
@@ -20,7 +21,7 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
|
|
|
20
21
|
astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
|
|
21
22
|
dataAst = astStatement.value
|
|
22
23
|
|
|
23
|
-
arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=
|
|
24
|
+
arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=dtypeAsName, ctx=ast.Load()))])
|
|
24
25
|
|
|
25
26
|
assignment = ast.Assign(targets=[ast.Name(id=assignee, ctx=ast.Store())], value=arrayCall)#NOTE
|
|
26
27
|
FunctionDefTarget.body.insert(0, assignment)
|
|
@@ -33,7 +34,8 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
|
|
|
33
34
|
|
|
34
35
|
return FunctionDefTarget, allImports
|
|
35
36
|
|
|
36
|
-
def
|
|
37
|
+
def findAndReplaceTrackArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str , arrayTarget: numpy.ndarray , allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
38
|
+
|
|
37
39
|
arrayType = type(arrayTarget)
|
|
38
40
|
moduleConstructor = arrayType.__module__
|
|
39
41
|
constructorName = arrayType.__name__
|
|
@@ -41,47 +43,41 @@ def findAndReplaceArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: s
|
|
|
41
43
|
constructorName = constructorName.replace('ndarray', 'array')
|
|
42
44
|
allImports.addImportFromStr(moduleConstructor, constructorName)
|
|
43
45
|
|
|
44
|
-
for
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
astSubscript: ast.Subscript = stmt.value
|
|
51
|
-
if isinstance(astSubscript.value, ast.Name) and astSubscript.value.id == identifier and isinstance(astSubscript.slice, ast.Attribute):
|
|
52
|
-
indexAs_astAttribute: ast.Attribute = astSubscript.slice
|
|
53
|
-
indexAsStr = ast.unparse(indexAs_astAttribute)
|
|
54
|
-
arraySlice = arrayTarget[eval(indexAsStr)]
|
|
46
|
+
for statement in FunctionDefTarget.body.copy():
|
|
47
|
+
if ifThis.isUnpackingAnArray(identifier)(statement):
|
|
48
|
+
datatypeName = hackSSOTdatatype(statement.targets[0].id) # type: ignore
|
|
49
|
+
dtypeAsName = f"{moduleConstructor}_{datatypeName}"
|
|
50
|
+
indexAsStr = ast.unparse(statement.value.slice) # type: ignore
|
|
51
|
+
arraySlice = arrayTarget[eval(indexAsStr)]
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
onlyDataRLE = autoDecodingRLE(arraySlice, addSpaces=True)
|
|
54
|
+
astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
|
|
55
|
+
dataAst = astStatement.value
|
|
59
56
|
|
|
60
|
-
|
|
57
|
+
arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=dtypeAsName, ctx=ast.Load()))])
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
assignment = ast.Assign(targets=[statement.targets[0]], value=arrayCall) # type: ignore
|
|
60
|
+
FunctionDefTarget.body.insert(0, assignment)
|
|
61
|
+
FunctionDefTarget.body.remove(statement)
|
|
62
|
+
allImports.addImportFromStr(moduleConstructor, datatypeName, dtypeAsName)
|
|
65
63
|
return FunctionDefTarget, allImports
|
|
66
64
|
|
|
67
65
|
def findAndReplaceArraySubscriptIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arrayTarget: numpy.ndarray, Z0Z_listChaff: List[str], allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
68
66
|
moduleConstructor = Z0Z_getDatatypeModuleScalar()
|
|
69
|
-
for
|
|
70
|
-
if
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
FunctionDefTarget.body.insert(0, assignment)
|
|
84
|
-
FunctionDefTarget.body.remove(stmt)
|
|
67
|
+
for statement in FunctionDefTarget.body.copy():
|
|
68
|
+
if ifThis.isUnpackingAnArray(identifier)(statement):
|
|
69
|
+
astSubscript: ast.Subscript = statement.value # type: ignore
|
|
70
|
+
astAssignee: ast.Name = statement.targets[0] # type: ignore
|
|
71
|
+
argData_dtypeName = hackSSOTdatatype(astAssignee.id)
|
|
72
|
+
allImports.addImportFromStr(moduleConstructor, argData_dtypeName)
|
|
73
|
+
indexAs_astAttribute: ast.Attribute = astSubscript.slice # type: ignore
|
|
74
|
+
indexAsStr = ast.unparse(indexAs_astAttribute)
|
|
75
|
+
argDataSlice: int = arrayTarget[eval(indexAsStr)].item()
|
|
76
|
+
astCall = ast.Call(func=ast.Name(id=argData_dtypeName, ctx=ast.Load()), args=[ast.Constant(value=argDataSlice)], keywords=[])
|
|
77
|
+
assignment = ast.Assign(targets=[astAssignee], value=astCall)
|
|
78
|
+
if astAssignee.id not in Z0Z_listChaff:
|
|
79
|
+
FunctionDefTarget.body.insert(0, assignment)
|
|
80
|
+
FunctionDefTarget.body.remove(statement)
|
|
85
81
|
return FunctionDefTarget, allImports
|
|
86
82
|
|
|
87
83
|
def removeAssignTargetFrom_body(FunctionDefTarget: ast.FunctionDef, identifier: str) -> ast.FunctionDef:
|
|
@@ -136,13 +132,10 @@ def findThingyReplaceWithConstantIn_body(FunctionDefTarget: ast.FunctionDef, obj
|
|
|
136
132
|
return newFunction
|
|
137
133
|
|
|
138
134
|
def findAstNameReplaceWithConstantIn_body(FunctionDefTarget: ast.FunctionDef, name: str, value: int) -> ast.FunctionDef:
|
|
139
|
-
def findName(node: ast.AST) -> bool:
|
|
140
|
-
return isinstance(node, ast.Name) and node.id == name
|
|
141
|
-
|
|
142
135
|
def replaceWithConstant(node: ast.AST) -> ast.AST:
|
|
143
136
|
return ast.copy_location(ast.Constant(value=value), node)
|
|
144
137
|
|
|
145
|
-
return cast(ast.FunctionDef, NodeReplacer(
|
|
138
|
+
return cast(ast.FunctionDef, NodeReplacer(ifThis.nameIs(name), replaceWithConstant).visit(FunctionDefTarget))
|
|
146
139
|
|
|
147
140
|
def insertReturnStatementIn_body(FunctionDefTarget: ast.FunctionDef, arrayTarget: numpy.ndarray, allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
148
141
|
"""Add multiplication and return statement to function, properly constructing AST nodes."""
|
|
@@ -155,6 +148,8 @@ def insertReturnStatementIn_body(FunctionDefTarget: ast.FunctionDef, arrayTarget
|
|
|
155
148
|
|
|
156
149
|
returnStatement = ast.Return(value=multiplyOperation)
|
|
157
150
|
|
|
151
|
+
datatype = hackSSOTdatatype(Z0Z_identifierCountFolds)
|
|
152
|
+
FunctionDefTarget.returns = ast.Name(id=datatype, ctx=ast.Load())
|
|
158
153
|
datatypeModuleScalar = Z0Z_getDatatypeModuleScalar()
|
|
159
154
|
allImports.addImportFromStr(datatypeModuleScalar, datatype)
|
|
160
155
|
|
|
@@ -240,9 +235,7 @@ if __name__ == '__main__':
|
|
|
240
235
|
"""
|
|
241
236
|
return ast.parse(linesLaunch)
|
|
242
237
|
|
|
243
|
-
def
|
|
244
|
-
astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
|
|
245
|
-
|
|
238
|
+
def makeFunctionDef(astModule: ast.Module, callableTarget: str, parametersNumba: Optional[ParametersNumba]=None, inlineCallables: Optional[bool]=False, unpackArrays: Optional[bool]=False, allImports: Optional[UniversalImportTracker]=None) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
246
239
|
if allImports is None:
|
|
247
240
|
allImports = UniversalImportTracker()
|
|
248
241
|
for statement in astModule.body:
|
|
@@ -252,6 +245,8 @@ def makeAstModuleForOneCallable(pythonSource: str, callableTarget: str, paramete
|
|
|
252
245
|
if inlineCallables:
|
|
253
246
|
dictionaryFunctionDef = {statement.name: statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
|
|
254
247
|
callableInlinerWorkhorse = RecursiveInliner(dictionaryFunctionDef)
|
|
248
|
+
# NOTE the inliner assumes each function is not called more than once
|
|
249
|
+
# TODO change the inliner to handle multiple calls to the same function
|
|
255
250
|
FunctionDefTarget = callableInlinerWorkhorse.inlineFunctionBody(callableTarget)
|
|
256
251
|
else:
|
|
257
252
|
FunctionDefTarget = next((node for node in astModule.body if isinstance(node, ast.FunctionDef) and node.name == callableTarget), None)
|
|
@@ -269,9 +264,7 @@ def makeAstModuleForOneCallable(pythonSource: str, callableTarget: str, paramete
|
|
|
269
264
|
FunctionDefTarget = cast(ast.FunctionDef, unpacker.visit(FunctionDefTarget))
|
|
270
265
|
ast.fix_missing_locations(FunctionDefTarget)
|
|
271
266
|
|
|
272
|
-
|
|
273
|
-
ast.fix_missing_locations(astModule)
|
|
274
|
-
return ast.unparse(astModule)
|
|
267
|
+
return FunctionDefTarget, allImports
|
|
275
268
|
|
|
276
269
|
def decorateCallableWithNumba(FunctionDefTarget: ast.FunctionDef, allImports: UniversalImportTracker, parametersNumba: Optional[ParametersNumba]=None) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
277
270
|
def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from mapFolding import (
|
|
2
2
|
computationState,
|
|
3
3
|
EnumIndices,
|
|
4
|
-
|
|
4
|
+
formatFilenameModuleDEFAULT,
|
|
5
5
|
FREAKOUT,
|
|
6
6
|
getAlgorithmDispatcher,
|
|
7
7
|
getAlgorithmSource,
|
|
@@ -36,7 +36,7 @@ from numpy import integer
|
|
|
36
36
|
from numpy.typing import NDArray
|
|
37
37
|
from types import ModuleType
|
|
38
38
|
from typing import Any, Callable, cast, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
|
|
39
|
-
from Z0Z_tools import autoDecodingRLE
|
|
39
|
+
from Z0Z_tools import autoDecodingRLE, updateExtendPolishDictionaryLists
|
|
40
40
|
import ast
|
|
41
41
|
import autoflake
|
|
42
42
|
import collections
|
|
@@ -49,9 +49,41 @@ import numpy
|
|
|
49
49
|
import os
|
|
50
50
|
import pathlib
|
|
51
51
|
import python_minifier
|
|
52
|
+
import warnings
|
|
52
53
|
|
|
53
54
|
youOughtaKnow = collections.namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
|
|
54
55
|
|
|
56
|
+
# idk how to use this
|
|
57
|
+
class ASTBodyTransformer:
|
|
58
|
+
"""
|
|
59
|
+
A helper class to apply multiple transformations on an AST FunctionDef's body.
|
|
60
|
+
This abstraction eliminates the need to write repetitive loops for removals,
|
|
61
|
+
replacements, or insertions.
|
|
62
|
+
"""
|
|
63
|
+
def __init__(self, functionDefinition: ast.FunctionDef) -> None:
|
|
64
|
+
self.functionDefinition = functionDefinition
|
|
65
|
+
|
|
66
|
+
def replaceIn_body(self, predicate: Callable[[ast.stmt], bool], replacementBuilder: Callable[[ast.stmt], Optional[ast.stmt]]) -> None:
|
|
67
|
+
newBody: List[ast.stmt] = []
|
|
68
|
+
for statement in self.functionDefinition.body:
|
|
69
|
+
if predicate(statement):
|
|
70
|
+
replacementStatement = replacementBuilder(statement)
|
|
71
|
+
if replacementStatement is not None:
|
|
72
|
+
newBody.append(replacementStatement)
|
|
73
|
+
else:
|
|
74
|
+
newBody.append(statement)
|
|
75
|
+
self.functionDefinition.body = newBody
|
|
76
|
+
|
|
77
|
+
def atIndexInsert(self, index: int, statement: ast.stmt) -> None:
|
|
78
|
+
self.functionDefinition.body.insert(index, statement)
|
|
79
|
+
|
|
80
|
+
def removeAllOf(self, predicate: Callable[[ast.stmt], bool]) -> None:
|
|
81
|
+
self.replaceIn_body(predicate, lambda stmt: None)
|
|
82
|
+
|
|
83
|
+
def Z0Z_apply(self) -> ast.FunctionDef:
|
|
84
|
+
ast.fix_missing_locations(self.functionDefinition)
|
|
85
|
+
return self.functionDefinition
|
|
86
|
+
|
|
55
87
|
# Generic
|
|
56
88
|
class ifThis:
|
|
57
89
|
"""Generic AST node predicate builder."""
|
|
@@ -71,10 +103,27 @@ class ifThis:
|
|
|
71
103
|
def isCallWithName(callableName: str) -> Callable[[ast.AST], bool]:
|
|
72
104
|
return lambda node: (isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == callableName)
|
|
73
105
|
|
|
106
|
+
@staticmethod
|
|
107
|
+
def isAssignTarget(identifier: str):
|
|
108
|
+
return lambda node: (isinstance(node, ast.Assign)
|
|
109
|
+
and node.targets
|
|
110
|
+
and isinstance(node.targets[0], ast.Name)
|
|
111
|
+
and node.targets[0].id == identifier)
|
|
112
|
+
|
|
74
113
|
@staticmethod
|
|
75
114
|
def anyOf(*predicates: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
76
115
|
return lambda node: any(pred(node) for pred in predicates)
|
|
77
116
|
|
|
117
|
+
@staticmethod
|
|
118
|
+
def isUnpackingAnArray(identifier:str):
|
|
119
|
+
return lambda node: (isinstance(node, ast.Assign)
|
|
120
|
+
and isinstance(node.targets[0], ast.Name)
|
|
121
|
+
and isinstance(node.value, ast.Subscript)
|
|
122
|
+
and isinstance(node.value.value, ast.Name)
|
|
123
|
+
and node.value.value.id == identifier
|
|
124
|
+
and isinstance(node.value.slice, ast.Attribute)
|
|
125
|
+
)
|
|
126
|
+
|
|
78
127
|
class Then:
|
|
79
128
|
"""Generic actions."""
|
|
80
129
|
@staticmethod
|
|
@@ -103,9 +152,8 @@ class NodeReplacer(ast.NodeTransformer):
|
|
|
103
152
|
None from the replacement builder indicates that the node should be removed.
|
|
104
153
|
|
|
105
154
|
Attributes:
|
|
106
|
-
findMe
|
|
107
|
-
nodeReplacementBuilder
|
|
108
|
-
or None to remove the node.
|
|
155
|
+
findMe: A function that determines whether a node should be replaced.
|
|
156
|
+
nodeReplacementBuilder: A function that returns a new node or None to remove the node.
|
|
109
157
|
|
|
110
158
|
Methods:
|
|
111
159
|
visit(node: ast.AST) -> Optional[ast.AST]:
|
|
@@ -142,19 +190,42 @@ class UniversalImportTracker:
|
|
|
142
190
|
self.setImport.add(alias.name)
|
|
143
191
|
elif isinstance(astImport_, ast.ImportFrom):
|
|
144
192
|
if astImport_.module is not None:
|
|
145
|
-
self.dictionaryImportFrom[astImport_.module].update(alias.name for alias in astImport_.names)
|
|
193
|
+
self.dictionaryImportFrom[astImport_.module].update((alias.name, alias.asname) for alias in astImport_.names)
|
|
146
194
|
|
|
147
|
-
def
|
|
148
|
-
self.
|
|
195
|
+
def addImportStr(self, module: str) -> None:
|
|
196
|
+
self.setImport.add(module)
|
|
149
197
|
|
|
150
|
-
def
|
|
151
|
-
self.
|
|
198
|
+
def addImportFromStr(self, module: str, name: str, asname: Optional[str] = None) -> None:
|
|
199
|
+
self.dictionaryImportFrom[module].add((name, asname))
|
|
152
200
|
|
|
153
201
|
def makeListAst(self) -> List[Union[ast.ImportFrom, ast.Import]]:
|
|
154
|
-
listAstImportFrom = [
|
|
155
|
-
|
|
202
|
+
listAstImportFrom = []
|
|
203
|
+
for module, setOfNameTuples in sorted(self.dictionaryImportFrom.items()):
|
|
204
|
+
listAliases = []
|
|
205
|
+
for name, asname in setOfNameTuples:
|
|
206
|
+
listAliases.append(ast.alias(name=name, asname=asname))
|
|
207
|
+
listAstImportFrom.append(ast.ImportFrom(module=module, names=listAliases, level=0))
|
|
208
|
+
|
|
209
|
+
listAstImport = [ast.Import(names=[ast.alias(name=name, asname=None)]) for name in sorted(self.setImport)]
|
|
156
210
|
return listAstImportFrom + listAstImport
|
|
157
211
|
|
|
212
|
+
def update(self, *fromTracker: 'UniversalImportTracker') -> None:
|
|
213
|
+
"""
|
|
214
|
+
Update this tracker with imports from one or more other trackers.
|
|
215
|
+
|
|
216
|
+
Parameters:
|
|
217
|
+
*fromTracker: One or more UniversalImportTracker objects to merge from.
|
|
218
|
+
"""
|
|
219
|
+
# Merge all import-from dictionaries
|
|
220
|
+
dictionaryMerged = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(tracker.dictionaryImportFrom for tracker in fromTracker), destroyDuplicates=True, reorderLists=True)
|
|
221
|
+
|
|
222
|
+
# Convert lists back to sets for each module's imports
|
|
223
|
+
self.dictionaryImportFrom = {module: set(listNames) for module, listNames in dictionaryMerged.items()}
|
|
224
|
+
|
|
225
|
+
# Update direct imports
|
|
226
|
+
for tracker in fromTracker:
|
|
227
|
+
self.setImport.update(tracker.setImport)
|
|
228
|
+
|
|
158
229
|
# Intricate and specialized
|
|
159
230
|
class RecursiveInliner(ast.NodeTransformer):
|
|
160
231
|
"""
|
|
@@ -64,6 +64,7 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
64
64
|
pythonSource = inspect.getsource(algorithmSource)
|
|
65
65
|
astModule = ast.parse(pythonSource)
|
|
66
66
|
setFunctionDef = {statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
|
|
67
|
+
|
|
67
68
|
if not callableTarget:
|
|
68
69
|
if len(setFunctionDef) == 1:
|
|
69
70
|
FunctionDefTarget = setFunctionDef.pop()
|
|
@@ -71,7 +72,8 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
71
72
|
else:
|
|
72
73
|
raise ValueError(f"I did not receive a `callableTarget` and {algorithmSource.__name__=} has more than one callable: {setFunctionDef}. Please select one.")
|
|
73
74
|
else:
|
|
74
|
-
|
|
75
|
+
listFunctionDefTarget = [statement for statement in setFunctionDef if statement.name == callableTarget]
|
|
76
|
+
FunctionDefTarget = listFunctionDefTarget[0] if listFunctionDefTarget else None
|
|
75
77
|
if not FunctionDefTarget: raise ValueError(f"I received `{callableTarget=}` and {algorithmSource.__name__=}, but I could not find that function in that source.")
|
|
76
78
|
|
|
77
79
|
# NOTE `allImports` is a complementary container to `FunctionDefTarget`; the `FunctionDefTarget` cannot track its own imports very well.
|
|
@@ -86,13 +88,15 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
86
88
|
case 'my':
|
|
87
89
|
FunctionDefTarget, allImports = findAndReplaceArraySubscriptIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], ['taskIndex', 'dimensionsTotal'], allImports)
|
|
88
90
|
case 'track':
|
|
89
|
-
FunctionDefTarget, allImports =
|
|
91
|
+
FunctionDefTarget, allImports = findAndReplaceTrackArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
90
92
|
case 'connectionGraph':
|
|
91
93
|
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
92
94
|
case 'gapsWhere':
|
|
93
95
|
FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
94
96
|
case 'foldGroups':
|
|
95
97
|
FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, pirateScowl.arg)
|
|
98
|
+
# FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
|
|
99
|
+
# continue
|
|
96
100
|
FunctionDefTarget.args.args.remove(pirateScowl)
|
|
97
101
|
|
|
98
102
|
# NOTE replace identifiers with static values with their values
|
|
@@ -110,8 +114,6 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
110
114
|
FunctionDefTarget, allImports = insertReturnStatementIn_body(FunctionDefTarget, stateJob['foldGroups'], allImports)
|
|
111
115
|
|
|
112
116
|
# NOTE add the perfect decorator
|
|
113
|
-
datatype = hackSSOTdatatype(Z0Z_identifierCountFolds)
|
|
114
|
-
FunctionDefTarget.returns = ast.Name(id=datatype, ctx=ast.Load())
|
|
115
117
|
FunctionDefTarget, allImports = decorateCallableWithNumba(FunctionDefTarget, allImports, parametersNumba)
|
|
116
118
|
if thisIsNumbaDotJit(FunctionDefTarget.decorator_list[0]):
|
|
117
119
|
astCall = cast(ast.Call, FunctionDefTarget.decorator_list[0])
|
|
@@ -124,21 +126,7 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
124
126
|
ast.fix_missing_locations(astModule)
|
|
125
127
|
pythonSource = ast.unparse(astModule)
|
|
126
128
|
pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
|
|
127
|
-
pythonSource = python_minifier.minify(pythonSource, remove_annotations = False,
|
|
128
|
-
remove_pass = False,
|
|
129
|
-
remove_literal_statements = False,
|
|
130
|
-
combine_imports = True,
|
|
131
|
-
hoist_literals = False,
|
|
132
|
-
rename_locals = False,
|
|
133
|
-
rename_globals = False,
|
|
134
|
-
remove_object_base = False,
|
|
135
|
-
convert_posargs_to_args = False,
|
|
136
|
-
preserve_shebang = True,
|
|
137
|
-
remove_asserts = False,
|
|
138
|
-
remove_debug = False,
|
|
139
|
-
remove_explicit_return_none = False,
|
|
140
|
-
remove_builtin_exception_brackets = False,
|
|
141
|
-
constant_folding = False)
|
|
129
|
+
# pythonSource = python_minifier.minify(pythonSource, remove_annotations = False, remove_pass = False, remove_literal_statements = False, combine_imports = True, hoist_literals = False, rename_locals = False, rename_globals = False, remove_object_base = False, convert_posargs_to_args = False, preserve_shebang = True, remove_asserts = False, remove_debug = False, remove_explicit_return_none = False, remove_builtin_exception_brackets = False, constant_folding = False)
|
|
142
130
|
|
|
143
131
|
# NOTE put on disk
|
|
144
132
|
if pathFilenameWriteJob is None:
|
|
@@ -155,17 +143,18 @@ def writeJobNumba(mapShape: Sequence[int]
|
|
|
155
143
|
|
|
156
144
|
if __name__ == '__main__':
|
|
157
145
|
mapShape = [5,5]
|
|
158
|
-
from mapFolding.syntheticModules import
|
|
159
|
-
algorithmSource: ModuleType =
|
|
146
|
+
from mapFolding.syntheticModules import numbaCount
|
|
147
|
+
algorithmSource: ModuleType = numbaCount
|
|
160
148
|
|
|
161
|
-
callableTarget =
|
|
149
|
+
callableTarget = 'countSequential'
|
|
162
150
|
|
|
163
151
|
parametersNumba = parametersNumbaDEFAULT
|
|
152
|
+
parametersNumba['boundscheck'] = True
|
|
164
153
|
|
|
165
154
|
pathFilenameWriteJob = None
|
|
166
155
|
|
|
167
156
|
setDatatypeFoldsTotal('int64', sourGrapes=True)
|
|
168
|
-
setDatatypeElephino('
|
|
157
|
+
setDatatypeElephino('int16', sourGrapes=True)
|
|
169
158
|
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
170
159
|
Z0Z_setDatatypeModuleScalar('numba')
|
|
171
160
|
Z0Z_setDecoratorCallable('jit')
|
|
@@ -4,42 +4,82 @@ everything I am doing. I would rather benefit from humanity's
|
|
|
4
4
|
collective wisdom."""
|
|
5
5
|
from mapFolding.someAssemblyRequired.synthesizeNumba import *
|
|
6
6
|
|
|
7
|
-
def
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
def getFunctionDef(algorithmSource: ModuleType, *arguments, **keywordArguments) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
|
|
8
|
+
pythonSource = inspect.getsource(algorithmSource)
|
|
9
|
+
astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
|
|
10
|
+
FunctionDefTarget, allImports = makeFunctionDef(astModule, *arguments, **keywordArguments)
|
|
11
|
+
return FunctionDefTarget, allImports
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
def makePythonSource(listFunctionDefs: List[ast.FunctionDef], listAstImports: List[ast.Import|ast.ImportFrom], additional_imports: List[str]) -> str:
|
|
14
|
+
astModule = ast.Module(body=cast(List[ast.stmt], listAstImports + listFunctionDefs), type_ignores=[])
|
|
15
|
+
ast.fix_missing_locations(astModule)
|
|
16
|
+
pythonSource = ast.unparse(astModule)
|
|
17
|
+
if not pythonSource: raise FREAKOUT
|
|
18
|
+
pythonSource = autoflake.fix_code(pythonSource, additional_imports)
|
|
19
|
+
return pythonSource
|
|
20
|
+
|
|
21
|
+
def writePythonAsModule(pythonSource: str, listCallableSynthesized: List[str], relativePathWrite: Optional[pathlib.Path], filenameWrite: Optional[str], formatFilenameWrite: Optional[str]) -> List[youOughtaKnow]:
|
|
22
|
+
pathFilename = None
|
|
23
|
+
if not relativePathWrite:
|
|
24
|
+
pathWrite = getPathSyntheticModules()
|
|
25
|
+
else:
|
|
26
|
+
pathWrite = getPathPackage() / relativePathWrite
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
pythonSource = makeAstModuleForOneCallable(pythonSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
18
|
-
if not pythonSource: raise FREAKOUT
|
|
19
|
-
pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
|
|
28
|
+
if not formatFilenameWrite:
|
|
29
|
+
formatFilenameWrite = formatFilenameModuleDEFAULT
|
|
20
30
|
|
|
21
|
-
|
|
22
|
-
|
|
31
|
+
if not filenameWrite:
|
|
32
|
+
if len(listCallableSynthesized) == 1:
|
|
33
|
+
callableTarget = listCallableSynthesized[0]
|
|
23
34
|
else:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
callableTarget = 'count'
|
|
36
|
+
filenameWrite = formatFilenameWrite.format(callableTarget=callableTarget)
|
|
37
|
+
else:
|
|
38
|
+
if not filenameWrite.endswith('.py'):
|
|
39
|
+
warnings.warn(f"Filename {filenameWrite=} does not end with '.py'.")
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
pathFilename = pathWrite / filenameWrite
|
|
30
42
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
pathFilename.write_text(pythonSource)
|
|
44
|
+
|
|
45
|
+
howIsThisStillAThing = getPathPackage().parent
|
|
46
|
+
dumbassPythonNamespace = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
|
|
47
|
+
ImaModule = '.'.join(dumbassPythonNamespace)
|
|
48
|
+
|
|
49
|
+
listStuffYouOughtaKnow: List[youOughtaKnow] = []
|
|
50
|
+
|
|
51
|
+
for callableTarget in listCallableSynthesized:
|
|
34
52
|
astImportFrom = ast.ImportFrom(module=ImaModule, names=[ast.alias(name=callableTarget, asname=None)], level=0)
|
|
53
|
+
stuff = youOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
|
|
54
|
+
listStuffYouOughtaKnow.append(stuff)
|
|
35
55
|
|
|
36
|
-
|
|
56
|
+
return listStuffYouOughtaKnow
|
|
37
57
|
|
|
58
|
+
def makeFlowNumbaOptimized(listCallablesInline: List[str]
|
|
59
|
+
, callableDispatcher: Optional[bool] = False
|
|
60
|
+
, algorithmSource: Optional[ModuleType] = None
|
|
61
|
+
, relativePathWrite: Optional[pathlib.Path] = None
|
|
62
|
+
, filenameModuleWrite: Optional[str] = None
|
|
63
|
+
, formatFilenameWrite: Optional[str] = None
|
|
64
|
+
) -> List[youOughtaKnow]:
|
|
65
|
+
if relativePathWrite and relativePathWrite.is_absolute():
|
|
66
|
+
raise ValueError("The path to write the module must be relative to the root of the package.")
|
|
67
|
+
if not algorithmSource:
|
|
68
|
+
algorithmSource = getAlgorithmSource()
|
|
69
|
+
|
|
70
|
+
Z0Z_filenameModuleWrite = 'numbaCount.py'
|
|
71
|
+
|
|
72
|
+
listStuffYouOughtaKnow: List[youOughtaKnow] = []
|
|
73
|
+
additional_imports = ['mapFolding', 'numba', 'numpy']
|
|
74
|
+
|
|
75
|
+
listFunctionDefs: List[ast.FunctionDef] = []
|
|
76
|
+
allImportsModule = UniversalImportTracker()
|
|
38
77
|
for callableTarget in listCallablesInline:
|
|
39
78
|
parametersNumba = None
|
|
40
79
|
inlineCallables = True
|
|
41
80
|
unpackArrays = False
|
|
42
81
|
allImports = None
|
|
82
|
+
filenameWrite = None
|
|
43
83
|
match callableTarget:
|
|
44
84
|
case 'countParallel':
|
|
45
85
|
parametersNumba = parametersNumbaSuperJitParallel
|
|
@@ -48,7 +88,17 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
|
|
|
48
88
|
unpackArrays = True
|
|
49
89
|
case 'countInitialize':
|
|
50
90
|
parametersNumba = parametersNumbaDEFAULT
|
|
51
|
-
|
|
91
|
+
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
92
|
+
listFunctionDefs.append(FunctionDefTarget)
|
|
93
|
+
allImportsModule.update(allImports)
|
|
94
|
+
|
|
95
|
+
listAstImports = allImportsModule.makeListAst()
|
|
96
|
+
pythonSource = makePythonSource(listFunctionDefs, listAstImports, additional_imports)
|
|
97
|
+
|
|
98
|
+
filenameWrite = filenameModuleWrite or Z0Z_filenameModuleWrite
|
|
99
|
+
|
|
100
|
+
listStuff = writePythonAsModule(pythonSource, listCallablesInline, relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
101
|
+
listStuffYouOughtaKnow.extend(listStuff)
|
|
52
102
|
|
|
53
103
|
if callableDispatcher:
|
|
54
104
|
callableTarget = getAlgorithmDispatcher().__name__
|
|
@@ -56,22 +106,24 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
|
|
|
56
106
|
inlineCallables = False
|
|
57
107
|
unpackArrays = False
|
|
58
108
|
allImports = UniversalImportTracker()
|
|
109
|
+
filenameWrite = None
|
|
59
110
|
for stuff in listStuffYouOughtaKnow:
|
|
60
111
|
statement = stuff.astForCompetentProgrammers
|
|
61
112
|
if isinstance(statement, (ast.Import, ast.ImportFrom)):
|
|
62
113
|
allImports.addAst(statement)
|
|
114
|
+
FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
|
|
115
|
+
listAstImports = allImports.makeListAst()
|
|
116
|
+
|
|
117
|
+
pythonSource = makePythonSource([FunctionDefTarget], listAstImports, additional_imports)
|
|
63
118
|
|
|
64
|
-
|
|
119
|
+
listStuff = writePythonAsModule(pythonSource, [callableTarget], relativePathWrite, filenameWrite, formatFilenameWrite)
|
|
120
|
+
listStuffYouOughtaKnow.extend(listStuff)
|
|
65
121
|
|
|
66
122
|
return listStuffYouOughtaKnow
|
|
67
123
|
|
|
68
124
|
if __name__ == '__main__':
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
setDatatypeElephino('uint8', sourGrapes=True)
|
|
72
|
-
setDatatypeLeavesTotal('uint8', sourGrapes=True)
|
|
73
|
-
Z0Z_setDatatypeModuleScalar('numba')
|
|
74
|
-
Z0Z_setDecoratorCallable('jit')
|
|
125
|
+
# Z0Z_setDatatypeModuleScalar('numba')
|
|
126
|
+
# Z0Z_setDecoratorCallable('jit')
|
|
75
127
|
listCallablesInline: List[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
76
128
|
callableDispatcher = True
|
|
77
129
|
makeFlowNumbaOptimized(listCallablesInline, callableDispatcher)
|