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