Bug 556732 – generate gir files consistently
[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 program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program 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
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, 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
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 type_names['size_t'] = TYPE_SIZET
110 type_names['ssize_t'] = TYPE_SSIZET
111 type_names['off_t'] = TYPE_SIZET
112 # FIXME - can we make libraries use GPid?
113 type_names['pid_t'] = TYPE_INT
114
115 # Suppress some GLib names
116 type_names['uchar'] = TYPE_UINT8
117 type_names['ushort'] = TYPE_UINT16
118 type_names['size'] = TYPE_SIZET
119 type_names['ssize'] = TYPE_SSIZET
120 type_names['pointer'] = TYPE_ANY
121 type_names['constpointer'] = TYPE_ANY
122
123
124 # These types, when seen by reference, are converted into an Array()
125 # by default
126 default_array_types = {}
127 default_array_types['uint8*'] = TYPE_UINT8
128 default_array_types['char**'] = TYPE_STRING
129
130 # These types, when seen by reference, are interpreted as out parameters
131 default_out_types = (TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG,
132                      TYPE_FLOAT, TYPE_DOUBLE, TYPE_SIZET, TYPE_SSIZET)
133
134
135 def type_name_from_ctype(ctype):
136     return type_names.get(ctype, ctype)
137
138
139 class Node(object):
140
141     def __init__(self, name=None):
142         self.name = name
143         self.deprecated = None
144         self.deprecated_version = None
145
146     def __repr__(self):
147         return '%s(%r)' % (self.__class__.__name__, self.name)
148
149
150 class Namespace(Node):
151
152     def __init__(self, name, version):
153         Node.__init__(self, name)
154         self.version = version
155         self.nodes = []
156
157     def __repr__(self):
158         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
159                                    self.version, self.nodes)
160
161
162 class Include(Node):
163
164     def __init__(self, name, version):
165         Node.__init__(self, 'include')
166         self.name = name
167         self.version = version
168
169     @classmethod
170     def from_string(self, string):
171         return Include(*string.split('-', 1))
172
173     def __cmp__(self, other):
174         if not isinstance(other, Include):
175             return cmp(self, other)
176         namecmp = cmp(self.name, other.name)
177         if namecmp != 0:
178             return namecmp
179         return cmp(self.version, other.version)
180
181     def __hash__(self):
182         return hash((self.name, self.version))
183
184     def __str__(self):
185         return '%s-%s' % (self.name, self.version)
186
187
188 class Function(Node):
189
190     def __init__(self, name, retval, parameters, symbol):
191         Node.__init__(self, name)
192         self.retval = retval
193         self.parameters = parameters
194         self.symbol = symbol
195
196     def __repr__(self):
197         return '%s(%r, %r, %r)' % (self.__class__.__name__,
198                                    self.name, self.retval,
199                                    self.parameters)
200
201
202 class VFunction(Function):
203     pass
204
205
206 class Type(Node):
207
208     def __init__(self, name, ctype=None):
209         Node.__init__(self, name)
210         self.ctype = ctype
211         self.resolved = False
212
213
214 class Varargs(Type):
215
216     def __init__(self):
217         Type.__init__(self, '<varargs>')
218
219
220 class Array(Type):
221
222     def __init__(self, ctype, element_type):
223         Type.__init__(self, '<carray>', ctype)
224         self.element_type = element_type
225         self.zeroterminated = True
226         self.length_param_index = -1
227         self.length_param_name = None
228
229     def __repr__(self):
230         return 'Array(%r of %r)' % (self.name, self.element_type, )
231
232
233 class List(Type):
234
235     def __init__(self, name, ctype, element_type):
236         Type.__init__(self, name, ctype)
237         self.element_type = element_type
238
239     def __repr__(self):
240         return 'List(%r of %r)' % (self.name, self.element_type, )
241
242
243 class Map(Type):
244
245     def __init__(self, name, ctype, key_type, value_type):
246         Type.__init__(self, name, ctype)
247         self.key_type = key_type
248         self.value_type = value_type
249
250     def __repr__(self):
251         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
252
253
254 class Alias(Node):
255
256     def __init__(self, name, target, ctype=None):
257         Node.__init__(self, name)
258         self.target = target
259         self.ctype = ctype
260
261     def __repr__(self):
262         return 'Alias(%r, %r)' % (self.name, self.target)
263
264
265 class Parameter(Node):
266
267     def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
268                  transfer=None, allow_none=False):
269         Node.__init__(self, name)
270         self.type = typenode
271         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
272                          PARAM_DIRECTION_INOUT]:
273             self.direction = direction
274         else:
275             self.direction = PARAM_DIRECTION_IN
276
277         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
278                         PARAM_TRANSFER_FULL]:
279             self.transfer = transfer
280         else:
281             self.transfer = None
282
283         self.allow_none = not not allow_none
284
285     def __repr__(self):
286         return 'Parameter(%r, %r)' % (self.name, self.type)
287
288
289 class Enum(Node):
290
291     def __init__(self, name, symbol, members):
292         Node.__init__(self, name)
293         self.symbol = symbol
294         self.members = members
295
296     def __repr__(self):
297         return 'Enum(%r, %r)' % (self.name, self.members)
298
299
300 class Member(Node):
301
302     def __init__(self, name, value, symbol):
303         Node.__init__(self, name)
304         self.value = value
305         self.symbol = symbol
306
307     def __repr__(self):
308         return 'Member(%r, %r)' % (self.name, self.value)
309
310
311 class Struct(Node):
312
313     def __init__(self, name, symbol):
314         Node.__init__(self, name)
315         self.fields = []
316         self.constructors = []
317         self.symbol = symbol
318
319
320 class Field(Node):
321
322     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
323         Node.__init__(self, name)
324         self.type = typenode
325         self.symbol = symbol
326         self.readable = readable
327         self.writable = writable
328         self.bits = bits
329
330     def __repr__(self):
331         if self.bits:
332             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
333         else:
334             return 'Field(%r, %r)' % (self.name, self.type)
335
336
337 class Return(Node):
338
339     def __init__(self, rtype, transfer=None):
340         Node.__init__(self)
341         self.type = rtype
342         if transfer is None and rtype.name in ['utf8', 'filename']:
343             self.transfer = 'full'
344         else:
345             self.transfer = transfer
346
347     def __repr__(self):
348         return 'Return(%r)' % (self.type, )
349
350
351 class Class(Node):
352
353     def __init__(self, name, parent):
354         Node.__init__(self, name)
355         self.ctype = name
356         self.parent = parent
357         self.methods = []
358         self.interfaces = []
359         self.constructors = []
360         self.properties = []
361         self.fields = []
362
363     def __repr__(self):
364         return '%s(%r, %r, %r)' % (
365             self.__class__.__name__,
366             self.name, self.parent, self.methods)
367
368
369 class Interface(Node):
370
371     def __init__(self, name, parent):
372         Node.__init__(self, name)
373         self.parent = parent
374         self.methods = []
375         self.properties = []
376         self.fields = []
377
378     def __repr__(self):
379         return '%s(%r, %r)' % (
380             self.__class__.__name__,
381             self.name, self.methods)
382
383
384 class Constant(Node):
385
386     def __init__(self, name, type_name, value):
387         Node.__init__(self, name)
388         self.type = Type(type_name)
389         self.value = value
390
391     def __repr__(self):
392         return 'Constant(%r, %r, %r)' % (
393             self.name, self.type, self.value)
394
395
396 class Property(Node):
397
398     def __init__(self, name, type_name, readable, writable,
399                  construct, construct_only, ctype=None):
400         Node.__init__(self, name)
401         self.type = Type(type_name, ctype)
402         self.readable = readable
403         self.writable = writable
404         self.construct = construct
405         self.construct_only = construct_only
406
407     def __repr__(self):
408         return '%s(%r, %r, %r)' % (
409             self.__class__.__name__,
410             self.name, self.type, self.value)
411
412
413 # FIXME: Inherit from Function
414
415
416 class Callback(Node):
417
418     def __init__(self, name, retval, parameters, ctype=None):
419         Node.__init__(self, name)
420         self.retval = retval
421         self.parameters = parameters
422         self.ctype = ctype
423
424     def __repr__(self):
425         return 'Callback(%r, %r, %r)' % (
426             self.name, self.retval, self.parameters)
427
428
429 class Union(Node):
430
431     def __init__(self, name, symbol):
432         Node.__init__(self, name)
433         self.fields = []
434         self.constructors = []
435         self.symbol = symbol
436
437     def __repr__(self):
438         return 'Union(%r, %r)' % (self.name, self.fields, )