Bug 563591 – Flags not recognized when there is no introspection data
[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
205     def get_parameter_index(self, name):
206         for i, parameter in enumerate(self.parameters):
207             if parameter.name == name:
208                 return i + int(self.is_method)
209
210     def get_parameter(self, name):
211         for parameter in self.parameters:
212             if parameter.name == name:
213                 return parameter
214
215     def __repr__(self):
216         return '%s(%r, %r, %r)' % (self.__class__.__name__,
217                                    self.name, self.retval,
218                                    self.parameters)
219
220
221 class VFunction(Function):
222     pass
223
224
225 class Type(Node):
226
227     def __init__(self, name, ctype=None):
228         Node.__init__(self, name)
229         self.ctype = ctype
230         self.resolved = False
231         self.is_const = False
232         self.canonical = None
233         self.derefed_canonical = None
234
235
236 class Varargs(Type):
237
238     def __init__(self):
239         Type.__init__(self, '<varargs>')
240
241
242 class Array(Type):
243
244     def __init__(self, ctype, element_type):
245         Type.__init__(self, '<carray>', ctype)
246         self.element_type = element_type
247         self.zeroterminated = True
248         self.length_param_index = -1
249         self.length_param_name = None
250         self.size = None
251
252     def __repr__(self):
253         return 'Array(%r, %r)' % (self.name, self.element_type, )
254
255
256 class List(Type):
257
258     def __init__(self, name, ctype, element_type):
259         Type.__init__(self, name, ctype)
260         self.element_type = element_type
261
262     def __repr__(self):
263         return 'List(%r of %r)' % (self.name, self.element_type, )
264
265
266 class Map(Type):
267
268     def __init__(self, name, ctype, key_type, value_type):
269         Type.__init__(self, name, ctype)
270         self.key_type = key_type
271         self.value_type = value_type
272
273     def __repr__(self):
274         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
275
276
277 class Alias(Node):
278
279     def __init__(self, name, target, ctype=None):
280         Node.__init__(self, name)
281         self.target = target
282         self.ctype = ctype
283
284     def __repr__(self):
285         return 'Alias(%r, %r)' % (self.name, self.target)
286
287
288 class TypeContainer(Node):
289
290     def __init__(self, name, typenode, transfer):
291         Node.__init__(self, name)
292         self.type = typenode
293         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
294                         PARAM_TRANSFER_FULL]:
295             self.transfer = transfer
296         else:
297             self.transfer = None
298
299
300 class Parameter(TypeContainer):
301
302     def __init__(self, name, typenode, direction=None,
303                  transfer=None, allow_none=False, scope=None):
304         TypeContainer.__init__(self, name, typenode, transfer)
305         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
306                          PARAM_DIRECTION_INOUT, None]:
307             self.direction = direction
308         else:
309             self.direction = PARAM_DIRECTION_IN
310
311         self.allow_none = allow_none
312         self.scope = scope
313         self.closure_index = -1
314         self.destroy_index = -1
315
316     def __repr__(self):
317         return 'Parameter(%r, %r)' % (self.name, self.type)
318
319
320 class Enum(Node):
321
322     def __init__(self, name, symbol, members):
323         Node.__init__(self, name)
324         self.symbol = symbol
325         self.members = members
326
327     def __repr__(self):
328         return 'Enum(%r, %r)' % (self.name, self.members)
329
330
331 class Bitfield(Node):
332
333     def __init__(self, name, symbol, members):
334         Node.__init__(self, name)
335         self.symbol = symbol
336         self.members = members
337
338     def __repr__(self):
339         return 'Bitfield(%r, %r)' % (self.name, self.members)
340
341
342 class Member(Node):
343
344     def __init__(self, name, value, symbol):
345         Node.__init__(self, name)
346         self.value = value
347         self.symbol = symbol
348
349     def __repr__(self):
350         return 'Member(%r, %r)' % (self.name, self.value)
351
352
353 class Record(Node):
354
355     def __init__(self, name, symbol, disguised=False):
356         Node.__init__(self, name)
357         self.fields = []
358         self.constructors = []
359         self.symbol = symbol
360         self.disguised = disguised
361
362 # BW compat, remove
363 Struct = Record
364
365
366 class Field(Node):
367
368     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
369         Node.__init__(self, name)
370         self.type = typenode
371         self.symbol = symbol
372         self.readable = readable
373         self.writable = writable
374         self.bits = bits
375
376     def __repr__(self):
377         if self.bits:
378             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
379         else:
380             return 'Field(%r, %r)' % (self.name, self.type)
381
382
383 class Return(TypeContainer):
384
385     def __init__(self, rtype, transfer=None):
386         TypeContainer.__init__(self, None, rtype, transfer)
387         self.direction = PARAM_DIRECTION_OUT
388
389     def __repr__(self):
390         return 'Return(%r)' % (self.type, )
391
392
393 class Class(Node):
394
395     def __init__(self, name, parent, is_abstract):
396         Node.__init__(self, name)
397         self.ctype = name
398         self.parent = parent
399         self.is_abstract = is_abstract
400         self.methods = []
401         self.static_methods = []
402         self.interfaces = []
403         self.constructors = []
404         self.properties = []
405         self.fields = []
406
407     def __repr__(self):
408         return '%s(%r, %r, %r)' % (
409             self.__class__.__name__,
410             self.name, self.parent, self.methods)
411
412
413 class Interface(Node):
414
415     def __init__(self, name, parent):
416         Node.__init__(self, name)
417         self.parent = parent
418         self.methods = []
419         self.properties = []
420         self.fields = []
421         self.prerequisites = []
422
423     def __repr__(self):
424         return '%s(%r, %r)' % (
425             self.__class__.__name__,
426             self.name, self.methods)
427
428
429 class Constant(Node):
430
431     def __init__(self, name, type_name, value):
432         Node.__init__(self, name)
433         self.type = Type(type_name)
434         self.value = value
435
436     def __repr__(self):
437         return 'Constant(%r, %r, %r)' % (
438             self.name, self.type, self.value)
439
440
441 class Property(Node):
442
443     def __init__(self, name, type_name, readable, writable,
444                  construct, construct_only, ctype=None):
445         Node.__init__(self, name)
446         self.type = Type(type_name, ctype)
447         self.readable = readable
448         self.writable = writable
449         self.construct = construct
450         self.construct_only = construct_only
451
452     def __repr__(self):
453         return '%s(%r, %r)' % (
454             self.__class__.__name__,
455             self.name, self.type)
456
457
458 # FIXME: Inherit from Function
459
460
461 class Callback(Node):
462
463     def __init__(self, name, retval, parameters, ctype=None):
464         Node.__init__(self, name)
465         self.retval = retval
466         self.parameters = parameters
467         self.ctype = ctype
468         self.throws = False
469
470     def __repr__(self):
471         return 'Callback(%r, %r, %r)' % (
472             self.name, self.retval, self.parameters)
473
474
475 class Union(Node):
476
477     def __init__(self, name, symbol):
478         Node.__init__(self, name)
479         self.fields = []
480         self.constructors = []
481         self.symbol = symbol
482
483     def __repr__(self):
484         return 'Union(%r, %r)' % (self.name, self.fields, )