2008-04-27 Johan Dahlin <johan@gnome.org>
+ * giscanner/scannerlexer.l:
+ Allow parenthesis in annotations
+
+ * giscanner/ast.py:
+ * giscanner/gidlwriter.py:
+ * giscanner/girwriter.py:
+ * giscanner/glibtransformer.py:
+ * giscanner/transformer.py:
+ Add initial sequence support, including annotation.
+ Refactor type handling a bit.
+
+2008-04-27 Johan Dahlin <johan@gnome.org>
+
* tests/parser/Foo-expected.gidl:
* tests/parser/foo-object.h:
* tests/parser/foo.c (foo_object_class_init),
pass
+class Type(Node):
+ def __init__(self, name):
+ Node.__init__(self, name)
+
+ def __repr__(self):
+ return 'Type(%r)' % (self.name,)
+
+
class Parameter(Node):
- def __init__(self, name, type):
+ def __init__(self, name, type_name):
Node.__init__(self, name)
- self.type = type
+ self.type = Type(type_name)
self.direction = 'in'
self.transfer = 'none'
class Return(Node):
- def __init__(self, type):
+ def __init__(self, type_name):
Node.__init__(self)
- self.type = type
+ self.type = Type(type_name)
self.transfer = 'none'
+ self.ctype = self.type
def __repr__(self):
return 'Return(%r)' % (self.type,)
class Constant(Node):
- def __init__(self, name, type, value):
+ def __init__(self, name, type_name, value):
Node.__init__(self, name)
- self.type = type
+ self.type = Type(type_name)
self.value = value
def __repr__(self):
class Property(Node):
- def __init__(self, name, type):
+ def __init__(self, name, type_name):
Node.__init__(self, name)
- self.type = type
+ self.type = Type(type_name)
def __repr__(self):
return '%s(%r, %r, %r)' % (
def __repr__(self):
return 'Callback(%r, %r, %r)' % (
self.name, self.retval, self.parameters)
+
+
+class Sequence(Type):
+ # Subclass, because a Sequence is a kind of Type
+ def __init__(self, name, element_type):
+ Type.__init__(self, name)
+ self.element_type = element_type
def _write_return_type(self, return_):
if not return_:
return
- attrs = [('type', return_.type)]
+ attrs = [('type', return_.ctype.name)]
if return_.transfer != 'none':
attrs.append(('transfer', return_.transfer))
self.write_tag('return-type', attrs)
def _write_parameter(self, parameter):
attrs = [('name', parameter.name),
- ('type', parameter.type)]
+ ('type', parameter.type.name)]
if parameter.direction != 'in':
attrs.append(('direction', parameter.direction))
if parameter.transfer != 'none':
def _write_property(self, prop):
attrs = [('name', prop.name),
- ('prop', prop.type)]
+ ('prop', prop.type.name)]
self.write_tag('property', attrs)
def _write_signal(self, signal):
from __future__ import with_statement
-from .ast import Callback, Class, Enum, Function, Interface
+from .ast import (Callback, Class, Enum, Function, Interface, Sequence)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
GLibFlags, GLibObject, GLibInterface)
from .xmlwriter import XMLWriter
def _write_return_type(self, return_):
if not return_:
return
- with self.tagcontext('return-values'):
- with self.tagcontext('return-value'):
- attrs = [('name', return_.type)]
- if return_.transfer != 'none':
- attrs.append(('transfer', return_.transfer))
- self.write_tag('type', attrs)
+ attrs = [('c:identifer', return_.type.name)]
+ with self.tagcontext('return-value', attrs):
+ if isinstance(return_.type, Sequence):
+ self._write_sequence(return_.type)
+ else:
+ self._write_type(return_.type)
def _write_parameters(self, parameters):
if not parameters:
attrs.append(('direction', parameter.direction))
if parameter.transfer != 'none':
attrs.append(('transfer', parameter.transfer))
- with self.tagcontext('parameters', attrs):
- self.write_tag('type', [('name', parameter.type)])
+ with self.tagcontext('parameter', attrs):
+ self._write_type(parameter.type)
+
+ def _write_type(self, type):
+ self.write_tag('type', [('name', type.name)])
+
+ def _write_sequence(self, sequence):
+ attrs = [('c:owner', sequence.cowner)]
+ with self.tagcontext('sequence', attrs):
+ attrs = [('c:identifier', sequence.element_type)]
+ self.write_tag('element-type', attrs)
def _write_enum(self, enum):
attrs = [('name', enum.name)]
def _write_property(self, prop):
attrs = [('name', prop.name),
- ('prop', prop.type)]
+ ('prop', prop.type.name)]
self.write_tag('property', attrs)
def _write_callback(self, callback):
from . import cgobject
from .odict import odict
-from .ast import (Callback, Enum, Function,
- Parameter, Property, Return, Struct)
-from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibInterface,
- GLibObject, GLibSignal)
+from .ast import (Callback, Enum, Function, Parameter, Property, Return,
+ Sequence, Struct)
+from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
+ GLibInterface, GLibObject, GLibSignal)
# Copied from h2defs.py
return type_name
def _resolve_param_type(self, ptype):
- type_name = ptype.replace('*', '')
- resolved_type_name = self._resolve_type_name(type_name)
- if type_name != resolved_type_name:
- return ptype.replace(type_name, resolved_type_name)
+ type_name = ptype.name.replace('*', '')
+ ptype.name = ptype.name.replace(type_name,
+ self._resolve_type_name(type_name))
return ptype
def _parse_node(self, node):
symbol = func.name
if not symbol.endswith('_get_type'):
return False
- if func.retval.type != 'GType':
+ if func.retval.type.name != 'GType':
return False
if func.parameters:
return False
# FIXME: This is hackish, we should preserve the pointer structures
# here, so we can find pointers to objects and not just
# pointers to anything
- first_arg = func.parameters[0].type
+ first_arg = func.parameters[0].type.name
if first_arg.count('*') != 1:
return False
# here, so we can find pointers to objects and not just
# pointers to anything
rtype = func.retval.type
- if rtype.count('*') != 1:
+ if rtype.name.count('*') != 1:
return False
- object_name = rtype.replace('*', '')
+ object_name = rtype.name.replace('*', '')
return self._parse_method_common(func, object_name, is_method=False)
def _parse_method_common(self, func, object_name, is_method):
{
char *ptr = parts[1];
GString *current = NULL;
- gboolean open = (*ptr == '(');
+ gint8 pstack = 0;
current = g_string_new ("");
value = parts[2];
- while (*ptr++)
+ do
{
if (*ptr == '(')
- open = TRUE;
- else if (*ptr != ')' && open)
- g_string_append_c (current, *ptr);
- else if (*ptr == ')') {
- options = g_slist_prepend (options, g_strdup (current->str));
- open = FALSE;
- }
+ {
+ pstack++;
+ if (pstack == 1)
+ continue;
+ }
+ else if (*ptr == ')')
+ pstack--;
+
+ if (pstack == 0)
+ {
+ options = g_slist_prepend (options, current->str);
+ break;
+ }
+ g_string_append_c (current, *ptr);
}
- g_string_free (current, TRUE);
+ while (*ptr++);
+
+ g_string_free (current, FALSE);
}
else
value = parts[1];
import giscanner
from giscanner.ast import (Callback, Enum, Function, Member, Parameter,
- Return, Struct)
+ Return, Sequence, Struct)
class Transformer(object):
option,)
return param
- def _create_return(self, symbol, options):
- return_ = Return(self._create_source_type(symbol))
+ def _create_return(self, source_type, options=None):
+ if not options:
+ options = []
+ return_type = self._create_source_type(source_type)
+ return_ = Return(return_type)
for option in options:
if option == 'caller-owns':
return_.transfer = 'full'
+ elif option.startswith('seq '):
+ value, element_options = option[3:].split(None, 2)
+ element_type = self._parse_type_annotation(value)
+ seq = Sequence(return_type, element_type)
+ seq.cowner = 'caller'
+ return_.type = seq
else:
print 'Unhandled parameter annotation option: %s' % (
option,)
def _create_callback(self, symbol):
parameters = self._create_parameters(symbol.base_type.base_type)
- retval = Return(self._create_source_type(symbol.base_type.base_type.base_type))
+ retval = self._create_return(symbol.base_type.base_type.base_type)
return Callback(symbol.ident, retval, list(parameters))
+
+ def _parse_type_annotation(self, annotation):
+ if (annotation[0] == "[" and
+ annotation[-1] == "]"):
+ return Sequence(self._parse_type_annotation(annotation[1:-1]))
+ return annotation