mirror of
https://github.com/triqs/dft_tools
synced 2024-11-01 03:33:50 +01:00
desc wrapper generator: small improve, clean
- detect the use module. - clean the code specific to wrapper generation from clang_parser. - add support for default arguments for int, double, char. - TODO : add more complex default arguments
This commit is contained in:
parent
03dbf576ae
commit
6fb71f50c9
@ -381,6 +381,7 @@ set(TRIQS_INCLUDE_ALL ${TRIQS_INCLUDE} ${TRIQS_INCLUDE_BOOST} ${TRIQS_INCLUDE_PY
|
|||||||
list (REMOVE_DUPLICATES TRIQS_INCLUDE_ALL)
|
list (REMOVE_DUPLICATES TRIQS_INCLUDE_ALL)
|
||||||
|
|
||||||
set(TRIQS_LIBCLANG_LOCATION "/usr/lib/libclang.dylib" CACHE STRING "Location of the libclang library")
|
set(TRIQS_LIBCLANG_LOCATION "/usr/lib/libclang.dylib" CACHE STRING "Location of the libclang library")
|
||||||
|
set(TRIQS_LIBCLANG_CXX_ADDITIONAL_FLAGS "" CACHE STRING "Additional flags to be passed to libclang when parsing with clang")
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
# pytriqs modules : MUST be before TRIQS, to have the py_converters
|
# pytriqs modules : MUST be before TRIQS, to have the py_converters
|
||||||
|
@ -33,6 +33,10 @@ class member_(object):
|
|||||||
def namespace(self) :
|
def namespace(self) :
|
||||||
return "::".join(self.ns)
|
return "::".join(self.ns)
|
||||||
|
|
||||||
|
class type_(object):
|
||||||
|
def __init__(self, cursor):
|
||||||
|
self.name, self.canonical_name = cursor.spelling, cursor.get_canonical().spelling
|
||||||
|
|
||||||
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
|
||||||
@ -43,35 +47,33 @@ class Function(object):
|
|||||||
self.name = cursor.spelling
|
self.name = cursor.spelling
|
||||||
self.annotations = get_annotations(cursor)
|
self.annotations = get_annotations(cursor)
|
||||||
self.access = cursor.access_specifier
|
self.access = cursor.access_specifier
|
||||||
self.params = []
|
self.params = [] # a list of tuple (type, name, default_value or None).
|
||||||
self.params_decay = []
|
|
||||||
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()
|
||||||
|
|
||||||
def decay(s) :
|
|
||||||
s = re.sub('const','',s)
|
|
||||||
s = re.sub('&&','',s)
|
|
||||||
s = re.sub('&','',s)
|
|
||||||
return s.strip()
|
|
||||||
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)
|
||||||
elif (c.kind == clang.cindex.CursorKind.PARM_DECL) :
|
elif (c.kind == clang.cindex.CursorKind.PARM_DECL) :
|
||||||
self.params.append ( (c.type.spelling, c.spelling))
|
default_value = None
|
||||||
self.params_decay.append ( (decay(c.type.spelling), c.spelling))
|
for ch in c.get_children() :
|
||||||
|
# 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,
|
||||||
|
clang.cindex.CursorKind.CHARACTER_LITERAL, clang.cindex.CursorKind.STRING_LITERAL] :
|
||||||
|
default_value = ch.get_tokens().next().spelling
|
||||||
|
t = type_(c.type)
|
||||||
|
self.params.append ( (t, c.spelling, default_value ))
|
||||||
#else :
|
#else :
|
||||||
# print " node in fun ", c.kind
|
# print " node in fun ", c.kind
|
||||||
# self.rtype = cursor.result_type.get_canonical().spelling
|
self.rtype = type_(cursor.result_type) if not is_constructor else None
|
||||||
self.rtype = cursor.result_type.spelling if not is_constructor else None
|
|
||||||
#print 'params for ', self.name, self.params_decay
|
|
||||||
|
|
||||||
def namespace(self) :
|
def namespace(self) :
|
||||||
return "::".join(self.ns)
|
return "::".join(self.ns)
|
||||||
|
|
||||||
def signature_cpp(self) :
|
def signature_cpp(self) :
|
||||||
s = "{name} ({args})" if not self.is_constructor else "{rtype} {name} ({args})"
|
s = "{name} ({args})" if not self.is_constructor else "{rtype} {name} ({args})"
|
||||||
s = s.format(args = ', '.join( ["%s %s"%t_n for t_n in self.params]), **self.__dict__)
|
s = s.format(args = ', '.join( ["%s %s"%(t.name,n) + "="%d if d else "" for t,n,d in self.params]), **self.__dict__)
|
||||||
if self.template_list :
|
if self.template_list :
|
||||||
s = "template<" + ', '.join(['typename ' + x for x in self.template_list]) + "> " + s
|
s = "template<" + ', '.join(['typename ' + x for x in self.template_list]) + "> " + s
|
||||||
if self.is_static : s = "static " + s
|
if self.is_static : s = "static " + s
|
||||||
|
@ -1,31 +1,78 @@
|
|||||||
from wrap_generator import *
|
|
||||||
|
|
||||||
# The module
|
|
||||||
module = module_(full_name = "${modulename}",
|
|
||||||
doc = " ")
|
|
||||||
|
|
||||||
#
|
|
||||||
# Need to add here the necessary include for compilation
|
|
||||||
#module.add_include("<iostream>")
|
|
||||||
#module.add_include("<triqs/xxxxx.hpp>")
|
|
||||||
|
|
||||||
# Some include, using, etc... Cf doc.
|
|
||||||
module.add_preamble("""
|
|
||||||
""")
|
|
||||||
|
|
||||||
<%
|
<%
|
||||||
|
import re
|
||||||
def deduce_normalized_python_class_name(s) :
|
def deduce_normalized_python_class_name(s) :
|
||||||
return ''.join([x.capitalize() for x in s.split('_')])
|
return ''.join([x.capitalize() for x in s.split('_')])
|
||||||
|
|
||||||
def make_signature(m) :
|
def decay(s) :
|
||||||
assert not m.template_list, "template functions can not be wrapped to Python"
|
for tok in ['const', '&&', '&'] :
|
||||||
s = "{rtype} {name} ({args})" if not m.is_constructor else "({args})"
|
s = re.sub(tok,'',s)
|
||||||
s = s.format(args = ', '.join( ["%s %s"%t_n for t_n in m.params_decay]), **m.__dict__)
|
|
||||||
return s.strip()
|
return s.strip()
|
||||||
|
|
||||||
%>
|
# compute used_module_list
|
||||||
|
recognized_namespace_for_using = {
|
||||||
|
'triqs::gfs::' : 'gf',
|
||||||
|
'triqs::params::' : 'parameters',
|
||||||
|
'triqs::utility::many_body_operator' : 'operators2',
|
||||||
|
}
|
||||||
|
|
||||||
|
used_module_list = []
|
||||||
|
def analyse(t) :
|
||||||
|
#global used_module_list
|
||||||
|
for ns, mod in recognized_namespace_for_using.items() :
|
||||||
|
if decay(t.canonical_name).startswith(ns) :
|
||||||
|
used_module_list.append(mod)
|
||||||
|
|
||||||
|
for c in classes :
|
||||||
|
for m in c.constructors :
|
||||||
|
for t,n,d in m.params : analyse(t)
|
||||||
|
for m in c.methods :
|
||||||
|
for t,n,d in m.params : analyse(t)
|
||||||
|
analyse(m.rtype)
|
||||||
|
|
||||||
|
for f in functions :
|
||||||
|
for t,n,d in f.params : analyse(t)
|
||||||
|
analyse(f.rtype)
|
||||||
|
|
||||||
|
used_module_list = set(used_module_list) # makes unique
|
||||||
|
|
||||||
|
def cls(t) :
|
||||||
|
tname = decay(t.name)
|
||||||
|
if 'gf' in used_module_list: tname = re.sub('triqs::gfs::','',tname)
|
||||||
|
if 'parameters' in used_module_list: tname = re.sub('triqs::params::','',tname)
|
||||||
|
return tname
|
||||||
|
|
||||||
|
def make_signature(m) :
|
||||||
|
assert not m.template_list, "template functions can not be wrapped to Python"
|
||||||
|
s = "({args})"
|
||||||
|
if not m.is_constructor :
|
||||||
|
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__)
|
||||||
|
return s.strip()
|
||||||
|
%>
|
||||||
|
##
|
||||||
|
##
|
||||||
|
# Generated automatically using libclang
|
||||||
|
from wrap_generator import *
|
||||||
|
|
||||||
|
# The module
|
||||||
|
module = module_(full_name = "${modulename}", doc = " ")
|
||||||
|
|
||||||
|
# All the triqs C++/Python modules
|
||||||
|
%for mod in used_module_list :
|
||||||
|
module.use_module('${mod}')
|
||||||
|
%endfor
|
||||||
|
|
||||||
|
# Add here all includes beyond what is automatically included by the triqs modules
|
||||||
|
module.add_include("${args.filename}")
|
||||||
|
|
||||||
|
# Add here anything to add in the C++ code at the start, e.g. namespace using
|
||||||
|
module.add_preamble("""
|
||||||
|
// using namespace XXX;
|
||||||
|
""")
|
||||||
|
##
|
||||||
|
##
|
||||||
%for c in classes :
|
%for c in classes :
|
||||||
|
# The class ${c.name}
|
||||||
g = class_(
|
g = 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
|
||||||
|
@ -38,9 +38,10 @@ if __name__ == '__main__' :
|
|||||||
|
|
||||||
compiler_options = args.compiler_options or []
|
compiler_options = args.compiler_options or []
|
||||||
|
|
||||||
|
|
||||||
compiler_options += ['-I%s'%x for x in args.includes]
|
compiler_options += ['-I%s'%x for x in args.includes]
|
||||||
|
add_opts = '@TRIQS_LIBCLANG_CXX_ADDITIONAL_FLAGS@'.strip()
|
||||||
|
if add_opts:
|
||||||
|
compiler_options.append(add_opts)
|
||||||
|
|
||||||
functions, classes = parse(args.filename, debug = False, compiler_options = compiler_options, where_is_libclang = args.libclang_location)
|
functions, classes = parse(args.filename, debug = False, compiler_options = compiler_options, where_is_libclang = args.libclang_location)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user