Bug 557786 - support fixed size arrays
[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         self.size = None
231
232     def __repr__(self):
233         return 'Array(%r of %r)' % (self.name, self.element_type, )
234
235
236 class List(Type):
237
238     def __init__(self, name, ctype, element_type):
239         Type.__init__(self, name, ctype)
240         self.element_type = element_type
241
242     def __repr__(self):
243         return 'List(%r of %r)' % (self.name, self.element_type, )
244
245
246 class Map(Type):
247
248     def __init__(self, name, ctype, key_type, value_type):
249         Type.__init__(self, name, ctype)
250         self.key_type = key_type
251         self.value_type = value_type
252
253     def __repr__(self):
254         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
255
256
257 class Alias(Node):
258
259     def __init__(self, name, target, ctype=None):
260         Node.__init__(self, name)
261         self.target = target
262         self.ctype = ctype
263
264     def __repr__(self):
265         return 'Alias(%r, %r)' % (self.name, self.target)
266
267
268 class TypeContainer(Node):
269
270     def __init__(self, name, typenode, transfer):
271         Node.__init__(self, name)
272         self.type = typenode
273         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
274                         PARAM_TRANSFER_FULL]:
275             self.transfer = transfer
276         else:
277             self.transfer = None
278
279         # transformer.py overrides this as needed
280         self.transfer_inferred = False
281
282
283 class Parameter(TypeContainer):
284
285     def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
286                  transfer=None, allow_none=False):
287         TypeContainer.__init__(self, name, typenode, transfer)
288         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
289                          PARAM_DIRECTION_INOUT]:
290             self.direction = direction
291         else:
292             self.direction = PARAM_DIRECTION_IN
293
294         self.allow_none = not not allow_none
295
296     def __repr__(self):
297         return 'Parameter(%r, %r)' % (self.name, self.type)
298
299
300 class Enum(Node):
301
302     def __init__(self, name, symbol, members):
303         Node.__init__(self, name)
304         self.symbol = symbol
305         self.members = members
306
307     def __repr__(self):
308         return 'Enum(%r, %r)' % (self.name, self.members)
309
310
311 class Member(Node):
312
313     def __init__(self, name, value, symbol):
314         Node.__init__(self, name)
315         self.value = value
316         self.symbol = symbol
317
318     def __repr__(self):
319         return 'Member(%r, %r)' % (self.name, self.value)
320
321
322 class Struct(Node):
323
324     def __init__(self, name, symbol):
325         Node.__init__(self, name)
326         self.fields = []
327         self.constructors = []
328         self.symbol = symbol
329
330
331 class Field(Node):
332
333     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
334         Node.__init__(self, name)
335         self.type = typenode
336         self.symbol = symbol
337         self.readable = readable
338         self.writable = writable
339         self.bits = bits
340
341     def __repr__(self):
342         if self.bits:
343             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
344         else:
345             return 'Field(%r, %r)' % (self.name, self.type)
346
347
348 class Return(TypeContainer):
349
350     def __init__(self, rtype, transfer=None):
351         TypeContainer.__init__(self, None, rtype, transfer)
352
353     def __repr__(self):
354         return 'Return(%r)' % (self.type, )
355
356
357 class Class(Node):
358
359     def __init__(self, name, parent, is_abstract):
360         Node.__init__(self, name)
361         self.ctype = name
362         self.parent = parent
363         self.is_abstract = is_abstract
364         self.methods = []
365         self.interfaces = []
366         self.constructors = []
367         self.properties = []
368         self.fields = []
369
370     def __repr__(self):
371         return '%s(%r, %r, %r)' % (
372             self.__class__.__name__,
373             self.name, self.parent, self.methods)
374
375
376 class Interface(Node):
377
378     def __init__(self, name, parent):
379         Node.__init__(self, name)
380         self.parent = parent
381         self.methods = []
382         self.properties = []
383         self.fields = []
384
385     def __repr__(self):
386         return '%s(%r, %r)' % (
387             self.__class__.__name__,
388             self.name, self.methods)
389
390
391 class Constant(Node):
392
393     def __init__(self, name, type_name, value):
394         Node.__init__(self, name)
395         self.type = Type(type_name)
396         self.value = value
397
398     def __repr__(self):
399         return 'Constant(%r, %r, %r)' % (
400             self.name, self.type, self.value)
401
402
403 class Property(Node):
404
405     def __init__(self, name, type_name, readable, writable,
406                  construct, construct_only, ctype=None):
407         Node.__init__(self, name)
408         self.type = Type(type_name, ctype)
409         self.readable = readable
410         self.writable = writable
411         self.construct = construct
412         self.construct_only = construct_only
413
414     def __repr__(self):
415         return '%s(%r, %r)' % (
416             self.__class__.__name__,
417             self.name, self.type)
418
419
420 # FIXME: Inherit from Function
421
422
423 class Callback(Node):
424
425     def __init__(self, name, retval, parameters, ctype=None):
426         Node.__init__(self, name)
427         self.retval = retval
428         self.parameters = parameters
429         self.ctype = ctype
430
431     def __repr__(self):
432         return 'Callback(%r, %r, %r)' % (
433             self.name, self.retval, self.parameters)
434
435
436 class Union(Node):
437
438     def __init__(self, name, symbol):
439         Node.__init__(self, name)
440         self.fields = []
441         self.constructors = []
442         self.symbol = symbol
443
444     def __repr__(self):
445         return 'Union(%r, %r)' % (self.name, self.fields, )