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