mirror of
https://github.com/triqs/dft_tools
synced 2024-10-31 19:23:45 +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)
|
||||
|
||||
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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# This module defines the function parse that
|
||||
# This module defines the function parse that
|
||||
# call libclang to parse a C++ file, and retrieve
|
||||
# from the clang AST the classes, functions, methods, members (including
|
||||
# template).
|
||||
@ -33,6 +33,10 @@ class member_(object):
|
||||
def namespace(self) :
|
||||
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):
|
||||
def __init__(self, cursor, is_constructor = False, ns=() ): #, template_list =()):
|
||||
loc = cursor.location.file.name
|
||||
@ -43,35 +47,33 @@ class Function(object):
|
||||
self.name = cursor.spelling
|
||||
self.annotations = get_annotations(cursor)
|
||||
self.access = cursor.access_specifier
|
||||
self.params = []
|
||||
self.params_decay = []
|
||||
self.params = [] # a list of tuple (type, name, default_value or None).
|
||||
self.template_list = [] #template_list
|
||||
self.is_constructor = is_constructor
|
||||
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():
|
||||
if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER :
|
||||
self.template_list.append(c.spelling)
|
||||
elif (c.kind == clang.cindex.CursorKind.PARM_DECL) :
|
||||
self.params.append ( (c.type.spelling, c.spelling))
|
||||
self.params_decay.append ( (decay(c.type.spelling), c.spelling))
|
||||
#else :
|
||||
default_value = None
|
||||
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 :
|
||||
# print " node in fun ", c.kind
|
||||
# self.rtype = cursor.result_type.get_canonical().spelling
|
||||
self.rtype = cursor.result_type.spelling if not is_constructor else None
|
||||
#print 'params for ', self.name, self.params_decay
|
||||
self.rtype = type_(cursor.result_type) if not is_constructor else None
|
||||
|
||||
def namespace(self) :
|
||||
return "::".join(self.ns)
|
||||
|
||||
def signature_cpp(self) :
|
||||
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 :
|
||||
s = "template<" + ', '.join(['typename ' + x for x in self.template_list]) + "> " + s
|
||||
if self.is_static : s = "static " + s
|
||||
|
@ -1,36 +1,83 @@
|
||||
<%
|
||||
import re
|
||||
def deduce_normalized_python_class_name(s) :
|
||||
return ''.join([x.capitalize() for x in s.split('_')])
|
||||
|
||||
def decay(s) :
|
||||
for tok in ['const', '&&', '&'] :
|
||||
s = re.sub(tok,'',s)
|
||||
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 = " ")
|
||||
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>")
|
||||
# All the triqs C++/Python modules
|
||||
%for mod in used_module_list :
|
||||
module.use_module('${mod}')
|
||||
%endfor
|
||||
|
||||
# Some include, using, etc... Cf doc.
|
||||
# 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;
|
||||
""")
|
||||
|
||||
<%
|
||||
def deduce_normalized_python_class_name(s) :
|
||||
return ''.join([x.capitalize() for x in s.split('_')])
|
||||
|
||||
def make_signature(m) :
|
||||
assert not m.template_list, "template functions can not be wrapped to Python"
|
||||
s = "{rtype} {name} ({args})" if not m.is_constructor else "({args})"
|
||||
s = s.format(args = ', '.join( ["%s %s"%t_n for t_n in m.params_decay]), **m.__dict__)
|
||||
return s.strip()
|
||||
|
||||
%>
|
||||
|
||||
%for c in classes :
|
||||
##
|
||||
##
|
||||
%for c in classes :
|
||||
# The class ${c.name}
|
||||
g = class_(
|
||||
py_type = "${deduce_normalized_python_class_name(c.name)}", # name of the python class
|
||||
c_type = "${c.name}", # name of the C++ class
|
||||
#
|
||||
# Hereafter several options to be selected by hand. Cf doc
|
||||
#Hereafter several options to be selected by hand. Cf doc
|
||||
#has_iterator = True,
|
||||
#boost_serializable= True,
|
||||
#is_printable= True,
|
||||
|
@ -37,10 +37,11 @@ class property_ :
|
||||
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.append(add_opts)
|
||||
|
||||
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