Bug 562615 – Struct methods missing
[platform/upstream/gobject-introspection.git] / giscanner / ast.py
1 # -*- Mode: Python -*-
2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008  Johan Dahlin
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA.
19 #
20
21 """AST nodes
22 This file descbribes abstract data type nodes independent on the
23 implementation language.
24
25 These can later on be extended (eg subclassed) with additional information
26 which is language/library/domain specific.
27 """
28
29 ##
30 ## Basic types, modeled on GITypeTag but not equivalent
31 ##
32
33 TYPE_NONE = 'none' # We differ from repository on these first two
34 TYPE_ANY = 'any'
35 TYPE_BOOLEAN = 'boolean'
36 TYPE_INT8 = 'int8'
37 TYPE_UINT8 = 'uint8'
38 TYPE_INT16 = 'int16'
39 TYPE_UINT16 = 'uint16'
40 TYPE_INT = 'int'
41 TYPE_UINT = 'uint'
42 TYPE_INT32 = 'int32'
43 TYPE_UINT32 = 'uint32'
44 TYPE_INT64 = 'int64'
45 TYPE_UINT64 = 'uint64'
46 TYPE_LONG = 'long'
47 TYPE_ULONG = 'ulong'
48 TYPE_SSIZET = 'ssize_t'
49 TYPE_SIZET = 'size_t'
50 TYPE_TIMET = 'time_t'
51 TYPE_GTYPE = 'GType'
52 TYPE_FLOAT = 'float'
53 TYPE_DOUBLE = 'double'
54 TYPE_STRING = 'utf8' # requires zero-terminated
55 TYPE_FILENAME = 'filename'
56
57 BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16,
58                    TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64,
59                    TYPE_UINT64, TYPE_INT, TYPE_UINT, TYPE_LONG,
60                    TYPE_ULONG, TYPE_SSIZET, TYPE_SIZET, TYPE_FLOAT,
61                    TYPE_DOUBLE, TYPE_TIMET, TYPE_GTYPE]
62 GIR_TYPES = [TYPE_NONE, TYPE_ANY]
63 GIR_TYPES.extend(BASIC_GIR_TYPES)
64 GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME])
65
66 # Higher-level data types
67 TYPE_SEQUENCE = 'sequence' # Sequence of something
68
69 # Wide/Unicode
70 TYPE_UCHAR = 'uchar'
71 TYPE_USTRING = 'ustring'
72
73 ##
74 ## Parameters
75 ##
76
77 PARAM_DIRECTION_IN = 'in'
78 PARAM_DIRECTION_OUT = 'out'
79 PARAM_DIRECTION_INOUT = 'inout'
80
81 PARAM_TRANSFER_NONE = 'none'
82 PARAM_TRANSFER_CONTAINER = 'container'
83 PARAM_TRANSFER_FULL = 'full'
84
85 type_names = {}
86 for name in GIR_TYPES:
87     type_names[name] = name
88
89 # C builtin
90 type_names['char'] = TYPE_INT8
91 type_names['signed char'] = TYPE_INT8
92 type_names['unsigned char'] = TYPE_UINT8
93 type_names['short'] = TYPE_INT16
94 type_names['signed short'] = TYPE_INT16
95 type_names['unsigned short'] = TYPE_UINT16
96 type_names['int'] = TYPE_INT
97 type_names['signed int'] = TYPE_INT
98 type_names['signed'] = TYPE_INT
99 type_names['unsigned int'] = TYPE_UINT
100 type_names['unsigned'] = TYPE_UINT
101 type_names['long'] = TYPE_LONG
102 type_names['signed long'] = TYPE_LONG
103 type_names['unsigned long'] = TYPE_ULONG
104 type_names['float'] = TYPE_FLOAT
105 type_names['double'] = TYPE_DOUBLE
106 type_names['char*'] = TYPE_STRING
107 type_names['void*'] = TYPE_ANY
108 type_names['void'] = TYPE_NONE
109
110 # C unix types
111 type_names['off_t'] = TYPE_SIZET
112 type_names['pid_t'] = TYPE_INT
113 type_names['size_t'] = TYPE_SIZET
114 type_names['ssize_t'] = TYPE_SSIZET
115 type_names['socklen_t'] = TYPE_INT32
116
117 # Obj-C
118 type_names['id'] = TYPE_ANY
119
120 # Suppress some GLib names
121 type_names['uchar'] = TYPE_UINT8
122 type_names['ushort'] = TYPE_UINT16
123 type_names['size'] = TYPE_SIZET
124 type_names['ssize'] = TYPE_SSIZET
125 type_names['pointer'] = TYPE_ANY
126 type_names['constpointer'] = TYPE_ANY
127
128
129 # These types, when seen by reference, are converted into an Array()
130 # by default
131 # If you add/change these, be sure to update glibast.py too
132 default_array_types = {}
133 default_array_types['uint8*'] = TYPE_UINT8
134 default_array_types['utf8*'] = TYPE_STRING
135
136 # These types, when seen by reference, are interpreted as out parameters
137 default_out_types = (TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG,
138                      TYPE_FLOAT, TYPE_DOUBLE, TYPE_SIZET, TYPE_SSIZET)
139
140
141 def type_name_from_ctype(ctype):
142     return type_names.get(ctype, ctype)
143
144
145 class Node(object):
146
147     def __init__(self, name=None):
148         self.name = name
149         self.deprecated = None
150         self.deprecated_version = None
151         self.version = None
152
153     def __repr__(self):
154         return '%s(%r)' % (self.__class__.__name__, self.name)
155
156
157 class Namespace(Node):
158
159     def __init__(self, name, version):
160         Node.__init__(self, name)
161         self.version = version
162         self.nodes = []
163
164     def __repr__(self):
165         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
166                                    self.version, self.nodes)
167
168
169 class Include(Node):
170
171     def __init__(self, name, version):
172         Node.__init__(self, 'include')
173         self.name = name
174         self.version = version
175
176     @classmethod
177     def from_string(self, string):
178         return Include(*string.split('-', 1))
179
180     def __cmp__(self, other):
181         if not isinstance(other, Include):
182             return cmp(self, other)
183         namecmp = cmp(self.name, other.name)
184         if namecmp != 0:
185             return namecmp
186         return cmp(self.version, other.version)
187
188     def __hash__(self):
189         return hash((self.name, self.version))
190
191     def __str__(self):
192         return '%s-%s' % (self.name, self.version)
193
194
195 class Function(Node):
196
197     def __init__(self, name, retval, parameters, symbol, throws=None):
198         Node.__init__(self, name)
199         self.retval = retval
200         self.parameters = parameters
201         self.symbol = symbol
202         self.throws = not not throws
203         self.is_method = False
204         self.doc = None
205
206     def get_parameter_index(self, name):
207         for i, parameter in enumerate(self.parameters):
208             if parameter.name == name:
209                 return i + int(self.is_method)
210
211     def get_parameter(self, name):
212         for parameter in self.parameters:
213             if parameter.name == name:
214                 return parameter
215
216     def __repr__(self):
217         return '%s(%r, %r, %r)' % (self.__class__.__name__,
218                                    self.name, self.retval,
219                                    self.parameters)
220
221
222 class VFunction(Function):
223     pass
224
225
226 class Type(Node):
227
228     def __init__(self, name, ctype=None):
229         Node.__init__(self, name)
230         self.ctype = ctype
231         self.resolved = False
232         self.is_const = False
233         self.canonical = None
234         self.derefed_canonical = None
235
236
237 class Varargs(Type):
238
239     def __init__(self):
240         Type.__init__(self, '<varargs>')
241
242
243 class Array(Type):
244
245     def __init__(self, ctype, element_type):
246         Type.__init__(self, '<carray>', ctype)
247         self.element_type = element_type
248         self.zeroterminated = True
249         self.length_param_index = -1
250         self.length_param_name = None
251         self.size = None
252
253     def __repr__(self):
254         return 'Array(%r, %r)' % (self.name, self.element_type, )
255
256
257 class List(Type):
258
259     def __init__(self, name, ctype, element_type):
260         Type.__init__(self, name, ctype)
261         self.element_type = element_type
262
263     def __repr__(self):
264         return 'List(%r of %r)' % (self.name, self.element_type, )
265
266
267 class Map(Type):
268
269     def __init__(self, name, ctype, key_type, value_type):
270         Type.__init__(self, name, ctype)
271         self.key_type = key_type
272         self.value_type = value_type
273
274     def __repr__(self):
275         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
276
277
278 class Alias(Node):
279
280     def __init__(self, name, target, ctype=None):
281         Node.__init__(self, name)
282         self.target = target
283         self.ctype = ctype
284
285     def __repr__(self):
286         return 'Alias(%r, %r)' % (self.name, self.target)
287
288
289 class TypeContainer(Node):
290
291     def __init__(self, name, typenode, transfer):
292         Node.__init__(self, name)
293         self.type = typenode
294         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
295                         PARAM_TRANSFER_FULL]:
296             self.transfer = transfer
297         else:
298             self.transfer = None
299
300
301 class Parameter(TypeContainer):
302
303     def __init__(self, name, typenode, direction=None,
304                  transfer=None, allow_none=False, scope=None):
305         TypeContainer.__init__(self, name, typenode, transfer)
306         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
307                          PARAM_DIRECTION_INOUT, None]:
308             self.direction = direction
309         else:
310             self.direction = PARAM_DIRECTION_IN
311
312         self.allow_none = allow_none
313         self.scope = scope
314         self.closure_index = -1
315         self.destroy_index = -1
316         self.doc = None
317
318     def __repr__(self):
319         return 'Parameter(%r, %r)' % (self.name, self.type)
320
321
322 class Enum(Node):
323
324     def __init__(self, name, symbol, members):
325         Node.__init__(self, name)
326         self.symbol = symbol
327         self.members = members
328         self.doc = None
329
330     def __repr__(self):
331         return 'Enum(%r, %r)' % (self.name, self.members)
332
333
334 class Bitfield(Node):
335
336     def __init__(self, name, symbol, members):
337         Node.__init__(self, name)
338         self.symbol = symbol
339         self.members = members
340         self.doc = None
341
342     def __repr__(self):
343         return 'Bitfield(%r, %r)' % (self.name, self.members)
344
345
346 class Member(Node):
347
348     def __init__(self, name, value, symbol):
349         Node.__init__(self, name)
350         self.value = value
351         self.symbol = symbol
352
353     def __repr__(self):
354         return 'Member(%r, %r)' % (self.name, self.value)
355
356
357 class Record(Node):
358
359     def __init__(self, name, symbol, disguised=False):
360         Node.__init__(self, name)
361         self.fields = []
362         self.constructors = []
363         self.symbol = symbol
364         self.disguised = disguised
365         self.doc = None
366         self.constructors = []
367         self.methods = []
368
369 # BW compat, remove
370 Struct = Record
371
372
373 class Field(Node):
374
375     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
376         Node.__init__(self, name)
377         self.type = typenode
378         self.symbol = symbol
379         self.readable = readable
380         self.writable = writable
381         self.bits = bits
382
383     def __repr__(self):
384         if self.bits:
385             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
386         else:
387             return 'Field(%r, %r)' % (self.name, self.type)
388
389
390 class Return(TypeContainer):
391
392     def __init__(self, rtype, transfer=None):
393         TypeContainer.__init__(self, None, rtype, transfer)
394         self.direction = PARAM_DIRECTION_OUT
395         self.doc = None
396
397     def __repr__(self):
398         return 'Return(%r)' % (self.type, )
399
400
401 class Class(Node):
402
403     def __init__(self, name, parent, is_abstract):
404         Node.__init__(self, name)
405         self.ctype = name
406         self.parent = parent
407         self.is_abstract = is_abstract
408         self.methods = []
409         self.static_methods = []
410         self.interfaces = []
411         self.constructors = []
412         self.properties = []
413         self.fields = []
414         self.doc = None
415
416     def __repr__(self):
417         return '%s(%r, %r, %r)' % (
418             self.__class__.__name__,
419             self.name, self.parent, self.methods)
420
421
422 class Interface(Node):
423
424     def __init__(self, name, parent):
425         Node.__init__(self, name)
426         self.parent = parent
427         self.methods = []
428         self.properties = []
429         self.fields = []
430         self.prerequisites = []
431         self.doc = None
432
433     def __repr__(self):
434         return '%s(%r, %r)' % (
435             self.__class__.__name__,
436             self.name, self.methods)
437
438
439 class Constant(Node):
440
441     def __init__(self, name, type_name, value):
442         Node.__init__(self, name)
443         self.type = Type(type_name)
444         self.value = value
445
446     def __repr__(self):
447         return 'Constant(%r, %r, %r)' % (
448             self.name, self.type, self.value)
449
450
451 class Property(Node):
452
453     def __init__(self, name, type_name, readable, writable,
454                  construct, construct_only, ctype=None):
455         Node.__init__(self, name)
456         self.type = Type(type_name, ctype)
457         self.readable = readable
458         self.writable = writable
459         self.construct = construct
460         self.construct_only = construct_only
461         self.doc = None
462
463     def __repr__(self):
464         return '%s(%r, %r)' % (
465             self.__class__.__name__,
466             self.name, self.type)
467
468
469 # FIXME: Inherit from Function
470
471
472 class Callback(Node):
473
474     def __init__(self, name, retval, parameters, ctype=None):
475         Node.__init__(self, name)
476         self.retval = retval
477         self.parameters = parameters
478         self.ctype = ctype
479         self.throws = False
480         self.doc = None
481
482     def __repr__(self):
483         return 'Callback(%r, %r, %r)' % (
484             self.name, self.retval, self.parameters)
485
486
487 class Union(Node):
488
489     def __init__(self, name, symbol):
490         Node.__init__(self, name)
491         self.fields = []
492         self.constructors = []
493         self.methods = []
494         self.symbol = symbol
495         self.doc = None
496
497     def __repr__(self):
498         return 'Union(%r, %r)' % (self.name, self.fields, )