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