Package pyplusplus :: Package code_creators :: Module calldef_transformed |

# Source Code for Module pyplusplus.code_creators.calldef_transformed

      1  # Copyright 2004-2008 Roman Yakovenko
      2  # Distributed under the Boost Software License, Version 1.0. (See
      3  # accompanying file LICENSE_1_0.txt or copy at
      4  # http://www.boost.org/LICENSE_1_0.txt)
      5
      6  import os
      7  import algorithm
      8  import code_creator
      9  import calldef_utils
     10  import class_declaration
     11  from pygccxml import declarations
     12  from pyplusplus import code_repository
     13  from calldef import calldef_t, calldef_wrapper_t
     14  import pyplusplus.function_transformers as function_transformers
     15
     16  #TODO: constructors also can have transformation defined. We should use make _init
     17  # function for this purpose
     18
     19 -def remove_duplicate_linesep( code ):
     20      lines = code.split( os.linesep )
     21      lines = filter( lambda line: line.strip(), lines )
     22      return os.linesep.join( lines )
     23
     24 -class sealed_fun_transformed_t( calldef_t ):
     25 -    def __init__( self, function, wrapper=None ):
     26          calldef_t.__init__( self, function=function, wrapper=wrapper )
     27
     28      @property
     29 -    def ft( self ): #function transformation
     30          return self.declaration.transformations[0]
     31
     32      @property
     33 -    def controller( self ):
     34          return self.ft.controller
     35
     36 -    def _get_alias_impl( self ):
     37          return self.wrapper.ft.alias
     38
     39 -    def create_function_type_alias_code( self, exported_class_alias=None  ):
     40          ftype = self.wrapper.function_type()
     41          return 'typedef %s;' % ftype.create_typedef( self.function_type_alias, exported_class_alias )
     42
     43 -    def create_function_ref_code(self, use_function_alias=False):
     44          full_name = self.wrapper.full_name()
     45
     46          if use_function_alias:
     47              return '%s( &%s )' \
     48                     % ( self.function_type_alias, full_name )
     49          elif self.declaration.create_with_signature:
     50              func_type = self.wrapper.function_type()
     51              return '(%s)( &%s )' % ( func_type, full_name )
     52          else:
     53              return '&%s' % full_name
     54
     55 -    def create_call_policies( self ):
     56          return ''
     57
     58 -class sealed_fun_transformed_wrapper_t( calldef_wrapper_t ):
     59 -    def __init__( self, function ):
     60          calldef_wrapper_t.__init__( self, function=function )
     61
     62      @property
     63 -    def ft( self ): #function transformation
     64          return self.declaration.transformations[0]
     65
     66      @property
     67 -    def controller( self ):
     68          return self.ft.controller
     69
     70 -    def resolve_function_ref( self ):
     71          raise NotImplementedError()
     72
     73 -    def create_fun_definition(self):
     74          cntrl = self.controller
     75
     76          make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' )
     77          make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' )
     78
     79          tmpl_values = dict()
     80
     81          tmpl_values['unique_function_name'] = self.wrapper_name()
     82          tmpl_values['return_type'] = self.controller.wrapper_return_type.decl_string
     83          tmpl_values['arg_declarations'] = self.args_declaration()
     84
     85          tmpl_values['declare_variables'] \
     86              = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() )
     87                                                   , cntrl.variables ) )
     88
     89          tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) )
     90
     91          tmpl_values['save_result'] = ''
     92          if not declarations.is_void( self.declaration.return_type ):
     93              tmpl_values['save_result'] \
     94                  = '%(type)s %(name)s = ' \
     95                    % { 'type': cntrl.result_variable.type.decl_string
     96                        , 'name' : cntrl.result_variable.name }
     97
     98          tmpl_values['function_name'] = self.resolve_function_ref()
     99          tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions )
    100          return_stmt_creator = calldef_utils.return_stmt_creator_t( self
    101                                      , self.controller
    102                                      , self.controller.result_variable
    103                                      , self.controller.return_variables )
    104
    105          tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) )
    106          if return_stmt_creator.pre_return_code:
    107              tmpl_values['post_call'] \
    108                  = os.linesep.join([ tmpl_values['post_call']
    109                                      , self.indent( return_stmt_creator.pre_return_code )])
    110          tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement )
    111
    112          f_def = self.controller.template.substitute(tmpl_values)
    113          return remove_duplicate_linesep( f_def )
    114
    115 -    def _create_impl(self):
    116          return self.create_fun_definition()
    117
    118 -class free_fun_transformed_t( sealed_fun_transformed_t ):
    119      """Creates code for public non-virtual member functions.
    120      """
    121
    122 -    def __init__( self, function, wrapper=None ):
    123          sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper )
    124          self.works_on_instance = False
    125
    126 -    def create_def_code( self ):
    127          return self.def_identifier()
    128
    129 -    def create_keywords_args(self):
    130          arg_utils = calldef_utils.argument_utils_t( self.declaration
    131                                                     , algorithm.make_id_creator( self )
    132                                                     , self.controller.wrapper_args )
    133          return arg_utils.keywords_args()
    134
    135
    136 -class free_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ):
    137 -    def __init__( self, function ):
    138          """Constructor.
    139
    140          @param function: Function declaration
    141          @type function: calldef_t
    142          """
    143          sealed_fun_transformed_wrapper_t .__init__( self, function=function )
    144
    145 -    def function_type(self):
    146          return declarations.free_function_type_t(
    147                    return_type=self.controller.wrapper_return_type
    148                  , arguments_types=[ arg.type for arg in self.controller.wrapper_args ] )
    149
    150 -    def wrapper_name( self ):
    151          return self.ft.unique_name
    152
    153 -    def full_name(self):
    154          return self.ft.unique_name
    155
    156 -    def args_declaration( self ):
    157          arg_utils = calldef_utils.argument_utils_t(
    158                            self.declaration
    159                          , algorithm.make_id_creator( self )
    160                          , self.controller.wrapper_args )
    161          return arg_utils.args_declaration()
    162
    163 -    def create_declaration(self, name):
    164          template = 'static %(return_type)s %(name)s( %(args)s )'
    165
    166          return template % {
    167              'return_type' : self.controller.wrapper_return_type.decl_string
    168              , 'name' : self.wrapper_name()
    169              , 'args' : self.args_declaration()
    170          }
    171
    172 -    def resolve_function_ref( self ):
    173          return declarations.full_name( self.declaration )
    174
    175
    176 -class mem_fun_transformed_t( sealed_fun_transformed_t ):
    177      """Creates code for public non-virtual member functions.
    178      """
    179 -    def __init__( self, function, wrapper=None ):
    180          sealed_fun_transformed_t.__init__( self, function=function, wrapper=wrapper )
    181
    182 -    def create_keywords_args(self):
    183          args = self.controller.wrapper_args[:]
    184          if self.controller.inst_arg:
    185              args.insert( 0, self.controller.inst_arg )
    186
    187          arg_utils = calldef_utils.argument_utils_t( self.declaration
    188                                                     , algorithm.make_id_creator( self )
    189                                                     , args )
    190          return arg_utils.keywords_args()
    191
    192 -class mem_fun_transformed_wrapper_t( sealed_fun_transformed_wrapper_t ):
    193 -    def __init__( self, function ):
    194          """Constructor.
    195
    196          @param function: Function declaration
    197          @type function: calldef_t
    198          """
    199          sealed_fun_transformed_wrapper_t.__init__( self, function=function )
    200
    201 -    def __is_global( self ):
    202          return not isinstance( self.parent, class_declaration.class_wrapper_t )
    203
    204 -    def function_type(self):
    205          args = map( lambda arg: arg.type, self.controller.wrapper_args )
    206          if self.controller.inst_arg:
    207              args.insert( 0, self.controller.inst_arg.type )
    208          return declarations.free_function_type_t(
    209                    return_type=self.controller.wrapper_return_type
    210                  , arguments_types=args )
    211
    212 -    def wrapper_name( self ):
    213          if self.__is_global():
    214              return self.ft.unique_name
    215          else:
    216              if self.declaration.overloads:
    217                  #it is possible that other functions will have same signature
    218                  return self.ft.unique_name
    219              else:
    220                  return self.declaration.name
    221
    222 -    def full_name(self):
    223          if self.__is_global():
    224              return self.ft.unique_name
    225          else:
    226              return self.parent.full_name + '::' + self.wrapper_name()
    227
    228 -    def args_declaration( self ):
    229          args = self.controller.wrapper_args[:]
    230          if self.controller.inst_arg:
    231              args.insert( 0, self.controller.inst_arg )
    232          arg_utils = calldef_utils.argument_utils_t(
    233                            self.declaration
    234                          , algorithm.make_id_creator( self )
    235                          , args )
    236          return arg_utils.args_declaration()
    237
    238 -    def resolve_function_ref( self ):
    239          if self.controller.inst_arg:
    240              return self.controller.inst_arg.name + '.' + self.declaration.name
    241          else:
    242              return declarations.full_name( self.declaration )
    243
    244 -class mem_fun_v_transformed_t( calldef_t ):
    245 -    def __init__( self, function, wrapper=None ):
    246          calldef_t.__init__( self, function=function, wrapper=wrapper )
    247
    248      @property
    249 -    def ft( self ): #function transformation
    250          return self.declaration.transformations[0]
    251
    252      @property
    253 -    def controller( self ):
    254          return self.ft.controller
    255
    256      @property
    257 -    def function_type_alias( self ):
    258          return 'default_' + self.alias + '_function_type'
    259
    260 -    def _get_alias_impl( self ):
    261          return self.wrapper.ft.alias
    262
    263 -    def create_function_type_alias_code( self, exported_class_alias=None ):
    264          ftype = self.wrapper.default_function_type()
    265          return 'typedef %s;' % ftype.create_typedef( self.function_type_alias )
    266
    267 -    def create_keywords_args(self):
    268          cntrl = self.controller.default_controller
    269          arg_utils = calldef_utils.argument_utils_t( self.declaration
    270                                                     , algorithm.make_id_creator( self )
    271                                                     , [cntrl.inst_arg] + cntrl.wrapper_args )
    272          return arg_utils.keywords_args()
    273
    274 -    def create_function_ref_code(self, use_function_alias=False):
    275          full_name = self.wrapper.default_full_name()
    276          if use_function_alias:
    277              return '%s( &%s )' % ( self.function_type_alias, full_name )
    278          elif self.declaration.create_with_signature:
    279              func_type = self.wrapper.default_function_type()
    280              return '(%s)( &%s )' % ( func_type, full_name )
    281          else:
    282              return '&%s' % full_name
    283
    284 -class mem_fun_v_transformed_wrapper_t( calldef_wrapper_t ):
    285 -    def __init__( self, function ):
    286          calldef_wrapper_t.__init__( self, function=function )
    287
    288      @property
    289 -    def ft( self ): #function transformation
    290          return self.declaration.transformations[0]
    291
    292      @property
    293 -    def controller( self ):
    294          return self.ft.controller
    295
    296 -    def default_name(self):
    297          if self.declaration.overloads:
    298              #it is possible that other functions will have same signature
    299              return 'default_' + self.ft.unique_name
    300          else:
    301              return 'default_' + self.declaration.alias
    302
    303 -    def default_full_name(self):
    304          return self.parent.full_name + '::' + self.default_name()
    305
    306 -    def args_override_declaration( self ):
    307          return self.args_declaration()
    308
    309 -    def args_default_declaration( self ):
    310          cntrl = self.controller.default_controller
    311          arg_utils = calldef_utils.argument_utils_t( self.declaration
    312                                                      , algorithm.make_id_creator( self )
    313                                                      , [cntrl.inst_arg] + cntrl.wrapper_args )
    314          return arg_utils.args_declaration()
    315
    316 -    def default_function_type(self):
    317          cntrl = self.controller.default_controller
    318          args = [cntrl.inst_arg.type] + map( lambda arg: arg.type, cntrl.wrapper_args )
    319          return declarations.free_function_type_t( return_type=cntrl.wrapper_return_type
    320                                                    , arguments_types=args )
    321
    322 -    def create_default(self):
    323          cntrl = self.controller.default_controller
    324
    325          make_object = algorithm.create_identifier( self, 'pyplusplus::call_policies::make_object' )
    326          make_tuple = algorithm.create_identifier( self, 'boost::python::make_tuple' )
    327
    328          tmpl_values = dict()
    329
    330          tmpl_values['unique_function_name'] = self.default_name()
    331          tmpl_values['return_type'] = cntrl.wrapper_return_type.decl_string
    332          tmpl_values['arg_declarations'] = self.args_default_declaration()
    333          tmpl_values['wrapper_class'] = self.parent.wrapper_alias
    334          tmpl_values['wrapped_class'] = declarations.full_name( self.declaration.parent )
    335          tmpl_values['wrapped_inst'] = cntrl.inst_arg.name
    336          tmpl_values['wrapped_inst_constness'] = ''
    337          if declarations.is_const( declarations.remove_reference( cntrl.inst_arg.type ) ):
    338              tmpl_values['wrapped_inst_constness'] = 'const'
    339
    340          decl_vars = cntrl.variables[:]
    341          if not declarations.is_void( self.declaration.return_type ):
    342              decl_vars.append( cntrl.result_variable )
    343          tmpl_values['declare_variables'] \
    344              = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() )
    345                                                   , decl_vars ) )
    346
    347          tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) )
    348
    349          tmpl_values['save_result'] = ''
    350          if not declarations.is_void( self.declaration.return_type ):
    351              tmpl_values['save_result'] = '%s = ' % cntrl.result_variable.name
    352
    353          tmpl_values['function_name'] = self.declaration.name
    354          tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions )
    355          return_stmt_creator = calldef_utils.return_stmt_creator_t( self
    356                                      , cntrl
    357                                      , cntrl.result_variable
    358                                      , cntrl.return_variables )
    359
    360          tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) )
    361          if return_stmt_creator.pre_return_code:
    362              tmpl_values['post_call'] \
    363                  = os.linesep.join([ tmpl_values['post_call']
    364                                      , self.indent( return_stmt_creator.pre_return_code )])
    365          tmpl_values['return'] = os.linesep + self.indent( return_stmt_creator.statement )
    366
    367          f_def = cntrl.template.substitute(tmpl_values)
    368          return remove_duplicate_linesep( f_def )
    369
    370 -    def wrapped_class_identifier( self ):
    371          return algorithm.create_identifier( self, declarations.full_name( self.declaration.parent ) )
    372
    373 -    def create_override(self):
    374          cntrl = self.controller.override_controller
    375
    376          tmpl_values = dict()
    377          tmpl_values['return_type' ] = self.declaration.return_type.decl_string
    378          tmpl_values['function_name'] = self.declaration.name
    379          tmpl_values['arg_declarations'] = self.args_override_declaration()
    380          tmpl_values['constness'] = ''
    381          if self.declaration.has_const:
    382              tmpl_values['constness'] = ' const '
    383          tmpl_values['throw'] = self.throw_specifier_code()
    384          tmpl_values['py_function_var'] = cntrl.py_function_var
    385          tmpl_values['function_alias'] = self.declaration.alias
    386          tmpl_values['declare_py_variables'] \
    387              = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string(), 2 )
    388                                                   , cntrl.py_variables ) )
    389
    390          tmpl_values['py_pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_pre_call ), 2 )
    391          tmpl_values['py_post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.py_post_call ), 2 )
    392          tmpl_values['py_arg_expressions'] = ''
    393          if cntrl.py_arg_expressions:
    394              tmpl_values['py_arg_expressions'] \
    395                  = ', ' + self.PARAM_SEPARATOR.join( cntrl.py_arg_expressions )
    396
    397          tmpl_values['save_py_result'] = "bpl::object %s = " % cntrl.py_result_variable.name
    398          tmpl_values['py_return'] = ''
    399          tmpl_values['cpp_return'] = ''
    400          if not declarations.is_void( self.declaration.return_type ):
    401              tmpl_values['py_return'] \
    402                  = 'return bpl::extract< %(type)s >( pyplus_conv::get_out_argument( %(py_result)s, 0 ) );' \
    403                    % { 'type' : self.declaration.return_type.decl_string
    404                      , 'py_result' : cntrl.py_result_variable.name }
    405              tmpl_values['cpp_return'] = 'return '
    406
    407          tmpl_values['wrapped_class'] = self.wrapped_class_identifier()
    408
    409          arg_utils = calldef_utils.argument_utils_t( self.declaration
    410                                                     , algorithm.make_id_creator( self )
    411                                                     , self.declaration.arguments )
    412          tmpl_values['cpp_arg_expressions'] = arg_utils.call_args()
    413
    414          f_def_code = cntrl.template.substitute(tmpl_values)
    415          return remove_duplicate_linesep( f_def_code )
    416
    417 -    def _create_impl(self):
    418          return os.linesep.join([ self.create_override(), '', self.create_default() ])
    419
    420 -    def _get_system_headers_impl( self ):
    421          files = super( mem_fun_v_transformed_wrapper_t, self )._get_system_headers_impl()
    422          files.append( code_repository.convenience.file_name )
    423          return files
    424
    425
    426 -class constructor_transformed_t( calldef_t ):
    427 -    def __init__( self, constructor, wrapper=None ):
    428          calldef_t.__init__( self, function=constructor, wrapper=wrapper )
    429
    430      @property
    431 -    def ft( self ): #function transformation
    432          return self.declaration.transformations[0]
    433
    434      @property
    435 -    def controller( self ):
    436          return self.ft.controller
    437
    438 -    def create_call_policies( self ):
    439          return ''
    440
    441 -    def _create_impl( self ):
    442          make_constructor = algorithm.create_identifier( self, 'boost::python::make_constructor' )
    443
    444          code = 'def( "__init__, %s( &::%s ) )' % self.wrapper.wrapper_name()
    445          if not self.works_on_instance:
    446              code = self.parent.class_var_name + '.' + code + ';'
    447          return code
    448
    449  #TODO: FT for constructor
    450  #~ class constructor_transformed_wrapper_t( calldef_wrapper_t ):
    451      #~ def __init__( self, constructor ):
    452          #~ calldef_wrapper_t.__init__( self, function=constructor )
    453
    454      #~ @property
    455      #~ def ft( self ): #function transformation
    456          #~ return self.declaration.transformations[0]
    457
    458      #~ @property
    459      #~ def controller( self ):
    460          #~ return self.ft.controller
    461
    462      #~ def resolve_function_ref( self ):
    463          #~ raise NotImplementedError()
    464
    465      #~ def wrapper_name( self ):
    466          #~ return self.ft.unique_name()
    467
    468      #~ def create_fun_definition(self):
    469          #~ cntrl = self.controller
    470
    471          #~ tmpl_values = dict()
    472
    473          #~ tmpl_values['unique_function_name'] = self.wrapper_name()
    474          #~ tmpl_values['exposed_class'] = self.decl_identifier
    475          #~ tmpl_values['arg_declarations'] = self.args_declaration()
    476          #~ tmpl_values['result'] = self.ft.result_variable
    477
    478          #~ tmpl_values['declare_variables'] \
    479              #~ = os.linesep + os.linesep.join( map( lambda var: self.indent( var.declare_var_string() )
    480                                                   #~ , cntrl.variables ) )
    481
    482          #~ tmpl_values['pre_call'] = os.linesep + self.indent( os.linesep.join( cntrl.pre_call ) )
    483
    484          #~ tmpl_values['arg_expressions'] = self.PARAM_SEPARATOR.join( cntrl.arg_expressions )
    485          #~ return_stmt_creator = calldef_utils.return_stmt_creator_t( self
    486                                      #~ , self.controller
    487                                      #~ , self.controller.result_variable
    488                                      #~ , self.controller.return_variables )
    489
    490          #~ tmpl_values['post_call'] = os.linesep + self.indent( os.linesep.join( cntrl.post_call ) )
    491          #~ if return_stmt_creator.pre_return_code:
    492              #~ tmpl_values['post_call'] \
    493                  #~ = os.linesep.join([ tmpl_values['post_call']
    494                                      #~ , self.indent( return_stmt_creator.pre_return_code )])
    495
    496          #~ f_def = self.controller.template.substitute(tmpl_values)
    497          #~ return remove_duplicate_linesep( f_def )
    498
    499      #~ def _create_impl(self):
    500          #~ return self.create_fun_definition()
    501