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