Bug 560248 – "disguised structures"
[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 library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
9 #
10 # This library 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 GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, 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 # Obj-C
116 type_names['id'] = TYPE_ANY
117
118 # Suppress some GLib names
119 type_names['uchar'] = TYPE_UINT8
120 type_names['ushort'] = TYPE_UINT16
121 type_names['size'] = TYPE_SIZET
122 type_names['ssize'] = TYPE_SSIZET
123 type_names['pointer'] = TYPE_ANY
124 type_names['constpointer'] = TYPE_ANY
125
126
127 # These types, when seen by reference, are converted into an Array()
128 # by default
129 # If you add/change these, be sure to update glibast.py too
130 default_array_types = {}
131 default_array_types['uint8*'] = TYPE_UINT8
132 default_array_types['char**'] = TYPE_STRING
133
134 # These types, when seen by reference, are interpreted as out parameters
135 default_out_types = (TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG,
136                      TYPE_FLOAT, TYPE_DOUBLE, TYPE_SIZET, TYPE_SSIZET)
137
138
139 def type_name_from_ctype(ctype):
140     return type_names.get(ctype, ctype)
141
142
143 class Node(object):
144
145     def __init__(self, name=None):
146         self.name = name
147         self.deprecated = None
148         self.deprecated_version = None
149
150     def __repr__(self):
151         return '%s(%r)' % (self.__class__.__name__, self.name)
152
153
154 class Namespace(Node):
155
156     def __init__(self, name, version):
157         Node.__init__(self, name)
158         self.version = version
159         self.nodes = []
160
161     def __repr__(self):
162         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
163                                    self.version, self.nodes)
164
165
166 class Include(Node):
167
168     def __init__(self, name, version):
169         Node.__init__(self, 'include')
170         self.name = name
171         self.version = version
172
173     @classmethod
174     def from_string(self, string):
175         return Include(*string.split('-', 1))
176
177     def __cmp__(self, other):
178         if not isinstance(other, Include):
179             return cmp(self, other)
180         namecmp = cmp(self.name, other.name)
181         if namecmp != 0:
182             return namecmp
183         return cmp(self.version, other.version)
184
185     def __hash__(self):
186         return hash((self.name, self.version))
187
188     def __str__(self):
189         return '%s-%s' % (self.name, self.version)
190
191
192 class Function(Node):
193
194     def __init__(self, name, retval, parameters, symbol, throws=None):
195         Node.__init__(self, name)
196         self.retval = retval
197         self.parameters = parameters
198         self.symbol = symbol
199         self.throws = not not throws
200
201     def __repr__(self):
202         return '%s(%r, %r, %r)' % (self.__class__.__name__,
203                                    self.name, self.retval,
204                                    self.parameters)
205
206
207 class VFunction(Function):
208     pass
209
210
211 class Type(Node):
212
213     def __init__(self, name, ctype=None):
214         Node.__init__(self, name)
215         self.ctype = ctype
216         self.resolved = False
217
218
219 class Varargs(Type):
220
221     def __init__(self):
222         Type.__init__(self, '<varargs>')
223
224
225 class Array(Type):
226
227     def __init__(self, ctype, element_type):
228         Type.__init__(self, '<carray>', ctype)
229         self.element_type = element_type
230         self.zeroterminated = True
231         self.length_param_index = -1
232         self.length_param_name = None
233         self.size = None
234
235     def __repr__(self):
236         return 'Array(%r of %r)' % (self.name, self.element_type, )
237
238
239 class List(Type):
240
241     def __init__(self, name, ctype, element_type):
242         Type.__init__(self, name, ctype)
243         self.element_type = element_type
244
245     def __repr__(self):
246         return 'List(%r of %r)' % (self.name, self.element_type, )
247
248
249 class Map(Type):
250
251     def __init__(self, name, ctype, key_type, value_type):
252         Type.__init__(self, name, ctype)
253         self.key_type = key_type
254         self.value_type = value_type
255
256     def __repr__(self):
257         return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type)
258
259
260 class Alias(Node):
261
262     def __init__(self, name, target, ctype=None):
263         Node.__init__(self, name)
264         self.target = target
265         self.ctype = ctype
266
267     def __repr__(self):
268         return 'Alias(%r, %r)' % (self.name, self.target)
269
270
271 class TypeContainer(Node):
272
273     def __init__(self, name, typenode, transfer):
274         Node.__init__(self, name)
275         self.type = typenode
276         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
277                         PARAM_TRANSFER_FULL]:
278             self.transfer = transfer
279         else:
280             self.transfer = None
281
282         # transformer.py overrides this as needed
283         self.transfer_inferred = False
284
285
286 class Parameter(TypeContainer):
287
288     def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN,
289                  transfer=None, allow_none=False):
290         TypeContainer.__init__(self, name, typenode, transfer)
291         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
292                          PARAM_DIRECTION_INOUT]:
293             self.direction = direction
294         else:
295             self.direction = PARAM_DIRECTION_IN
296
297         self.allow_none = not not allow_none
298
299     def __repr__(self):
300         return 'Parameter(%r, %r)' % (self.name, self.type)
301
302
303 class Enum(Node):
304
305     def __init__(self, name, symbol, members):
306         Node.__init__(self, name)
307         self.symbol = symbol
308         self.members = members
309
310     def __repr__(self):
311         return 'Enum(%r, %r)' % (self.name, self.members)
312
313
314 class Member(Node):
315
316     def __init__(self, name, value, symbol):
317         Node.__init__(self, name)
318         self.value = value
319         self.symbol = symbol
320
321     def __repr__(self):
322         return 'Member(%r, %r)' % (self.name, self.value)
323
324
325 class Struct(Node):
326
327     def __init__(self, name, symbol, disguised=False):
328         Node.__init__(self, name)
329         self.fields = []
330         self.constructors = []
331         self.symbol = symbol
332         self.disguised = disguised
333
334
335 class Field(Node):
336
337     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
338         Node.__init__(self, name)
339         self.type = typenode
340         self.symbol = symbol
341         self.readable = readable
342         self.writable = writable
343         self.bits = bits
344
345     def __repr__(self):
346         if self.bits:
347             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
348         else:
349             return 'Field(%r, %r)' % (self.name, self.type)
350
351
352 class Return(TypeContainer):
353
354     def __init__(self, rtype, transfer=None):
355         TypeContainer.__init__(self, None, rtype, transfer)
356
357     def __repr__(self):
358         return 'Return(%r)' % (self.type, )
359
360
361 class Class(Node):
362
363     def __init__(self, name, parent, is_abstract):
364         Node.__init__(self, name)
365         self.ctype = name
366         self.parent = parent
367         self.is_abstract = is_abstract
368         self.methods = []
369         self.interfaces = []
370         self.constructors = []
371         self.properties = []
372         self.fields = []
373
374     def __repr__(self):
375         return '%s(%r, %r, %r)' % (
376             self.__class__.__name__,
377             self.name, self.parent, self.methods)
378
379
380 class Interface(Node):
381
382     def __init__(self, name, parent):
383         Node.__init__(self, name)
384         self.parent = parent
385         self.methods = []
386         self.properties = []
387         self.fields = []
388
389     def __repr__(self):
390         return '%s(%r, %r)' % (
391             self.__class__.__name__,
392             self.name, self.methods)
393
394
395 class Constant(Node):
396
397     def __init__(self, name, type_name, value):
398         Node.__init__(self, name)
399         self.type = Type(type_name)
400         self.value = value
401
402     def __repr__(self):
403         return 'Constant(%r, %r, %r)' % (
404             self.name, self.type, self.value)
405
406
407 class Property(Node):
408
409     def __init__(self, name, type_name, readable, writable,
410                  construct, construct_only, ctype=None):
411         Node.__init__(self, name)
412         self.type = Type(type_name, ctype)
413         self.readable = readable
414         self.writable = writable
415         self.construct = construct
416         self.construct_only = construct_only
417
418     def __repr__(self):
419         return '%s(%r, %r)' % (
420             self.__class__.__name__,
421             self.name, self.type)
422
423
424 # FIXME: Inherit from Function
425
426
427 class Callback(Node):
428
429     def __init__(self, name, retval, parameters, ctype=None):
430         Node.__init__(self, name)
431         self.retval = retval
432         self.parameters = parameters
433         self.ctype = ctype
434         self.throws = False
435
436     def __repr__(self):
437         return 'Callback(%r, %r, %r)' % (
438             self.name, self.retval, self.parameters)
439
440
441 class Union(Node):
442
443     def __init__(self, name, symbol):
444         Node.__init__(self, name)
445         self.fields = []
446         self.constructors = []
447         self.symbol = symbol
448
449     def __repr__(self):
450         return 'Union(%r, %r)' % (self.name, self.fields, )