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