Package pyplusplus :: Package decl_wrappers :: Module algorithm |

# Source Code for Module pyplusplus.decl_wrappers.algorithm

      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  """Contains few unrelated algorithms, which works on code creators tree"""
      7
      8  import re
      9  from pygccxml import declarations
     10
     11 -def creators_affect_on_me( me ):
     12      """Find all relevant code creators, which influennce on code generated by "me".
     13
     14      C++ allows to define aliases to namespaces. Py++ allows user to define aliases
     15      to the namespace and will take this aliases into account when it generates
     16      the code.
     17
     18      Example:
     19
     20        [a b c d e f g]
     21               |
     22               + [k l m]
     23                    |
     24                    + [y x] <-- we are here ( x )
     25
     26      return value is: [y,l,k,d,c,b,a]
     27      """
     28      class impl:
     29          def __init__( self, creator):
     30              self._creator = creator
     31
     32          def _get_left_siblings( self, child ):
     33              if not child or not child.parent:
     34                  return []
     35              ids = map( id, child.parent.creators )
     36              child_index = ids.index( id( child ) )
     37              return child.parent.creators[:child_index]
     38
     39          def _get_definition_set( self, child ):
     40              answer = []
     41              while child:
     42                  answer.extend( self._get_left_siblings( child ) )
     43                  child = child.parent
     44              return answer
     45
     46          def affect_creators(self):
     47              return self._get_definition_set( self._creator )
     48      return impl( me ).affect_creators()
     49
     50  __RE_VALID_IDENTIFIER = re.compile( r"[_a-z]\w*", re.I | re.L | re.U )
     51 -def create_valid_name(name):
     52      """Create valid name\\Python identifier from a string
     53
     54      As input this functions takes valid C++ name\identifier and replaces all invalid
     55      characters.
     56
     57      Invalid characters are introduced by a template instantiation.
     58      """
     59      global __RE_VALID_IDENTIFIER
     60      match_found = __RE_VALID_IDENTIFIER.match(name)
     61      if match_found and ( match_found.end() - match_found.start() == len(name) ):
     62          return name
     63      replace_table = {
     64            '<'  : '_less_'
     65          , '>'  : '_greater_'
     66          , '::' : '_scope_'
     67          , ','  : '_comma_'
     68          , ' '  : '_'
     69          , '\t' : '_'
     70          , '*'  : '_ptr_'
     71          , '&'  : '_ref_'
     72          , '('  : '_obrace_'
     73          , ')'  : '_cbrace_'
     74          , '['  : '_o_sq_brace_'
     75          , ']'  : '_c_sq_brace_'
     76          , '='  : '_equal_'
     77          , '.'  : '_dot_'
     78          , '$'  : '_dollar_'
     79      }
     80      for orig, dest in replace_table.items():
     81          name = name.replace( orig, dest )
     82      return name
     83
     84
     85 -def create_identifier(creator, full_name ):
     86      """Return new full name, which takes into account namespace aliases"""
     87
     88      from pyplusplus import code_creators
     89      dset = creators_affect_on_me( creator )
     90      dset = filter( lambda x: isinstance( x, code_creators.namespace_alias_t ), dset )
     91      full_name = full_name.lstrip( '::' )
     92      for nsalias in dset:
     93          fnsname = nsalias.full_namespace_name + '::'
     94          if full_name.startswith( fnsname ):
     95              new_name = nsalias.alias + '::' + full_name[ len(fnsname) :  ]
     96              return new_name
     97      else:
     98          return full_name
     99
    100 -class registration_order:
    101      """class-namespace, introduce few functions, which deals with functions
    102      registration order problem: http://www.language-binding.net/pyplusplus/documentation/functions/registration_order.html
    103      """
    104
    105      @staticmethod
    106 -    def is_related( t1, t2 ):
    107          """Check whether two types\\classes t1 and t2 could introduce the problem"""
    108
    109          if declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ):
    110              return registration_order.is_related( declarations.remove_pointer( t1 )
    111                                                    , declarations.remove_pointer( t2 ) )
    112          elif declarations.is_pointer( t1 ) and not declarations.is_pointer( t2 ):
    113              t1 = declarations.remove_cv( declarations.remove_pointer( t1 ) )
    114              t2 = declarations.remove_cv( t2 )
    115              if declarations.is_same( t1, t2 ):
    116                  return 1
    117          elif not declarations.is_pointer( t1 ) and declarations.is_pointer( t2 ):
    118              t1 = declarations.remove_cv( t1 )
    119              t2 = declarations.remove_cv( declarations.remove_pointer( t2 ) )
    120              if declarations.is_same( t1, t2 ):
    121                  return -1
    122          else: #not is_pointer( t1 ) and not is_pointer( t2 ):
    123              if declarations.is_integral( t1 ) and not declarations.is_bool( t1 ) \
    124                 and declarations.is_bool( t2 ):
    125                  return -1
    126              elif declarations.is_bool( t1 ) \
    127                   and declarations.is_integral( t2 ) and not declarations.is_bool( t2 ):
    128                  return 1
    129              else:
    130                  pass
    131          return None
    132
    133      @staticmethod
    134 -    def select_problematics( calldef ):
    135          """Return list of problematic functions for function "calldef" """
    136          if 1 != len( calldef.required_args ):
    137              return []
    138          arg_type = calldef.arguments[0].type
    139          if declarations.is_calldef_pointer( arg_type ):
    140              return []
    141          problematics = []
    142          for f in calldef.overloads:
    143              if 1 != len( f.required_args ):
    144                  continue
    145              if f.ignore:
    146                  continue
    147              if None != registration_order.is_related( calldef.arguments[0].type, f.arguments[0].type ):
    148                  problematics.append( f )
    149          return problematics
    150