Automatically turn Gdk.Rectangle gtype into cairo.RectangleInt
[platform/upstream/gobject-introspection.git] / 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 from .message import Position
23 from .odict import odict
24 from .utils import to_underscores
25
26 class Type(object):
27     """A Type can be either:
28 * A reference to a node (target_giname)
29 * A reference to a "fundamental" type like 'utf8'
30 * A "foreign" type - this can be any string."
31 If none are specified, then it's in an "unresolved" state.  An
32 unresolved type can have two data sources; a "ctype" which comes
33 from a C type string, or a gtype_name (from g_type_name()).
34 """ # '''
35
36     def __init__(self,
37                  ctype=None,
38                  gtype_name=None,
39                  target_fundamental=None,
40                  target_giname=None,
41                  target_foreign=None,
42                  _target_unknown=False,
43                  is_const=False,
44                  origin_symbol=None):
45         self.ctype = ctype
46         self.gtype_name = gtype_name
47         self.origin_symbol = origin_symbol
48         if _target_unknown:
49             assert isinstance(self, TypeUnknown)
50         elif target_fundamental:
51             assert target_giname is None
52             assert target_foreign is None
53         elif target_giname:
54             assert '.' in target_giname
55             assert target_fundamental is None
56             assert target_foreign is None
57         elif target_foreign:
58             assert ctype is not None
59             assert target_giname is None
60             assert target_fundamental is None
61         else:
62             assert (ctype is not None) or (gtype_name is not None)
63         self.target_fundamental = target_fundamental
64         self.target_giname = target_giname
65         self.target_foreign = target_foreign
66         self.is_const = is_const
67
68     @property
69     def resolved(self):
70         return (self.target_fundamental or
71                 self.target_giname or
72                 self.target_foreign)
73
74     @property
75     def unresolved_string(self):
76         if self.ctype:
77             return self.ctype
78         elif self.gtype_name:
79             return self.gtype_name
80         else:
81             assert False
82
83     @classmethod
84     def create_from_gtype_name(cls, gtype_name):
85         """Parse a GType name (as from g_type_name()), and return a
86 Type instance.  Note that this function performs namespace lookup,
87 in contrast to the other create_type() functions."""
88         # First, is it a fundamental?
89         fundamental = type_names.get(gtype_name)
90         if fundamental is not None:
91             return cls(target_fundamental=fundamental.target_fundamental)
92         if gtype_name == 'GHashTable':
93             return Map(TYPE_ANY, TYPE_ANY, gtype_name=gtype_name)
94         elif gtype_name in ('GArray', 'GPtrArray', 'GByteArray'):
95             return Array('GLib.' + gtype_name[1:], TYPE_ANY,
96                          gtype_name=gtype_name)
97         elif gtype_name == 'GStrv':
98             bare_utf8 = TYPE_STRING.clone()
99             bare_utf8.ctype = None
100             return Array(None, bare_utf8, ctype=None, gtype_name=gtype_name,
101                          is_const=False)
102
103         # Workaround for Gdk.Rectangle being boxed alias for
104         # cairo.RectangleInt.  G-I does not support boxing of aliases.
105         # See https://bugzilla.gnome.org/show_bug.cgi?id=655423
106         if gtype_name == 'GdkRectangle':
107             gtype_name = 'CairoRectangleInt'
108
109         return cls(gtype_name=gtype_name)
110
111     def get_giname(self):
112         assert self.target_giname is not None
113         return self.target_giname.split('.')[1]
114
115     def __cmp__(self, other):
116         if self.target_fundamental:
117             return cmp(self.target_fundamental, other.target_fundamental)
118         if self.target_giname:
119             return cmp(self.target_giname, other.target_giname)
120         if self.target_foreign:
121             return cmp(self.target_foreign, other.target_foreign)
122         return cmp(self.ctype, other.ctype)
123
124     def is_equiv(self, typeval):
125         """Return True if the specified types are compatible at
126         an introspection level, disregarding their C types.
127         A sequence may be given for typeval, in which case
128         this function returns True if the type is compatible with
129         any."""
130         if isinstance(typeval, (list, tuple)):
131             for val in typeval:
132                 if self.is_equiv(val):
133                     return True
134             return False
135         return self == typeval
136
137     def clone(self):
138         return Type(target_fundamental=self.target_fundamental,
139                     target_giname=self.target_giname,
140                     target_foreign=self.target_foreign,
141                     ctype=self.ctype,
142                     is_const=self.is_const)
143
144     def __str__(self):
145         if self.target_fundamental:
146             return self.target_fundamental
147         elif self.target_giname:
148             return self.target_giname
149         elif self.target_foreign:
150             return self.target_foreign
151
152     def __repr__(self):
153         if self.target_fundamental:
154             data = 'target_fundamental=%s, ' % (self.target_fundamental, )
155         elif self.target_giname:
156             data = 'target_giname=%s, ' % (self.target_giname, )
157         elif self.target_foreign:
158             data = 'target_foreign=%s, ' % (self.target_foreign, )
159         else:
160             data = ''
161         return '%s(%sctype=%s)' % (self.__class__.__name__, data, self.ctype)
162
163 class TypeUnknown(Type):
164     def __init__(self):
165         Type.__init__(self, _target_unknown=True)
166
167 ######
168 ## Fundamental types
169 ######
170 # Two special ones
171 TYPE_NONE = Type(target_fundamental='none', ctype='void')
172 TYPE_ANY = Type(target_fundamental='gpointer', ctype='gpointer')
173 # "Basic" types
174 TYPE_BOOLEAN = Type(target_fundamental='gboolean', ctype='gboolean')
175 TYPE_INT8 = Type(target_fundamental='gint8', ctype='gint8')
176 TYPE_UINT8 = Type(target_fundamental='guint8', ctype='guint8')
177 TYPE_INT16 = Type(target_fundamental='gint16', ctype='gint16')
178 TYPE_UINT16 = Type(target_fundamental='guint16', ctype='guint16')
179 TYPE_INT32 = Type(target_fundamental='gint32', ctype='gint32')
180 TYPE_UINT32 = Type(target_fundamental='guint32', ctype='guint32')
181 TYPE_INT64 = Type(target_fundamental='gint64', ctype='gint64')
182 TYPE_UINT64 = Type(target_fundamental='guint64', ctype='guint64')
183 TYPE_CHAR = Type(target_fundamental='gchar', ctype='gchar')
184 TYPE_SHORT = Type(target_fundamental='gshort', ctype='gshort')
185 TYPE_USHORT = Type(target_fundamental='gushort', ctype='gushort')
186 TYPE_INT = Type(target_fundamental='gint', ctype='gint')
187 TYPE_UINT = Type(target_fundamental='guint', ctype='guint')
188 TYPE_LONG = Type(target_fundamental='glong', ctype='glong')
189 TYPE_ULONG = Type(target_fundamental='gulong', ctype='gulong')
190 TYPE_SIZE = Type(target_fundamental='gsize', ctype='gsize')
191 TYPE_SSIZE = Type(target_fundamental='gssize', ctype='gssize')
192 TYPE_INTPTR = Type(target_fundamental='gintptr', ctype='gintptr')
193 TYPE_UINTPTR = Type(target_fundamental='guintptr', ctype='guintptr')
194 # C99 types
195 TYPE_LONG_LONG = Type(target_fundamental='long long', ctype='long long')
196 TYPE_LONG_ULONG = Type(target_fundamental='unsigned long long',
197                        ctype='unsigned long long')
198 TYPE_FLOAT = Type(target_fundamental='gfloat', ctype='gfloat')
199 TYPE_DOUBLE = Type(target_fundamental='gdouble', ctype='gdouble')
200 # ?
201 TYPE_LONG_DOUBLE = Type(target_fundamental='long double',
202                         ctype='long double')
203 TYPE_UNICHAR = Type(target_fundamental='gunichar', ctype='gunichar')
204
205 # C types with semantics overlaid
206 TYPE_GTYPE = Type(target_fundamental='GType', ctype='GType')
207 TYPE_STRING = Type(target_fundamental='utf8', ctype='gchar*')
208 TYPE_FILENAME = Type(target_fundamental='filename', ctype='gchar*')
209
210 TYPE_VALIST = Type(target_fundamental='va_list', ctype='va_list')
211
212 BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16,
213                    TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64,
214                    TYPE_UINT64, TYPE_CHAR, TYPE_SHORT, TYPE_USHORT, TYPE_INT,
215                    TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_SIZE, TYPE_SSIZE,
216                    TYPE_LONG_LONG, TYPE_LONG_ULONG, TYPE_INTPTR, TYPE_UINTPTR,
217                    TYPE_FLOAT, TYPE_DOUBLE,
218                    TYPE_LONG_DOUBLE, TYPE_UNICHAR, TYPE_GTYPE]
219 GIR_TYPES = [TYPE_NONE, TYPE_ANY]
220 GIR_TYPES.extend(BASIC_GIR_TYPES)
221 GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME, TYPE_VALIST])
222
223 INTROSPECTABLE_BASIC = list(GIR_TYPES)
224 for v in [TYPE_NONE, TYPE_ANY,
225           TYPE_LONG_LONG, TYPE_LONG_ULONG,
226           TYPE_LONG_DOUBLE, TYPE_VALIST]:
227     INTROSPECTABLE_BASIC.remove(v)
228
229 type_names = {}
230 for typeval in GIR_TYPES:
231     type_names[typeval.target_fundamental] = typeval
232 basic_type_names = {}
233 for typeval in BASIC_GIR_TYPES:
234     basic_type_names[typeval.target_fundamental] = typeval
235
236 # C builtin
237 type_names['char'] = TYPE_CHAR
238 type_names['signed char'] = TYPE_INT8
239 type_names['unsigned char'] = TYPE_UINT8
240 type_names['short'] = TYPE_SHORT
241 type_names['signed short'] = TYPE_SHORT
242 type_names['unsigned short'] = TYPE_USHORT
243 type_names['int'] = TYPE_INT
244 type_names['signed int'] = TYPE_INT
245 type_names['unsigned short int'] = TYPE_USHORT
246 type_names['signed'] = TYPE_INT
247 type_names['unsigned int'] = TYPE_UINT
248 type_names['unsigned'] = TYPE_UINT
249 type_names['long'] = TYPE_LONG
250 type_names['signed long'] = TYPE_LONG
251 type_names['unsigned long'] = TYPE_ULONG
252 type_names['unsigned long int'] = TYPE_ULONG
253 type_names['float'] = TYPE_FLOAT
254 type_names['double'] = TYPE_DOUBLE
255 type_names['char*'] = TYPE_STRING
256 type_names['void*'] = TYPE_ANY
257 type_names['void'] = TYPE_NONE
258 # Also alias the signed one here
259 type_names['signed long long'] = TYPE_LONG_LONG
260
261 # A few additional GLib type aliases
262 type_names['guchar'] = TYPE_UINT8
263 type_names['gchararray'] = TYPE_STRING
264 type_names['gchar*'] = TYPE_STRING
265 type_names['goffset'] = TYPE_INT64
266 type_names['gunichar2'] = TYPE_UINT16
267 type_names['gsize'] = TYPE_SIZE
268 type_names['gssize'] = TYPE_SSIZE
269 type_names['gintptr'] = TYPE_INTPTR
270 type_names['guintptr'] = TYPE_UINTPTR
271 type_names['gconstpointer'] = TYPE_ANY
272
273 # We used to support these; continue to do so
274 type_names['any'] = TYPE_ANY
275 type_names['boolean'] = TYPE_BOOLEAN
276 type_names['uint'] = TYPE_UINT
277 type_names['ulong'] = TYPE_ULONG
278
279 # C stdio, used in GLib public headers; squash this for now here
280 # until we move scanning into GLib and can (skip)
281 type_names['FILE*'] = TYPE_ANY
282
283 # One off C unix type definitions; note some of these may be GNU Libc
284 # specific.  If someone is actually bitten by this, feel free to do
285 # the required configure goop to determine their size and replace
286 # here.
287 #
288 # We don't want to encourage people to use these in their APIs because
289 # they compromise the platform-independence that GLib gives you.
290 # These are here mostly to avoid blowing when random platform-specific
291 # methods are added under #ifdefs inside GLib itself.  We could just (skip)
292 # the relevant methods, but on the other hand, since these types are just
293 # integers it's easy enough to expand them.
294 type_names['size_t'] = type_names['gsize']
295 type_names['time_t'] = TYPE_LONG
296 type_names['off_t'] = type_names['gsize']
297 type_names['pid_t'] = TYPE_INT
298 type_names['uid_t'] = TYPE_UINT
299 type_names['gid_t'] = TYPE_UINT
300 type_names['dev_t'] = TYPE_INT
301 type_names['socklen_t'] = TYPE_INT32
302 type_names['size_t'] = TYPE_ULONG
303 type_names['ssize_t'] = TYPE_LONG
304
305 # Obj-C
306 type_names['id'] = TYPE_ANY
307
308 ##
309 ## Parameters
310 ##
311
312 PARAM_DIRECTION_IN = 'in'
313 PARAM_DIRECTION_OUT = 'out'
314 PARAM_DIRECTION_INOUT = 'inout'
315
316 PARAM_SCOPE_CALL = 'call'
317 PARAM_SCOPE_ASYNC = 'async'
318 PARAM_SCOPE_NOTIFIED = 'notified'
319
320 PARAM_TRANSFER_NONE = 'none'
321 PARAM_TRANSFER_CONTAINER = 'container'
322 PARAM_TRANSFER_FULL = 'full'
323
324 class Namespace(object):
325     def __init__(self, name, version,
326                  identifier_prefixes=None,
327                  symbol_prefixes=None):
328         self.name = name
329         self.version = version
330         if identifier_prefixes is not None:
331             self.identifier_prefixes = identifier_prefixes
332         else:
333             self.identifier_prefixes = [name]
334         if symbol_prefixes is not None:
335             self.symbol_prefixes = symbol_prefixes
336         else:
337             ps = self.identifier_prefixes
338             self.symbol_prefixes = [to_underscores(p).lower() for p in ps]
339         # cache upper-cased versions
340         self._ucase_symbol_prefixes = [p.upper() for p in self.symbol_prefixes]
341         self._names = odict() # Maps from GIName -> node
342         self._aliases = {} # Maps from GIName -> GIName
343         self._type_names = {} # Maps from GTName -> node
344         self._ctypes = {} # Maps from CType -> node
345         self._symbols = {} # Maps from function symbols -> Function
346
347     @property
348     def names(self):
349         return self._names
350
351     @property
352     def aliases(self):
353         return self._aliases
354
355     @property
356     def type_names(self):
357         return self._type_names
358
359     @property
360     def ctypes(self):
361         return self._ctypes
362
363     def type_from_name(self, name, ctype=None):
364         """Backwards compatibility method for older .gir files, which
365 only use the 'name' attribute.  If name refers to a fundamental type,
366 create a Type object referncing it.  If name is already a
367 fully-qualified GIName like 'Foo.Bar', returns a Type targeting it .
368 Otherwise a Type targeting name qualififed with the namespace name is
369 returned."""
370         if name in type_names:
371             return Type(target_fundamental=name, ctype=ctype)
372         if '.' in name:
373             target = name
374         else:
375             target = '%s.%s' % (self.name, name)
376         return Type(target_giname=target, ctype=ctype)
377
378     def append(self, node, replace=False):
379         previous = self._names.get(node.name)
380         if previous is not None:
381             if not replace:
382                 raise ValueError("Namespace conflict: %r" % (node, ))
383             self.remove(previous)
384         # A layering violation...but oh well.
385         if isinstance(node, Alias):
386             self._aliases[node.name] = node
387         elif isinstance(node, Registered) and node.gtype_name is not None:
388             self._type_names[node.gtype_name] = node
389         elif isinstance(node, Function):
390             self._symbols[node.symbol] = node
391         assert isinstance(node, Node)
392         assert node.namespace is None
393         node.namespace = self
394         self._names[node.name] = node
395         if hasattr(node, 'ctype'):
396             self._ctypes[node.ctype] = node
397         if hasattr(node, 'symbol'):
398             self._ctypes[node.symbol] = node
399
400     def remove(self, node):
401         if isinstance(node, Alias):
402             del self._aliases[node.name]
403         elif isinstance(node, Registered) and node.gtype_name is not None:
404             del self._type_names[node.gtype_name]
405         del self._names[node.name]
406         node.namespace = None
407         if hasattr(node, 'ctype'):
408             del self._ctypes[node.ctype]
409         if isinstance(node, Function):
410             del self._symbols[node.symbol]
411
412     def float(self, node):
413         """Like remove(), but doesn't unset the node's namespace
414 back-reference, and it's still possible to look up
415 functions via get_by_symbol()."""
416         if isinstance(node, Function):
417             symbol = node.symbol
418         self.remove(node)
419         self._symbols[symbol] = node
420         node.namespace = self
421
422     def __iter__(self):
423         return iter(self._names)
424
425     def iteritems(self):
426         return self._names.iteritems()
427
428     def itervalues(self):
429         return self._names.itervalues()
430
431     def get(self, name):
432         return self._names.get(name)
433
434     def get_by_ctype(self, ctype):
435         return self._ctypes.get(ctype)
436
437     def get_by_symbol(self, symbol):
438         return self._symbols.get(symbol)
439
440     def walk(self, callback):
441         for node in self.itervalues():
442             node.walk(callback, [])
443
444 class Include(object):
445
446     def __init__(self, name, version):
447         self.name = name
448         self.version = version
449
450     @classmethod
451     def from_string(cls, string):
452         return cls(*string.split('-', 1))
453
454     def __cmp__(self, other):
455         namecmp = cmp(self.name, other.name)
456         if namecmp != 0:
457             return namecmp
458         return cmp(self.version, other.version)
459
460     def __hash__(self):
461         return hash(str(self))
462
463     def __str__(self):
464         return '%s-%s' % (self.name, self.version)
465
466 class Annotated(object):
467     """An object which has a few generic metadata
468 properties."""
469     def __init__(self):
470         self.version = None
471         self.skip = False
472         self.introspectable = True
473         self.attributes = [] # (key, value)*
474         self.deprecated = None
475         self.deprecated_version = None
476         self.doc = None
477
478 class Node(Annotated):
479     """A node is a type of object which is uniquely identified by its
480 (namespace, name) pair.  When combined with a ., this is called a
481 GIName.  It's possible for nodes to contain or point to other nodes."""
482
483     c_name = property(lambda self: self.namespace.name + self.name)
484     gi_name = property(lambda self: '%s.%s' % (self.namespace.name, self.name))
485
486     def __init__(self, name=None):
487         Annotated.__init__(self)
488         self.namespace = None # Should be set later by Namespace.append()
489         self.name = name
490         self.foreign = False
491         self.file_positions = set()
492
493     def create_type(self):
494         """Create a Type object referencing this node."""
495         assert self.namespace is not None
496         return Type(target_giname=('%s.%s' % (self.namespace.name, self.name)))
497
498     def __cmp__(self, other):
499         nscmp = cmp(self.namespace, other.namespace)
500         if nscmp != 0:
501             return nscmp
502         return cmp(self.name, other.name)
503
504     def __repr__(self):
505         return '%s(%r)' % (self.__class__.__name__, self.name)
506
507     def inherit_file_positions(self, node):
508         self.file_positions.update(node.file_positions)
509
510     def add_file_position(self, position):
511         self.file_positions.add(position)
512
513     def add_symbol_reference(self, symbol):
514         if symbol.source_filename:
515             self.add_file_position(Position(symbol.source_filename, symbol.line))
516
517     def walk(self, callback, chain):
518         res = callback(self, chain)
519         assert res in (True, False), "Walk function must return boolean, not %r" % (res, )
520         if not res:
521             return False
522         chain.append(self)
523         self._walk(callback, chain)
524         chain.pop()
525
526     def _walk(self, callback, chain):
527         pass
528
529
530 class Registered:
531     """A node that (possibly) has gtype_name and get_type."""
532     def __init__(self, gtype_name, get_type):
533         assert (gtype_name is None and get_type is None) or \
534                (gtype_name is not None and get_type is not None)
535         self.gtype_name = gtype_name
536         self.get_type = get_type
537
538
539 class Callable(Node):
540
541     def __init__(self, name, retval, parameters, throws):
542         Node.__init__(self, name)
543         self.retval = retval
544         self.parameters = parameters
545         self.throws = not not throws
546         self.instance_parameter = None # Parameter
547
548     def get_parameter_index(self, name):
549         for i, parameter in enumerate(self.parameters):
550             if parameter.argname == name:
551                 return i
552         raise ValueError("Unknown argument %s" % (name, ))
553
554     def get_parameter(self, name):
555         for parameter in self.parameters:
556             if parameter.argname == name:
557                 return parameter
558         raise ValueError("Unknown argument %s" % (name, ))
559
560
561 class Function(Callable):
562
563     def __init__(self, name, retval, parameters, throws, symbol):
564         Callable.__init__(self, name, retval, parameters, throws)
565         self.symbol = symbol
566         self.is_method = False
567         self.is_constructor = False
568         self.shadowed_by = None # C symbol string
569         self.shadows = None # C symbol string
570
571
572 class VFunction(Callable):
573
574     def __init__(self, name, retval, parameters, throws):
575         Callable.__init__(self, name, retval, parameters, throws)
576         self.invoker = None
577
578     @classmethod
579     def from_callback(cls, cb):
580         obj = cls(cb.name, cb.retval, cb.parameters[1:],
581                   cb.throws)
582         return obj
583
584
585
586 class Varargs(Type):
587
588     def __init__(self):
589         Type.__init__(self, '<varargs>', target_fundamental='<varargs>')
590
591
592 class Array(Type):
593     C = '<c>'
594     GLIB_ARRAY = 'GLib.Array'
595     GLIB_BYTEARRAY = 'GLib.ByteArray'
596     GLIB_PTRARRAY = 'GLib.PtrArray'
597
598     def __init__(self, array_type, element_type, **kwargs):
599         Type.__init__(self, target_fundamental='<array>',
600                       **kwargs)
601         if (array_type is None or array_type == self.C):
602             self.array_type = self.C
603         else:
604             assert array_type in (self.GLIB_ARRAY,
605                                   self.GLIB_BYTEARRAY,
606                                   self.GLIB_PTRARRAY), array_type
607             self.array_type = array_type
608         assert isinstance(element_type, Type)
609         self.element_type = element_type
610         self.zeroterminated = True
611         self.length_param_name = None
612         self.size = None
613
614     def clone(self):
615         arr = Array(self.array_type, self.element_type)
616         arr.zeroterminated = self.zeroterminated
617         arr.length_param_name = self.length_param_name
618         arr.size = self.size
619         return arr
620
621 class List(Type):
622
623     def __init__(self, name, element_type, **kwargs):
624         Type.__init__(self, target_fundamental='<list>',
625                       **kwargs)
626         self.name = name
627         assert isinstance(element_type, Type)
628         self.element_type = element_type
629
630     def clone(self):
631         l = List(self.name, self.element_type)
632         l.zeroterminated = self.zeroterminated
633         l.length_param_name = self.length_param_name
634         l.size = self.size
635         return l
636
637 class Map(Type):
638
639     def __init__(self, key_type, value_type, **kwargs):
640         Type.__init__(self, target_fundamental='<map>', **kwargs)
641         assert isinstance(key_type, Type)
642         self.key_type = key_type
643         assert isinstance(value_type, Type)
644         self.value_type = value_type
645
646     def clone(self):
647         return Map(self.key_type, self.value_type)
648
649 class Alias(Node):
650
651     def __init__(self, name, target, ctype=None):
652         Node.__init__(self, name)
653         self.target = target
654         self.ctype = ctype
655
656
657 class TypeContainer(Annotated):
658     """A fundamental base class for Return and Parameter."""
659
660     def __init__(self, typenode, transfer):
661         Annotated.__init__(self)
662         self.type = typenode
663         if transfer is not None:
664             self.transfer = transfer
665         elif typenode.is_const:
666             self.transfer = PARAM_TRANSFER_NONE
667         else:
668             self.transfer = None
669
670
671 class Parameter(TypeContainer):
672     """An argument to a function."""
673
674     def __init__(self, argname, typenode, direction=None,
675                  transfer=None, allow_none=False, scope=None,
676                  caller_allocates=False):
677         TypeContainer.__init__(self, typenode, transfer)
678         self.argname = argname
679         self.direction = direction
680         self.allow_none = allow_none
681         self.scope = scope
682         self.caller_allocates = caller_allocates
683         self.closure_name = None
684         self.destroy_name = None
685
686
687 class Return(TypeContainer):
688     """A return value from a function."""
689
690     def __init__(self, rtype, transfer=None):
691         TypeContainer.__init__(self, rtype, transfer)
692         self.direction = PARAM_DIRECTION_OUT
693
694
695 class Enum(Node, Registered):
696
697     def __init__(self, name, ctype,
698                  gtype_name=None,
699                  get_type=None,
700                  c_symbol_prefix=None,
701                  members=None):
702         Node.__init__(self, name)
703         Registered.__init__(self, gtype_name, get_type)
704         self.c_symbol_prefix = c_symbol_prefix
705         self.ctype = ctype
706         self.members = members
707         # Associated error quark
708         self.error_quark = None
709
710
711 class Bitfield(Node, Registered):
712
713     def __init__(self, name, ctype,
714                  gtype_name=None,
715                  c_symbol_prefix=None,
716                  get_type=None,
717                  members=None):
718         Node.__init__(self, name)
719         Registered.__init__(self, gtype_name, get_type)
720         self.ctype = ctype
721         self.c_symbol_prefix = c_symbol_prefix
722         self.members = members
723
724
725 class Member(Annotated):
726
727     def __init__(self, name, value, symbol, nick):
728         Annotated.__init__(self)
729         self.name = name
730         self.value = value
731         self.symbol = symbol
732         self.nick = nick
733
734     def __cmp__(self, other):
735         return cmp(self.name, other.name)
736
737
738
739 class Compound(Node, Registered):
740     def __init__(self, name,
741                  ctype=None,
742                  gtype_name=None,
743                  get_type=None,
744                  c_symbol_prefix=None,
745                  disguised=False):
746         Node.__init__(self, name)
747         Registered.__init__(self, gtype_name, get_type)
748         self.ctype = ctype
749         self.methods = []
750         self.static_methods = []
751         self.fields = []
752         self.constructors = []
753         self.disguised = disguised
754         self.gtype_name = gtype_name
755         self.get_type = get_type
756         self.c_symbol_prefix = c_symbol_prefix
757
758     def add_gtype(self, gtype_name, get_type):
759         self.gtype_name = gtype_name
760         self.get_type = get_type
761
762     def _walk(self, callback, chain):
763         for ctor in self.constructors:
764             ctor.walk(callback, chain)
765         for func in self.methods:
766             func.walk(callback, chain)
767         for func in self.static_methods:
768             func.walk(callback, chain)
769         for field in self.fields:
770             if field.anonymous_node is not None:
771                 field.anonymous_node.walk(callback, chain)
772
773 class Field(Annotated):
774
775     def __init__(self, name, typenode, readable, writable, bits=None,
776                  anonymous_node=None):
777         Annotated.__init__(self)
778         assert (typenode or anonymous_node)
779         self.name = name
780         self.type = typenode
781         self.readable = readable
782         self.writable = writable
783         self.bits = bits
784         self.anonymous_node = anonymous_node
785         self.private = False
786
787     def __cmp__(self, other):
788         return cmp(self.name, other.name)
789
790
791 class Record(Compound):
792
793     def __init__(self, name,
794                  ctype=None,
795                  gtype_name=None,
796                  get_type=None,
797                  c_symbol_prefix=None,
798                  disguised=False):
799         Compound.__init__(self, name,
800                           ctype=ctype,
801                           gtype_name=gtype_name,
802                           get_type=get_type,
803                           c_symbol_prefix=c_symbol_prefix,
804                           disguised=disguised)
805         # If non-None, this record defines the FooClass C structure
806         # for some Foo GObject (or similar for GInterface)
807         self.is_gtype_struct_for = None
808
809
810 class Union(Compound):
811
812     def __init__(self, name,
813                  ctype=None,
814                  gtype_name=None,
815                  get_type=None,
816                  c_symbol_prefix=None,
817                  disguised=False):
818         Compound.__init__(self, name,
819                           ctype=ctype,
820                           gtype_name=gtype_name,
821                           get_type=get_type,
822                           c_symbol_prefix=c_symbol_prefix,
823                           disguised=disguised)
824
825
826 class Boxed(Node, Registered):
827     """A boxed type with no known associated structure/union."""
828     def __init__(self, name,
829                  gtype_name=None,
830                  get_type=None,
831                  c_symbol_prefix=None):
832         assert gtype_name is not None
833         assert get_type is not None
834         Node.__init__(self, name)
835         Registered.__init__(self, gtype_name, get_type)
836         if get_type is not None:
837             assert c_symbol_prefix is not None
838         self.c_symbol_prefix = c_symbol_prefix
839         self.constructors = []
840         self.methods = []
841         self.static_methods = []
842
843     def _walk(self, callback, chain):
844         for ctor in self.constructors:
845             ctor.walk(callback, chain)
846         for meth in self.methods:
847             meth.walk(callback, chain)
848         for meth in self.static_methods:
849             meth.walk(callback, chain)
850
851
852 class Signal(Callable):
853
854     def __init__(self, name, retval, parameters):
855         Callable.__init__(self, name, retval, parameters, False)
856
857
858 class Class(Node, Registered):
859
860     def __init__(self, name, parent,
861                  ctype=None,
862                  gtype_name=None,
863                  get_type=None,
864                  c_symbol_prefix=None,
865                  is_abstract=False):
866         Node.__init__(self, name)
867         Registered.__init__(self, gtype_name, get_type)
868         self.ctype = ctype
869         self.c_symbol_prefix = c_symbol_prefix
870         self.parent = parent
871         self.fundamental = False
872         self.unref_func = None
873         self.ref_func = None
874         self.set_value_func = None
875         self.get_value_func = None
876         # When we're in the scanner, we keep around a list
877         # of parents so that we can transparently fall back
878         # if there are 'hidden' parents
879         self.parent_chain = []
880         self.glib_type_struct = None
881         self.is_abstract = is_abstract
882         self.methods = []
883         self.virtual_methods = []
884         self.static_methods = []
885         self.interfaces = []
886         self.constructors = []
887         self.properties = []
888         self.fields = []
889         self.signals = []
890
891     def _walk(self, callback, chain):
892         for meth in self.methods:
893             meth.walk(callback, chain)
894         for meth in self.virtual_methods:
895             meth.walk(callback, chain)
896         for meth in self.static_methods:
897             meth.walk(callback, chain)
898         for ctor in self.constructors:
899             ctor.walk(callback, chain)
900         for field in self.fields:
901             if field.anonymous_node:
902                 field.anonymous_node.walk(callback, chain)
903         for sig in self.signals:
904             sig.walk(callback, chain)
905
906
907 class Interface(Node, Registered):
908
909     def __init__(self, name, parent,
910                  ctype=None,
911                  gtype_name=None,
912                  get_type=None,
913                  c_symbol_prefix=None):
914         Node.__init__(self, name)
915         Registered.__init__(self, gtype_name, get_type)
916         self.ctype = ctype
917         self.c_symbol_prefix = c_symbol_prefix
918         self.parent = parent
919         self.parent_chain = []
920         self.methods = []
921         self.signals = []
922         self.static_methods = []
923         self.virtual_methods = []
924         self.glib_type_struct = None
925         self.properties = []
926         self.fields = []
927         self.prerequisites = []
928
929     def _walk(self, callback, chain):
930         for meth in self.methods:
931             meth.walk(callback, chain)
932         for meth in self.static_methods:
933             meth.walk(callback, chain)
934         for meth in self.virtual_methods:
935             meth.walk(callback, chain)
936         for field in self.fields:
937             if field.anonymous_node:
938                 field.anonymous_node.walk(callback, chain)
939         for sig in self.signals:
940             sig.walk(callback, chain)
941
942
943 class Constant(Node):
944
945     def __init__(self, name, value_type, value):
946         Node.__init__(self, name)
947         self.value_type = value_type
948         self.value = value
949
950
951 class Property(Node):
952
953     def __init__(self, name, typeobj, readable, writable,
954                  construct, construct_only, transfer=None):
955         Node.__init__(self, name)
956         self.type = typeobj
957         self.readable = readable
958         self.writable = writable
959         self.construct = construct
960         self.construct_only = construct_only
961         if transfer is None:
962             self.transfer = PARAM_TRANSFER_NONE
963         else:
964             self.transfer = transfer
965
966
967 class Callback(Callable):
968
969     def __init__(self, name, retval, parameters, throws, ctype=None):
970         Callable.__init__(self, name, retval, parameters, throws)
971         self.ctype = ctype