Read about our upcoming Code of Conduct on this issue

This instance will be upgraded to Heptapod 0.28.1 on 2022-01-26 at 16:00 UTC+1 (a few minutes of down time)

Commit 6894c72d authored by Pierre Blanc-fatin's avatar Pierre Blanc-fatin
Browse files

Factorisation of get_ext_code() in analyse.util

parent 3e857d5b8298
......@@ -27,6 +27,7 @@ from .util import (
find_path,
change_import_name,
filter_external_code,
get_exterior_code,
)
from .capturex import CaptureX
from .blocks_if import get_block_definitions
......@@ -233,65 +234,20 @@ def analyse_aot(code, pathfile):
consider_annotations=False,
blocks=blocks_for_capturex,
)
code_dependance = capturex.make_code_external()
code_ext = {"function": {}, "classe": {}}
def get_exterior_code(
codes_dependance: dict, previous_file_name=None, classes: str = None
):
""" Get all imported functions needed by boosted functions and methods at multiple levels,
(i.e get functions needed by functions imported by boosted function) and add them into code_ext
"""
for func, dep in codes_dependance.items():
if dep:
module_ext = extast.parse(dep)
for node in module_ext.body:
if isinstance(node, (ast.ImportFrom, ast.Import)):
# get the path of the imported module
file_name, file_path = find_path(node, pathfile)
if file_name:
file_name = "__" + func + "__" + file_name
# get the content of the file
with open(str(file_path), "r") as file:
content = file.read()
mod = extast.parse(content)
# filter the code and add it to code_ext dict
code_ext[classes][file_name] = str(
filter_external_code(mod, node.names)
)
# change imported module names
codes_dependance[func] = change_import_name(
codes_dependance[func], node, func
)
# recursively get the exterior codes
if code_ext[classes][file_name]:
get_exterior_code(
{func: code_ext[classes][file_name]},
file_name,
classes,
)
if previous_file_name:
code_ext[classes][
previous_file_name
] = change_import_name(
code_ext[classes][previous_file_name],
node,
func,
)
return codes_dependance[func]
code_dependance = capturex.make_code_external()
if boosted_dicts["functions"]:
func = next(iter(boosted_dicts["functions"]))
code_dependance = get_exterior_code(
{func: code_dependance}, classes="function"
code_dependance, code_ext = get_exterior_code(
{func: code_dependance}, pathfile, classes="function", relative=True
)
code_dependance = code_dependance[func]
if boosted_dicts["classes"]:
cls = next(iter(boosted_dicts["classes"]))
code_dependance = get_exterior_code(
{cls: code_dependance}, classes="classe"
code_dependance, code_ext = get_exterior_code(
{cls: code_dependance}, pathfile, classes="classe", relative=True
)
code_dependance = code_dependance[cls]
debug(code_dependance)
debug("parse_code")
signatures_p = parse_code(code)
......
......@@ -11,7 +11,12 @@ from transonic.analyses import compute_ancestors_chains, get_decorated_dicts
from transonic.analyses.capturex import CaptureX
from transonic.analyses.util import print_dumped
from .util import find_path, change_import_name, filter_external_code
from .util import (
find_path,
change_import_name,
filter_external_code,
get_exterior_code,
)
def analysis_jit(code, pathfile):
......@@ -93,115 +98,19 @@ def analysis_jit(code, pathfile):
codes_dependance_classes[key] = capturex.make_code_external()
def adapt_code_dependance(func: str, codes_dependance: str):
"""
Adapt code_dependance to the call of a jitted function in a jitted function:
- Remove the import transonic
- Remove the jitted function statement (i.e func = jit(func))
- Add a import statement to the jitted function
- remove the definition of the jitted function if its on the file, or remove the import statement
"""
module = extast.parse(codes_dependance)
module_body = module.body.copy()
jitted_functions = []
for node in module_body:
# remove the transonic import
if isinstance(node, ast.ImportFrom):
if node.module == "transonic":
module.body.remove(node)
# remove the jitted function by jit() (i.e. func = jit(func))
# and add the import statement for the jitted function
elif isinstance(node, ast.Assign):
if node.value.func.id == "jit":
jitted_functions.append(node.targets[0].id)
module.body.remove(node)
module.body.insert(
0,
[
extast.parse(
"from "
+ node.value.args[0].id
+ " import "
+ node.value.args[0].id
)
],
)
# remove the definition:
for node in module_body:
# of the jitted function in the file
if isinstance(node, ast.FunctionDef):
if node.name in jitted_functions:
module.body.remove(node)
# of the jitted imported function
if isinstance(node, ast.ImportFrom):
for name in node.names:
if name.name in jitted_functions:
node.names.remove(name)
# remove the importFrom if no function is imported
if not node.names:
module.body.remove(node)
return extast.unparse(module)
code_ext = {"function": {}, "classe": {}}
def get_exterior_code(
codes_dependance: dict,
previous_file_name=None,
classes: str = None,
relative: bool = None,
):
""" Get all imported functions needed by boosted functions and methods at multiple levels,
(i.e get functions needed by functions imported by boosted function) and add them into code_ext
"""
for func, dep in codes_dependance.items():
if dep:
module_ext = extast.parse(dep)
for node in module_ext.body:
if isinstance(node, (ast.ImportFrom, ast.Import)):
# get the path of the imported module
file_name, file_path = find_path(node, pathfile)
# a jitted function or method needs another jitted function
if file_name == "transonic":
codes_dependance[func] = adapt_code_dependance(
func, codes_dependance[func]
)
elif file_name:
file_name = "__" + func + "__" + file_name
# get the content of the file
with open(str(file_path), "r") as file:
content = file.read()
mod = extast.parse(content)
# filter the code and add it to code_ext dict
code_ext[classes][file_name] = str(
filter_external_code(mod, node.names)
)
# change imported module names
codes_dependance[func] = change_import_name(
codes_dependance[func], node, func, relative
)
# recursively get the exterior codes
if code_ext[classes][file_name]:
get_exterior_code(
{func: code_ext[classes][file_name]},
file_name,
classes,
)
if previous_file_name:
code_ext[classes][
previous_file_name
] = change_import_name(
code_ext[classes][previous_file_name],
node,
func,
relative,
)
return codes_dependance
if jitted_dicts["methods"]:
codes_dependance_classes = get_exterior_code(
codes_dependance_classes, classes="classe", relative=False
codes_dependance_classes, code_ext = get_exterior_code(
codes_dependance_classes,
pathfile,
previous_file_name=None,
classes="classe",
relative=False,
)
codes_dependance = get_exterior_code(
codes_dependance, classes="function", relative=False
codes_dependance, code_ext = get_exterior_code(
codes_dependance,
pathfile,
previous_file_name=None,
classes="function",
relative=False,
)
return (jitted_dicts, codes_dependance, codes_dependance_classes, code_ext)
......@@ -252,3 +252,113 @@ def filter_external_code(module: object, names: list):
lines_code.append(str(extast.unparse(node)))
return code_dependance_annotations + "\n".join(lines_code)
def adapt_code_dependance(func: str, codes_dependance: str):
"""
Adapt code_dependance to the call of a jitted function in a jitted function:
- Remove the import transonic
- Remove the jitted function statement (i.e func = jit(func))
- Add a import statement to the jitted function
- remove the definition of the jitted function if its on the file, or remove the import statement
"""
module = extast.parse(codes_dependance)
module_body = module.body.copy()
jitted_functions = []
for node in module_body:
# remove the transonic import
if isinstance(node, ast.ImportFrom):
if node.module == "transonic":
module.body.remove(node)
# remove the jitted function by jit() (i.e. func = jit(func))
# and add the import statement for the jitted function
elif isinstance(node, ast.Assign):
if node.value.func.id == "jit":
jitted_functions.append(node.targets[0].id)
module.body.remove(node)
module.body.insert(
0,
[
extast.parse(
"from "
+ node.value.args[0].id
+ " import "
+ node.value.args[0].id
)
],
)
# remove the definition:
for node in module_body:
# of the jitted function in the file
if isinstance(node, ast.FunctionDef):
if node.name in jitted_functions:
module.body.remove(node)
# of the jitted imported function
if isinstance(node, ast.ImportFrom):
for name in node.names:
if name.name in jitted_functions:
node.names.remove(name)
# remove the importFrom if no function is imported
if not node.names:
module.body.remove(node)
return extast.unparse(module)
code_ext = {"function": {}, "classe": {}}
def get_exterior_code(
codes_dependance: dict,
pathfile: str,
previous_file_name=None,
classes: str = None,
relative: bool = None,
):
""" Get all imported functions needed by boosted functions and methods at multiple levels,
(i.e get functions needed by functions imported by boosted function) and add them into code_ext
"""
for func, dep in codes_dependance.items():
if dep:
module_ext = extast.parse(dep)
for node in module_ext.body:
if isinstance(node, (ast.ImportFrom, ast.Import)):
# get the path of the imported module
file_name, file_path = find_path(node, pathfile)
# a jitted function or method needs another jitted function
if file_name == "transonic":
codes_dependance[func] = adapt_code_dependance(
func, codes_dependance[func]
)
elif file_name:
file_name = "__" + func + "__" + file_name
# get the content of the file
with open(str(file_path), "r") as file:
content = file.read()
mod = extast.parse(content)
# filter the code and add it to code_ext dict
code_ext[classes][file_name] = str(
filter_external_code(mod, node.names)
)
# change imported module names
codes_dependance[func] = change_import_name(
codes_dependance[func], node, func, relative
)
# recursively get the exterior codes
if code_ext[classes][file_name]:
get_exterior_code(
{func: code_ext[classes][file_name]},
pathfile,
file_name,
classes,
)
if previous_file_name:
print(code_ext)
code_ext[classes][
previous_file_name
] = change_import_name(
code_ext[classes][previous_file_name],
node,
func,
relative,
)
return codes_dependance, code_ext
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment