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