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