Always write out transfer-ownership attribute
[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 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 # 02110-1301, USA.
19 #
20
21 """AST nodes
22 This file descbribes abstract data type nodes independent on the
23 implementation language.
24
25 These can later on be extended (eg subclassed) with additional information
26 which is language/library/domain specific.
27 """
28
29 ##
30 ## Basic types, modeled on GITypeTag but not equivalent
31 ##
32
33 TYPE_NONE = 'none' # We differ from repository on these first two
34 TYPE_ANY = 'any'
35 TYPE_BOOLEAN = 'boolean'
36 TYPE_INT8 = 'int8'
37 TYPE_UINT8 = 'uint8'
38 TYPE_INT16 = 'int16'
39 TYPE_UINT16 = 'uint16'
40 TYPE_INT = 'int'
41 TYPE_UINT = 'uint'
42 TYPE_INT32 = 'int32'
43 TYPE_UINT32 = 'uint32'
44 TYPE_INT64 = 'int64'
45 TYPE_UINT64 = 'uint64'
46 TYPE_LONG = 'long'
47 TYPE_ULONG = 'ulong'
48 TYPE_SSIZET = 'ssize_t'
49 TYPE_SIZET = 'size_t'
50 TYPE_TIMET = 'time_t'
51 TYPE_GTYPE = 'GType'
52 TYPE_FLOAT = 'float'
53 TYPE_DOUBLE = 'double'
54 TYPE_STRING = 'utf8' # requires zero-terminated
55 TYPE_FILENAME = 'filename'
56
57 BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16,
58                    TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64,
59                    TYPE_UINT64, TYPE_INT, TYPE_UINT, TYPE_LONG,
60                    TYPE_ULONG, TYPE_SSIZET, TYPE_SIZET, TYPE_FLOAT,
61                    TYPE_DOUBLE, TYPE_TIMET, TYPE_GTYPE]
62 GIR_TYPES = [TYPE_NONE, TYPE_ANY]
63 GIR_TYPES.extend(BASIC_GIR_TYPES)
64 GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME])
65
66 # Higher-level data types
67 TYPE_SEQUENCE = 'sequence' # Sequence of something
68
69 # Wide/Unicode
70 TYPE_UCHAR = 'uchar'
71 TYPE_USTRING = 'ustring'
72
73 ##
74 ## Parameters
75 ##
76
77 PARAM_DIRECTION_IN = 'in'
78 PARAM_DIRECTION_OUT = 'out'
79 PARAM_DIRECTION_INOUT = 'inout'
80
81 PARAM_TRANSFER_NONE = 'none'
82 PARAM_TRANSFER_CONTAINER = 'container'
83 PARAM_TRANSFER_FULL = 'full'
84
85 type_names = {}
86 for name in GIR_TYPES:
87     type_names[name] = name
88
89 # C
90 type_names['char'] = TYPE_INT8
91 type_names['signed char'] = TYPE_INT8
92 type_names['unsigned char'] = TYPE_UINT8
93 type_names['short'] = TYPE_INT16
94 type_names['signed short'] = TYPE_INT16
95 type_names['unsigned short'] = TYPE_UINT16
96 type_names['int'] = TYPE_INT
97 type_names['signed int'] = TYPE_INT
98 type_names['signed'] = TYPE_INT
99 type_names['unsigned int'] = TYPE_UINT
100 type_names['unsigned'] = TYPE_UINT
101 type_names['long'] = TYPE_LONG
102 type_names['signed long'] = TYPE_LONG
103 type_names['unsigned long'] = TYPE_ULONG
104 type_names['float'] = TYPE_FLOAT
105 type_names['double'] = TYPE_DOUBLE
106 type_names['char*'] = TYPE_STRING
107 type_names['void*'] = TYPE_ANY
108 type_names['void'] = TYPE_NONE
109 type_names['size_t'] = TYPE_SIZET
110 type_names['ssize_t'] = TYPE_SSIZET
111 type_names['off_t'] = TYPE_SIZET
112 # FIXME - can we make libraries use GPid?
113 type_names['pid_t'] = TYPE_INT
114
115 # Suppress some GLib names
116 type_names['uchar'] = TYPE_UINT8
117 type_names['ushort'] = TYPE_UINT16
118 type_names['size'] = TYPE_SIZET
119 type_names['ssize'] = TYPE_SSIZET
120 type_names['pointer'] = TYPE_ANY
121 type_names['constpointer'] = TYPE_ANY
122
123
124 # These types, when seen by reference, are converted into an Array()
125 # by default
126 # If you add/change these, be sure to update glibast.py too
127 default_array_types = {}
128 default_array_types['uint8*'] = TYPE_UINT8
129 default_array_types['char**'] = TYPE_STRING
130
131 # These types, when seen by reference, are interpreted as out parameters
132 default_out_types = (TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG,
133                      TYPE_FLOAT, TYPE_DOUBLE, TYPE_SIZET, TYPE_SSIZET)
134
135
136 def type_name_from_ctype(ctype):
137     return type_names.get(ctype, ctype)
138
139
140 class Node(object):
141
142     def __init__(self, name=None):
143         self.name = name
144         self.deprecated = None
145         self.deprecated_version = None
146
147     def __repr__(self):
148         return '%s(%r)' % (self.__class__.__name__, self.name)
149
150
151 class Namespace(Node):
152
153     def __init__(self, name, version):
154         Node.__init__(self, name)
155         self.version = version
156         self.nodes = []
157
158     def __repr__(self):
159         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
160                                    self.version, self.nodes)
161
162
163 class Include(Node):
164
165     def __init__(self, name, version):
166         Node.__init__(self, 'include')
167         self.name = name
168         self.version = version
169
170     @classmethod
171     def from_string(self, string):
172         return Include(*string.split('-', 1))
173
174     def __cmp__(self, other):
175         if not isinstance(other, Include):
176             return cmp(self, other)
177         namecmp = cmp(self.name, other.name)
178         if namecmp != 0:
179             return namecmp
180         return cmp(self.version, other.version)
181
182     def __hash__(self):
183         return hash((self.name, self.version))
184
185     def __str__(self):
186         return '%s-%s' % (self.name, self.version)
187
188
189 class Function(Node):
190
191     def __init__(self, name, retval, parameters, symbol, throws=None):
192         Node.__init__(self, name)
193         self.retval = retval
194         self.parameters = parameters
195         self.symbol = symbol
196         self.throws = not not throws
197
198     def __repr__(self):
199         return '%s(%r, %r, %r)' % (self.__class__.__name__,
200                                    self.name, self.retval,
201                                    self.parameters)
202
203
204 class VFunction(Function):
205     pass
206
207
208 class Type(Node):
209
210     def __init__(self, name, ctype=None):
211         Node.__init__(self, name)
212         self.ctype = ctype
213         self.resolved = False
214
215
216 class Varargs(Type):
217
218     def __init__(self):
219         Type.__init__(self, '<varargs>')
220
221
222 class Array(Type):
223
224     def __init__(self, ctype, element_type):
225         Type.__init__(self, '<carray>', ctype)
226         self.element_type = element_type
227         self.zeroterminated = True
228         self.length_param_index = -1
229         self.length_param_name = None
230
231     def __repr__(self):
232         return 'Array(%r of %r)' % (self.name, self.element_type, )
233
234
235 class List(Type):
236
237     def __init__(self, name, ctype, element_type):
238         Type.__init__(self, name, ctype)
239         self.element_type = element_type
240
241     def __repr__(self):
242         return 'List(%r of %r)' % (self.name, self.element_type, )
243
244
245 class Map(Type):
246
247     def __init__(self, name, ctype, key_type, value_type):
248         Type.__init__(self, name, ctype)
249         self.key_type = key_type
250         self.value_type = value_type
251
252     def __repr__(self):
253         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
254
255
256 class Alias(Node):
257
258     def __init__(self, name, target, ctype=None):
259         Node.__init__(self, name)
260         self.target = target
261         self.ctype = ctype
262
263     def __repr__(self):
264         return 'Alias(%r, %r)' % (self.name, self.target)
265
266
267 class TypeContainer(Node):
268
269     def __init__(self, name, typenode, transfer):
270         Node.__init__(self, name)
271         self.type = typenode
272         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
273                         PARAM_TRANSFER_FULL]:
274             self.transfer = transfer
275         else:
276             self.transfer = None
277
278         # transformer.py overrides this as needed
279         self.transfer_inferred = False
280
281
282 class Parameter(TypeContainer):
283
284     def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
285                  transfer=None, allow_none=False):
286         TypeContainer.__init__(self, name, typenode, transfer)
287         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
288                          PARAM_DIRECTION_INOUT]:
289             self.direction = direction
290         else:
291             self.direction = PARAM_DIRECTION_IN
292
293         self.allow_none = not not allow_none
294
295     def __repr__(self):
296         return 'Parameter(%r, %r)' % (self.name, self.type)
297
298
299 class Enum(Node):
300
301     def __init__(self, name, symbol, members):
302         Node.__init__(self, name)
303         self.symbol = symbol
304         self.members = members
305
306     def __repr__(self):
307         return 'Enum(%r, %r)' % (self.name, self.members)
308
309
310 class Member(Node):
311
312     def __init__(self, name, value, symbol):
313         Node.__init__(self, name)
314         self.value = value
315         self.symbol = symbol
316
317     def __repr__(self):
318         return 'Member(%r, %r)' % (self.name, self.value)
319
320
321 class Struct(Node):
322
323     def __init__(self, name, symbol):
324         Node.__init__(self, name)
325         self.fields = []
326         self.constructors = []
327         self.symbol = symbol
328
329
330 class Field(Node):
331
332     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
333         Node.__init__(self, name)
334         self.type = typenode
335         self.symbol = symbol
336         self.readable = readable
337         self.writable = writable
338         self.bits = bits
339
340     def __repr__(self):
341         if self.bits:
342             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
343         else:
344             return 'Field(%r, %r)' % (self.name, self.type)
345
346
347 class Return(TypeContainer):
348
349     def __init__(self, rtype, transfer=None):
350         TypeContainer.__init__(self, None, rtype, transfer)
351
352     def __repr__(self):
353         return 'Return(%r)' % (self.type, )
354
355
356 class Class(Node):
357
358     def __init__(self, name, parent, is_abstract):
359         Node.__init__(self, name)
360         self.ctype = name
361         self.parent = parent
362         self.is_abstract = is_abstract
363         self.methods = []
364         self.interfaces = []
365         self.constructors = []
366         self.properties = []
367         self.fields = []
368
369     def __repr__(self):
370         return '%s(%r, %r, %r)' % (
371             self.__class__.__name__,
372             self.name, self.parent, self.methods)
373
374
375 class Interface(Node):
376
377     def __init__(self, name, parent):
378         Node.__init__(self, name)
379         self.parent = parent
380         self.methods = []
381         self.properties = []
382         self.fields = []
383
384     def __repr__(self):
385         return '%s(%r, %r)' % (
386             self.__class__.__name__,
387             self.name, self.methods)
388
389
390 class Constant(Node):
391
392     def __init__(self, name, type_name, value):
393         Node.__init__(self, name)
394         self.type = Type(type_name)
395         self.value = value
396
397     def __repr__(self):
398         return 'Constant(%r, %r, %r)' % (
399             self.name, self.type, self.value)
400
401
402 class Property(Node):
403
404     def __init__(self, name, type_name, readable, writable,
405                  construct, construct_only, ctype=None):
406         Node.__init__(self, name)
407         self.type = Type(type_name, ctype)
408         self.readable = readable
409         self.writable = writable
410         self.construct = construct
411         self.construct_only = construct_only
412
413     def __repr__(self):
414         return '%s(%r, %r)' % (
415             self.__class__.__name__,
416             self.name, self.type)
417
418
419 # FIXME: Inherit from Function
420
421
422 class Callback(Node):
423
424     def __init__(self, name, retval, parameters, ctype=None):
425         Node.__init__(self, name)
426         self.retval = retval
427         self.parameters = parameters
428         self.ctype = ctype
429
430     def __repr__(self):
431         return 'Callback(%r, %r, %r)' % (
432             self.name, self.retval, self.parameters)
433
434
435 class Union(Node):
436
437     def __init__(self, name, symbol):
438         Node.__init__(self, name)
439         self.fields = []
440         self.constructors = []
441         self.symbol = symbol
442
443     def __repr__(self):
444         return 'Union(%r, %r)' % (self.name, self.fields, )