Bug 571548 - Generic attributes
[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
162 class Namespace(Node):
163
164     def __init__(self, name, version):
165         Node.__init__(self, name)
166         self.version = version
167         self.nodes = []
168
169     def __repr__(self):
170         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
171                                    self.version, self.nodes)
172
173
174 class Include(Node):
175
176     def __init__(self, name, version):
177         Node.__init__(self, 'include')
178         self.name = name
179         self.version = version
180
181     @classmethod
182     def from_string(self, string):
183         return Include(*string.split('-', 1))
184
185     def __cmp__(self, other):
186         if not isinstance(other, Include):
187             return cmp(self, other)
188         namecmp = cmp(self.name, other.name)
189         if namecmp != 0:
190             return namecmp
191         return cmp(self.version, other.version)
192
193     def __hash__(self):
194         return hash((self.name, self.version))
195
196     def __str__(self):
197         return '%s-%s' % (self.name, self.version)
198
199
200 class Function(Node):
201
202     def __init__(self, name, retval, parameters, symbol, throws=None):
203         Node.__init__(self, name)
204         self.retval = retval
205         self.parameters = parameters
206         self.symbol = symbol
207         self.throws = not not throws
208         self.is_method = False
209         self.doc = None
210
211     def get_parameter_index(self, name):
212         for i, parameter in enumerate(self.parameters):
213             if parameter.name == name:
214                 return i + int(self.is_method)
215
216     def get_parameter(self, name):
217         for parameter in self.parameters:
218             if parameter.name == name:
219                 return parameter
220
221     def __repr__(self):
222         return '%s(%r, %r, %r)' % (self.__class__.__name__,
223                                    self.name, self.retval,
224                                    self.parameters)
225
226
227 class VFunction(Function):
228     pass
229
230
231 class Type(Node):
232
233     def __init__(self, name, ctype=None):
234         Node.__init__(self, name)
235         self.ctype = ctype
236         self.resolved = False
237         self.is_const = False
238         self.canonical = None
239         self.derefed_canonical = None
240
241
242 class Varargs(Type):
243
244     def __init__(self):
245         Type.__init__(self, '<varargs>')
246
247
248 class Array(Type):
249
250     def __init__(self, ctype, element_type):
251         Type.__init__(self, '<carray>', ctype)
252         self.element_type = element_type
253         self.zeroterminated = True
254         self.length_param_index = -1
255         self.length_param_name = None
256         self.size = None
257
258     def __repr__(self):
259         return 'Array(%r, %r)' % (self.name, self.element_type, )
260
261
262 class List(Type):
263
264     def __init__(self, name, ctype, element_type):
265         Type.__init__(self, name, ctype)
266         self.element_type = element_type
267
268     def __repr__(self):
269         return 'List(%r of %r)' % (self.name, self.element_type, )
270
271
272 class Map(Type):
273
274     def __init__(self, name, ctype, key_type, value_type):
275         Type.__init__(self, name, ctype)
276         self.key_type = key_type
277         self.value_type = value_type
278
279     def __repr__(self):
280         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
281
282
283 class Alias(Node):
284
285     def __init__(self, name, target, ctype=None):
286         Node.__init__(self, name)
287         self.target = target
288         self.ctype = ctype
289
290     def __repr__(self):
291         return 'Alias(%r, %r)' % (self.name, self.target)
292
293
294 class TypeContainer(Node):
295
296     def __init__(self, name, typenode, transfer):
297         Node.__init__(self, name)
298         self.type = typenode
299         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
300                         PARAM_TRANSFER_FULL]:
301             self.transfer = transfer
302         else:
303             self.transfer = None
304
305
306 class Parameter(TypeContainer):
307
308     def __init__(self, name, typenode, direction=None,
309                  transfer=None, allow_none=False, scope=None):
310         TypeContainer.__init__(self, name, typenode, transfer)
311         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
312                          PARAM_DIRECTION_INOUT, None]:
313             self.direction = direction
314         else:
315             self.direction = PARAM_DIRECTION_IN
316
317         self.allow_none = allow_none
318         self.scope = scope
319         self.closure_index = -1
320         self.destroy_index = -1
321         self.doc = None
322
323     def __repr__(self):
324         return 'Parameter(%r, %r)' % (self.name, self.type)
325
326
327 class Enum(Node):
328
329     def __init__(self, name, symbol, members):
330         Node.__init__(self, name)
331         self.symbol = symbol
332         self.members = members
333         self.doc = None
334
335     def __repr__(self):
336         return 'Enum(%r, %r)' % (self.name, self.members)
337
338
339 class Bitfield(Node):
340
341     def __init__(self, name, symbol, members):
342         Node.__init__(self, name)
343         self.symbol = symbol
344         self.members = members
345         self.doc = None
346
347     def __repr__(self):
348         return 'Bitfield(%r, %r)' % (self.name, self.members)
349
350
351 class Member(Node):
352
353     def __init__(self, name, value, symbol):
354         Node.__init__(self, name)
355         self.value = value
356         self.symbol = symbol
357
358     def __repr__(self):
359         return 'Member(%r, %r)' % (self.name, self.value)
360
361
362 class Record(Node):
363
364     def __init__(self, name, symbol, disguised=False):
365         Node.__init__(self, name)
366         self.fields = []
367         self.constructors = []
368         self.symbol = symbol
369         self.disguised = disguised
370         self.doc = None
371         self.methods = []
372
373 # BW compat, remove
374 Struct = Record
375
376
377 class Field(Node):
378
379     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
380         Node.__init__(self, name)
381         self.type = typenode
382         self.symbol = symbol
383         self.readable = readable
384         self.writable = writable
385         self.bits = bits
386
387     def __repr__(self):
388         if self.bits:
389             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
390         else:
391             return 'Field(%r, %r)' % (self.name, self.type)
392
393
394 class Return(TypeContainer):
395
396     def __init__(self, rtype, transfer=None):
397         TypeContainer.__init__(self, None, rtype, transfer)
398         self.direction = PARAM_DIRECTION_OUT
399         self.doc = None
400
401     def __repr__(self):
402         return 'Return(%r)' % (self.type, )
403
404
405 class Class(Node):
406
407     def __init__(self, name, parent, is_abstract):
408         Node.__init__(self, name)
409         self.ctype = name
410         self.parent = parent
411         self.glib_type_struct = None
412         self.is_abstract = is_abstract
413         self.methods = []
414         self.static_methods = []
415         self.interfaces = []
416         self.constructors = []
417         self.properties = []
418         self.fields = []
419         self.doc = None
420
421     def __repr__(self):
422         return '%s(%r, %r, %r)' % (
423             self.__class__.__name__,
424             self.name, self.parent, self.methods)
425
426
427 class Interface(Node):
428
429     def __init__(self, name, parent):
430         Node.__init__(self, name)
431         self.parent = parent
432         self.methods = []
433         self.glib_type_struct = None
434         self.properties = []
435         self.fields = []
436         self.prerequisites = []
437         self.doc = None
438
439     def __repr__(self):
440         return '%s(%r, %r)' % (
441             self.__class__.__name__,
442             self.name, self.methods)
443
444
445 class Constant(Node):
446
447     def __init__(self, name, type_name, value):
448         Node.__init__(self, name)
449         self.type = Type(type_name)
450         self.value = value
451
452     def __repr__(self):
453         return 'Constant(%r, %r, %r)' % (
454             self.name, self.type, self.value)
455
456
457 class Property(Node):
458
459     def __init__(self, name, type_name, readable, writable,
460                  construct, construct_only, ctype=None):
461         Node.__init__(self, name)
462         self.type = Type(type_name, ctype)
463         self.readable = readable
464         self.writable = writable
465         self.construct = construct
466         self.construct_only = construct_only
467         self.doc = None
468
469     def __repr__(self):
470         return '%s(%r, %r)' % (
471             self.__class__.__name__,
472             self.name, self.type)
473
474
475 # FIXME: Inherit from Function
476
477
478 class Callback(Node):
479
480     def __init__(self, name, retval, parameters, ctype=None):
481         Node.__init__(self, name)
482         self.retval = retval
483         self.parameters = parameters
484         self.ctype = ctype
485         self.throws = False
486         self.doc = None
487
488     def __repr__(self):
489         return 'Callback(%r, %r, %r)' % (
490             self.name, self.retval, self.parameters)
491
492
493 class Union(Node):
494
495     def __init__(self, name, symbol):
496         Node.__init__(self, name)
497         self.fields = []
498         self.constructors = []
499         self.methods = []
500         self.symbol = symbol
501         self.doc = None
502
503     def __repr__(self):
504         return 'Union(%r, %r)' % (self.name, self.fields, )