1# Copyright 2014-2017 Insight Software Consortium. 2# Copyright 2004-2009 Roman Yakovenko. 3# Distributed under the Boost Software License, Version 1.0. 4# See http://www.boost.org/LICENSE_1_0.txt 5 6""" 7defines classes, that describes "callable" declarations 8 9This modules contains definition for next C++ declarations: 10 - operator 11 - member 12 - free 13 - function 14 - member 15 - free 16 - constructor 17 - destructor 18""" 19from . import cpptypes 20from . import declaration 21from . import calldef_types 22 23 24# First level in hierarchy of calldef 25class argument_t(object): 26 27 """ 28 class, that describes argument of "callable" declaration 29 """ 30 31 def __init__( 32 self, 33 name='', 34 decl_type=None, 35 default_value=None, 36 attributes=None): 37 object.__init__(self) 38 39 self._name = name 40 self._default_value = default_value 41 self._decl_type = decl_type 42 self._attributes = attributes 43 44 def clone(self, **keywd): 45 """constructs new argument_t instance 46 47 return argument_t( 48 name=keywd.get('name', self.name), 49 decl_type=keywd.get('decl_type', self.decl_type), 50 default_value=keywd.get('default_value', self.default_value), 51 attributes=keywd.get('attributes', self.attributes )) 52 53 """ 54 return argument_t( 55 name=keywd.get('name', self.name), 56 decl_type=keywd.get('decl_type', self.decl_type), 57 default_value=keywd.get('default_value', self.default_value), 58 attributes=keywd.get('attributes', self.attributes)) 59 60 def __str__(self): 61 if self.ellipsis: 62 return "..." 63 64 if self.default_value is None: 65 return "%s %s" % (self.decl_type, self.name) 66 67 return "%s %s=%s" % (self.decl_type, self.name, self.default_value) 68 69 def __eq__(self, other): 70 if not isinstance(other, self.__class__): 71 return False 72 return self.name == other.name \ 73 and self.default_value == other.default_value \ 74 and self.decl_type == other.decl_type 75 76 def __hash__(self): 77 return (hash(self.__class__) ^ 78 hash(self.name) ^ 79 hash(self.default_value) ^ 80 hash(self.decl_type)) 81 82 def __ne__(self, other): 83 return not self.__eq__(other) 84 85 def __lt__(self, other): 86 if not isinstance(other, self.__class__): 87 return self.__class__.__name__ < other.__class__.__name__ 88 return self.name < other.name \ 89 and self.default_value < other.default_value \ 90 and self.decl_type < other.decl_type 91 92 @property 93 def name(self): 94 """Argument name. 95 @type: str""" 96 return self._name 97 98 @name.setter 99 def name(self, name): 100 self._name = name 101 102 @property 103 def ellipsis(self): 104 """bool, if True argument represents ellipsis ( "..." ) 105 in function definition""" 106 return isinstance(self.decl_type, cpptypes.ellipsis_t) 107 108 @property 109 def default_value(self): 110 """Argument's default value or None. 111 @type: str""" 112 return self._default_value 113 114 @default_value.setter 115 def default_value(self, default_value): 116 self._default_value = default_value 117 118 @property 119 def decl_type(self): 120 return self._decl_type 121 122 @decl_type.setter 123 def decl_type(self, decl_type): 124 self._decl_type = decl_type 125 126 @property 127 def attributes(self): 128 """GCCXML attributes, set using __attribute__((gccxml("..."))) 129 @type: str""" 130 return self._attributes 131 132 @attributes.setter 133 def attributes(self, attributes): 134 self._attributes = attributes 135 136 137class calldef_t(declaration.declaration_t): 138 139 """base class for all "callable" declarations""" 140 141 def __init__( 142 self, 143 name='', 144 arguments=None, 145 exceptions=None, 146 return_type=None, 147 has_extern=False, 148 does_throw=True, 149 mangled=None): 150 declaration.declaration_t.__init__(self, name) 151 if not arguments: 152 arguments = [] 153 self._arguments = arguments 154 if not exceptions: 155 exceptions = [] 156 self._does_throw = does_throw 157 self._exceptions = exceptions 158 self._return_type = return_type 159 self._has_extern = has_extern 160 self._calling_convention = None 161 self._has_inline = None 162 self._mangled = mangled 163 164 def _get__cmp__call_items(self): 165 """ 166 Implementation detail. 167 168 """ 169 170 raise NotImplementedError() 171 172 def _get__cmp__items(self): 173 """ 174 Implementation detail. 175 176 """ 177 178 items = [ 179 self.arguments, 180 self.return_type, 181 self.has_extern, 182 self.does_throw, 183 self.exceptions.sort(), 184 self.has_inline] 185 186 items.extend(self._get__cmp__call_items()) 187 return items 188 189 def __eq__(self, other): 190 if not declaration.declaration_t.__eq__(self, other): 191 return False 192 193 return self.return_type == other.return_type \ 194 and self.arguments == other.arguments \ 195 and self.has_extern == other.has_extern \ 196 and self.does_throw == other.does_throw \ 197 and self.exceptions.sort() == other.exceptions.sort() 198 199 def __hash__(self): 200 return (super(calldef_t, self).__hash__() ^ 201 hash(self.return_type) ^ 202 hash(self.name)) 203 204 @property 205 def arguments(self): 206 """The argument list. 207 @type: list of :class:`argument_t`""" 208 return self._arguments 209 210 @arguments.setter 211 def arguments(self, arguments): 212 self._arguments = arguments 213 214 @property 215 def has_ellipsis(self): 216 return self.arguments and self.arguments[-1].ellipsis 217 218 @property 219 def argument_types(self): 220 """list of all argument types""" 221 return [arg.decl_type for arg in self.arguments] 222 223 @property 224 def required_args(self): 225 """list of all required arguments""" 226 r_args = [] 227 for arg in self.arguments: 228 if not arg.default_value: 229 r_args.append(arg) 230 else: 231 break 232 return r_args 233 234 @property 235 def optional_args(self): 236 """list of all optional arguments, the arguments that have default 237 value""" 238 return self.arguments[len(self.required_args):] 239 240 @property 241 def does_throw(self): 242 """If False, than function does not throw any exception. 243 In this case, function was declared with empty throw 244 statement.""" 245 return self._does_throw 246 247 @does_throw.setter 248 def does_throw(self, does_throw): 249 self._does_throw = does_throw 250 251 @property 252 def exceptions(self): 253 """The list of exceptions. 254 @type: list of :class:`declaration_t`""" 255 return self._exceptions 256 257 @exceptions.setter 258 def exceptions(self, exceptions): 259 self._exceptions = exceptions 260 261 @property 262 def return_type(self): 263 """The type of the return value of the "callable" or None 264 (constructors). 265 @type: :class:`type_t`""" 266 return self._return_type 267 268 @return_type.setter 269 def return_type(self, return_type): 270 self._return_type = return_type 271 272 @property 273 def overloads(self): 274 """A list of overloaded "callables" (i.e. other callables with the 275 same name within the same scope. 276 277 @type: list of :class:`calldef_t` 278 """ 279 if not self.parent: 280 return [] 281 # finding all functions with the same name 282 return self.parent.calldefs( 283 name=self.name, 284 function=lambda decl: decl is not self, 285 allow_empty=True, 286 recursive=False) 287 288 @property 289 def has_extern(self): 290 """Was this callable declared as "extern"? 291 @type: bool""" 292 return self._has_extern 293 294 @has_extern.setter 295 def has_extern(self, has_extern): 296 self._has_extern = has_extern 297 298 @property 299 def has_inline(self): 300 """Was this callable declared with "inline" specifier 301 @type: bool""" 302 return self._has_inline 303 304 @has_inline.setter 305 def has_inline(self, has_inline): 306 self._has_inline = has_inline 307 308 def _report(self, *args, **keywd): 309 # Implementation detail. Will be removed when the deprecated 310 # i_depend_on_them method is dropped 311 from . import dependencies # pylint: disable=R0401 312 return dependencies.dependency_info_t(self, *args, **keywd) 313 314 def i_depend_on_them(self, recursive=True): 315 self._warn_deprecated() 316 answer = [] 317 if self.return_type: 318 answer.append( 319 self._report(self.return_type, hint="return type")) 320 for arg in self.arguments: 321 answer.append(self._report(arg.decl_type)) 322 for exc in self.exceptions: 323 answer.append(self._report(exc, hint="exception")) 324 return answer 325 326 # pylint: disable=R0201 327 def guess_calling_convention(self): 328 """This function should be overriden in the derived classes and return 329 more-or-less successfull guess about calling convention""" 330 return calldef_types.CALLING_CONVENTION_TYPES.UNKNOWN 331 332 @property 333 def calling_convention(self): 334 """function calling convention. See 335 :class:CALLING_CONVENTION_TYPES class for possible values""" 336 if self._calling_convention is None: 337 self._calling_convention = \ 338 calldef_types.CALLING_CONVENTION_TYPES.extract(self.attributes) 339 if not self._calling_convention: 340 self._calling_convention = self.guess_calling_convention() 341 return self._calling_convention 342 343 @calling_convention.setter 344 def calling_convention(self, cc): 345 self._calling_convention = cc 346 347 @property 348 def mangled(self): 349 """ 350 Unique declaration name generated by the compiler. 351 352 :return: the mangled name 353 :rtype: str 354 355 """ 356 357 return self.get_mangled_name() 358 359 @mangled.setter 360 def mangled(self, mangled): 361 self._mangled = mangled 362