Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
fluiddyn
transonic
Commits
87d48f505dbf
Commit
8244837a
authored
Sep 16, 2019
by
Pierre Augier
Browse files
Signatures + TypeFormatter
parent
8ae68e11ba30
Changes
8
Hide whitespace changes
Inline
Side-by-side
doc/index.rst
View file @
87d48f50
...
...
@@ -44,6 +44,7 @@ modules, classes and functions.
transonic.log
transonic.mpi
transonic.run
transonic.signatures
transonic.typing
transonic.util
...
...
transonic/backends/base.py
View file @
87d48f50
...
...
@@ -19,11 +19,11 @@ from typing import Iterable, Optional
import
transonic
from
transonic.analyses
import
extast
,
analyse_aot
from
transonic.typing
import
compute_signatures_from_typeobjects
from
transonic.log
import
logger
from
transonic.compiler
import
compile_extension
,
ext_suffix
from
transonic
import
mpi
from
transonic.mpi
import
PathSeq
from
transonic.signatures
import
compute_signatures_from_typeobjects
from
transonic.util
import
(
has_to_build
,
...
...
@@ -53,7 +53,7 @@ class Backend:
def
__init__
(
self
):
self
.
name
=
self
.
backend_name
self
.
name_capitalized
=
self
.
name
.
capitalize
()
self
.
type_formatter
=
TypeFormatter
()
self
.
type_formatter
=
TypeFormatter
(
self
.
name
)
self
.
jit
=
self
.
_SubBackendJIT
(
self
.
name
,
self
.
type_formatter
)
def
_make_code_from_fdef_node
(
self
,
fdef
):
...
...
transonic/backends/base_jit.py
View file @
87d48f50
...
...
@@ -18,10 +18,7 @@ except ImportError:
np
=
None
from
transonic.analyses
import
extast
from
transonic.typing
import
(
make_signatures_from_typehinted_func
,
normalize_type_name
,
)
from
transonic.signatures
import
make_signatures_from_typehinted_func
from
transonic.log
import
logger
from
transonic
import
mpi
from
transonic.util
import
get_source_without_decorator
...
...
@@ -32,10 +29,10 @@ from .for_classes import produce_code_class
class
SubBackendJIT
:
"""Sub-class for Transonic JIT compilation"""
def
__init__
(
self
,
name
,
backend_
type_formatter
):
def
__init__
(
self
,
name
,
type_formatter
):
self
.
name
=
name
self
.
name_capitalized
=
name
.
capitalize
()
self
.
backend_
type_formatter
=
backend_
type_formatter
self
.
type_formatter
=
type_formatter
def
make_backend_source
(
self
,
info_analysis
,
func
,
path_backend
):
func_name
=
func
.
__name__
...
...
@@ -64,7 +61,7 @@ class SubBackendJIT:
def
make_new_header
(
self
,
func
,
arg_types
):
# Include signature comming from type hints
signatures
=
make_signatures_from_typehinted_func
(
func
,
self
.
backend_
type_formatter
func
,
self
.
type_formatter
)
exports
=
set
(
f
"export
{
signature
}
"
for
signature
in
signatures
)
...
...
@@ -121,7 +118,7 @@ class SubBackendJIT:
def
compute_typename_from_object
(
self
,
obj
:
object
):
"""return the Pythran type name"""
name
=
type
(
obj
).
__name__
name
=
normalize_type_name
(
name
)
name
=
self
.
type_formatter
.
normalize_type_name
(
name
)
if
np
and
isinstance
(
obj
,
np
.
ndarray
):
name
=
obj
.
dtype
.
name
...
...
transonic/backends/cython.py
View file @
87d48f50
...
...
@@ -24,10 +24,8 @@ from warnings import warn
import
itertools
from
transonic.analyses.extast
import
unparse
,
ast
,
FunctionDef
,
Name
from
transonic.typing
import
(
format_type_as_backend_type
,
make_signatures_from_typehinted_func
,
)
from
transonic.signatures
import
make_signatures_from_typehinted_func
from
transonic.typing
import
format_type_as_backend_type
from
.base
import
BackendAOT
,
TypeHintRemover
,
format_str
from
.base_jit
import
SubBackendJIT
...
...
@@ -173,7 +171,7 @@ class SubBackendJITCython(SubBackendJIT):
)
signatures
=
make_signatures_from_typehinted_func
(
func
,
self
.
backend_
type_formatter
,
as_list_str
=
True
func
,
self
.
type_formatter
,
as_list_str
=
True
)
for
signature
in
signatures
:
...
...
transonic/backends/for_classes.py
View file @
87d48f50
...
...
@@ -9,7 +9,7 @@ from tokenize import tokenize, untokenize, NAME, OP
import
inspect
from
io
import
BytesIO
from
transonic.
typing
import
compute_signatures_from_typeobjects
from
transonic.
signatures
import
compute_signatures_from_typeobjects
# from transonic.log import logger
from
transonic.util
import
(
...
...
transonic/backends/typing.py
View file @
87d48f50
normalized_types
=
{
"float"
:
"float64"
,
"complex"
:
"complex128"
}
class
TypeFormatter
:
pass
def
__init__
(
self
,
backend_name
=
None
):
self
.
backend_name
=
backend_name
def
normalize_type_name
(
self
,
name
):
if
self
.
backend_name
==
"cython"
:
return
name
try
:
return
normalized_types
[
name
]
except
KeyError
:
return
name
base_type_formatter
=
TypeFormatter
()
transonic/signatures.py
0 → 100644
View file @
87d48f50
"""Compute function signatures
==============================
Internal API
------------
.. autofunction:: _format_types_as_backend_types
.. autofunction:: compute_signatures_from_typeobjects
.. autofunction:: _make_signature_from_template_variables
.. autofunction:: make_signatures_from_typehinted_func
"""
import
itertools
import
inspect
from
typing
import
List
from
transonic.typing
import
format_type_as_backend_type
def
_format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
kwargs
):
"""Compute a list of pythran types
"""
backend_types
=
[]
for
type_
in
types
:
backend_types
.
append
(
format_type_as_backend_type
(
type_
,
backend_type_formatter
,
**
kwargs
)
)
# TODO: handle this with an exception
if
"_empty"
in
backend_types
:
raise
ValueError
(
"At least one annotation type lacking in a signature.
\n
"
f
"types =
{
types
}
"
)
return
backend_types
def
compute_signatures_from_typeobjects
(
types
,
backend_type_formatter
)
->
List
[
List
[
str
]]:
"""Compute a list of lists (signatures) of strings (pythran types)
"""
if
isinstance
(
types
,
dict
):
types
=
types
.
values
()
template_parameters
=
set
()
for
type_
in
types
:
if
hasattr
(
type_
,
"get_template_parameters"
):
template_parameters
.
update
(
type_
.
get_template_parameters
())
if
not
template_parameters
:
str_types
=
[]
for
type_
in
types
:
if
isinstance
(
type_
,
type
):
str_type
=
type_
.
__name__
else
:
str_type
=
type_
str_types
.
append
(
str_type
)
if
"_empty"
in
str_types
:
raise
ValueError
(
"At least one annotation type lacking in a signature.
\n
"
f
"types =
{
types
}
"
)
return
(
str_types
,)
if
not
all
(
param
.
values
for
param
in
template_parameters
):
raise
ValueError
(
f
"
{
template_parameters
}
,
{
[
param
.
values
for
param
in
template_parameters
]
}
"
)
values_template_parameters
=
{}
for
param
in
template_parameters
:
values_template_parameters
[
param
.
__name__
]
=
param
.
values
backend_types
=
[]
names
=
values_template_parameters
.
keys
()
for
set_types
in
itertools
.
product
(
*
values_template_parameters
.
values
()):
template_variables
=
dict
(
zip
(
names
,
set_types
))
backend_types
.
append
(
_format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
template_variables
)
)
return
backend_types
def
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
None
,
as_list_str
=
False
,
**
kwargs
):
"""Create signature for a function with values for the template types
(This function should only be used in
:func:`make_signatures_from_typehinted_func`)
Parameters
----------
func: a function
kwargs : dict
The template types and their value
"""
if
_signature
is
None
:
_signature
=
inspect
.
signature
(
func
)
types
=
[
param
.
annotation
for
param
in
_signature
.
parameters
.
values
()]
backend_types
=
_format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
kwargs
)
# "multiply" the signatures to take into account the "or" syntax
multi_pythran_types
=
[
_
for
_
in
itertools
.
product
(
*
[
t
.
split
(
" or "
)
for
t
in
backend_types
])
]
signatures
=
[]
for
backend_types
in
multi_pythran_types
:
if
as_list_str
:
signature
=
backend_types
else
:
signature
=
f
"
{
func
.
__name__
}
("
+
", "
.
join
(
backend_types
)
+
")"
signatures
.
append
(
signature
)
return
signatures
def
make_signatures_from_typehinted_func
(
func
,
backend_type_formatter
,
as_list_str
=
False
):
"""Make the signatures from annotations if it is possible
Useful when there are only "not templated" types.
"""
annotations
=
func
.
__annotations__
if
not
annotations
:
return
tuple
()
types
=
annotations
.
values
()
template_parameters
=
[]
for
type_
in
types
:
if
hasattr
(
type_
,
"get_template_parameters"
):
template_parameters
.
extend
(
type_
.
get_template_parameters
())
template_parameters
=
set
(
template_parameters
)
_signature
=
inspect
.
signature
(
func
)
if
not
template_parameters
:
signatures
=
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
_signature
,
as_list_str
=
as_list_str
,
)
return
signatures
if
not
all
(
param
.
values
for
param
in
template_parameters
):
return
tuple
()
values_template_parameters
=
{}
for
param
in
template_parameters
:
values_template_parameters
[
param
.
__name__
]
=
param
.
values
names
=
values_template_parameters
.
keys
()
signatures
=
[]
for
set_types
in
itertools
.
product
(
*
values_template_parameters
.
values
()):
template_variables
=
dict
(
zip
(
names
,
set_types
))
signatures
.
extend
(
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
_signature
,
as_list_str
=
as_list_str
,
**
template_variables
,
)
)
return
signatures
transonic/typing.py
View file @
87d48f50
...
...
@@ -35,22 +35,12 @@ Internal API
:members:
:private-members:
.. autofunction:: compute_signatures_from_typeobjects
.. autofunction:: format_types_as_backend_types
.. autofunction:: _make_signature_from_template_variables
.. autofunction:: make_signatures_from_typehinted_func
.. autofunction:: format_type_as_backend_type
"""
import
itertools
import
inspect
from
typing
import
List
from
transonic.util
import
get_name_calling_module
from
transonic.config
import
backend_default
names_template_variables
=
{}
...
...
@@ -403,29 +393,17 @@ class Union(metaclass=UnionMeta):
pass
if
backend_default
==
"cython"
:
normalized_types
=
{
"float"
:
"float"
,
"complex"
:
"complex"
}
else
:
normalized_types
=
{
"float"
:
"float64"
,
"complex"
:
"complex128"
}
def
normalize_type_name
(
name
):
try
:
return
normalized_types
[
name
]
except
KeyError
:
return
name
def
format_type_as_backend_type
(
type_
,
backend_type_formatter
,
**
kwargs
):
normalize_type_name
=
backend_type_formatter
.
normalize_type_name
if
hasattr
(
type_
,
"format_as_backend_type"
):
pythran
_type
=
type_
.
format_as_backend_type
(
backend
_type
=
type_
.
format_as_backend_type
(
backend_type_formatter
,
**
kwargs
)
elif
hasattr
(
type_
,
"__name__"
):
pythran
_type
=
type_
.
__name__
backend
_type
=
type_
.
__name__
else
:
pythran
_type
=
str
(
type_
)
types
=
pythran
_type
.
split
(
" or "
)
backend
_type
=
str
(
type_
)
types
=
backend
_type
.
split
(
" or "
)
new_types
=
[]
for
_type
in
types
:
_type
=
normalize_type_name
(
_type
)
...
...
@@ -437,179 +415,6 @@ def format_type_as_backend_type(type_, backend_type_formatter, **kwargs):
elif
_type
.
endswith
(
"[]"
):
_type
=
normalize_type_name
(
_type
[:
-
2
])
+
"[:]"
new_types
.
append
(
_type
)
pythran_type
=
" or "
.
join
(
new_types
)
return
normalize_type_name
(
pythran_type
)
def
format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
kwargs
):
"""Compute a list of pythran types
"""
backend_types
=
[]
for
type_
in
types
:
backend_types
.
append
(
format_type_as_backend_type
(
type_
,
backend_type_formatter
,
**
kwargs
)
)
# TODO: handle this with an exception
if
"_empty"
in
backend_types
:
raise
ValueError
(
"At least one annotation type lacking in a signature.
\n
"
f
"types =
{
types
}
"
)
return
backend_types
def
compute_signatures_from_typeobjects
(
types
,
backend_type_formatter
)
->
List
[
List
[
str
]]:
"""Compute a list of lists (signatures) of strings (pythran types)
"""
if
isinstance
(
types
,
dict
):
types
=
types
.
values
()
template_parameters
=
set
()
for
type_
in
types
:
if
hasattr
(
type_
,
"get_template_parameters"
):
template_parameters
.
update
(
type_
.
get_template_parameters
())
if
not
template_parameters
:
str_types
=
[]
for
type_
in
types
:
if
isinstance
(
type_
,
type
):
str_type
=
type_
.
__name__
else
:
str_type
=
type_
str_types
.
append
(
str_type
)
if
"_empty"
in
str_types
:
raise
ValueError
(
"At least one annotation type lacking in a signature.
\n
"
f
"types =
{
types
}
"
)
return
(
str_types
,)
if
not
all
(
param
.
values
for
param
in
template_parameters
):
raise
ValueError
(
f
"
{
template_parameters
}
,
{
[
param
.
values
for
param
in
template_parameters
]
}
"
)
values_template_parameters
=
{}
for
param
in
template_parameters
:
values_template_parameters
[
param
.
__name__
]
=
param
.
values
backend_types
=
[]
names
=
values_template_parameters
.
keys
()
for
set_types
in
itertools
.
product
(
*
values_template_parameters
.
values
()):
template_variables
=
dict
(
zip
(
names
,
set_types
))
backend_types
.
append
(
format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
template_variables
)
)
return
backend_types
def
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
None
,
as_list_str
=
False
,
**
kwargs
):
"""Create signature for a function with values for the template types
(This function should only be used in
:func:`make_signatures_from_typehinted_func`)
Parameters
----------
func: a function
kwargs : dict
The template types and their value
"""
if
_signature
is
None
:
_signature
=
inspect
.
signature
(
func
)
types
=
[
param
.
annotation
for
param
in
_signature
.
parameters
.
values
()]
backend_types
=
format_types_as_backend_types
(
types
,
backend_type_formatter
,
**
kwargs
)
# "multiply" the signatures to take into account the "or" syntax
multi_pythran_types
=
[
_
for
_
in
itertools
.
product
(
*
[
t
.
split
(
" or "
)
for
t
in
backend_types
])
]
signatures
=
[]
for
backend_types
in
multi_pythran_types
:
if
as_list_str
:
signature
=
backend_types
else
:
signature
=
f
"
{
func
.
__name__
}
("
+
", "
.
join
(
backend_types
)
+
")"
signatures
.
append
(
signature
)
return
signatures
def
make_signatures_from_typehinted_func
(
func
,
backend_type_formatter
,
as_list_str
=
False
):
"""Make the signatures from annotations if it is possible
Useful when there are only "not templated" types.
"""
annotations
=
func
.
__annotations__
if
not
annotations
:
return
tuple
()
types
=
annotations
.
values
()
template_parameters
=
[]
for
type_
in
types
:
if
hasattr
(
type_
,
"get_template_parameters"
):
template_parameters
.
extend
(
type_
.
get_template_parameters
())
template_parameters
=
set
(
template_parameters
)
_signature
=
inspect
.
signature
(
func
)
if
not
template_parameters
:
signatures
=
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
_signature
,
as_list_str
=
as_list_str
,
)
return
signatures
if
not
all
(
param
.
values
for
param
in
template_parameters
):
return
tuple
()
values_template_parameters
=
{}
for
param
in
template_parameters
:
values_template_parameters
[
param
.
__name__
]
=
param
.
values
names
=
values_template_parameters
.
keys
()
signatures
=
[]
for
set_types
in
itertools
.
product
(
*
values_template_parameters
.
values
()):
template_variables
=
dict
(
zip
(
names
,
set_types
))
signatures
.
extend
(
_make_signature_from_template_variables
(
func
,
backend_type_formatter
,
_signature
=
_signature
,
as_list_str
=
as_list_str
,
**
template_variables
,
)
)
backend_type
=
" or "
.
join
(
new_types
)
return
signatures
return
normalize_type_name
(
backend_type
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment