Bug 557241 – "throws" flag for functions
[gnome.gobject-introspection] / 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 Parameter(Node):
268
269     def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
270                  transfer=None, allow_none=False):
271         Node.__init__(self, name)
272         self.type = typenode
273         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
274                          PARAM_DIRECTION_INOUT]:
275             self.direction = direction
276         else:
277             self.direction = PARAM_DIRECTION_IN
278
279         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
280                         PARAM_TRANSFER_FULL]:
281             self.transfer = transfer
282         else:
283             self.transfer = None
284
285         self.allow_none = not not allow_none
286
287     def __repr__(self):
288         return 'Parameter(%r, %r)' % (self.name, self.type)
289
290
291 class Enum(Node):
292
293     def __init__(self, name, symbol, members):
294         Node.__init__(self, name)
295         self.symbol = symbol
296         self.members = members
297
298     def __repr__(self):
299         return 'Enum(%r, %r)' % (self.name, self.members)
300
301
302 class Member(Node):
303
304     def __init__(self, name, value, symbol):
305         Node.__init__(self, name)
306         self.value = value
307         self.symbol = symbol
308
309     def __repr__(self):
310         return 'Member(%r, %r)' % (self.name, self.value)
311
312
313 class Struct(Node):
314
315     def __init__(self, name, symbol):
316         Node.__init__(self, name)
317         self.fields = []
318         self.constructors = []
319         self.symbol = symbol
320
321
322 class Field(Node):
323
324     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
325         Node.__init__(self, name)
326         self.type = typenode
327         self.symbol = symbol
328         self.readable = readable
329         self.writable = writable
330         self.bits = bits
331
332     def __repr__(self):
333         if self.bits:
334             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
335         else:
336             return 'Field(%r, %r)' % (self.name, self.type)
337
338
339 class Return(Node):
340
341     def __init__(self, rtype, transfer=None):
342         Node.__init__(self)
343         self.type = rtype
344         if transfer is None and rtype.name in ['utf8', 'filename']:
345             self.transfer = 'full'
346         else:
347             self.transfer = transfer
348
349     def __repr__(self):
350         return 'Return(%r)' % (self.type, )
351
352
353 class Class(Node):
354
355     def __init__(self, name, parent, is_abstract):
356         Node.__init__(self, name)
357         self.ctype = name
358         self.parent = parent
359         self.is_abstract = is_abstract
360         self.methods = []
361         self.interfaces = []
362         self.constructors = []
363         self.properties = []
364         self.fields = []
365
366     def __repr__(self):
367         return '%s(%r, %r, %r)' % (
368             self.__class__.__name__,
369             self.name, self.parent, self.methods)
370
371
372 class Interface(Node):
373
374     def __init__(self, name, parent):
375         Node.__init__(self, name)
376         self.parent = parent
377         self.methods = []
378         self.properties = []
379         self.fields = []
380
381     def __repr__(self):
382         return '%s(%r, %r)' % (
383             self.__class__.__name__,
384             self.name, self.methods)
385
386
387 class Constant(Node):
388
389     def __init__(self, name, type_name, value):
390         Node.__init__(self, name)
391         self.type = Type(type_name)
392         self.value = value
393
394     def __repr__(self):
395         return 'Constant(%r, %r, %r)' % (
396             self.name, self.type, self.value)
397
398
399 class Property(Node):
400
401     def __init__(self, name, type_name, readable, writable,
402                  construct, construct_only, ctype=None):
403         Node.__init__(self, name)
404         self.type = Type(type_name, ctype)
405         self.readable = readable
406         self.writable = writable
407         self.construct = construct
408         self.construct_only = construct_only
409
410     def __repr__(self):
411         return '%s(%r, %r)' % (
412             self.__class__.__name__,
413             self.name, self.type)
414
415
416 # FIXME: Inherit from Function
417
418
419 class Callback(Node):
420
421     def __init__(self, name, retval, parameters, ctype=None):
422         Node.__init__(self, name)
423         self.retval = retval
424         self.parameters = parameters
425         self.ctype = ctype
426
427     def __repr__(self):
428         return 'Callback(%r, %r, %r)' % (
429             self.name, self.retval, self.parameters)
430
431
432 class Union(Node):
433
434     def __init__(self, name, symbol):
435         Node.__init__(self, name)
436         self.fields = []
437         self.constructors = []
438         self.symbol = symbol
439
440     def __repr__(self):
441         return 'Union(%r, %r)' % (self.name, self.fields, )