5e2a010d63f947c8fb006567a4887261b6aa325b
[gnome.gobject-introspection] / 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, ctype, element_type):
279         Type.__init__(self, '<carray>', ctype)
280         self.element_type = element_type
281         self.zeroterminated = True
282         self.length_param_index = -1
283         self.length_param_name = None
284         self.size = None
285
286     def __repr__(self):
287         return 'Array(%r, %r)' % (self.name, self.element_type, )
288
289
290 class List(Type):
291
292     def __init__(self, name, ctype, element_type):
293         Type.__init__(self, name, ctype)
294         self.element_type = element_type
295
296     def __repr__(self):
297         return 'List(%r of %r)' % (self.name, self.element_type, )
298
299
300 class Map(Type):
301
302     def __init__(self, name, ctype, key_type, value_type):
303         Type.__init__(self, name, ctype)
304         self.key_type = key_type
305         self.value_type = value_type
306
307     def __repr__(self):
308         return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
309
310
311 class Alias(Node):
312
313     def __init__(self, name, target, ctype=None):
314         Node.__init__(self, name)
315         self.target = target
316         self.ctype = ctype
317
318     def __repr__(self):
319         return 'Alias(%r, %r)' % (self.name, self.target)
320
321
322 class TypeContainer(Node):
323
324     def __init__(self, name, typenode, transfer):
325         Node.__init__(self, name)
326         self.type = typenode
327         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
328                         PARAM_TRANSFER_FULL]:
329             self.transfer = transfer
330         else:
331             self.transfer = None
332
333
334 class Parameter(TypeContainer):
335
336     def __init__(self, name, typenode, direction=None,
337                  transfer=None, allow_none=False, scope=None):
338         TypeContainer.__init__(self, name, typenode, transfer)
339         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
340                          PARAM_DIRECTION_INOUT, None]:
341             self.direction = direction
342         else:
343             self.direction = PARAM_DIRECTION_IN
344
345         self.allow_none = allow_none
346         self.scope = scope
347         self.closure_index = -1
348         self.destroy_index = -1
349         self.doc = None
350
351     def __repr__(self):
352         return 'Parameter(%r, %r)' % (self.name, self.type)
353
354
355 class Enum(Node):
356
357     def __init__(self, name, symbol, members):
358         Node.__init__(self, name)
359         self.symbol = symbol
360         self.members = members
361         self.doc = None
362
363     def __repr__(self):
364         return 'Enum(%r, %r)' % (self.name, self.members)
365
366
367 class Bitfield(Node):
368
369     def __init__(self, name, symbol, members):
370         Node.__init__(self, name)
371         self.symbol = symbol
372         self.members = members
373         self.doc = None
374
375     def __repr__(self):
376         return 'Bitfield(%r, %r)' % (self.name, self.members)
377
378
379 class Member(Node):
380
381     def __init__(self, name, value, symbol):
382         Node.__init__(self, name)
383         self.value = value
384         self.symbol = symbol
385
386     def __repr__(self):
387         return 'Member(%r, %r)' % (self.name, self.value)
388
389
390 class Record(Node):
391
392     def __init__(self, name, symbol, disguised=False):
393         Node.__init__(self, name)
394         self.fields = []
395         self.constructors = []
396         self.symbol = symbol
397         self.disguised = disguised
398         self.doc = None
399         self.methods = []
400
401     def remove_matching_children(self, pred):
402         self.fields = filter(pred, self.fields)
403         self.constructors = filter(pred, self.constructors)
404         self.methods = filter(pred, self.methods)
405
406 # BW compat, remove
407 Struct = Record
408
409
410 class Field(Node):
411
412     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
413         Node.__init__(self, name)
414         self.type = typenode
415         self.symbol = symbol
416         self.readable = readable
417         self.writable = writable
418         self.bits = bits
419
420     def __repr__(self):
421         if self.bits:
422             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
423         else:
424             return 'Field(%r, %r)' % (self.name, self.type)
425
426
427 class Return(TypeContainer):
428
429     def __init__(self, rtype, transfer=None):
430         TypeContainer.__init__(self, None, rtype, transfer)
431         self.direction = PARAM_DIRECTION_OUT
432         self.doc = None
433
434     def __repr__(self):
435         return 'Return(%r)' % (self.type, )
436
437
438 class Class(Node):
439
440     def __init__(self, name, parent, is_abstract):
441         Node.__init__(self, name)
442         self.ctype = name
443         self.parent = parent
444         self.glib_type_struct = None
445         self.is_abstract = is_abstract
446         self.methods = []
447         self.virtual_methods = []
448         self.static_methods = []
449         self.interfaces = []
450         self.constructors = []
451         self.properties = []
452         self.fields = []
453         self.doc = None
454
455     def remove_matching_children(self, pred):
456         self.methods = filter(pred, self.methods)
457         self.constructors = filter(pred, self.constructors)
458         self.properties = filter(pred, self.properties)
459         self.fields = filter(pred, self.fields)
460
461     def __repr__(self):
462         return '%s(%r, %r, %r)' % (
463             self.__class__.__name__,
464             self.name, self.parent, self.methods)
465
466
467 class Interface(Node):
468
469     def __init__(self, name, parent):
470         Node.__init__(self, name)
471         self.parent = parent
472         self.methods = []
473         self.virtual_methods = []
474         self.glib_type_struct = None
475         self.properties = []
476         self.fields = []
477         self.prerequisites = []
478         self.doc = None
479
480     def __repr__(self):
481         return '%s(%r, %r)' % (
482             self.__class__.__name__,
483             self.name, self.methods)
484
485
486 class Constant(Node):
487
488     def __init__(self, name, type_name, value):
489         Node.__init__(self, name)
490         self.type = Type(type_name)
491         self.value = value
492
493     def __repr__(self):
494         return 'Constant(%r, %r, %r)' % (
495             self.name, self.type, self.value)
496
497
498 class Property(Node):
499
500     def __init__(self, name, type_name, readable, writable,
501                  construct, construct_only, ctype=None):
502         Node.__init__(self, name)
503         self.type = Type(type_name, ctype)
504         self.readable = readable
505         self.writable = writable
506         self.construct = construct
507         self.construct_only = construct_only
508         self.doc = None
509
510     def __repr__(self):
511         return '%s(%r, %r)' % (
512             self.__class__.__name__,
513             self.name, self.type)
514
515
516 # FIXME: Inherit from Function
517
518
519 class Callback(Node):
520
521     def __init__(self, name, retval, parameters, ctype=None):
522         Node.__init__(self, name)
523         self.retval = retval
524         self.parameters = parameters
525         self.ctype = ctype
526         self.throws = False
527         self.doc = None
528
529     def get_parameter_index(self, name):
530         for i, parameter in enumerate(self.parameters):
531             if parameter.name == name:
532                 return i
533
534     def get_parameter(self, name):
535         for parameter in self.parameters:
536             if parameter.name == name:
537                 return parameter
538
539     def __repr__(self):
540         return 'Callback(%r, %r, %r)' % (
541             self.name, self.retval, self.parameters)
542
543
544 class Union(Node):
545
546     def __init__(self, name, symbol):
547         Node.__init__(self, name)
548         self.fields = []
549         self.constructors = []
550         self.methods = []
551         self.symbol = symbol
552         self.doc = None
553
554     def __repr__(self):
555         return 'Union(%r, %r)' % (self.name, self.fields, )