diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | giscanner/ast.py | 11 | ||||
-rw-r--r-- | giscanner/girwriter.py | 14 | ||||
-rw-r--r-- | giscanner/glibtransformer.py | 20 | ||||
-rw-r--r-- | giscanner/transformer.py | 37 | ||||
-rw-r--r-- | tests/scanner/Foo-expected.gir | 12 |
6 files changed, 96 insertions, 8 deletions
@@ -1,5 +1,15 @@ 2008-08-19 Johan Dahlin <johan@gnome.org> + * giscanner/ast.py: + * giscanner/girwriter.py: + * giscanner/glibtransformer.py: + * giscanner/transformer.py: + * tests/scanner/Foo-expected.gir: + Add basic support for union, base the code much + on Struct. Add a testcase. + +2008-08-19 Johan Dahlin <johan@gnome.org> + * tests/scanner/Foo-expected.gir: * tests/scanner/foo-object.h: Add a union testcase which the compiler currently diff --git a/giscanner/ast.py b/giscanner/ast.py index bde22ad0..7d2e7667 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -306,3 +306,14 @@ class Sequence(Type): def __repr__(self): return 'Sequence(%r of %r)' % (self.name, self.element_type, ) + + +class Union(Node): + + def __init__(self, name, symbol): + Node.__init__(self, name) + self.fields = [] + self.symbol = symbol + + def __repr__(self): + return 'Union(%r, %r)' % (self.name, self.fields, ) diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 996893e3..a5e8ffc2 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -21,7 +21,7 @@ from __future__ import with_statement from .ast import (Callback, Class, Enum, Function, Interface, Member, - Sequence, Struct, Alias) + Sequence, Struct, Alias, Union) from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibObject, GLibInterface) from .xmlwriter import XMLWriter @@ -62,6 +62,8 @@ class GIRWriter(XMLWriter): self._write_callback(node) elif isinstance(node, Struct): self._write_record(node) + elif isinstance(node, Union): + self._write_union(node) elif isinstance(node, Member): # FIXME: atk_misc_instance singleton pass @@ -227,6 +229,16 @@ class GIRWriter(XMLWriter): else: self.write_tag('record', attrs) + def _write_union(self, union): + attrs = [('name', union.name), + ('c:type', union.symbol)] + if union.fields: + with self.tagcontext('union', attrs): + for field in union.fields: + self._write_field(field) + else: + self.write_tag('union', attrs) + def _write_field(self, field): # FIXME: Just function if isinstance(field, (Callback, Function)): diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index 52651564..266f5038 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -23,7 +23,7 @@ import ctypes from . import cgobject from .ast import (Callback, Enum, Function, Member, Namespace, Parameter, Sequence, Property, Return, Struct, Type, Alias, - type_name_from_ctype) + Union, type_name_from_ctype) from .transformer import Names from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibInterface, GLibObject, GLibSignal, type_names) @@ -160,8 +160,10 @@ class GLibTransformer(object): elif isinstance(node, Member): # FIXME: atk_misc_instance singletons pass + elif isinstance(node, Union): + self._parse_union(node) else: - print 'GOBJECT BUILDER: Unhandled node:', node + print 'GLIB Transformer: Unhandled node:', node def _parse_alias(self, alias): self._names.aliases[alias.name] = (None, alias) @@ -277,6 +279,14 @@ class GLibTransformer(object): (ns, node) = node node.fields = struct.fields[:] + def _parse_union(self, union): + node = self._names.names.get(union.name) + if node is None: + self._add_attribute(union, replace=True) + return + (ns, node) = node + node.fields = union.fields[:] + def _parse_callback(self, callback): self._add_attribute(callback) @@ -489,6 +499,8 @@ class GLibTransformer(object): self._resolve_glib_boxed(node) elif isinstance(node, Struct): self._resolve_struct(node) + elif isinstance(node, Union): + self._resolve_union(node) elif isinstance(node, Alias): self._resolve_alias(node) @@ -496,6 +508,10 @@ class GLibTransformer(object): for field in node.fields: self._resolve_field(field) + def _resolve_union(self, node): + for field in node.fields: + self._resolve_field(field) + def _resolve_parent(self, node): if not isinstance(node, (GLibInterface, GLibObject)): raise AssertionError diff --git a/giscanner/transformer.py b/giscanner/transformer.py index 3b117fff..89bdf28f 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -20,7 +20,7 @@ from giscanner.ast import (Callback, Enum, Function, Namespace, Member, Parameter, Return, Sequence, Struct, Field, - Type, Alias, Interface, Class, Node, + Type, Alias, Interface, Class, Node, Union, type_name_from_ctype, type_names) from .glibast import GLibBoxed from giscanner.sourcescanner import ( @@ -149,8 +149,7 @@ class Transformer(object): elif stype == CSYMBOL_TYPE_MEMBER: return self._create_member(symbol) elif stype == CSYMBOL_TYPE_UNION: - # Unions are not supported - pass + return self._create_union(symbol) else: raise NotImplementedError( 'Transformer: unhandled symbol: %r' % (symbol, )) @@ -227,12 +226,13 @@ class Transformer(object): node = self._create_callback(symbol) elif ctype == CTYPE_STRUCT: node = self._create_typedef_struct(symbol) + elif ctype == CTYPE_UNION: + node = self._create_typedef_union(symbol) elif ctype == CTYPE_ENUM: return self._create_enum(symbol) elif ctype in (CTYPE_TYPEDEF, CTYPE_POINTER, CTYPE_BASIC_TYPE, - CTYPE_UNION, CTYPE_VOID): if symbol.base_type.name: name = self.strip_namespace_object(symbol.ident) @@ -308,6 +308,13 @@ class Transformer(object): self._typedefs_ns[symbol.ident] = struct return struct + def _create_typedef_union(self, symbol): + name = self._remove_prefix(symbol.ident) + name = self.strip_namespace_object(name) + union = Union(name, symbol.ident) + self._typedefs_ns[symbol.ident] = union + return union + def _create_struct(self, symbol): struct = self._typedefs_ns.get(symbol.ident, None) if struct is None: @@ -330,6 +337,28 @@ class Transformer(object): return struct + def _create_union(self, symbol): + union = self._typedefs_ns.get(symbol.ident, None) + if union is None: + # This is a bit of a hack; really we should try + # to resolve through the typedefs to find the real + # name + if symbol.ident.startswith('_'): + name = symbol.ident[1:] + else: + name = symbol.ident + name = self._remove_prefix(name) + name = self.strip_namespace_object(name) + name = self.resolve_type_name(name) + union = Union(name, symbol.ident) + + for child in symbol.base_type.child_list: + field = self._traverse_one(child) + if field: + union.fields.append(field) + + return union + def _create_callback(self, symbol): parameters = self._create_parameters(symbol.base_type.base_type) retval = self._create_return(symbol.base_type.base_type.base_type) diff --git a/tests/scanner/Foo-expected.gir b/tests/scanner/Foo-expected.gir index 7ff7c5d8..ce0854be 100644 --- a/tests/scanner/Foo-expected.gir +++ b/tests/scanner/Foo-expected.gir @@ -4,7 +4,6 @@ xmlns:glib="http://www.gtk.org/introspection/glib/1.0"> <namespace name="Foo"> <alias name="List" target="GSList" c:type="FooList"/> - <alias name="Event" target="Event" c:type="FooEvent"/> <interface name="Interface" c:type="FooInterface" glib:type-name="FooInterface" @@ -420,5 +419,16 @@ <type name="int" c:type="gint"/> </field> </record> + <union name="Event" c:type="FooEvent"> + <field name="type"> + <type name="int" c:type="int"/> + </field> + <field name="any"> + <type name="EventAny" c:type="FooEventAny"/> + </field> + <field name="expose"> + <type name="EventExpose" c:type="FooEventExpose"/> + </field> + </union> </namespace> </repository> |