Add support for the 'foreign' annotation to g-i-scanner
[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         self.foreign = False
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 class Namespace(Node):
191
192     def __init__(self, name, version):
193         Node.__init__(self, name)
194         self.version = version
195         self.nodes = []
196
197     def __repr__(self):
198         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
199                                    self.version, self.nodes)
200
201     def remove_matching(self, pred):
202
203         def recursive_pred(node):
204             node.remove_matching_children(pred)
205             return pred(node)
206
207         self.nodes = filter(recursive_pred, self.nodes)
208
209 class Include(Node):
210
211     def __init__(self, name, version):
212         Node.__init__(self, 'include')
213         self.name = name
214         self.version = version
215
216     @classmethod
217     def from_string(self, string):
218         return Include(*string.split('-', 1))
219
220     def __cmp__(self, other):
221         if not isinstance(other, Include):
222             return cmp(self, other)
223         namecmp = cmp(self.name, other.name)
224         if namecmp != 0:
225             return namecmp
226         return cmp(self.version, other.version)
227
228     def __hash__(self):
229         return hash((self.name, self.version))
230
231     def __str__(self):
232         return '%s-%s' % (self.name, self.version)
233
234 class Callable(Node):
235
236     def __init__(self, name, retval, parameters, throws):
237         Node.__init__(self, name)
238         self.retval = retval
239         self.parameters = parameters
240         self.throws = not not throws
241         self.doc = None
242
243     def __repr__(self):
244         return '%s(%r, %r, %r)' % (self.__class__.__name__,
245                                    self.name, self.retval,
246                                    self.parameters)
247
248 class Function(Callable):
249
250     def __init__(self, name, retval, parameters, symbol, throws=None):
251         Callable.__init__(self, name, retval, parameters, throws)
252         self.symbol = symbol
253         self.is_method = False
254         self.doc = None
255
256     def get_parameter_index(self, name):
257         for i, parameter in enumerate(self.parameters):
258             if parameter.name == name:
259                 return i + int(self.is_method)
260
261     def get_parameter(self, name):
262         for parameter in self.parameters:
263             if parameter.name == name:
264                 return parameter
265
266
267 class VFunction(Callable):
268
269     def __init__(self, name, retval, parameters, throws):
270         Callable.__init__(self, name, retval, parameters, throws)
271         self.invoker = None
272
273     @classmethod
274     def from_callback(cls, cb):
275         obj = cls(cb.name, cb.retval, cb.parameters[1:],
276                   cb.throws)
277         return obj
278
279
280 class Type(Node):
281
282     def __init__(self, name, ctype=None):
283         Node.__init__(self, name)
284         self.ctype = ctype
285         self.resolved = False
286         self.is_const = False
287         self.canonical = None
288         self.derefed_canonical = None
289
290
291 class Varargs(Type):
292
293     def __init__(self):
294         Type.__init__(self, '<varargs>')
295
296
297 class Array(Type):
298
299     def __init__(self, name, ctype, element_type):
300         if name is None:
301             name = '<carray>'
302         Type.__init__(self, name, ctype)
303         self.element_type = element_type
304         self.zeroterminated = True
305         self.length_param_index = -1
306         self.length_param_name = None
307         self.size = None
308
309     def __repr__(self):
310         return 'Array(%r, %r)' % (self.name, self.element_type, )
311
312
313 class List(Type):
314
315     def __init__(self, name, ctype, element_type):
316         Type.__init__(self, name, ctype)
317         self.element_type = element_type
318
319     def __repr__(self):
320         return 'List(%r of %r)' % (self.name, self.element_type, )
321
322
323 class Map(Type):
324
325     def __init__(self, name, ctype, key_type, value_type):
326         Type.__init__(self, name, ctype)
327         self.key_type = key_type
328         self.value_type = value_type
329
330     def __repr__(self):
331         return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
332
333
334 class Alias(Node):
335
336     def __init__(self, name, target, ctype=None):
337         Node.__init__(self, name)
338         self.target = target
339         self.ctype = ctype
340
341     def __repr__(self):
342         return 'Alias(%r, %r)' % (self.name, self.target)
343
344
345 class TypeContainer(Node):
346
347     def __init__(self, name, typenode, transfer):
348         Node.__init__(self, name)
349         self.type = typenode
350         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
351                         PARAM_TRANSFER_FULL]:
352             self.transfer = transfer
353         else:
354             self.transfer = None
355
356
357 class Parameter(TypeContainer):
358
359     def __init__(self, name, typenode, direction=None,
360                  transfer=None, allow_none=False, scope=None):
361         TypeContainer.__init__(self, name, typenode, transfer)
362         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
363                          PARAM_DIRECTION_INOUT, None]:
364             self.direction = direction
365         else:
366             self.direction = PARAM_DIRECTION_IN
367
368         self.allow_none = allow_none
369         self.scope = scope
370         self.closure_index = -1
371         self.destroy_index = -1
372         self.doc = None
373
374     def __repr__(self):
375         return 'Parameter(%r, %r)' % (self.name, self.type)
376
377
378 class Enum(Node):
379
380     def __init__(self, name, symbol, members):
381         Node.__init__(self, name)
382         self.symbol = symbol
383         self.members = members
384         self.doc = None
385
386     def __repr__(self):
387         return 'Enum(%r, %r)' % (self.name, self.members)
388
389
390 class Bitfield(Node):
391
392     def __init__(self, name, symbol, members):
393         Node.__init__(self, name)
394         self.symbol = symbol
395         self.members = members
396         self.doc = None
397
398     def __repr__(self):
399         return 'Bitfield(%r, %r)' % (self.name, self.members)
400
401
402 class Member(Node):
403
404     def __init__(self, name, value, symbol):
405         Node.__init__(self, name)
406         self.value = value
407         self.symbol = symbol
408
409     def __repr__(self):
410         return 'Member(%r, %r)' % (self.name, self.value)
411
412
413 class Record(Node):
414
415     def __init__(self, name, symbol, disguised=False):
416         Node.__init__(self, name)
417         self.fields = []
418         self.constructors = []
419         self.symbol = symbol
420         self.disguised = disguised
421         self.doc = None
422         self.methods = []
423
424     def remove_matching_children(self, pred):
425         self.fields = filter(pred, self.fields)
426         self.constructors = filter(pred, self.constructors)
427         self.methods = filter(pred, self.methods)
428
429 # BW compat, remove
430 Struct = Record
431
432
433 class Field(Node):
434
435     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
436         Node.__init__(self, name)
437         self.type = typenode
438         self.symbol = symbol
439         self.readable = readable
440         self.writable = writable
441         self.bits = bits
442
443     def __repr__(self):
444         if self.bits:
445             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
446         else:
447             return 'Field(%r, %r)' % (self.name, self.type)
448
449
450 class Return(TypeContainer):
451
452     def __init__(self, rtype, transfer=None):
453         TypeContainer.__init__(self, None, rtype, transfer)
454         self.direction = PARAM_DIRECTION_OUT
455         self.doc = None
456
457     def __repr__(self):
458         return 'Return(%r)' % (self.type, )
459
460
461 class Class(Node):
462
463     def __init__(self, name, parent, is_abstract):
464         Node.__init__(self, name)
465         self.ctype = name
466         self.parent = parent
467         self.glib_type_struct = None
468         self.is_abstract = is_abstract
469         self.methods = []
470         self.virtual_methods = []
471         self.static_methods = []
472         self.interfaces = []
473         self.constructors = []
474         self.properties = []
475         self.fields = []
476         self.doc = None
477
478     def remove_matching_children(self, pred):
479         self.methods = filter(pred, self.methods)
480         self.constructors = filter(pred, self.constructors)
481         self.properties = filter(pred, self.properties)
482         self.fields = filter(pred, self.fields)
483
484     def __repr__(self):
485         return '%s(%r, %r, %r)' % (
486             self.__class__.__name__,
487             self.name, self.parent, self.methods)
488
489
490 class Interface(Node):
491
492     def __init__(self, name, parent):
493         Node.__init__(self, name)
494         self.parent = parent
495         self.methods = []
496         self.virtual_methods = []
497         self.glib_type_struct = None
498         self.properties = []
499         self.fields = []
500         self.prerequisites = []
501         self.doc = None
502
503     def __repr__(self):
504         return '%s(%r, %r)' % (
505             self.__class__.__name__,
506             self.name, self.methods)
507
508
509 class Constant(Node):
510
511     def __init__(self, name, type_name, value):
512         Node.__init__(self, name)
513         self.type = Type(type_name)
514         self.value = value
515
516     def __repr__(self):
517         return 'Constant(%r, %r, %r)' % (
518             self.name, self.type, self.value)
519
520
521 class Property(Node):
522
523     def __init__(self, name, type_name, readable, writable,
524                  construct, construct_only, ctype=None):
525         Node.__init__(self, name)
526         self.type = Type(type_name, ctype)
527         self.readable = readable
528         self.writable = writable
529         self.construct = construct
530         self.construct_only = construct_only
531         self.doc = None
532
533     def __repr__(self):
534         return '%s(%r, %r)' % (
535             self.__class__.__name__,
536             self.name, self.type)
537
538
539 # FIXME: Inherit from Function
540
541
542 class Callback(Node):
543
544     def __init__(self, name, retval, parameters, ctype=None):
545         Node.__init__(self, name)
546         self.retval = retval
547         self.parameters = parameters
548         self.ctype = ctype
549         self.throws = False
550         self.doc = None
551
552     def get_parameter_index(self, name):
553         for i, parameter in enumerate(self.parameters):
554             if parameter.name == name:
555                 return i
556
557     def get_parameter(self, name):
558         for parameter in self.parameters:
559             if parameter.name == name:
560                 return parameter
561
562     def __repr__(self):
563         return 'Callback(%r, %r, %r)' % (
564             self.name, self.retval, self.parameters)
565
566
567 class Union(Node):
568
569     def __init__(self, name, symbol):
570         Node.__init__(self, name)
571         self.fields = []
572         self.constructors = []
573         self.methods = []
574         self.symbol = symbol
575         self.doc = None
576
577     def __repr__(self):
578         return 'Union(%r, %r)' % (self.name, self.fields, )