Package pygccxml :: Package declarations :: Module calldef

Source Code for Module pygccxml.declarations.calldef

  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  """ 
  7  defines classes, that describes "callable" declarations 
  8   
  9  This modules contains definition for next C++ declarations: 
 10      - operator 
 11          - member 
 12          - free 
 13      - function 
 14          - member 
 15          - free 
 16      - constructor 
 17      - destructor 
 18  """ 
 19   
 20  import cpptypes 
 21  import algorithm 
 22  import declaration 
 23  import type_traits 
 24  import dependencies 
 25  import call_invocation 
26 27 -class VIRTUALITY_TYPES:
28 """class that defines "virtuality" constants""" 29 NOT_VIRTUAL = 'not virtual' 30 VIRTUAL = 'virtual' 31 PURE_VIRTUAL = 'pure virtual' 32 ALL = [NOT_VIRTUAL, VIRTUAL, PURE_VIRTUAL]
33 #preserving backward compatebility
34 FUNCTION_VIRTUALITY_TYPES = VIRTUALITY_TYPES 35 36 #First level in hierarchy of calldef 37 -class argument_t(object):
38 """ 39 class, that describes argument of "callable" declaration 40 """ 41
42 - def __init__( self, name='', type=None, default_value=None, attributes=None):
43 object.__init__(self) 44 self._name = name 45 self._default_value = default_value 46 self._type = type 47 self._attributes = attributes
48
49 - def clone( self, **keywd ):
50 """constructs new argument_t instance 51 52 return argument_t( name=keywd.get( 'name', self.name ) 53 , type=keywd.get( 'type', self.type ) 54 , default_value=keywd.get( 'default_value', self.default_value ) 55 , attributes=keywd.get( 'attributes', self.attributes ) ) 56 57 """ 58 return argument_t( name=keywd.get( 'name', self.name ) 59 , type=keywd.get( 'type', self.type ) 60 , default_value=keywd.get( 'default_value', self.default_value ) 61 , attributes=keywd.get( 'attributes', self.attributes ) )
62
63 - def __str__(self):
64 if self.ellipsis: 65 return "..." 66 else: 67 if self.default_value==None: 68 return "%s %s"%(self.type, self.name) 69 else: 70 return "%s %s=%s"%(self.type, self.name, self.default_value)
71
72 - def __eq__(self, other):
73 if not isinstance( other, self.__class__ ): 74 return False 75 return self.name == other.name \ 76 and self.default_value == other.default_value \ 77 and self.type == other.type
78
79 - def __ne__( self, other):
80 return not self.__eq__( other )
81
82 - def __lt__(self, other):
83 if not isinstance( other, self.__class__ ): 84 return self.__class__.__name__ < other.__class__.__name__ 85 return self.name < other.name \ 86 and self.default_value < other.default_value \ 87 and self.type < other.type
88
89 - def _get_name(self):
90 return self._name
91 - def _set_name(self, name):
92 self._name = name
93 name = property( _get_name, _set_name 94 , doc="""Argument name. 95 @type: str""" ) 96 97 @property
98 - def ellipsis(self):
99 """bool, if True argument represents ellipsis ( "..." ) in function definition""" 100 return isinstance( self.type, cpptypes.ellipsis_t )
101
102 - def _get_default_value(self):
103 return self._default_value
104 - def _set_default_value(self, default_value):
105 self._default_value = default_value
106 default_value = property( _get_default_value, _set_default_value 107 , doc="""Argument's default value or None. 108 @type: str""") 109
110 - def _get_type(self):
111 return self._type
112 - def _set_type(self, type):
113 self._type = type
114 type = property( _get_type, _set_type 115 , doc="""The type of the argument. 116 @type: L{type_t}""") 117
118 - def _get_attributes( self ):
119 return self._attributes
120 - def _set_attributes( self, attributes ):
121 self._attributes = attributes
122 attributes = property( _get_attributes, _set_attributes 123 , doc="""GCCXML attributes, set using __attribute__((gccxml("..."))) 124 @type: str 125 """ )
126
127 128 -class calldef_t( declaration.declaration_t ):
129 """base class for all "callable" declarations"""
130 - def __init__( self, name='', arguments=None, exceptions=None, return_type=None, has_extern=False, does_throw=True ):
131 declaration.declaration_t.__init__( self, name ) 132 if not arguments: 133 arguments = [] 134 self._arguments = arguments 135 if not exceptions: 136 exceptions = [] 137 self._does_throw = does_throw 138 self._exceptions = exceptions 139 self._return_type = return_type 140 self._has_extern = has_extern 141 self._demangled_name = None
142
143 - def _get__cmp__call_items(self):
144 """implementation details""" 145 raise NotImplementedError()
146
147 - def _get__cmp__items( self ):
148 """implementation details""" 149 items = [ self.arguments 150 , self.return_type 151 , self.has_extern 152 , self.does_throw 153 , self._sorted_list( self.exceptions ) ] 154 items.extend( self._get__cmp__call_items() ) 155 return items
156
157 - def __eq__(self, other):
158 if not declaration.declaration_t.__eq__( self, other ): 159 return False 160 return self.return_type == other.return_type \ 161 and self.arguments == other.arguments \ 162 and self.has_extern == other.has_extern \ 163 and self.does_throw == other.does_throw \ 164 and self._sorted_list( self.exceptions ) \ 165 == other._sorted_list( other.exceptions )
166
167 - def _get_arguments(self):
168 return self._arguments
169 - def _set_arguments(self, arguments):
170 self._arguments = arguments
171 arguments = property( _get_arguments , _set_arguments 172 , doc="""The argument list. 173 @type: list of L{argument_t}""") 174 175 @property
176 - def has_ellipsis( self ):
177 return self.arguments and self.arguments[-1].ellipsis
178 179 @property
180 - def argument_types( self ):
181 """list of all argument types""" 182 return [ arg.type for arg in self.arguments ]
183 184 @property
185 - def required_args(self):
186 """list of all required arguments""" 187 r_args = [] 188 for arg in self.arguments: 189 if not arg.default_value: 190 r_args.append( arg ) 191 else: 192 break 193 return r_args
194 195 @property
196 - def optional_args(self):
197 """list of all optional arguments, the arguments that have default value""" 198 return self.arguments[ len( self.required_args ) : ]
199
200 - def _get_does_throw(self):
201 return self._does_throw
202 - def _set_does_throw(self, does_throw):
203 self._does_throw = does_throw
204 does_throw = property( _get_does_throw, _set_does_throw, 205 doc="""If False, than function does not throw any exception. 206 In this case, function was declared with empty throw 207 statement. 208 """) 209
210 - def _get_exceptions(self):
211 return self._exceptions
212 - def _set_exceptions(self, exceptions):
213 self._exceptions = exceptions
214 exceptions = property( _get_exceptions, _set_exceptions 215 , doc="""The list of exceptions. 216 @type: list of L{declaration_t}""") 217
218 - def _get_return_type(self):
219 return self._return_type
220 - def _set_return_type(self, return_type):
221 self._return_type = return_type
222 return_type = property( _get_return_type, _set_return_type 223 , doc='''The type of the return value of the "callable" or None (constructors). 224 @type: L{type_t} 225 ''') 226 @property
227 - def overloads(self):
228 """A list of overloaded "callables" (i.e. other callables with the same name within the same scope. 229 230 @type: list of L{calldef_t} 231 """ 232 if not self.parent: 233 return [] 234 # finding all functions with the same name 235 return self.parent.calldefs( name=self.name 236 , function=lambda decl: not (decl is self ) 237 , allow_empty=True 238 , recursive=False )
239
240 - def _get_has_extern(self):
241 return self._has_extern
242 - def _set_has_extern(self, has_extern):
243 self._has_extern = has_extern
244 has_extern = property( _get_has_extern, _set_has_extern, 245 doc="""Was this callable declared as "extern"? 246 @type: bool 247 """) 248
249 - def __remove_parent_fname( self, demangled ):
250 """implementation details""" 251 demangled = demangled.strip() 252 parent_fname = algorithm.full_name( self.parent ) 253 if parent_fname.startswith( '::' ) and not demangled.startswith( '::' ): 254 parent_fname = parent_fname[2:] 255 demangled = demangled[ len( parent_fname ): ] 256 return demangled
257
258 - def _get_demangled_name( self ):
259 if not self.demangled: 260 self._demangled_name = '' 261 262 if self._demangled_name: 263 return self._demangled_name 264 265 if self._demangled_name == '': 266 return self.name 267 268 demangled = self.demangled 269 if self.return_type: 270 return_type = type_traits.remove_alias( self.return_type ).decl_string 271 272 if return_type.startswith( '::' ) and not self.demangled.startswith( '::' ): 273 return_type = return_type[2:] 274 demangled = self.demangled 275 if demangled.startswith( return_type ): 276 demangled = demangled[ len( return_type ): ] 277 demangled = demangled.strip() 278 #removing scope 279 demangled_name = call_invocation.name( self.__remove_parent_fname( demangled ) ) 280 if demangled_name.startswith( '::' ): 281 demangled_name = demangled_name[2:] 282 #to be on the safe side 283 if demangled_name.startswith( self.name ): 284 self._demangled_name = demangled_name 285 return self._demangled_name 286 287 #well, I am going to try an other strategy 288 fname = algorithm.full_name( self ) 289 found = self.demangled.find( fname ) 290 if -1 == found: 291 if fname.startswith( '::' ): 292 fname = fname[2:] 293 found = self.demangled.find( fname ) 294 if -1 == found: 295 self._demangled_name = '' 296 return self.name 297 demangled_name = call_invocation.name( self.demangled[ found: ] ) 298 demangled_name = self.__remove_parent_fname( demangled_name ) 299 if demangled_name.startswith( '::' ): 300 demangled_name = demangled_name[2:] 301 #to be on the safe side 302 if demangled_name.startswith( self.name ): 303 self._demangled_name = demangled_name 304 return self._demangled_name 305 #if -1 == found: 306 self._demangled_name = '' 307 return self.name
308 309 demangled_name = property( _get_demangled_name 310 , doc="returns function demangled name. It can help you to deal with function template instantiations") 311
312 - def i_depend_on_them( self, recursive=True ):
313 report_dependency = lambda *args, **keywd: dependencies.dependency_info_t( self, *args, **keywd ) 314 answer = [] 315 if self.return_type: 316 answer.append( report_dependency( self.return_type, hint="return type" ) ) 317 map( lambda arg: answer.append( report_dependency( arg.type ) ) 318 , self.arguments ) 319 map( lambda exception: answer.append( report_dependency( exception, hint="exception" ) ) 320 , self.exceptions ) 321 return answer
322
323 #Second level in hierarchy of calldef 324 -class member_calldef_t( calldef_t ):
325 """base class for "callable" declarations that defined within C++ class or struct"""
326 - def __init__( self, virtuality=None, has_const=None, has_static=None, *args, **keywords ):
327 calldef_t.__init__( self, *args, **keywords ) 328 self._virtuality = virtuality 329 self._has_const = has_const 330 self._has_static = has_static
331
332 - def __str__(self):
333 # Get the full name of the calldef... 334 name = algorithm.full_name(self) 335 if name[:2]=="::": 336 name = name[2:] 337 # Add the arguments... 338 args = map(lambda a: str(a), self.arguments) 339 res = "%s(%s)"%(name, ", ".join(args)) 340 # Add the return type... 341 if self.return_type!=None: 342 res = "%s %s"%(self.return_type, res) 343 # const? 344 if self.has_const: 345 res += " const" 346 # static? 347 if self.has_static: 348 res = "static "+res 349 # Append the declaration class 350 cls = self.__class__.__name__ 351 if cls[-2:]=="_t": 352 cls = cls[:-2] 353 cls = cls.replace( '_', ' ' ) 354 return "%s [%s]"%(res, cls)
355
356 - def _get__cmp__call_items(self):
357 """implementation details""" 358 return [ self.virtuality, self.has_static, self.has_const ]
359
360 - def __eq__(self, other):
361 if not calldef_t.__eq__( self, other ): 362 return False 363 return self.virtuality == other.virtuality \ 364 and self.has_static == other.has_static \ 365 and self.has_const == other.has_const
366
367 - def get_virtuality(self):
368 return self._virtuality
369 - def set_virtuality(self, virtuality):
370 assert virtuality in VIRTUALITY_TYPES.ALL 371 self._virtuality = virtuality
372 virtuality = property( get_virtuality, set_virtuality 373 , doc="""Describes the "virtuality" of the member (as defined by the string constants in the class L{VIRTUALITY_TYPES}). 374 @type: str""") 375
376 - def _get_access_type(self):
377 return self.parent.find_out_member_access_type( self )
378 access_type = property( _get_access_type 379 , doc="""Return the access type of the member (as defined by the string constants in the class L{ACCESS_TYPES}. 380 @type: str""") 381
382 - def _get_has_const(self):
383 return self._has_const
384 - def _set_has_const(self, has_const):
385 self._has_const = has_const
386 has_const = property( _get_has_const, _set_has_const 387 , doc="""describes, whether "callable" has const modifier or not""") 388
389 - def _get_has_static(self):
390 return self._has_static
391 - def _set_has_static(self, has_static):
392 self._has_static = has_static
393 has_static = property( _get_has_static, _set_has_static 394 , doc="""describes, whether "callable" has static modifier or not""") 395
396 - def function_type(self):
397 """returns function type. See L{type_t} hierarchy""" 398 if self.has_static: 399 return cpptypes.free_function_type_t( return_type=self.return_type 400 , arguments_types=[ arg.type for arg in self.arguments ] ) 401 else: 402 return cpptypes.member_function_type_t( class_inst=self.parent 403 , return_type=self.return_type 404 , arguments_types=[ arg.type for arg in self.arguments ] 405 , has_const=self.has_const )
406
407 - def create_decl_string(self, with_defaults=True):
408 f_type = self.function_type() 409 if with_defaults: 410 return f_type.decl_string 411 else: 412 return f_type.partial_decl_string
413
414 -class free_calldef_t( calldef_t ):
415 """base class for "callable" declarations that defined within C++ namespace"""
416 - def __init__( self, *args, **keywords ):
417 calldef_t.__init__( self, *args, **keywords )
418
419 - def __str__(self):
420 # Get the full name of the calldef... 421 name = algorithm.full_name(self) 422 if name[:2]=="::": 423 name = name[2:] 424 # Add the arguments... 425 args = map(lambda a: str(a), self.arguments) 426 res = "%s(%s)"%(name, ", ".join(args)) 427 # Add the return type... 428 if self.return_type!=None: 429 res = "%s %s"%(self.return_type, res) 430 # extern? 431 if self.has_extern: 432 res = "extern "+res 433 # Append the declaration class 434 cls = self.__class__.__name__ 435 if cls[-2:]=="_t": 436 cls = cls[:-2] 437 cls = cls.replace( '_', ' ' ) 438 return "%s [%s]"%(res, cls)
439
440 - def _get__cmp__call_items(self):
441 """implementation details""" 442 return []
443
444 - def function_type(self):
445 """returns function type. See L{type_t} hierarchy""" 446 return cpptypes.free_function_type_t( return_type=self.return_type 447 , arguments_types=[ arg.type for arg in self.arguments ] )
448
449 - def create_decl_string(self, with_defaults=True):
450 f_type = self.function_type() 451 if with_defaults: 452 return f_type.decl_string 453 else: 454 return f_type.partial_decl_string
455
456 457 -class operator_t(object):
458 """base class for "operator" declarations""" 459 OPERATOR_WORD_LEN = len( 'operator' )
460 - def __init__(self):
461 object.__init__(self)
462 463 @property
464 - def symbol(self):
465 "operator's symbol. For example: operator+, symbol is equal to '+'" 466 return self.name[operator_t.OPERATOR_WORD_LEN:].strip()
467
468 #Third level in hierarchy of calldef 469 -class member_function_t( member_calldef_t ):
470 """describes member function declaration"""
471 - def __init__( self, *args, **keywords ):
472 member_calldef_t.__init__( self, *args, **keywords )
473
474 -class constructor_t( member_calldef_t ):
475 """describes constructor declaration"""
476 - def __init__( self, *args, **keywords ):
477 member_calldef_t.__init__( self, *args, **keywords )
478
479 - def __str__(self):
480 # Get the full name of the calldef... 481 name = algorithm.full_name(self) 482 if name[:2]=="::": 483 name = name[2:] 484 # Add the arguments... 485 args = map(lambda a: str(a), self.arguments) 486 res = "%s(%s)"%(name, ", ".join(args)) 487 # Append the declaration class 488 cls = 'constructor' 489 if self.is_copy_constructor: 490 cls = 'copy ' + cls 491 return "%s [%s]"%(res, cls)
492 493 @property
494 - def is_copy_constructor(self):
495 """returns True if described declaration is copy constructor, otherwise False""" 496 args = self.arguments 497 if 1 != len( args ): 498 return False 499 arg = args[0] 500 if not type_traits.is_reference( arg.type ): 501 return False 502 if not type_traits.is_const( arg.type.base ): 503 return False 504 unaliased = type_traits.remove_alias( arg.type.base ) 505 #unaliased now refers to const_t instance 506 if not isinstance( unaliased.base, cpptypes.declarated_t ): 507 return False 508 return id(unaliased.base.declaration) == id(self.parent)
509 510 @property
511 - def is_trivial_constructor(self):
512 return not bool( self.arguments )
513
514 515 -class destructor_t( member_calldef_t ):
516 """describes deconstructor declaration"""
517 - def __init__( self, *args, **keywords ):
518 member_calldef_t.__init__( self, *args, **keywords )
519
520 -class member_operator_t( member_calldef_t, operator_t ):
521 """describes member operator declaration"""
522 - def __init__( self, *args, **keywords ):
523 member_calldef_t.__init__( self, *args, **keywords ) 524 operator_t.__init__( self, *args, **keywords ) 525 self.__class_types = None
526
527 -class casting_operator_t( member_calldef_t, operator_t ):
528 """describes casting operator declaration"""
529 - def __init__( self, *args, **keywords ):
530 member_calldef_t.__init__( self, *args, **keywords ) 531 operator_t.__init__( self, *args, **keywords )
532
533 -class free_function_t( free_calldef_t ):
534 """describes free function declaration"""
535 - def __init__( self, *args, **keywords ):
536 free_calldef_t.__init__( self, *args, **keywords )
537
538 -class free_operator_t( free_calldef_t, operator_t ):
539 """describes free operator declaration"""
540 - def __init__( self, *args, **keywords ):
541 free_calldef_t.__init__( self, *args, **keywords ) 542 operator_t.__init__( self, *args, **keywords ) 543 self.__class_types = None
544 545 @property
546 - def class_types( self ):
547 """list of class/class declaration types, extracted from the operator arguments""" 548 if None is self.__class_types: 549 self.__class_types = [] 550 for type_ in self.argument_types: 551 decl = None 552 type_ = type_traits.remove_reference( type_ ) 553 if type_traits.is_class( type_ ): 554 decl = type_traits.class_traits.get_declaration( type_ ) 555 elif type_traits.is_class_declaration( type_ ): 556 decl = type_traits.class_declaration_traits.get_declaration( type_ ) 557 else: 558 pass 559 if decl: 560 self.__class_types.append( decl ) 561 return self.__class_types
562