Package pyplusplus :: Package module_creator :: Module types_database |

# Source Code for Module pyplusplus.module_creator.types_database

      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  from pyplusplus import messages
      7  from pygccxml import declarations
      8  from pyplusplus import code_creators
      9  from pyplusplus import _logging_
     10  templates = declarations.templates
     11
     12 -class types_database_t( object ):
     13 -    def __init__( self ):
     14          object.__init__( self )
     15          self.__variables = {} # decl_string : [type]
     16          self.__return_types = {} # decl_string : [type]
     17          self.__arguments_types = {} #decl_string : [type]
     18          self.__smart_ptrs = [ 'shared_ptr', 'auto_ptr' ]
     19          self.__fundamental_strs = declarations.FUNDAMENTAL_TYPES.keys()
     20          self.__normalize_data = [ ',', '<', '>', '*', '&', '(', ')', '::' ]
     21          self.__containers = set()
     22
     23 -    def update( self, decl ):
     24          if isinstance( decl, declarations.calldef_t ):
     25              if not isinstance( decl, declarations.constructor_t ):
     26                  self._update_db( self.__return_types, decl.return_type )
     27              map( lambda arg: self._update_db( self.__arguments_types, arg.type )
     28                   , decl.arguments )
     29          elif isinstance( decl, declarations.variable_t ):
     30              self._update_db( self.__variables, decl.type )
     31          else:
     32              assert not "types_database_t class can not process " + str( decl )
     33
     34 -    def _is_relevant(self, decl_string):
     35          for smart_ptr in self.__smart_ptrs:
     36              if smart_ptr in decl_string:
     37                  return True
     38          return False
     39
     40 -    def _is_relevant_inst( self, name, args ):
     41          return self._is_relevant( name )
     42
     43 -    def _normalize( self, decl_string ):
     44          if decl_string.startswith( '::' ):
     45              decl_string = decl_string[2:]
     46          answer = decl_string
     47          for data in self.__normalize_data:
     48              answer = answer.replace( data + ' ', data )
     49              answer = answer.replace( ' ' + data, data )
     50          return answer.replace( '  ', ' ' )
     51
     52 -    def _update_containers_db( self, type_ ):
     53          #will return True is type was treated
     54          type_ = declarations.remove_alias( type_ )
     55          type_ = declarations.remove_pointer( type_ )
     56          type_ = declarations.remove_reference( type_ )
     57          type_ = declarations.remove_cv( type_ )
     58          type_ = declarations.remove_declarated( type_ )
     59
     60          class_traits = declarations.class_traits
     61          class_declaration_traits = declarations.class_declaration_traits
     62          if not class_traits.is_my_case( type_ ) and not class_declaration_traits.is_my_case( type_ ):
     63              return False
     64
     65          if class_traits.is_my_case( type_ ):
     66              container_cls = class_traits.get_declaration( type_ )
     67          else:
     68              container_cls = class_declaration_traits.get_declaration( type_ )
     69
     70          if None is container_cls.indexing_suite:
     71              return False
     72
     73          try:
     74              #check extraction of element type from container
     75              container_cls.indexing_suite.element_type
     76          except RuntimeError:
     77              decls_logger = _logging_.loggers.declarations
     78              if not messages.filter_disabled_msgs([messages.W1042], container_cls.disabled_messages ):
     79                  return #user disabled property warning
     80              decls_logger.warn( "%s;%s" % ( container_cls, messages.W1042 ) )
     81          self.__containers.add( container_cls )
     82          return True
     83
     84
     85 -    def _update_db( self, db, type_ ):
     86          if self._update_containers_db( type_ ):
     87              return
     88          decl_string = self._normalize( declarations.base_type( type_ ).decl_string )
     89          if not templates.is_instantiation( decl_string ):
     90              return
     91          if not self._is_relevant( decl_string ):
     92              return
     93          insts = filter( lambda inst: self._is_relevant_inst( inst[0], inst[1] )
     94                          , templates.split_recursive( decl_string ) )
     95          for smart_ptr, args in insts:
     96              assert len( args ) == 1
     97              pointee = self._normalize( args[0] )
     98              if not db.has_key(pointee):
     99                  db[ pointee ] = []
    100              smart_ptr = self._normalize( smart_ptr )
    101              if (smart_ptr, type_) not in db[pointee]:
    102                  db[ pointee ].append( (smart_ptr, type_) )
    103
    104 -    def _find_smart_ptrs( self, db, class_decl ):
    105          decl_string = self._normalize( class_decl.decl_string )
    106          if db.has_key( decl_string ):
    107              return db[ decl_string ]
    108          else:
    109              return None
    110
    111 -    def create_holder( self, class_decl ):
    112          #holder should be created when we pass object created in python
    113          #as parameter to function in C++ that takes the smart pointer by reference
    114          found = self._find_smart_ptrs( self.__arguments_types, class_decl )
    115          if not found:
    116              return None#not found or ambiguty
    117
    118          held_type = None
    119          for smart_ptr, type_ in found:
    120              if declarations.is_reference( type_ ) and not declarations.is_const( type_.base ):
    121                  temp = code_creators.held_type_t( smart_ptr=smart_ptr )
    122                  if not held_type or 'shared_ptr' in smart_ptr:
    123                      held_type = temp
    124          return held_type
    125
    126 -    def _create_registrators_from_db( self, db, class_creator, registered ):
    127          spregistrator_t = code_creators.smart_pointer_registrator_t
    128          found = self._find_smart_ptrs( db, class_creator.declaration )
    129          if not found:
    130              return
    131          for smart_ptr, type_ in found:
    132              already_registered = filter( lambda registrator: registrator.smart_ptr == smart_ptr
    133                                           , registered )
    134              if not already_registered:
    135                  registered.append( spregistrator_t( smart_ptr=smart_ptr, class_creator=class_creator) )
    136
    137 -    def create_registrators( self, class_creator ):
    138          """ Look for places where the class may be used as smart_ptr.
    139              - If found then create smart_pointer_registrator_t for that class and ptr type.
    140          """
    141          spconverter_t = code_creators.smart_pointers_converter_t
    142          registrators = []
    143          dbs = [ self.__arguments_types, self.__return_types, self.__variables ]
    144          for db in dbs:
    145              self._create_registrators_from_db( db, class_creator, registrators )
    146          if not class_creator.declaration.bases:
    147              return registrators
    148          # Add implicit converters from me to base classes and from derived classes to me
    149          answer = []
    150          for registrator in registrators:
    151              answer.append( registrator )
    152              decl = registrator.declaration
    153              for hierarchy_info in decl.recursive_bases:
    154                  if hierarchy_info.access_type != declarations.ACCESS_TYPES.PRIVATE:
    155                      converter = spconverter_t( smart_ptr=registrator.smart_ptr
    156                                                 , source=class_creator.declaration
    157                                                 , target=hierarchy_info.related_class )
    158                      answer.append( converter )
    159              for hierarchy_info in decl.recursive_derived:
    160                  if hierarchy_info.access_type != declarations.ACCESS_TYPES.PRIVATE:
    161                      converter = spconverter_t( smart_ptr=registrator.smart_ptr
    162                                                 , source=hierarchy_info.related_class
    163                                                 , target=class_creator.declaration )
    164                      answer.append( converter )
    165          return answer
    166
    167 -    def _print_single_db(self, db):
    168          for decl_string in db.keys():
    169              print 'decl_string : ', decl_string
    170              for smart_ptr, type_ in db[ decl_string ]:
    171                  print '    smart_ptr : ', smart_ptr
    172                  print '    type_     : ', type_.decl_string
    173
    174 -    def print_db( self ):
    175          dbs = [ self.__arguments_types, self.__return_types, self.__variables ]
    176          for db in dbs:
    177              self._print_single_db( db )
    178
    179 -    def _get_used_containers( self ):
    180          return self.__containers
    181      used_containers = property( _get_used_containers)
    182