Add support for GArrays: add g_type_info_get_array_type() and properly scan GArray...
[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_TRANSFER_NONE = 'none'
86 PARAM_TRANSFER_CONTAINER = 'container'
87 PARAM_TRANSFER_FULL = 'full'
88
89 type_names = {}
90 for name in GIR_TYPES:
91     type_names[name] = name
92
93 # C builtin
94 type_names['char'] = TYPE_INT8
95 type_names['signed char'] = TYPE_INT8
96 type_names['unsigned char'] = TYPE_UINT8
97 type_names['short'] = TYPE_SHORT
98 type_names['signed short'] = TYPE_SHORT
99 type_names['unsigned short'] = TYPE_USHORT
100 type_names['int'] = TYPE_INT
101 type_names['signed int'] = TYPE_INT
102 type_names['signed'] = TYPE_INT
103 type_names['unsigned int'] = TYPE_UINT
104 type_names['unsigned'] = TYPE_UINT
105 type_names['long'] = TYPE_LONG
106 type_names['signed long'] = TYPE_LONG
107 type_names['unsigned long'] = TYPE_ULONG
108 type_names['float'] = TYPE_FLOAT
109 type_names['double'] = TYPE_DOUBLE
110 type_names['char*'] = TYPE_STRING
111 type_names['void*'] = TYPE_ANY
112 type_names['void'] = TYPE_NONE
113
114 # C unix types
115 type_names['off_t'] = TYPE_SIZET
116 type_names['pid_t'] = TYPE_INT
117 type_names['size_t'] = TYPE_SIZET
118 type_names['ssize_t'] = TYPE_SSIZET
119 type_names['socklen_t'] = TYPE_INT32
120
121 # Obj-C
122 type_names['id'] = TYPE_ANY
123
124 # Suppress some GLib names
125 type_names['uchar'] = TYPE_UINT8
126 type_names['ushort'] = TYPE_USHORT
127 type_names['size'] = TYPE_SIZET
128 type_names['ssize'] = TYPE_SSIZET
129 type_names['pointer'] = TYPE_ANY
130 type_names['constpointer'] = TYPE_ANY
131
132
133 # These types, when seen by reference, are converted into an Array()
134 # by default
135 # If you add/change these, be sure to update glibast.py too
136 default_array_types = {}
137 default_array_types['uint8*'] = TYPE_UINT8
138 default_array_types['utf8*'] = TYPE_STRING
139
140 # These types, when seen by reference, are interpreted as out parameters
141 default_out_types = (TYPE_SHORT, TYPE_USHORT, TYPE_INT, TYPE_UINT,
142                      TYPE_LONG, TYPE_ULONG, TYPE_FLOAT, TYPE_DOUBLE,
143                      TYPE_SIZET, TYPE_SSIZET)
144
145
146 def type_name_from_ctype(ctype):
147     return type_names.get(ctype, ctype)
148
149
150 class Node(object):
151
152     def __init__(self, name=None):
153         self.name = name
154         self.attributes = [] # (key, value)*
155         self.skip = False
156         self.deprecated = None
157         self.deprecated_version = None
158         self.version = None
159
160     def __cmp__(self, other):
161         return cmp(self.name, other.name)
162
163     def __repr__(self):
164         return '%s(%r)' % (self.__class__.__name__, self.name)
165
166     def remove_matching_children(self, pred):
167         pass
168
169 class Namespace(Node):
170
171     def __init__(self, name, version):
172         Node.__init__(self, name)
173         self.version = version
174         self.nodes = []
175
176     def __repr__(self):
177         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
178                                    self.version, self.nodes)
179
180     def remove_matching(self, pred):
181
182         def recursive_pred(node):
183             node.remove_matching_children(pred)
184             return pred(node)
185
186         self.nodes = filter(recursive_pred, self.nodes)
187
188 class Include(Node):
189
190     def __init__(self, name, version):
191         Node.__init__(self, 'include')
192         self.name = name
193         self.version = version
194
195     @classmethod
196     def from_string(self, string):
197         return Include(*string.split('-', 1))
198
199     def __cmp__(self, other):
200         if not isinstance(other, Include):
201             return cmp(self, other)
202         namecmp = cmp(self.name, other.name)
203         if namecmp != 0:
204             return namecmp
205         return cmp(self.version, other.version)
206
207     def __hash__(self):
208         return hash((self.name, self.version))
209
210     def __str__(self):
211         return '%s-%s' % (self.name, self.version)
212
213 class Callable(Node):
214
215     def __init__(self, name, retval, parameters, throws):
216         Node.__init__(self, name)
217         self.retval = retval
218         self.parameters = parameters
219         self.throws = not not throws
220         self.doc = None
221
222     def __repr__(self):
223         return '%s(%r, %r, %r)' % (self.__class__.__name__,
224                                    self.name, self.retval,
225                                    self.parameters)
226
227 class Function(Callable):
228
229     def __init__(self, name, retval, parameters, symbol, throws=None):
230         Callable.__init__(self, name, retval, parameters, throws)
231         self.symbol = symbol
232         self.is_method = False
233         self.doc = None
234
235     def get_parameter_index(self, name):
236         for i, parameter in enumerate(self.parameters):
237             if parameter.name == name:
238                 return i + int(self.is_method)
239
240     def get_parameter(self, name):
241         for parameter in self.parameters:
242             if parameter.name == name:
243                 return parameter
244
245
246 class VFunction(Callable):
247
248     def __init__(self, name, retval, parameters, throws):
249         Callable.__init__(self, name, retval, parameters, throws)
250         self.invoker = None
251
252     @classmethod
253     def from_callback(cls, cb):
254         obj = cls(cb.name, cb.retval, cb.parameters[1:],
255                   cb.throws)
256         return obj
257
258
259 class Type(Node):
260
261     def __init__(self, name, ctype=None):
262         Node.__init__(self, name)
263         self.ctype = ctype
264         self.resolved = False
265         self.is_const = False
266         self.canonical = None
267         self.derefed_canonical = None
268
269
270 class Varargs(Type):
271
272     def __init__(self):
273         Type.__init__(self, '<varargs>')
274
275
276 class Array(Type):
277
278     def __init__(self, name, ctype, element_type):
279         if name is None:
280             name = '<carray>'
281         Type.__init__(self, name, ctype)
282         self.element_type = element_type
283         self.zeroterminated = True
284         self.length_param_index = -1
285         self.length_param_name = None
286         self.size = None
287
288     def __repr__(self):
289         return 'Array(%r, %r)' % (self.name, self.element_type, )
290
291
292 class List(Type):
293
294     def __init__(self, name, ctype, element_type):
295         Type.__init__(self, name, ctype)
296         self.element_type = element_type
297
298     def __repr__(self):
299         return 'List(%r of %r)' % (self.name, self.element_type, )
300
301
302 class Map(Type):
303
304     def __init__(self, name, ctype, key_type, value_type):
305         Type.__init__(self, name, ctype)
306         self.key_type = key_type
307         self.value_type = value_type
308
309     def __repr__(self):
310         return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
311
312
313 class Alias(Node):
314
315     def __init__(self, name, target, ctype=None):
316         Node.__init__(self, name)
317         self.target = target
318         self.ctype = ctype
319
320     def __repr__(self):
321         return 'Alias(%r, %r)' % (self.name, self.target)
322
323
324 class TypeContainer(Node):
325
326     def __init__(self, name, typenode, transfer):
327         Node.__init__(self, name)
328         self.type = typenode
329         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
330                         PARAM_TRANSFER_FULL]:
331             self.transfer = transfer
332         else:
333             self.transfer = None
334
335
336 class Parameter(TypeContainer):
337
338     def __init__(self, name, typenode, direction=None,
339                  transfer=None, allow_none=False, scope=None):
340         TypeContainer.__init__(self, name, typenode, transfer)
341         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
342                          PARAM_DIRECTION_INOUT, None]:
343             self.direction = direction
344         else:
345             self.direction = PARAM_DIRECTION_IN
346
347         self.allow_none = allow_none
348         self.scope = scope
349         self.closure_index = -1
350         self.destroy_index = -1
351         self.doc = None
352
353     def __repr__(self):
354         return 'Parameter(%r, %r)' % (self.name, self.type)
355
356
357 class Enum(Node):
358
359     def __init__(self, name, symbol, members):
360         Node.__init__(self, name)
361         self.symbol = symbol
362         self.members = members
363         self.doc = None
364
365     def __repr__(self):
366         return 'Enum(%r, %r)' % (self.name, self.members)
367
368
369 class Bitfield(Node):
370
371     def __init__(self, name, symbol, members):
372         Node.__init__(self, name)
373         self.symbol = symbol
374         self.members = members
375         self.doc = None
376
377     def __repr__(self):
378         return 'Bitfield(%r, %r)' % (self.name, self.members)
379
380
381 class Member(Node):
382
383     def __init__(self, name, value, symbol):
384         Node.__init__(self, name)
385         self.value = value
386         self.symbol = symbol
387
388     def __repr__(self):
389         return 'Member(%r, %r)' % (self.name, self.value)
390
391
392 class Record(Node):
393
394     def __init__(self, name, symbol, disguised=False):
395         Node.__init__(self, name)
396         self.fields = []
397         self.constructors = []
398         self.symbol = symbol
399         self.disguised = disguised
400         self.doc = None
401         self.methods = []
402
403     def remove_matching_children(self, pred):
404         self.fields = filter(pred, self.fields)
405         self.constructors = filter(pred, self.constructors)
406         self.methods = filter(pred, self.methods)
407
408 # BW compat, remove
409 Struct = Record
410
411
412 class Field(Node):
413
414     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
415         Node.__init__(self, name)
416         self.type = typenode
417         self.symbol = symbol
418         self.readable = readable
419         self.writable = writable
420         self.bits = bits
421
422     def __repr__(self):
423         if self.bits:
424             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
425         else:
426             return 'Field(%r, %r)' % (self.name, self.type)
427
428
429 class Return(TypeContainer):
430
431     def __init__(self, rtype, transfer=None):
432         TypeContainer.__init__(self, None, rtype, transfer)
433         self.direction = PARAM_DIRECTION_OUT
434         self.doc = None
435
436     def __repr__(self):
437         return 'Return(%r)' % (self.type, )
438
439
440 class Class(Node):
441
442     def __init__(self, name, parent, is_abstract):
443         Node.__init__(self, name)
444         self.ctype = name
445         self.parent = parent
446         self.glib_type_struct = None
447         self.is_abstract = is_abstract
448         self.methods = []
449         self.virtual_methods = []
450         self.static_methods = []
451         self.interfaces = []
452         self.constructors = []
453         self.properties = []
454         self.fields = []
455         self.doc = None
456
457     def remove_matching_children(self, pred):
458         self.methods = filter(pred, self.methods)
459         self.constructors = filter(pred, self.constructors)
460         self.properties = filter(pred, self.properties)
461         self.fields = filter(pred, self.fields)
462
463     def __repr__(self):
464         return '%s(%r, %r, %r)' % (
465             self.__class__.__name__,
466             self.name, self.parent, self.methods)
467
468
469 class Interface(Node):
470
471     def __init__(self, name, parent):
472         Node.__init__(self, name)
473         self.parent = parent
474         self.methods = []
475         self.virtual_methods = []
476         self.glib_type_struct = None
477         self.properties = []
478         self.fields = []
479         self.prerequisites = []
480         self.doc = None
481
482     def __repr__(self):
483         return '%s(%r, %r)' % (
484             self.__class__.__name__,
485             self.name, self.methods)
486
487
488 class Constant(Node):
489
490     def __init__(self, name, type_name, value):
491         Node.__init__(self, name)
492         self.type = Type(type_name)
493         self.value = value
494
495     def __repr__(self):
496         return 'Constant(%r, %r, %r)' % (
497             self.name, self.type, self.value)
498
499
500 class Property(Node):
501
502     def __init__(self, name, type_name, readable, writable,
503                  construct, construct_only, ctype=None):
504         Node.__init__(self, name)
505         self.type = Type(type_name, ctype)
506         self.readable = readable
507         self.writable = writable
508         self.construct = construct
509         self.construct_only = construct_only
510         self.doc = None
511
512     def __repr__(self):
513         return '%s(%r, %r)' % (
514             self.__class__.__name__,
515             self.name, self.type)
516
517
518 # FIXME: Inherit from Function
519
520
521 class Callback(Node):
522
523     def __init__(self, name, retval, parameters, ctype=None):
524         Node.__init__(self, name)
525         self.retval = retval
526         self.parameters = parameters
527         self.ctype = ctype
528         self.throws = False
529         self.doc = None
530
531     def get_parameter_index(self, name):
532         for i, parameter in enumerate(self.parameters):
533             if parameter.name == name:
534                 return i
535
536     def get_parameter(self, name):
537         for parameter in self.parameters:
538             if parameter.name == name:
539                 return parameter
540
541     def __repr__(self):
542         return 'Callback(%r, %r, %r)' % (
543             self.name, self.retval, self.parameters)
544
545
546 class Union(Node):
547
548     def __init__(self, name, symbol):
549         Node.__init__(self, name)
550         self.fields = []
551         self.constructors = []
552         self.methods = []
553         self.symbol = symbol
554         self.doc = None
555
556     def __repr__(self):
557         return 'Union(%r, %r)' % (self.name, self.fields, )