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