Bug 571483 - Sort toplevel .gir entries
[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 __cmp__(self, other):
154         return cmp(self.name, other.name)
155
156     def __repr__(self):
157         return '%s(%r)' % (self.__class__.__name__, self.name)
158
159
160 class Namespace(Node):
161
162     def __init__(self, name, version):
163         Node.__init__(self, name)
164         self.version = version
165         self.nodes = []
166
167     def __repr__(self):
168         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
169                                    self.version, self.nodes)
170
171
172 class Include(Node):
173
174     def __init__(self, name, version):
175         Node.__init__(self, 'include')
176         self.name = name
177         self.version = version
178
179     @classmethod
180     def from_string(self, string):
181         return Include(*string.split('-', 1))
182
183     def __cmp__(self, other):
184         if not isinstance(other, Include):
185             return cmp(self, other)
186         namecmp = cmp(self.name, other.name)
187         if namecmp != 0:
188             return namecmp
189         return cmp(self.version, other.version)
190
191     def __hash__(self):
192         return hash((self.name, self.version))
193
194     def __str__(self):
195         return '%s-%s' % (self.name, self.version)
196
197
198 class Function(Node):
199
200     def __init__(self, name, retval, parameters, symbol, throws=None):
201         Node.__init__(self, name)
202         self.retval = retval
203         self.parameters = parameters
204         self.symbol = symbol
205         self.throws = not not throws
206         self.is_method = False
207         self.doc = None
208
209     def get_parameter_index(self, name):
210         for i, parameter in enumerate(self.parameters):
211             if parameter.name == name:
212                 return i + int(self.is_method)
213
214     def get_parameter(self, name):
215         for parameter in self.parameters:
216             if parameter.name == name:
217                 return parameter
218
219     def __repr__(self):
220         return '%s(%r, %r, %r)' % (self.__class__.__name__,
221                                    self.name, self.retval,
222                                    self.parameters)
223
224
225 class VFunction(Function):
226     pass
227
228
229 class Type(Node):
230
231     def __init__(self, name, ctype=None):
232         Node.__init__(self, name)
233         self.ctype = ctype
234         self.resolved = False
235         self.is_const = False
236         self.canonical = None
237         self.derefed_canonical = None
238
239
240 class Varargs(Type):
241
242     def __init__(self):
243         Type.__init__(self, '<varargs>')
244
245
246 class Array(Type):
247
248     def __init__(self, ctype, element_type):
249         Type.__init__(self, '<carray>', ctype)
250         self.element_type = element_type
251         self.zeroterminated = True
252         self.length_param_index = -1
253         self.length_param_name = None
254         self.size = None
255
256     def __repr__(self):
257         return 'Array(%r, %r)' % (self.name, self.element_type, )
258
259
260 class List(Type):
261
262     def __init__(self, name, ctype, element_type):
263         Type.__init__(self, name, ctype)
264         self.element_type = element_type
265
266     def __repr__(self):
267         return 'List(%r of %r)' % (self.name, self.element_type, )
268
269
270 class Map(Type):
271
272     def __init__(self, name, ctype, key_type, value_type):
273         Type.__init__(self, name, ctype)
274         self.key_type = key_type
275         self.value_type = value_type
276
277     def __repr__(self):
278         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
279
280
281 class Alias(Node):
282
283     def __init__(self, name, target, ctype=None):
284         Node.__init__(self, name)
285         self.target = target
286         self.ctype = ctype
287
288     def __repr__(self):
289         return 'Alias(%r, %r)' % (self.name, self.target)
290
291
292 class TypeContainer(Node):
293
294     def __init__(self, name, typenode, transfer):
295         Node.__init__(self, name)
296         self.type = typenode
297         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
298                         PARAM_TRANSFER_FULL]:
299             self.transfer = transfer
300         else:
301             self.transfer = None
302
303
304 class Parameter(TypeContainer):
305
306     def __init__(self, name, typenode, direction=None,
307                  transfer=None, allow_none=False, scope=None):
308         TypeContainer.__init__(self, name, typenode, transfer)
309         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
310                          PARAM_DIRECTION_INOUT, None]:
311             self.direction = direction
312         else:
313             self.direction = PARAM_DIRECTION_IN
314
315         self.allow_none = allow_none
316         self.scope = scope
317         self.closure_index = -1
318         self.destroy_index = -1
319         self.doc = None
320
321     def __repr__(self):
322         return 'Parameter(%r, %r)' % (self.name, self.type)
323
324
325 class Enum(Node):
326
327     def __init__(self, name, symbol, members):
328         Node.__init__(self, name)
329         self.symbol = symbol
330         self.members = members
331         self.doc = None
332
333     def __repr__(self):
334         return 'Enum(%r, %r)' % (self.name, self.members)
335
336
337 class Bitfield(Node):
338
339     def __init__(self, name, symbol, members):
340         Node.__init__(self, name)
341         self.symbol = symbol
342         self.members = members
343         self.doc = None
344
345     def __repr__(self):
346         return 'Bitfield(%r, %r)' % (self.name, self.members)
347
348
349 class Member(Node):
350
351     def __init__(self, name, value, symbol):
352         Node.__init__(self, name)
353         self.value = value
354         self.symbol = symbol
355
356     def __repr__(self):
357         return 'Member(%r, %r)' % (self.name, self.value)
358
359
360 class Record(Node):
361
362     def __init__(self, name, symbol, disguised=False):
363         Node.__init__(self, name)
364         self.fields = []
365         self.constructors = []
366         self.symbol = symbol
367         self.disguised = disguised
368         self.doc = None
369         self.constructors = []
370         self.methods = []
371         # If true, this record defines the FooClass C structure
372         # for some Foo GObject
373         self.is_gobject_struct_for = False
374
375 # BW compat, remove
376 Struct = Record
377
378
379 class Field(Node):
380
381     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
382         Node.__init__(self, name)
383         self.type = typenode
384         self.symbol = symbol
385         self.readable = readable
386         self.writable = writable
387         self.bits = bits
388
389     def __repr__(self):
390         if self.bits:
391             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
392         else:
393             return 'Field(%r, %r)' % (self.name, self.type)
394
395
396 class Return(TypeContainer):
397
398     def __init__(self, rtype, transfer=None):
399         TypeContainer.__init__(self, None, rtype, transfer)
400         self.direction = PARAM_DIRECTION_OUT
401         self.doc = None
402
403     def __repr__(self):
404         return 'Return(%r)' % (self.type, )
405
406
407 class Class(Node):
408
409     def __init__(self, name, parent, is_abstract):
410         Node.__init__(self, name)
411         self.ctype = name
412         self.parent = parent
413         self.class_struct = None
414         self.is_abstract = is_abstract
415         self.methods = []
416         self.static_methods = []
417         self.interfaces = []
418         self.constructors = []
419         self.properties = []
420         self.fields = []
421         self.doc = None
422
423     def __repr__(self):
424         return '%s(%r, %r, %r)' % (
425             self.__class__.__name__,
426             self.name, self.parent, self.methods)
427
428
429 class Interface(Node):
430
431     def __init__(self, name, parent):
432         Node.__init__(self, name)
433         self.parent = parent
434         self.methods = []
435         self.properties = []
436         self.fields = []
437         self.prerequisites = []
438         self.doc = None
439
440     def __repr__(self):
441         return '%s(%r, %r)' % (
442             self.__class__.__name__,
443             self.name, self.methods)
444
445
446 class Constant(Node):
447
448     def __init__(self, name, type_name, value):
449         Node.__init__(self, name)
450         self.type = Type(type_name)
451         self.value = value
452
453     def __repr__(self):
454         return 'Constant(%r, %r, %r)' % (
455             self.name, self.type, self.value)
456
457
458 class Property(Node):
459
460     def __init__(self, name, type_name, readable, writable,
461                  construct, construct_only, ctype=None):
462         Node.__init__(self, name)
463         self.type = Type(type_name, ctype)
464         self.readable = readable
465         self.writable = writable
466         self.construct = construct
467         self.construct_only = construct_only
468         self.doc = None
469
470     def __repr__(self):
471         return '%s(%r, %r)' % (
472             self.__class__.__name__,
473             self.name, self.type)
474
475
476 # FIXME: Inherit from Function
477
478
479 class Callback(Node):
480
481     def __init__(self, name, retval, parameters, ctype=None):
482         Node.__init__(self, name)
483         self.retval = retval
484         self.parameters = parameters
485         self.ctype = ctype
486         self.throws = False
487         self.doc = None
488
489     def __repr__(self):
490         return 'Callback(%r, %r, %r)' % (
491             self.name, self.retval, self.parameters)
492
493
494 class Union(Node):
495
496     def __init__(self, name, symbol):
497         Node.__init__(self, name)
498         self.fields = []
499         self.constructors = []
500         self.methods = []
501         self.symbol = symbol
502         self.doc = None
503
504     def __repr__(self):
505         return 'Union(%r, %r)' % (self.name, self.fields, )