[TYPE_SUPPORT] Better type support
[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_SHORT = 'short'
40 TYPE_USHORT = 'ushort'
41 TYPE_INT16 = 'int16'
42 TYPE_UINT16 = 'uint16'
43 TYPE_INT = 'int'
44 TYPE_UINT = 'uint'
45 TYPE_INT32 = 'int32'
46 TYPE_UINT32 = 'uint32'
47 TYPE_INT64 = 'int64'
48 TYPE_UINT64 = 'uint64'
49 TYPE_LONG = 'long'
50 TYPE_ULONG = 'ulong'
51 TYPE_SSIZET = 'ssize_t'
52 TYPE_SIZET = 'size_t'
53 TYPE_TIMET = 'time_t'
54 TYPE_GTYPE = 'GType'
55 TYPE_FLOAT = 'float'
56 TYPE_DOUBLE = 'double'
57 TYPE_STRING = 'utf8' # requires zero-terminated
58 TYPE_FILENAME = 'filename'
59
60 BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16,
61                    TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64,
62                    TYPE_UINT64, TYPE_SHORT, TYPE_USHORT, TYPE_INT,
63                    TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_SSIZET,
64                    TYPE_SIZET, TYPE_FLOAT, TYPE_DOUBLE, TYPE_TIMET,
65                    TYPE_GTYPE]
66 GIR_TYPES = [TYPE_NONE, TYPE_ANY]
67 GIR_TYPES.extend(BASIC_GIR_TYPES)
68 GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME])
69
70 # Higher-level data types
71 TYPE_SEQUENCE = 'sequence' # Sequence of something
72
73 # Wide/Unicode
74 TYPE_UCHAR = 'uchar'
75 TYPE_USTRING = 'ustring'
76
77 ##
78 ## Parameters
79 ##
80
81 PARAM_DIRECTION_IN = 'in'
82 PARAM_DIRECTION_OUT = 'out'
83 PARAM_DIRECTION_INOUT = 'inout'
84
85 PARAM_TRANSFER_NONE = 'none'
86 PARAM_TRANSFER_CONTAINER = 'container'
87 PARAM_TRANSFER_FULL = 'full'
88
89 type_names = {}
90 for name in GIR_TYPES:
91     type_names[name] = name
92
93 # C builtin
94 type_names['char'] = TYPE_INT8
95 type_names['signed char'] = TYPE_INT8
96 type_names['unsigned char'] = TYPE_UINT8
97 type_names['short'] = TYPE_SHORT
98 type_names['signed short'] = TYPE_SHORT
99 type_names['unsigned short'] = TYPE_USHORT
100 type_names['int'] = TYPE_INT
101 type_names['signed int'] = TYPE_INT
102 type_names['unsigned short int'] = TYPE_USHORT
103 type_names['signed'] = TYPE_INT
104 type_names['unsigned int'] = TYPE_UINT
105 type_names['unsigned'] = TYPE_UINT
106 type_names['long'] = TYPE_LONG
107 type_names['signed long'] = TYPE_LONG
108 type_names['unsigned long'] = TYPE_ULONG
109 type_names['unsigned long int'] = TYPE_ULONG
110 type_names['float'] = TYPE_FLOAT
111 type_names['double'] = TYPE_DOUBLE
112 type_names['char*'] = TYPE_STRING
113 type_names['void*'] = TYPE_ANY
114 type_names['void'] = TYPE_NONE
115
116 # C unix types
117 type_names['off_t'] = TYPE_SIZET
118 type_names['pid_t'] = TYPE_INT
119 type_names['size_t'] = TYPE_SIZET
120 type_names['ssize_t'] = TYPE_SSIZET
121 type_names['socklen_t'] = TYPE_INT32
122
123 # Obj-C
124 type_names['id'] = TYPE_ANY
125
126 # Suppress some GLib names
127 type_names['uchar'] = TYPE_UINT8
128 type_names['ushort'] = TYPE_USHORT
129 type_names['size'] = TYPE_SIZET
130 type_names['ssize'] = TYPE_SSIZET
131 type_names['pointer'] = TYPE_ANY
132 type_names['constpointer'] = TYPE_ANY
133
134
135 # These types, when seen by reference, are converted into an Array()
136 # by default
137 # If you add/change these, be sure to update glibast.py too
138 default_array_types = {}
139 default_array_types['uint8*'] = TYPE_UINT8
140 default_array_types['utf8*'] = TYPE_STRING
141
142 # These types, when seen by reference, are interpreted as out parameters
143 default_out_types = (TYPE_SHORT, TYPE_USHORT, TYPE_INT, TYPE_UINT,
144                      TYPE_LONG, TYPE_ULONG, TYPE_FLOAT, TYPE_DOUBLE,
145                      TYPE_SIZET, TYPE_SSIZET)
146
147
148 def type_name_from_ctype(ctype):
149     return type_names.get(ctype, ctype)
150
151
152 class Node(object):
153
154     def __init__(self, name=None):
155         self.name = name
156         self.attributes = [] # (key, value)*
157         self.skip = False
158         self.deprecated = None
159         self.deprecated_version = None
160         self.version = None
161
162     def __cmp__(self, other):
163         return cmp(self.name, other.name)
164
165     def __repr__(self):
166         return '%s(%r)' % (self.__class__.__name__, self.name)
167
168     def remove_matching_children(self, pred):
169         pass
170
171 class Namespace(Node):
172
173     def __init__(self, name, version):
174         Node.__init__(self, name)
175         self.version = version
176         self.nodes = []
177
178     def __repr__(self):
179         return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name,
180                                    self.version, self.nodes)
181
182     def remove_matching(self, pred):
183
184         def recursive_pred(node):
185             node.remove_matching_children(pred)
186             return pred(node)
187
188         self.nodes = filter(recursive_pred, self.nodes)
189
190 class Include(Node):
191
192     def __init__(self, name, version):
193         Node.__init__(self, 'include')
194         self.name = name
195         self.version = version
196
197     @classmethod
198     def from_string(self, string):
199         return Include(*string.split('-', 1))
200
201     def __cmp__(self, other):
202         if not isinstance(other, Include):
203             return cmp(self, other)
204         namecmp = cmp(self.name, other.name)
205         if namecmp != 0:
206             return namecmp
207         return cmp(self.version, other.version)
208
209     def __hash__(self):
210         return hash((self.name, self.version))
211
212     def __str__(self):
213         return '%s-%s' % (self.name, self.version)
214
215 class Callable(Node):
216
217     def __init__(self, name, retval, parameters, throws):
218         Node.__init__(self, name)
219         self.retval = retval
220         self.parameters = parameters
221         self.throws = not not throws
222         self.doc = None
223
224     def __repr__(self):
225         return '%s(%r, %r, %r)' % (self.__class__.__name__,
226                                    self.name, self.retval,
227                                    self.parameters)
228
229 class Function(Callable):
230
231     def __init__(self, name, retval, parameters, symbol, throws=None):
232         Callable.__init__(self, name, retval, parameters, throws)
233         self.symbol = symbol
234         self.is_method = False
235         self.doc = None
236
237     def get_parameter_index(self, name):
238         for i, parameter in enumerate(self.parameters):
239             if parameter.name == name:
240                 return i + int(self.is_method)
241
242     def get_parameter(self, name):
243         for parameter in self.parameters:
244             if parameter.name == name:
245                 return parameter
246
247
248 class VFunction(Callable):
249
250     def __init__(self, name, retval, parameters, throws):
251         Callable.__init__(self, name, retval, parameters, throws)
252         self.invoker = None
253
254     @classmethod
255     def from_callback(cls, cb):
256         obj = cls(cb.name, cb.retval, cb.parameters[1:],
257                   cb.throws)
258         return obj
259
260
261 class Type(Node):
262
263     def __init__(self, name, ctype=None):
264         Node.__init__(self, name)
265         self.ctype = ctype
266         self.resolved = False
267         self.is_const = False
268         self.canonical = None
269         self.derefed_canonical = None
270
271
272 class Varargs(Type):
273
274     def __init__(self):
275         Type.__init__(self, '<varargs>')
276
277
278 class Array(Type):
279
280     def __init__(self, ctype, element_type):
281         Type.__init__(self, '<carray>', ctype)
282         self.element_type = element_type
283         self.zeroterminated = True
284         self.length_param_index = -1
285         self.length_param_name = None
286         self.size = None
287
288     def __repr__(self):
289         return 'Array(%r, %r)' % (self.name, self.element_type, )
290
291
292 class List(Type):
293
294     def __init__(self, name, ctype, element_type):
295         Type.__init__(self, name, ctype)
296         self.element_type = element_type
297
298     def __repr__(self):
299         return 'List(%r of %r)' % (self.name, self.element_type, )
300
301
302 class Map(Type):
303
304     def __init__(self, name, ctype, key_type, value_type):
305         Type.__init__(self, name, ctype)
306         self.key_type = key_type
307         self.value_type = value_type
308
309     def __repr__(self):
310         return 'Map(%r <%r,%r>)' % (self.name, self.key_type, self.value_type)
311
312
313 class Alias(Node):
314
315     def __init__(self, name, target, ctype=None):
316         Node.__init__(self, name)
317         self.target = target
318         self.ctype = ctype
319
320     def __repr__(self):
321         return 'Alias(%r, %r)' % (self.name, self.target)
322
323
324 class TypeContainer(Node):
325
326     def __init__(self, name, typenode, transfer):
327         Node.__init__(self, name)
328         self.type = typenode
329         if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER,
330                         PARAM_TRANSFER_FULL]:
331             self.transfer = transfer
332         else:
333             self.transfer = None
334
335
336 class Parameter(TypeContainer):
337
338     def __init__(self, name, typenode, direction=None,
339                  transfer=None, allow_none=False, scope=None):
340         TypeContainer.__init__(self, name, typenode, transfer)
341         if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT,
342                          PARAM_DIRECTION_INOUT, None]:
343             self.direction = direction
344         else:
345             self.direction = PARAM_DIRECTION_IN
346
347         self.allow_none = allow_none
348         self.scope = scope
349         self.closure_index = -1
350         self.destroy_index = -1
351         self.doc = None
352
353     def __repr__(self):
354         return 'Parameter(%r, %r)' % (self.name, self.type)
355
356
357 class Enum(Node):
358
359     def __init__(self, name, symbol, members):
360         Node.__init__(self, name)
361         self.symbol = symbol
362         self.members = members
363         self.doc = None
364
365     def __repr__(self):
366         return 'Enum(%r, %r)' % (self.name, self.members)
367
368
369 class Bitfield(Node):
370
371     def __init__(self, name, symbol, members):
372         Node.__init__(self, name)
373         self.symbol = symbol
374         self.members = members
375         self.doc = None
376
377     def __repr__(self):
378         return 'Bitfield(%r, %r)' % (self.name, self.members)
379
380
381 class Member(Node):
382
383     def __init__(self, name, value, symbol):
384         Node.__init__(self, name)
385         self.value = value
386         self.symbol = symbol
387
388     def __repr__(self):
389         return 'Member(%r, %r)' % (self.name, self.value)
390
391
392 class Record(Node):
393
394     def __init__(self, name, symbol, disguised=False):
395         Node.__init__(self, name)
396         self.fields = []
397         self.constructors = []
398         self.symbol = symbol
399         self.disguised = disguised
400         self.doc = None
401         self.methods = []
402
403     def remove_matching_children(self, pred):
404         self.fields = filter(pred, self.fields)
405         self.constructors = filter(pred, self.constructors)
406         self.methods = filter(pred, self.methods)
407
408 # BW compat, remove
409 Struct = Record
410
411
412 class Field(Node):
413
414     def __init__(self, name, typenode, symbol, readable, writable, bits=None):
415         Node.__init__(self, name)
416         self.type = typenode
417         self.symbol = symbol
418         self.readable = readable
419         self.writable = writable
420         self.bits = bits
421
422     def __repr__(self):
423         if self.bits:
424             return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits)
425         else:
426             return 'Field(%r, %r)' % (self.name, self.type)
427
428
429 class Return(TypeContainer):
430
431     def __init__(self, rtype, transfer=None):
432         TypeContainer.__init__(self, None, rtype, transfer)
433         self.direction = PARAM_DIRECTION_OUT
434         self.doc = None
435
436     def __repr__(self):
437         return 'Return(%r)' % (self.type, )
438
439
440 class Class(Node):
441
442     def __init__(self, name, parent, is_abstract):
443         Node.__init__(self, name)
444         self.ctype = name
445         self.parent = parent
446         self.glib_type_struct = None
447         self.is_abstract = is_abstract
448         self.methods = []
449         self.virtual_methods = []
450         self.static_methods = []
451         self.interfaces = []
452         self.constructors = []
453         self.properties = []
454         self.fields = []
455         self.doc = None
456
457     def remove_matching_children(self, pred):
458         self.methods = filter(pred, self.methods)
459         self.constructors = filter(pred, self.constructors)
460         self.properties = filter(pred, self.properties)
461         self.fields = filter(pred, self.fields)
462
463     def __repr__(self):
464         return '%s(%r, %r, %r)' % (
465             self.__class__.__name__,
466             self.name, self.parent, self.methods)
467
468
469 class Interface(Node):
470
471     def __init__(self, name, parent):
472         Node.__init__(self, name)
473         self.parent = parent
474         self.methods = []
475         self.virtual_methods = []
476         self.glib_type_struct = None
477         self.properties = []
478         self.fields = []
479         self.prerequisites = []
480         self.doc = None
481
482     def __repr__(self):
483         return '%s(%r, %r)' % (
484             self.__class__.__name__,
485             self.name, self.methods)
486
487
488 class Constant(Node):
489
490     def __init__(self, name, type_name, value):
491         Node.__init__(self, name)
492         self.type = Type(type_name)
493         self.value = value
494
495     def __repr__(self):
496         return 'Constant(%r, %r, %r)' % (
497             self.name, self.type, self.value)
498
499
500 class Property(Node):
501
502     def __init__(self, name, type_name, readable, writable,
503                  construct, construct_only, ctype=None):
504         Node.__init__(self, name)
505         self.type = Type(type_name, ctype)
506         self.readable = readable
507         self.writable = writable
508         self.construct = construct
509         self.construct_only = construct_only
510         self.doc = None
511
512     def __repr__(self):
513         return '%s(%r, %r)' % (
514             self.__class__.__name__,
515             self.name, self.type)
516
517
518 # FIXME: Inherit from Function
519
520
521 class Callback(Node):
522
523     def __init__(self, name, retval, parameters, ctype=None):
524         Node.__init__(self, name)
525         self.retval = retval
526         self.parameters = parameters
527         self.ctype = ctype
528         self.throws = False
529         self.doc = None
530
531     def get_parameter_index(self, name):
532         for i, parameter in enumerate(self.parameters):
533             if parameter.name == name:
534                 return i
535
536     def get_parameter(self, name):
537         for parameter in self.parameters:
538             if parameter.name == name:
539                 return parameter
540
541     def __repr__(self):
542         return 'Callback(%r, %r, %r)' % (
543             self.name, self.retval, self.parameters)
544
545
546 class Union(Node):
547
548     def __init__(self, name, symbol):
549         Node.__init__(self, name)
550         self.fields = []
551         self.constructors = []
552         self.methods = []
553         self.symbol = symbol
554         self.doc = None
555
556     def __repr__(self):
557         return 'Union(%r, %r)' % (self.name, self.fields, )