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