mirror of
https://github.com/triqs/dft_tools
synced 2025-01-12 22:18:23 +01:00
[clang tool] add parameter class treatment and h5 generator
wrapper generator: add treatment of parameter class - methods taking a parameter class are called by **kw - the dict is passed to the C++ - the converters for the parameters are generated.
This commit is contained in:
parent
0a1285405c
commit
ed6379ce63
@ -373,7 +373,7 @@ g.add_method(name = "set_from_legendre",
|
|||||||
|
|
||||||
g.add_method(name = "fit_tail",
|
g.add_method(name = "fit_tail",
|
||||||
signature = "void(tail_view known_moments, int n_moments, int n_min, int n_max, bool replace_by_fit = true)",
|
signature = "void(tail_view known_moments, int n_moments, int n_min, int n_max, bool replace_by_fit = true)",
|
||||||
calling_pattern = "fit_tail(self_c, known_moments, n_moments, n_min, n_max, replace_by_fit)",
|
calling_pattern = "fit_tail(self_c, *known_moments, n_moments, n_min, n_max, replace_by_fit)",
|
||||||
doc = """Set the tail by fitting""")
|
doc = """Set the tail by fitting""")
|
||||||
|
|
||||||
# Pure python methods
|
# Pure python methods
|
||||||
|
@ -5,10 +5,16 @@ SET(PYTHON_SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
install(FILES ${PYTHON_SOURCES} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/triqs/wrap_generator)
|
install(FILES ${PYTHON_SOURCES} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/triqs/wrap_generator)
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/clang_parser.py DESTINATION bin)
|
||||||
|
|
||||||
# The desc_file generator from libclang ...
|
# The desc_file generator from libclang ...
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wrapper_desc_generator.py.in ${CMAKE_CURRENT_BINARY_DIR}/wrapper_desc_generator.py @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wrapper_desc_generator.py.in ${CMAKE_CURRENT_BINARY_DIR}/wrapper_desc_generator.py @ONLY)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wrapper_desc_generator.py DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE )
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/wrapper_desc_generator.py DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE )
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/clang_parser.py DESTINATION bin)
|
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wrap_desc.mako.py DESTINATION share/triqs/wrap_generator/)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/wrap_desc.mako.py DESTINATION share/triqs/wrap_generator/)
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/converters.mako.hxx DESTINATION share/triqs/wrap_generator/)
|
||||||
|
|
||||||
|
# The param generator
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/param_generator.py.in ${CMAKE_CURRENT_BINARY_DIR}/param_generator.py @ONLY)
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/param_generator.py DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE )
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/param.mako.cxx DESTINATION share/triqs/wrap_generator/)
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@ def process_doc (doc) :
|
|||||||
|
|
||||||
file_locations = set(())
|
file_locations = set(())
|
||||||
|
|
||||||
|
def decay(s) :
|
||||||
|
for tok in ['const', '&&', '&'] :
|
||||||
|
s = re.sub(tok,'',s)
|
||||||
|
return s.strip()
|
||||||
|
|
||||||
class member_(object):
|
class member_(object):
|
||||||
def __init__(self, cursor,ns=()):
|
def __init__(self, cursor,ns=()):
|
||||||
loc = cursor.location.file.name
|
loc = cursor.location.file.name
|
||||||
@ -28,7 +33,14 @@ class member_(object):
|
|||||||
self.ns = ns
|
self.ns = ns
|
||||||
self.name = cursor.spelling
|
self.name = cursor.spelling
|
||||||
self.access = cursor.access_specifier
|
self.access = cursor.access_specifier
|
||||||
|
self.type = type_(cursor.type)
|
||||||
self.ctype = cursor.type.spelling
|
self.ctype = cursor.type.spelling
|
||||||
|
self.annotations = get_annotations(cursor)
|
||||||
|
# the declaration split in small tokens
|
||||||
|
tokens = [t.spelling for t in cursor.get_tokens()]
|
||||||
|
self.initializer = None
|
||||||
|
if '=' in tokens:
|
||||||
|
self.initializer = ''.join(tokens[tokens.index('=') + 1:tokens.index(';')])
|
||||||
|
|
||||||
def namespace(self) :
|
def namespace(self) :
|
||||||
return "::".join(self.ns)
|
return "::".join(self.ns)
|
||||||
@ -37,6 +49,10 @@ class type_(object):
|
|||||||
def __init__(self, cursor):
|
def __init__(self, cursor):
|
||||||
self.name, self.canonical_name = cursor.spelling, cursor.get_canonical().spelling
|
self.name, self.canonical_name = cursor.spelling, cursor.get_canonical().spelling
|
||||||
|
|
||||||
|
def __repr__(self) :
|
||||||
|
return "type : %s"%(self.name)
|
||||||
|
#return "type : %s %s\n"%(self.name, self.canonical_name)
|
||||||
|
|
||||||
class Function(object):
|
class Function(object):
|
||||||
def __init__(self, cursor, is_constructor = False, ns=() ): #, template_list =()):
|
def __init__(self, cursor, is_constructor = False, ns=() ): #, template_list =()):
|
||||||
loc = cursor.location.file.name
|
loc = cursor.location.file.name
|
||||||
@ -51,7 +67,7 @@ class Function(object):
|
|||||||
self.template_list = [] #template_list
|
self.template_list = [] #template_list
|
||||||
self.is_constructor = is_constructor
|
self.is_constructor = is_constructor
|
||||||
self.is_static = cursor.is_static_method()
|
self.is_static = cursor.is_static_method()
|
||||||
|
self.parameter_arg = None # If exists, it is the parameter class
|
||||||
for c in cursor.get_children():
|
for c in cursor.get_children():
|
||||||
if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER :
|
if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER :
|
||||||
self.template_list.append(c.spelling)
|
self.template_list.append(c.spelling)
|
||||||
@ -60,12 +76,25 @@ class Function(object):
|
|||||||
for ch in c.get_children() :
|
for ch in c.get_children() :
|
||||||
# TODO : string literal do not work.. needs to use location ? useful ?
|
# TODO : string literal do not work.. needs to use location ? useful ?
|
||||||
if ch.kind in [clang.cindex.CursorKind.INTEGER_LITERAL, clang.cindex.CursorKind.FLOATING_LITERAL,
|
if ch.kind in [clang.cindex.CursorKind.INTEGER_LITERAL, clang.cindex.CursorKind.FLOATING_LITERAL,
|
||||||
clang.cindex.CursorKind.CHARACTER_LITERAL, clang.cindex.CursorKind.STRING_LITERAL] :
|
clang.cindex.CursorKind.CHARACTER_LITERAL, clang.cindex.CursorKind.STRING_LITERAL,
|
||||||
default_value = ch.get_tokens().next().spelling
|
clang.cindex.CursorKind.UNARY_OPERATOR, clang.cindex.CursorKind.UNEXPOSED_EXPR,
|
||||||
|
clang.cindex.CursorKind.CXX_BOOL_LITERAL_EXPR ] :
|
||||||
|
#print [x.spelling for x in ch.get_tokens()]
|
||||||
|
#default_value = ch.get_tokens().next().spelling
|
||||||
|
default_value = ''.join([x.spelling for x in ch.get_tokens()][:-1])
|
||||||
t = type_(c.type)
|
t = type_(c.type)
|
||||||
|
|
||||||
|
# We look if this argument is a parameter class...
|
||||||
|
if 'use_parameter_class' in self.annotations :
|
||||||
|
tt = c.type.get_declaration() # guess it is not a ref
|
||||||
|
if not tt.location.file : tt = c.type.get_pointee().get_declaration() # it is a T &
|
||||||
|
#if tt.raw_comment and 'triqs:is_parameter' in tt.raw_comment:
|
||||||
|
self.parameter_arg = Class(tt, ns)
|
||||||
|
|
||||||
self.params.append ( (t, c.spelling, default_value ))
|
self.params.append ( (t, c.spelling, default_value ))
|
||||||
#else :
|
#else :
|
||||||
# print " node in fun ", c.kind
|
# print " node in fun ", c.kind
|
||||||
|
if self.parameter_arg : assert len(self.params) == 1, "When using a parameter class, it must have exactly one argument"
|
||||||
self.rtype = type_(cursor.result_type) if not is_constructor else None
|
self.rtype = type_(cursor.result_type) if not is_constructor else None
|
||||||
|
|
||||||
def namespace(self) :
|
def namespace(self) :
|
||||||
@ -129,6 +158,8 @@ class Class(object):
|
|||||||
def namespace(self) :
|
def namespace(self) :
|
||||||
return "::".join(self.ns)
|
return "::".join(self.ns)
|
||||||
|
|
||||||
|
def canonical_name(self) : return self.namespace() + '::' + self.name
|
||||||
|
|
||||||
def __str__(self) :
|
def __str__(self) :
|
||||||
s,s2 = "class {name}:\n {doc}\n\n".format(**self.__dict__),[]
|
s,s2 = "class {name}:\n {doc}\n\n".format(**self.__dict__),[]
|
||||||
for m in self.members :
|
for m in self.members :
|
||||||
@ -140,12 +171,15 @@ class Class(object):
|
|||||||
s2 = '\n'.join( [ " " + l.strip() + '\n' for l in s2 if l.strip()])
|
s2 = '\n'.join( [ " " + l.strip() + '\n' for l in s2 if l.strip()])
|
||||||
return s + s2
|
return s + s2
|
||||||
|
|
||||||
|
def __repr__(self) :
|
||||||
|
return "Class %s"%self.name
|
||||||
|
|
||||||
def build_functions_and_classes(cursor, namespaces=[]):
|
def build_functions_and_classes(cursor, namespaces=[]):
|
||||||
classes,functions = [],[]
|
classes,functions = [],[]
|
||||||
for c in cursor.get_children():
|
for c in cursor.get_children():
|
||||||
if (c.kind == clang.cindex.CursorKind.FUNCTION_DECL
|
if (c.kind == clang.cindex.CursorKind.FUNCTION_DECL
|
||||||
and c.location.file.name == sys.argv[1]):
|
and c.location.file.name == sys.argv[1]):
|
||||||
functions.append( Function(c,namespaces))
|
functions.append( Function(c,is_constructor = False, ns =namespaces))
|
||||||
elif (c.kind in [clang.cindex.CursorKind.CLASS_DECL, clang.cindex.CursorKind.STRUCT_DECL]
|
elif (c.kind in [clang.cindex.CursorKind.CLASS_DECL, clang.cindex.CursorKind.STRUCT_DECL]
|
||||||
and c.location.file.name == sys.argv[1]):
|
and c.location.file.name == sys.argv[1]):
|
||||||
classes.append( Class(c,namespaces))
|
classes.append( Class(c,namespaces))
|
||||||
@ -163,6 +197,7 @@ def parse(filename, debug, compiler_options, where_is_libclang):
|
|||||||
clang.cindex.Config.set_library_file(where_is_libclang)
|
clang.cindex.Config.set_library_file(where_is_libclang)
|
||||||
index = clang.cindex.Index.create()
|
index = clang.cindex.Index.create()
|
||||||
print "Parsing the C++ file (may take a few seconds) ..."
|
print "Parsing the C++ file (may take a few seconds) ..."
|
||||||
|
#print filename, ['-x', 'c++'] + compiler_options
|
||||||
translation_unit = index.parse(filename, ['-x', 'c++'] + compiler_options)
|
translation_unit = index.parse(filename, ['-x', 'c++'] + compiler_options)
|
||||||
print "... done. \nExtracting ..."
|
print "... done. \nExtracting ..."
|
||||||
|
|
||||||
@ -180,9 +215,9 @@ def parse(filename, debug, compiler_options, where_is_libclang):
|
|||||||
print "... done"
|
print "... done"
|
||||||
|
|
||||||
global file_locations
|
global file_locations
|
||||||
if len(file_locations) != 1 :
|
#if len(file_locations) != 1 :
|
||||||
print file_locations
|
# print file_locations
|
||||||
raise RuntimeError, "Multiple file location not implemented"
|
# raise RuntimeError, "Multiple file location not implemented"
|
||||||
file_locations = list(file_locations)
|
file_locations = list(file_locations)
|
||||||
|
|
||||||
if debug :
|
if debug :
|
||||||
|
109
pytriqs/wrap_generator/converters.mako.hxx
Normal file
109
pytriqs/wrap_generator/converters.mako.hxx
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// DO NOT EDIT
|
||||||
|
// Generated automatically using libclang using the command :
|
||||||
|
// ${shell_command}
|
||||||
|
%for c in classes :
|
||||||
|
<%
|
||||||
|
def name_lmax(member_list) :
|
||||||
|
return max(len(m.name) for m in member_list)
|
||||||
|
|
||||||
|
def name_format(name) :
|
||||||
|
f = '{:<%s}'%(name_lmax(c.members)+2)
|
||||||
|
return f.format(name)
|
||||||
|
|
||||||
|
def name_format_q(name) : return name_format('"%s"'%name)
|
||||||
|
|
||||||
|
def type_format(name) :
|
||||||
|
f = '{:<%s}'%(max(len(m.ctype) for m in c.members))
|
||||||
|
return f.format(name)
|
||||||
|
%>
|
||||||
|
|
||||||
|
// --- C++ Python converter for ${c.name}
|
||||||
|
|
||||||
|
namespace triqs { namespace py_tools {
|
||||||
|
|
||||||
|
template <> struct py_converter<${c.name}> {
|
||||||
|
static PyObject *c2py(${c.name} const & x) {
|
||||||
|
PyObject * d = PyDict_New();
|
||||||
|
%for m in c.members :
|
||||||
|
PyDict_SetItemString( d, ${name_format('"%s"'%m.name)}, convert_to_python(x.${m.name}));
|
||||||
|
%endfor
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U> static void _get_optional(PyObject *dic, const char *name, T &r, U const &init_default) {
|
||||||
|
if (PyDict_Contains(dic, pyref::string(name)))
|
||||||
|
r = convert_from_python<T>(PyDict_GetItemString(dic, name));
|
||||||
|
else
|
||||||
|
r = init_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ${c.name} py2c(PyObject *dic) {
|
||||||
|
${c.name} res;
|
||||||
|
%for m in c.members :
|
||||||
|
%if m.initializer == None :
|
||||||
|
res.${m.name} = convert_from_python<${m.ctype}>(PyDict_GetItemString(dic, "${m.name}"));
|
||||||
|
%else:
|
||||||
|
_get_optional(dic, ${name_format_q(m.name)}, res.${name_format(m.name)}, ${m.initializer});
|
||||||
|
%endif
|
||||||
|
%endfor
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void _check(PyObject *dic, std::stringstream &fs, int &err, const char *name, const char *tname) {
|
||||||
|
if (!convertible_from_python<T>(PyDict_GetItemString(dic, name), false))
|
||||||
|
fs << "\n" << ++err << " The parameter " << name << " does not have the right type : expecting " << tname
|
||||||
|
<< " in C++, but got '" << PyDict_GetItemString(dic, name)->ob_type->tp_name << "' in Python.";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void _check_mandatory(PyObject *dic, std::stringstream &fs, int &err, const char *name, const char *tname) {
|
||||||
|
if (!PyDict_Contains(dic, pyref::string(name)))
|
||||||
|
fs << "\n" << ++err << " Mandatory parameter " << name << " is missing.";
|
||||||
|
else _check<T>(dic,fs,err,name,tname);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static void _check_optional(PyObject *dic, std::stringstream &fs, int &err, const char *name, const char *tname) {
|
||||||
|
if (PyDict_Contains(dic, pyref::string(name))) _check<T>(dic, fs, err, name, tname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_convertible(PyObject *dic, bool raise_exception) {
|
||||||
|
if (!PyDict_Check(dic)) {
|
||||||
|
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Not a python dict");}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::stringstream fs, fs2; int err=0;
|
||||||
|
|
||||||
|
#ifndef TRIQS_ALLOW_UNUSED_PARAMETERS
|
||||||
|
std::vector<std::string> ks, all_keys = {${','.join('"%s"'%m.name for m in c.members)}};
|
||||||
|
pyref keys = PyDict_Keys(dic);
|
||||||
|
if (!convertible_from_python<std::vector<std::string>>(keys, true)) {
|
||||||
|
fs << "\nThe dict keys are not strings";
|
||||||
|
goto _error;
|
||||||
|
}
|
||||||
|
ks = convert_from_python<std::vector<std::string>>(keys);
|
||||||
|
for (auto & k : ks)
|
||||||
|
if (std::find(all_keys.begin(), all_keys.end(), k) == all_keys.end())
|
||||||
|
fs << "\n"<< ++err << " The parameter '" << k << "' is not recognized.";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%for m in c.members :
|
||||||
|
%if m.initializer == None :
|
||||||
|
_check_mandatory<${type_format(m.ctype)}>(dic, fs, err, ${name_format_q(m.name)}, "${m.ctype}");
|
||||||
|
%else:
|
||||||
|
_check_optional <${type_format(m.ctype)}>(dic, fs, err, ${name_format_q(m.name)}, "${m.ctype}");
|
||||||
|
%endif
|
||||||
|
%endfor
|
||||||
|
if (err) goto _error;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
_error:
|
||||||
|
fs2 << "\n---- There " << (err > 1 ? "are " : "is ") << err<< " error"<<(err >1 ?"s" : "")<< " in Python -> C++ transcription for the class ${c.name}\n" <<fs.str();
|
||||||
|
if (raise_exception) PyErr_SetString(PyExc_TypeError, fs2.str().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
%endfor
|
47
pytriqs/wrap_generator/param.mako.cxx
Normal file
47
pytriqs/wrap_generator/param.mako.cxx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// DO NOT EDIT
|
||||||
|
// Generated automatically using libclang using the command :
|
||||||
|
// ${shell_command}
|
||||||
|
%for c in classes :
|
||||||
|
<%
|
||||||
|
def name_lmax(member_list) :
|
||||||
|
return max(len(m.name) for m in member_list)
|
||||||
|
|
||||||
|
def name_format(name) :
|
||||||
|
f = '{:<%s}'%(name_lmax(c.members)+2)
|
||||||
|
return f.format(name)
|
||||||
|
|
||||||
|
def name_format_q(name) : return name_format('"%s"'%name)
|
||||||
|
|
||||||
|
def type_format(name) :
|
||||||
|
f = '{:<%s}'%(max(len(m.ctype) for m in c.members))
|
||||||
|
return f.format(name)
|
||||||
|
%>
|
||||||
|
${''.join('namespace %s {'%n for n in c.ns)}
|
||||||
|
|
||||||
|
/// Write into HDF5
|
||||||
|
void h5_write(h5::group fg, std::string subgroup_name, ${c.name} const &x) {
|
||||||
|
auto gr = fg.create_group(subgroup_name);
|
||||||
|
gr.write_triqs_hdf5_data_scheme("TRIQS_PARAM:${c.name}");
|
||||||
|
%for m in c.members:
|
||||||
|
h5_write(gr, ${name_format_q(m.name)}, x.${m.name});
|
||||||
|
%endfor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read from HDF5
|
||||||
|
void h5_read(h5::group fg, std::string subgroup_name, ${c.name} &x) {
|
||||||
|
auto gr = fg.open_group(subgroup_name);
|
||||||
|
// Check the attribute or throw
|
||||||
|
auto tag_file = gr.read_triqs_hdf5_data_scheme();
|
||||||
|
auto tag_expected = "TRIQS_PARAM:${c.name}";
|
||||||
|
if (tag_file != tag_expected)
|
||||||
|
TRIQS_RUNTIME_ERROR << "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found " << tag_file
|
||||||
|
<< " while I expected " << tag_expected;
|
||||||
|
%for m in c.members:
|
||||||
|
h5_read(gr, ${name_format_q(m.name)}, x.${m.name});
|
||||||
|
%endfor
|
||||||
|
}
|
||||||
|
|
||||||
|
## close namespace
|
||||||
|
${'}'*len(c.ns)}
|
||||||
|
|
||||||
|
%endfor
|
52
pytriqs/wrap_generator/param_generator.py.in
Normal file
52
pytriqs/wrap_generator/param_generator.py.in
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!@PYTHON_INTERPRETER@
|
||||||
|
|
||||||
|
from clang_parser import parse
|
||||||
|
import sys, os
|
||||||
|
from mako.template import Template
|
||||||
|
|
||||||
|
# the instruction that created this file
|
||||||
|
shell_command = ' '.join( [ sys.argv[0].rsplit('/')[-1]] + [x if ' ' not in x else '"%s"'%x for x in sys.argv[1:]])
|
||||||
|
|
||||||
|
#
|
||||||
|
print "Welcome to the C++ code generator of TRIQS, based on libclang !"
|
||||||
|
|
||||||
|
# --- Parsing the arguments of the script and options
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='From a regular class, generate the h5_read/h5_write, mpi, python interface for a parameter class')
|
||||||
|
|
||||||
|
parser.add_argument('filename', help = "Name of the file")
|
||||||
|
parser.add_argument('--libclang_location', help='Location of the libclang', default = '@TRIQS_LIBCLANG_LOCATION@')
|
||||||
|
parser.add_argument('--compiler_options', nargs ='*', help='Options to pass to clang')
|
||||||
|
parser.add_argument('--includes', '-I', action='append', help='Includes to pass to clang')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.includes = (args.includes or []) + '@TRIQS_INCLUDE_ALL@'.split(';')
|
||||||
|
|
||||||
|
triqs_install_location = '@CMAKE_INSTALL_PREFIX@'
|
||||||
|
args.includes.insert(0, triqs_install_location + '/include')
|
||||||
|
|
||||||
|
#------------
|
||||||
|
|
||||||
|
if __name__ == '__main__' :
|
||||||
|
|
||||||
|
compiler_options = args.compiler_options or []
|
||||||
|
|
||||||
|
compiler_options += ['-I%s'%x for x in args.includes]
|
||||||
|
add_opts = '@TRIQS_LIBCLANG_CXX_ADDITIONAL_FLAGS@'.strip()
|
||||||
|
if add_opts:
|
||||||
|
compiler_options += add_opts.split()
|
||||||
|
|
||||||
|
functions, classes = parse(args.filename, debug = False, compiler_options = compiler_options, where_is_libclang = args.libclang_location)
|
||||||
|
|
||||||
|
print "Generating ..."
|
||||||
|
|
||||||
|
tpl = Template(filename=triqs_install_location + '/share/triqs/wrap_generator/param.mako.cxx')
|
||||||
|
shell_command = ' '.join( [ sys.argv[0].rsplit('/')[-1]] + sys.argv[1:])
|
||||||
|
rendered = tpl.render(classes = classes, functions = functions, args = args, shell_command= shell_command )
|
||||||
|
|
||||||
|
with open(args.filename.replace('.hpp',".hxx"), "w") as f:
|
||||||
|
f.write(rendered)
|
||||||
|
|
||||||
|
print "... done"
|
||||||
|
|
@ -4,8 +4,9 @@
|
|||||||
return ''.join([x.capitalize() for x in s.split('_')])
|
return ''.join([x.capitalize() for x in s.split('_')])
|
||||||
|
|
||||||
def decay(s) :
|
def decay(s) :
|
||||||
for tok in ['const', '&&', '&'] :
|
for tok in ['const ', 'const&', '&&', '&'] :
|
||||||
s = re.sub(tok,'',s)
|
s = re.sub(tok,'',s)
|
||||||
|
s = s.replace('const_view', 'view') # DISCUSS THIS
|
||||||
return s.strip()
|
return s.strip()
|
||||||
|
|
||||||
# compute used_module_list
|
# compute used_module_list
|
||||||
@ -15,12 +16,19 @@
|
|||||||
'triqs::utility::many_body_operator' : 'operators2',
|
'triqs::utility::many_body_operator' : 'operators2',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using_needed_for_modules = {
|
||||||
|
'gf' : 'namespace triqs::gfs',
|
||||||
|
'parameters' : 'namespace triqs::params',
|
||||||
|
'operators2' : 'triqs::utility::many_body_operator',
|
||||||
|
}
|
||||||
|
|
||||||
used_module_list = []
|
used_module_list = []
|
||||||
def analyse(t) :
|
def analyse(t) :
|
||||||
|
if t is None :return
|
||||||
#global used_module_list
|
#global used_module_list
|
||||||
for ns, mod in recognized_namespace_for_using.items() :
|
for ns, mod in recognized_namespace_for_using.items() :
|
||||||
if decay(t.canonical_name).startswith(ns) :
|
if decay(t.canonical_name).startswith(ns) :
|
||||||
used_module_list.append(mod)
|
used_module_list.append(mod)
|
||||||
|
|
||||||
for c in classes :
|
for c in classes :
|
||||||
for m in c.constructors :
|
for m in c.constructors :
|
||||||
@ -31,16 +39,22 @@
|
|||||||
for p in c.proplist :
|
for p in c.proplist :
|
||||||
analyse(p.getter.rtype)
|
analyse(p.getter.rtype)
|
||||||
|
|
||||||
|
for c in classes_of_parameters :
|
||||||
|
for m in c.members :
|
||||||
|
analyse(m.type)
|
||||||
|
|
||||||
for f in functions :
|
for f in functions :
|
||||||
for t,n,d in f.params : analyse(t)
|
for t,n,d in f.params : analyse(t)
|
||||||
analyse(f.rtype)
|
analyse(f.rtype)
|
||||||
|
|
||||||
used_module_list = set(used_module_list) # makes unique
|
used_module_list = set(used_module_list) # makes unique
|
||||||
|
using_list = [using_needed_for_modules[m] for m in used_module_list]
|
||||||
|
|
||||||
def cls(t) :
|
def cls(t) :
|
||||||
tname = decay(t.name)
|
tname = decay(t.name)
|
||||||
if 'gf' in used_module_list: tname = re.sub('triqs::gfs::','',tname)
|
if 'gf' in used_module_list: tname = re.sub('triqs::gfs::','',tname)
|
||||||
if 'parameters' in used_module_list: tname = re.sub('triqs::params::','',tname)
|
if 'parameters' in used_module_list: tname = re.sub('triqs::params::','',tname)
|
||||||
|
tname = tname.replace(' ','')
|
||||||
return tname
|
return tname
|
||||||
|
|
||||||
def make_signature(m) :
|
def make_signature(m) :
|
||||||
@ -48,47 +62,74 @@
|
|||||||
s = "({args})"
|
s = "({args})"
|
||||||
if not m.is_constructor :
|
if not m.is_constructor :
|
||||||
s = cls(m.rtype) + " {name} " + s
|
s = cls(m.rtype) + " {name} " + s
|
||||||
s = s.format(args = ', '.join( ["%s %s"%(cls(t),n) + (" = %s"%d if d else "") for t,n,d in m.params]), **m.__dict__)
|
args = ', '.join( ["%s %s"%(cls(t),n) + (" = %s"%d if d else "") for t,n,d in m.params]) if m.parameter_arg == None else '**%s'%cls(m.params[0][0])
|
||||||
|
s = s.format(args = args, **m.__dict__)
|
||||||
return s.strip()
|
return s.strip()
|
||||||
%>
|
%>
|
||||||
##
|
# Generated automatically using the command :
|
||||||
##
|
|
||||||
# Generated automatically using libclang using the command :
|
|
||||||
# ${shell_command}
|
# ${shell_command}
|
||||||
from wrap_generator import *
|
from wrap_generator import *
|
||||||
|
|
||||||
# The module
|
# The module
|
||||||
module = module_(full_name = "${modulename}", doc = " ")
|
module = module_(full_name = "${modulename}", doc = "${moduledoc}")
|
||||||
|
|
||||||
# All the triqs C++/Python modules
|
# All the triqs C++/Python modules
|
||||||
%for mod in used_module_list :
|
%for mod in used_module_list :
|
||||||
module.use_module('${mod}')
|
module.use_module('${mod}')
|
||||||
%endfor
|
%endfor
|
||||||
|
##
|
||||||
|
## All the using
|
||||||
|
##%for ns in using_list :
|
||||||
|
##module.add_using('${ns}')
|
||||||
|
##%endfor
|
||||||
|
|
||||||
# Add here all includes beyond what is automatically included by the triqs modules
|
# Add here all includes beyond what is automatically included by the triqs modules
|
||||||
module.add_include("${args.filename}")
|
module.add_include("${args.filename}")
|
||||||
|
|
||||||
# Add here anything to add in the C++ code at the start, e.g. namespace using
|
# Add here anything to add in the C++ code at the start, e.g. namespace using
|
||||||
module.add_preamble("""
|
module.add_preamble("""
|
||||||
// using namespace XXX;
|
%for ns in using_list :
|
||||||
|
using ${ns};
|
||||||
|
%endfor
|
||||||
|
%for c in classes :
|
||||||
|
%for ns in c.ns :
|
||||||
|
using namespace ${ns};
|
||||||
|
%endfor
|
||||||
|
%endfor
|
||||||
|
%if classes_of_parameters :
|
||||||
|
#include "./converters.hxx"
|
||||||
|
%endif
|
||||||
""")
|
""")
|
||||||
|
|
||||||
##
|
##
|
||||||
%for c in classes :
|
%for c in classes :
|
||||||
|
<%
|
||||||
|
def doc_format(member_list) :
|
||||||
|
h= ['Parameter Name', 'Type', 'Default', 'Documentation']
|
||||||
|
n_lmax = max(len(h[0]), max(len(m.name) for m in member_list))
|
||||||
|
type_lmax = max(len(h[1]), max(len(m.ctype) for m in member_list))
|
||||||
|
opt_lmax = max(len(h[2]), max(len(m.initializer) for m in member_list if m.initializer))
|
||||||
|
doc_lmax = max(len(h[3]), max(len(m.doc) for m in member_list))
|
||||||
|
form = " {:<%s} {:<%s} {:<%s} {:<%s}"%(n_lmax, type_lmax, opt_lmax, doc_lmax)
|
||||||
|
header = form.format(*h)
|
||||||
|
r = '\n'.join( form.format(m.name, m.ctype, m.initializer if m.initializer else '--', m.doc) for m in member_list)
|
||||||
|
return header + '\n\n' + r
|
||||||
|
%>
|
||||||
# The class ${c.name}
|
# The class ${c.name}
|
||||||
g = class_(
|
c = class_(
|
||||||
py_type = "${deduce_normalized_python_class_name(c.name)}", # name of the python class
|
py_type = "${deduce_normalized_python_class_name(c.name)}", # name of the python class
|
||||||
c_type = "${c.name}", # name of the C++ class
|
c_type = "${c.name}", # name of the C++ class
|
||||||
|
%if 0 :
|
||||||
#
|
#
|
||||||
#Hereafter several options to be selected by hand. Cf doc
|
#Hereafter several options to be selected by hand. Cf doc
|
||||||
#has_iterator = True,
|
#has_iterator = True,
|
||||||
#boost_serializable= True,
|
#boost_serializable= True,
|
||||||
#is_printable= True,
|
#is_printable= True,
|
||||||
#arithmetic = ("algebra","double")
|
#arithmetic = ("algebra","double")
|
||||||
)
|
%endif
|
||||||
|
)
|
||||||
|
|
||||||
%for m in c.members :
|
%for m in c.members :
|
||||||
g.add_member(c_name = "${m.name}",
|
c.add_member(c_name = "${m.name}",
|
||||||
c_type = "${m.ctype}",
|
c_type = "${m.ctype}",
|
||||||
read_only= False,
|
read_only= False,
|
||||||
doc = """${m.doc} """)
|
doc = """${m.doc} """)
|
||||||
@ -96,23 +137,22 @@ g.add_member(c_name = "${m.name}",
|
|||||||
%endfor
|
%endfor
|
||||||
##
|
##
|
||||||
%for m in [m for m in c.constructors if not m.is_template]:
|
%for m in [m for m in c.constructors if not m.is_template]:
|
||||||
g.add_constructor("${make_signature(m)}",
|
c.add_constructor("""${make_signature(m)}""",
|
||||||
doc = """${m.doc} """)
|
doc = """${m.doc} """)
|
||||||
|
|
||||||
%endfor
|
%endfor
|
||||||
##
|
##
|
||||||
##
|
%for m in c.methods:
|
||||||
%for m in [m for m in c.methods]:
|
c.add_method("""${make_signature(m)}""",
|
||||||
g.add_method("${make_signature(m)}",
|
|
||||||
%if m.is_static :
|
%if m.is_static :
|
||||||
is_static = True,
|
is_static = True,
|
||||||
%endif
|
%endif
|
||||||
doc = """${m.doc} """)
|
doc = """${m.doc if m.parameter_arg==None else doc_format(m.parameter_arg.members) } """)
|
||||||
|
|
||||||
%endfor
|
%endfor
|
||||||
##
|
##
|
||||||
%for p in [p for p in c.proplist]:
|
%for p in [p for p in c.proplist]:
|
||||||
g.add_property(name = "${p.name}",
|
c.add_property(name = "${p.name}",
|
||||||
getter = cfunction("${make_signature(p.getter)}"),
|
getter = cfunction("${make_signature(p.getter)}"),
|
||||||
%if p.setter :
|
%if p.setter :
|
||||||
setter = cfunction("${make_signature(p.setter)}"),
|
setter = cfunction("${make_signature(p.setter)}"),
|
||||||
@ -121,7 +161,7 @@ g.add_property(name = "${p.name}",
|
|||||||
|
|
||||||
%endfor
|
%endfor
|
||||||
##
|
##
|
||||||
module.add_class(g)
|
module.add_class(c)
|
||||||
|
|
||||||
%endfor
|
%endfor
|
||||||
##
|
##
|
||||||
|
@ -79,6 +79,7 @@ class cfunction :
|
|||||||
self.doc = doc
|
self.doc = doc
|
||||||
self.is_method = is_method
|
self.is_method = is_method
|
||||||
self.is_static = is_static
|
self.is_static = is_static
|
||||||
|
self._dict_call = None
|
||||||
if is_static : assert is_method, "is_static only works with method"
|
if is_static : assert is_method, "is_static only works with method"
|
||||||
self.release_GIL_and_enable_signal = release_GIL_and_enable_signal
|
self.release_GIL_and_enable_signal = release_GIL_and_enable_signal
|
||||||
assert isinstance(signature, str) or isinstance(signature, dict), "Signature must be a string of a dict: cf doc"
|
assert isinstance(signature, str) or isinstance(signature, dict), "Signature must be a string of a dict: cf doc"
|
||||||
@ -95,7 +96,10 @@ class cfunction :
|
|||||||
if not is_constructor and len(spl)> 1 and '>' not in spl[-1] :
|
if not is_constructor and len(spl)> 1 and '>' not in spl[-1] :
|
||||||
self.rtype, self.c_name = spl
|
self.rtype, self.c_name = spl
|
||||||
if self.c_name == '__operator_call' : self.c_name = "operator()"
|
if self.c_name == '__operator_call' : self.c_name = "operator()"
|
||||||
|
if args.strip().startswith("**") : # special case : dict call
|
||||||
|
assert calling_pattern is None, "When ** is given as argument, no calling pattern can be provided"
|
||||||
|
self._dict_call = args[2:]
|
||||||
|
args, self.args = '','' # no argument
|
||||||
def f(): # analyse the argument, be careful that , can also be in type, like A<B,C>, so we count the < >
|
def f(): # analyse the argument, be careful that , can also be in type, like A<B,C>, so we count the < >
|
||||||
acc = ''
|
acc = ''
|
||||||
for s in args.split(',') :
|
for s in args.split(',') :
|
||||||
@ -103,7 +107,14 @@ class cfunction :
|
|||||||
if acc.count('<') == acc.count('>') :
|
if acc.count('<') == acc.count('>') :
|
||||||
r, acc = acc,''
|
r, acc = acc,''
|
||||||
yield r
|
yield r
|
||||||
args = [ re.sub('=',' ',x).split() for x in f() if x] # list of (type, name, default) or (type, name)
|
def g(a) :
|
||||||
|
if '=' in a :
|
||||||
|
l,r = a.split('=')
|
||||||
|
return l.strip().rsplit(' ') + [r]
|
||||||
|
else :
|
||||||
|
return a.rsplit(' ',1)
|
||||||
|
#args = [ re.sub('=',' ',x).split() for x in f() if x] # list of (type, name, default) or (type, name)
|
||||||
|
args = [ g(x) for x in f() if x] # list of (type, name, default) or (type, name)
|
||||||
else :
|
else :
|
||||||
self.rtype = signature.pop("rtype", None)
|
self.rtype = signature.pop("rtype", None)
|
||||||
args = signature.pop('args',())
|
args = signature.pop('args',())
|
||||||
@ -116,7 +127,7 @@ class cfunction :
|
|||||||
if len(a) == 2 : (t,n),d = a,None
|
if len(a) == 2 : (t,n),d = a,None
|
||||||
elif len(a) == 3 : t,n,d = a
|
elif len(a) == 3 : t,n,d = a
|
||||||
else : raise RuntimeError, "Syntax error in overload: args = %s"%args
|
else : raise RuntimeError, "Syntax error in overload: args = %s"%args
|
||||||
self.args.append([t,n,d])
|
self.args.append([t.strip(),n.strip(),d])
|
||||||
# end analyze signature
|
# end analyze signature
|
||||||
assert self.c_name or self._calling_pattern or self.is_constructor, "You must specify a calling_pattern or the signature must contain the name of the function"
|
assert self.c_name or self._calling_pattern or self.is_constructor, "You must specify a calling_pattern or the signature must contain the name of the function"
|
||||||
if self.is_constructor :
|
if self.is_constructor :
|
||||||
@ -126,12 +137,15 @@ class cfunction :
|
|||||||
def _get_calling_pattern(self) :
|
def _get_calling_pattern(self) :
|
||||||
"""Generation only: gets the calling_pattern or synthesize the default"""
|
"""Generation only: gets the calling_pattern or synthesize the default"""
|
||||||
if self._calling_pattern : return self._calling_pattern
|
if self._calling_pattern : return self._calling_pattern
|
||||||
s= "%s result = "%self.rtype if self.rtype != "void" else ""
|
s1 = '' if self._dict_call is None else "if (!convertible_from_python<%s>(keywds,true)) goto error_return;\n"%self._dict_call
|
||||||
|
s = "%s result = "%self.rtype if self.rtype != "void" else ""
|
||||||
self_c = ""
|
self_c = ""
|
||||||
if self.is_method:
|
if self.is_method:
|
||||||
self_c = "self_c." if not self.is_static else "self_class::"
|
self_c = "self_c." if not self.is_static else "self_class::"
|
||||||
# the wrapped types are called by pointer
|
# the wrapped types are called by pointer
|
||||||
return "%s %s%s(%s)"%(s,self_c, self.c_name , ",".join([ ('*' if t in module_._wrapped_types else '') + n for t,n,d in self.args]))
|
args = ",".join([ ('*' if t in module_._wrapped_types else '') + n for t,n,d in self.args])
|
||||||
|
args = args if self._dict_call is None else "convert_from_python<%s>(keywds)"%self._dict_call # call with the keywds argument
|
||||||
|
return "%s %s %s%s(%s)"%(s1, s,self_c, self.c_name , args)
|
||||||
|
|
||||||
def _get_signature (self):
|
def _get_signature (self):
|
||||||
"""Signature for the python doc"""
|
"""Signature for the python doc"""
|
||||||
@ -160,6 +174,9 @@ class cfunction :
|
|||||||
|
|
||||||
def _generate_doc(self) :
|
def _generate_doc(self) :
|
||||||
doc = "\n".join([ " " + x.strip() for x in self.doc.split('\n')])
|
doc = "\n".join([ " " + x.strip() for x in self.doc.split('\n')])
|
||||||
|
doc = doc.replace('"',"'") # the " are replaced by \"r.
|
||||||
|
#doc = doc.replace('"',r'\"') # the " are replaced by \"r. Does not work, makes \\"
|
||||||
|
if self._dict_call is not None : return doc
|
||||||
return "Signature : %s\n%s"%( self._get_signature(),doc)
|
return "Signature : %s\n%s"%( self._get_signature(),doc)
|
||||||
|
|
||||||
class pure_pyfunction_from_module :
|
class pure_pyfunction_from_module :
|
||||||
@ -234,7 +251,10 @@ class pyfunction :
|
|||||||
self.overloads.append(cfunction(**kw))
|
self.overloads.append(cfunction(**kw))
|
||||||
|
|
||||||
def _generate_doc(self) :
|
def _generate_doc(self) :
|
||||||
s = "\n".join([self.doc, "\n"] + [f._generate_doc() for f in self.overloads])
|
if len(self.overloads) == 1 : #only one overload
|
||||||
|
s = "\n".join([f._generate_doc() for f in self.overloads])
|
||||||
|
else :
|
||||||
|
s = "\n".join([self.doc, "\n"] + [f._generate_doc() for f in self.overloads])
|
||||||
return repr(s)[1:-1] # remove the ' ' made by repr
|
return repr(s)[1:-1] # remove the ' ' made by repr
|
||||||
|
|
||||||
def _is_type_a_view(c_type) :
|
def _is_type_a_view(c_type) :
|
||||||
@ -417,7 +437,7 @@ class class_ :
|
|||||||
all_args = ",".join([ ('*' if t in module_._wrapped_types else '') + n for t,n,d in f.args])
|
all_args = ",".join([ ('*' if t in module_._wrapped_types else '') + n for t,n,d in f.args])
|
||||||
f._calling_pattern = ''
|
f._calling_pattern = ''
|
||||||
if calling_pattern is not None :
|
if calling_pattern is not None :
|
||||||
f._calling_pattern, all_args = calling_pattern + '\n', "std::move(result)"
|
f._calling_pattern, all_args = calling_pattern + ';\n', "std::move(result)"
|
||||||
if self.c_type_is_view and build_from_regular_type_if_view :
|
if self.c_type_is_view and build_from_regular_type_if_view :
|
||||||
f._calling_pattern += "((%s *)self)->_c = new %s(%s (%s));"%(self.py_type, self.c_type,_regular_type_if_view_else_type(self.c_type),all_args)
|
f._calling_pattern += "((%s *)self)->_c = new %s(%s (%s));"%(self.py_type, self.c_type,_regular_type_if_view_else_type(self.c_type),all_args)
|
||||||
else :
|
else :
|
||||||
|
@ -555,6 +555,7 @@ template<typename T>
|
|||||||
// If no overload, we avoid the err_list and let the error go through (to save some code).
|
// If no overload, we avoid the err_list and let the error go through (to save some code).
|
||||||
%for n_overload, overload in enumerate(py_meth.overloads) :
|
%for n_overload, overload in enumerate(py_meth.overloads) :
|
||||||
{// overload ${overload._get_c_signature()}
|
{// overload ${overload._get_c_signature()}
|
||||||
|
%if not overload._dict_call :
|
||||||
// define the variable to be filled by the parsing method
|
// define the variable to be filled by the parsing method
|
||||||
// wrapped types are converted to a pointer, other converted types to a value or a view
|
// wrapped types are converted to a pointer, other converted types to a value or a view
|
||||||
%for t,n,d in overload.args :
|
%for t,n,d in overload.args :
|
||||||
@ -568,7 +569,9 @@ template<typename T>
|
|||||||
%endfor
|
%endfor
|
||||||
static char *kwlist[] = {${",".join([ '"%s"'%n for t,n,d in overload.args] + ["NULL"])}};
|
static char *kwlist[] = {${",".join([ '"%s"'%n for t,n,d in overload.args] + ["NULL"])}};
|
||||||
static const char * format = "${overload._parsing_format()}";
|
static const char * format = "${overload._parsing_format()}";
|
||||||
if (PyArg_ParseTupleAndKeywords(args, keywds, format, kwlist ${"".join([ module._get_proper_converter(t) + ' ,&%s'%n for t,n,d in overload.args])})) {
|
if (PyArg_ParseTupleAndKeywords(args, keywds, format, kwlist ${"".join([ module._get_proper_converter(t) + ' ,&%s'%n for t,n,d in overload.args])}))
|
||||||
|
%endif
|
||||||
|
{
|
||||||
%if overload.is_method and not overload.is_constructor and not overload.no_self_c and not overload.is_static :
|
%if overload.is_method and not overload.is_constructor and not overload.no_self_c and not overload.is_static :
|
||||||
auto & self_c = convert_from_python<${self_c_type}>(self);
|
auto & self_c = convert_from_python<${self_c_type}>(self);
|
||||||
%endif
|
%endif
|
||||||
|
@ -1,24 +1,37 @@
|
|||||||
#!@PYTHON_INTERPRETER@
|
#!@PYTHON_INTERPRETER@
|
||||||
|
|
||||||
from clang_parser import parse
|
from clang_parser import parse, decay
|
||||||
import sys, os
|
import sys, os
|
||||||
from mako.template import Template
|
from mako.template import Template
|
||||||
|
|
||||||
|
# the instruction that created this file
|
||||||
|
shell_command = ' '.join( [ sys.argv[0].rsplit('/')[-1]] + [x if ' ' not in x else '"%s"'%x for x in sys.argv[1:]])
|
||||||
|
|
||||||
|
#
|
||||||
|
print "Welcome to the wrapper desc file generator of TRIQS, based on libclang !"
|
||||||
|
|
||||||
|
# macro vim to replace the old param class ...
|
||||||
|
# :'<,'>s/\s*\.add_field("\(.\{-}\)",\s*\(.\{-}\)(\(.\{-}\)),\s*"\(.\{-}\)")/\/\/\/\4\r\2 \1 = \3;\r/g
|
||||||
|
|
||||||
# --- Parsing the arguments of the script and options
|
# --- Parsing the arguments of the script and options
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='C++/Python wrapper desc file generator from C++ header code')
|
parser = argparse.ArgumentParser(description="""
|
||||||
|
Generate the C++/Python wrapper desc file from C++ header code
|
||||||
|
""")
|
||||||
|
|
||||||
parser.add_argument('filename', help = "Name of the file")
|
parser.add_argument('filename', help = "Name of the file")
|
||||||
parser.add_argument('--modulename', help='Name of the Python module', default = '')
|
parser.add_argument('--outputname', '-o', help="Name of the xxx_desc.py file [default is same as the filename]", default = '')
|
||||||
parser.add_argument('--libclang_location', help='Location of the libclang', default = '@TRIQS_LIBCLANG_LOCATION@')
|
parser.add_argument('--modulename', '-m', help="Name of the Python module [default ='', it will take the name of file", default = '')
|
||||||
parser.add_argument('--compiler_options', nargs ='*', help='Options to pass to clang')
|
parser.add_argument('--moduledoc', help="Documentation of the module", default = '')
|
||||||
parser.add_argument('--includes', '-I', action='append', help='Includes to pass to clang')
|
|
||||||
parser.add_argument('--properties', '-p', action='store_true',
|
parser.add_argument('--properties', '-p', action='store_true',
|
||||||
help="""Transforms i) every method with no arguments into read-only property
|
help="""Transforms i) every method with no arguments into read-only property
|
||||||
ii) every method get_X into read-only property
|
ii) every method get_X into read-only property
|
||||||
iii) every couple of methods get_X, set_X into rw property
|
iii) every couple of methods get_X, set_X into rw property
|
||||||
""")
|
""")
|
||||||
|
parser.add_argument('--libclang_location', help='Location of the libclang', default = '@TRIQS_LIBCLANG_LOCATION@')
|
||||||
|
parser.add_argument('--compiler_options', nargs ='*', help='Options to pass to clang')
|
||||||
|
parser.add_argument('--includes', '-I', action='append', help='Includes to pass to clang')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
args.includes = (args.includes or []) + '@TRIQS_INCLUDE_ALL@'.split(';')
|
args.includes = (args.includes or []) + '@TRIQS_INCLUDE_ALL@'.split(';')
|
||||||
@ -29,6 +42,7 @@ args.includes.insert(0, triqs_install_location + '/include')
|
|||||||
#------------
|
#------------
|
||||||
|
|
||||||
modulename = args.modulename or os.path.split(args.filename)[1].split('.',1)[0]
|
modulename = args.modulename or os.path.split(args.filename)[1].split('.',1)[0]
|
||||||
|
output_name = args.outputname or os.path.split(args.filename)[1].split('.',1)[0]
|
||||||
|
|
||||||
class property_ :
|
class property_ :
|
||||||
def __init__ (self, **kw) :
|
def __init__ (self, **kw) :
|
||||||
@ -55,31 +69,50 @@ if __name__ == '__main__' :
|
|||||||
m_by_names =dict( (m.name,m) for m in cls.methods)
|
m_by_names =dict( (m.name,m) for m in cls.methods)
|
||||||
# Find all the couples get_X, set_X
|
# Find all the couples get_X, set_X
|
||||||
for m in cls.methods :
|
for m in cls.methods :
|
||||||
if m.is_template or m.name.startswith('operator') or m.name in ['begin','end'] :
|
if m.is_template or m.name.startswith('operator') or m.name in ['begin','end'] : # or m.rtype.name=="void" :
|
||||||
exclude.append(m)
|
exclude.append(m)
|
||||||
elif m.name.startswith('get_') :
|
elif len(m.params) == 0 and not m.is_static : # it is a property
|
||||||
X = m.name[4:]
|
X = m.name[4:] if m.name.startswith('get_') else m.name # remove the get_ if present
|
||||||
set_m = m_by_names.get('set_' + X, None)
|
set_m = m_by_names.get('set_' + X, None)
|
||||||
if set_m and set_m.rtype == "void" and len(set_m.params_decay) ==1 :
|
if set_m and set_m.rtype.name == "void" and len(set_m.params) ==1 :
|
||||||
if set_m.params_decay[0][0] == m.rtype :
|
if decay(set_m.params[0][0].name) == m.rtype.name :
|
||||||
cls.proplist.append(property_(name= X, doc = m.doc, getter = m, setter = set_m))
|
exclude.append(set_m)
|
||||||
exclude += [m,set_m]
|
|
||||||
else :
|
else :
|
||||||
print "Warning :"
|
print "Warning :"
|
||||||
print " in get_%s/set_%s" %(X,X)
|
print " in get_%s/set_%s" %(X,X)
|
||||||
print " The type taken from set_%s is not the return type of get_%s"%(X,X)
|
print " The type taken from set_%s is not the return type of get_%s"%(X,X)
|
||||||
print " I am not transforming to property"
|
print " Expected ",m.rtype.name
|
||||||
|
print " Got ", decay(set_m.params[0][0].name)
|
||||||
elif len(m.params) == 0 and not m.is_static : # it is a property not starting with get_, pure getter
|
print " I am not adding the setter to the property"
|
||||||
cls.proplist.append(property_(name= m.name, doc = m.doc, getter = m, setter = None))
|
set_m = None
|
||||||
|
cls.proplist.append(property_(name= X, doc = m.doc, getter = m, setter = set_m))
|
||||||
|
print "Property : ", m.name, set_m.name if set_m else ''
|
||||||
exclude.append(m)
|
exclude.append(m)
|
||||||
cls.methods = [m for m in cls.methods if m not in exclude]
|
cls.methods = [m for m in cls.methods if m not in exclude]
|
||||||
|
|
||||||
tpl = Template(filename=triqs_install_location + '/share/triqs/wrap_generator/wrap_desc.mako.py')
|
# all classes used as parameters needs to be converted from / to Python
|
||||||
rendered = tpl.render(classes = classes, functions = functions, modulename=modulename, args = args, shell_command= ' '.join(sys.argv) )
|
classes_of_parameters = [m.parameter_arg for m in sum((c.methods for c in classes),[]) if m.parameter_arg != None]
|
||||||
|
classes_of_parameters = dict(((c.name,c) for c in classes_of_parameters)).values() # make unique
|
||||||
|
if classes_of_parameters :
|
||||||
|
print "Generating the converters for parameters classes : " + ', '.join([c.name for c in classes_of_parameters])
|
||||||
|
# Generate the converter code for all the classes.
|
||||||
|
tpl = Template(filename=triqs_install_location + '/share/triqs/wrap_generator/converters.mako.hxx')
|
||||||
|
rendered = tpl.render(classes = classes_of_parameters, args = args, shell_command= shell_command )
|
||||||
|
|
||||||
with open("{modulename}_desc.py".format(modulename=modulename), "w") as f:
|
#with open(args.filename.replace('.hpp',".hxx"), "w") as f:
|
||||||
|
with open("converters.hxx", "w") as f:
|
||||||
|
f.write(rendered)
|
||||||
|
|
||||||
|
print "... done"
|
||||||
|
|
||||||
|
# Making the desc file
|
||||||
|
tpl = Template(filename=triqs_install_location + '/share/triqs/wrap_generator/wrap_desc.mako.py')
|
||||||
|
rendered = tpl.render(classes = classes, functions = functions, modulename=modulename, moduledoc=args.moduledoc, args = args,
|
||||||
|
shell_command= shell_command, classes_of_parameters = classes_of_parameters )
|
||||||
|
|
||||||
|
with open("{output_name}_desc.py".format(output_name=output_name), "w") as f:
|
||||||
f.write(rendered)
|
f.write(rendered)
|
||||||
|
|
||||||
print "... done"
|
print "... done"
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,4 +53,4 @@ namespace triqs { namespace gfs {
|
|||||||
int n_max, bool replace_by_fit = false) ;
|
int n_max, bool replace_by_fit = false) ;
|
||||||
|
|
||||||
void fit_tail(gf_view<imfreq, scalar_valued> gf, tail_view known_moments, int n_moments, int n_min, int n_max, bool replace_by_fit = false) ;
|
void fit_tail(gf_view<imfreq, scalar_valued> gf, tail_view known_moments, int n_moments, int n_min, int n_max, bool replace_by_fit = false) ;
|
||||||
}}} // namespace
|
}} // namespace
|
||||||
|
@ -516,6 +516,10 @@ template <typename... T> struct py_converter<triqs::gfs::gf_view<triqs::gfs::blo
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Treat the block_gf as view
|
||||||
|
template <typename... T> struct py_converter<triqs::gfs::gf<triqs::gfs::block_index, triqs::gfs::gf<T...>>> :
|
||||||
|
py_converter<triqs::gfs::gf_view<triqs::gfs::block_index, triqs::gfs::gf<T...>>> {};
|
||||||
|
|
||||||
// Converter for scalar_valued gf : reinterpreted as 1x1 matrix
|
// Converter for scalar_valued gf : reinterpreted as 1x1 matrix
|
||||||
template <typename Variable, typename Opt> struct py_converter<triqs::gfs::gf_view<Variable, triqs::gfs::scalar_valued, Opt>>{
|
template <typename Variable, typename Opt> struct py_converter<triqs::gfs::gf_view<Variable, triqs::gfs::scalar_valued, Opt>>{
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user