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