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