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