[gobject-introspection/wip/transformer] major: Use names for parameters internally
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gobject-introspection/wip/transformer] major: Use names for parameters internally
- Date: Fri, 20 Aug 2010 17:14:44 +0000 (UTC)
commit 82619e9e74cc6620aa86fcedddab081cea3fef82
Author: Colin Walters <walters verbum org>
Date: Fri Aug 20 13:13:50 2010 -0400
major: Use names for parameters internally
This avoids all the indexes we've cached becoming wrong when something
turns from a function into a method (or vice versa).
giscanner/ast.py | 19 ++-------
giscanner/girparser.py | 43 ++++++++++++++-----
giscanner/girwriter.py | 36 +++++++++-------
giscanner/primarytransformer.py | 64 ++++++++++++-----------------
giscanner/transformer.py | 2 +-
tests/scanner/Annotation-1.0-expected.gir | 12 +++---
6 files changed, 90 insertions(+), 86 deletions(-)
---
diff --git a/giscanner/ast.py b/giscanner/ast.py
index ae1af8b..501b439 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -480,11 +480,13 @@ class Callable(Node):
for i, parameter in enumerate(self.parameters):
if parameter.argname == name:
return i
+ raise ValueError("Unknown argument %s" % (name, ))
def get_parameter(self, name):
for parameter in self.parameters:
if parameter.argname == name:
return parameter
+ raise ValueError("Unknown argument %s" % (name, ))
class Function(Callable):
@@ -497,16 +499,6 @@ class Function(Callable):
self.shadowed_by = None # C symbol string
self.shadows = None # C symbol string
- def get_parameter_index(self, name):
- for i, parameter in enumerate(self.parameters):
- if parameter.argname == name:
- return i + int(self.is_method)
-
- def get_parameter(self, name):
- for parameter in self.parameters:
- if parameter.argname == name:
- return parameter
-
class VFunction(Callable):
@@ -547,7 +539,6 @@ class Array(Type):
assert isinstance(element_type, Type)
self.element_type = element_type
self.zeroterminated = True
- self.length_param_index = -1
self.length_param_name = None
self.size = None
@@ -555,7 +546,6 @@ class Array(Type):
arr = Array(self.array_type, self.element_type)
arr.element_type = self.element_type
arr.zeroterminated = self.zeroterminated
- arr.length_param_index = self.length_param_index
arr.length_param_name = self.length_param_name
arr.size = self.size
return arr
@@ -573,7 +563,6 @@ class List(Type):
l = List(self.name, self.element_type)
l.element_type = self.element_type
l.zeroterminated = self.zeroterminated
- l.length_param_index = self.length_param_index
l.length_param_name = self.length_param_name
l.size = self.size
return l
@@ -625,8 +614,8 @@ class Parameter(TypeContainer):
self.allow_none = allow_none
self.scope = scope
self.caller_allocates = caller_allocates
- self.closure_index = -1
- self.destroy_index = -1
+ self.closure_name = None
+ self.destroy_name = None
class Return(TypeContainer):
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index 2c40c48..acb005c 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -294,21 +294,32 @@ class GIRParser(object):
parameters_node = node.find(_corens('parameters'))
if (parameters_node is not None):
for paramnode in self._find_children(parameters_node, _corens('parameter')):
+ typeval = self._parse_type(paramnode)
param = ast.Parameter(paramnode.attrib.get('name'),
- self._parse_type(paramnode),
+ typeval,
paramnode.attrib.get('direction') or ast.PARAM_DIRECTION_IN,
paramnode.attrib.get('transfer-ownership'),
paramnode.attrib.get('allow-none') == '1',
paramnode.attrib.get('scope'),
paramnode.attrib.get('caller-allocates') == '1')
+ self._parse_generic_attribs(paramnode, param)
+ parameters.append(param)
+ for i, paramnode in enumerate(self._find_children(parameters_node,
+ _corens('parameter'))):
+ param = parameters[i]
+ self._parse_type_second_pass(func, paramnode, param.type)
closure = paramnode.attrib.get('closure')
if closure:
- param.closure_index = int(closure)
+ idx = int(closure)
+ assert idx < len(parameters), "%d >= %d" % (idx, len(parameters))
+ param.closure_name = parameters[idx].argname
destroy = paramnode.attrib.get('destroy')
if destroy:
- param.destroy_index = int(destroy)
- self._parse_generic_attribs(paramnode, param)
- parameters.append(param)
+ idx = int(destroy)
+ assert idx < len(parameters), "%d >= %d" % (idx, len(parameters))
+ param.destroy_name = parameters[idx].argname
+
+ self._parse_type_second_pass(func, returnnode, retval.type)
self._parse_generic_attribs(node, func)
@@ -383,7 +394,7 @@ class GIRParser(object):
self._parse_function_common(ctor, ast.Function))
return union
- def _parse_type_1(self, typenode):
+ def _parse_type_simple(self, typenode):
# ast.Fields can contain inline callbacks
if typenode.tag == _corens('callback'):
typeval = self._namespace.type_from_name(typenode.attrib['name'])
@@ -403,9 +414,6 @@ class GIRParser(object):
if fixed_size:
ret.size = int(fixed_size)
- lenidx = typenode.attrib.get('length')
- if lenidx:
- ret.length_param_index = int(lenidx)
return ret
elif typenode.tag == _corens('varargs'):
return ast.Varargs()
@@ -425,7 +433,7 @@ class GIRParser(object):
return ast.List(name, element_type, ctype=ctype)
elif name == 'GLib.HashTable':
subchildren = self._find_children(typenode, _corens('type'))
- subchildren_types = map(self._parse_type_1, subchildren)
+ subchildren_types = map(self._parse_type_simple, subchildren)
while len(subchildren_types) < 2:
subchildren_types.append(ast.TYPE_ANY)
return ast.Map(subchildren_types[0],
@@ -440,9 +448,22 @@ class GIRParser(object):
for name in map(_corens, ('callback', 'array', 'varargs', 'type')):
typenode = node.find(name)
if typenode is not None:
- return self._parse_type_1(typenode)
+ return self._parse_type_simple(typenode)
assert False, "Failed to parse toplevel type"
+ def _parse_type_second_pass(self, parent, node, typeval):
+ """A hack necessary to handle the integer parameter indexes on
+ array types."""
+ typenode = node.find(_corens('array'))
+ if typenode is None:
+ return
+ lenidx = typenode.attrib.get('length')
+ if lenidx is not None:
+ idx = int(lenidx)
+ assert idx < len(parent.parameters), "%r %d >= %d" \
+ % (parent, idx, len(parent.parameters))
+ typeval.length_param_name = parent.parameters[idx].argname
+
def _parse_boxed(self, node):
obj = glibast.GLibBoxedOther(node.attrib[_glibns('name')],
node.attrib[_glibns('type-name')],
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 7386d93..d9062b5 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -170,8 +170,8 @@ and/or use gtk-doc annotations. ''')
self._append_throws(callable, attrs)
with self.tagcontext(tag_name, attrs):
self._write_generic(callable)
- self._write_return_type(callable.retval)
- self._write_parameters(callable.parameters)
+ self._write_return_type(callable.retval, parent=callable)
+ self._write_parameters(callable, callable.parameters)
def _write_function(self, func, tag_name='function'):
attrs = []
@@ -192,7 +192,7 @@ and/or use gtk-doc annotations. ''')
def _write_constructor(self, method):
self._write_function(method, tag_name='constructor')
- def _write_return_type(self, return_):
+ def _write_return_type(self, return_, parent=None):
if not return_:
return
@@ -201,16 +201,16 @@ and/or use gtk-doc annotations. ''')
attrs.append(('transfer-ownership', return_.transfer))
with self.tagcontext('return-value', attrs):
self._write_generic(return_)
- self._write_type(return_.type)
+ self._write_type(return_.type, function=parent)
- def _write_parameters(self, parameters):
+ def _write_parameters(self, parent, parameters):
if not parameters:
return
with self.tagcontext('parameters'):
for parameter in parameters:
- self._write_parameter(parameter)
+ self._write_parameter(parent, parameter)
- def _write_parameter(self, parameter):
+ def _write_parameter(self, parent, parameter):
attrs = []
if parameter.argname is not None:
attrs.append(('name', parameter.argname))
@@ -225,13 +225,15 @@ and/or use gtk-doc annotations. ''')
attrs.append(('allow-none', '1'))
if parameter.scope:
attrs.append(('scope', parameter.scope))
- if parameter.closure_index >= 0:
- attrs.append(('closure', '%d' % parameter.closure_index))
- if parameter.destroy_index >= 0:
- attrs.append(('destroy', '%d' % parameter.destroy_index))
+ if parameter.closure_name is not None:
+ idx = parent.get_parameter_index(parameter.closure_name)
+ attrs.append(('closure', '%d' % (idx, )))
+ if parameter.destroy_name is not None:
+ idx = parent.get_parameter_index(parameter.destroy_name)
+ attrs.append(('destroy', '%d' % (idx, )))
with self.tagcontext('parameter', attrs):
self._write_generic(parameter)
- self._write_type(parameter.type)
+ self._write_type(parameter.type, function=parent)
def _type_to_name(self, typeval):
if not typeval.resolved:
@@ -242,7 +244,7 @@ and/or use gtk-doc annotations. ''')
return typeval.target_giname[len(prefix):]
return typeval.target_giname
- def _write_type(self, ntype, relation=None):
+ def _write_type(self, ntype, relation=None, function=None):
assert isinstance(ntype, Type), ntype
attrs = []
if ntype.ctype:
@@ -257,8 +259,10 @@ and/or use gtk-doc annotations. ''')
attrs.insert(0, ('zero-terminated', '0'))
if ntype.size is not None:
attrs.append(('fixed-size', '%d' % (ntype.size, )))
- if ntype.length_param_index >= 0:
- attrs.insert(0, ('length', '%d' % (ntype.length_param_index, )))
+ if ntype.length_param_name is not None:
+ assert function
+ attrs.insert(0, ('length', '%d' \
+ % (function.get_parameter_index(ntype.length_param_name, ))))
with self.tagcontext('array', attrs):
self._write_type(ntype.element_type)
@@ -527,4 +531,4 @@ and/or use gtk-doc annotations. ''')
with self.tagcontext('glib:signal', attrs):
self._write_generic(signal)
self._write_return_type(signal.retval)
- self._write_parameters(signal.parameters)
+ self._write_parameters(signal, signal.parameters)
diff --git a/giscanner/primarytransformer.py b/giscanner/primarytransformer.py
index 1dda3c4..7bac244 100644
--- a/giscanner/primarytransformer.py
+++ b/giscanner/primarytransformer.py
@@ -100,9 +100,12 @@ class PrimaryTransformer(object):
return self._is_gi_subclass(cls.parent, supercls_type)
return False
- def _get_parameter_index(self, parent, param_name, origin):
- index = parent.get_parameter_index(param_name)
- if index is None:
+ def _get_validate_parameter_name(self, parent, param_name, origin):
+ try:
+ param = parent.get_parameter(param_name)
+ except ValueError, e:
+ param = None
+ if param is None:
if isinstance(origin, ast.Parameter):
origin_name = 'parameter %s' % (origin.argname, )
else:
@@ -111,7 +114,7 @@ class PrimaryTransformer(object):
"can't find parameter %s referenced by %s of %r"
% (param_name, origin_name, parent.name), fatal=True)
- return index
+ return param.argname
def _apply_annotations_function(self, node, chain):
block = self._blocks.get(node.symbol)
@@ -182,16 +185,6 @@ class PrimaryTransformer(object):
node.get_value_func = tag.value if tag else None
return True
- def _fixup_param_destroy(self, parent, param):
- for p in parent.parameters:
- if p is not param and p.destroy_index == param.destroy_index:
- p.destroy_index = -1
-
- def _fixup_param_closure(self, parent, param):
- for p in parent.parameters:
- if p is not param and p.closure_index == param.closure_index:
- p.closure_index = -1
-
def _adjust_container_type(self, parent, node, options):
has_element_type = OPT_ELEMENT_TYPE in options
has_array = OPT_ARRAY in options
@@ -272,12 +265,13 @@ class PrimaryTransformer(object):
OPT_ARRAY_ZERO_TERMINATED) == '1'
length = array_values.get(OPT_ARRAY_LENGTH)
if length is not None:
- param_index = self._get_parameter_index(parent, length, node)
- param = parent.parameters[param_index]
- param.direction = node.direction
- if param.direction == ast.PARAM_DIRECTION_OUT:
- param.transfer = ast.PARAM_TRANSFER_FULL
- container_type.length_param_index = param_index
+ paramname = self._get_validate_parameter_name(parent, length, node)
+ if paramname:
+ param = parent.get_parameter(paramname)
+ param.direction = node.direction
+ if param.direction == ast.PARAM_DIRECTION_OUT:
+ param.transfer = ast.PARAM_TRANSFER_FULL
+ container_type.length_param_name = param.argname
fixed = array_values.get(OPT_ARRAY_FIXED_SIZE)
if fixed:
container_type.size = int(fixed)
@@ -479,32 +473,28 @@ class PrimaryTransformer(object):
destroy = options.get(OPT_DESTROY)
if destroy:
- destroy_name = destroy.one()
- param.destroy_index = self._get_parameter_index(parent,
- destroy_name,
- param)
- param.scope = ast.PARAM_SCOPE_NOTIFIED
- if param.destroy_index >= 0:
- destroy_param = parent.parameters[param.destroy_index]
+ param.destroy_name = self._get_validate_parameter_name(parent,
+ destroy.one(),
+ param)
+ if param.destroy_name is not None:
+ param.scope = ast.PARAM_SCOPE_NOTIFIED
+ destroy_param = parent.get_parameter(param.destroy_name)
# This is technically bogus; we're setting the scope on the destroy
# itself. But this helps avoid tripping a warning from finaltransformer,
# since we don't have a way right now to flag this callback a destroy.
destroy_param.scope = ast.PARAM_SCOPE_NOTIFIED
- self._fixup_param_destroy(parent, param)
closure = options.get(OPT_CLOSURE)
if closure:
- param.closure_index = self._get_parameter_index(parent,
- closure.one(),
- param)
- self._fixup_param_closure(parent, param)
+ param.closure_name = self._get_validate_parameter_name(parent,
+ closure.one(),
+ param)
elif isinstance(parent, ast.Callback):
if OPT_CLOSURE in options:
# For callbacks, (closure) appears without an
# argument, and tags a parameter that is a closure. We
# represent it (weirdly) in the gir and typelib by
- # setting param.closure_index to its own index.
- param.closure_index = parent.get_parameter_index(param.argname)
- self._fixup_param_closure(parent, param)
+ # setting param.closure_name to itself.
+ param.closure_name = param.argname
self._apply_annotations_param_ret_common(parent, param, tag)
@@ -912,12 +902,12 @@ method or constructor of some type."""
if callback_param is None:
continue
if is_destroynotify:
- callback_param.destroy_index = i
+ callback_param.destroy_name = param.argname
callback_param.scope = ast.PARAM_SCOPE_NOTIFIED
callback_param.transfer = ast.PARAM_TRANSFER_NONE
elif (param.type.is_equiv(ast.TYPE_ANY) and
param.argname.endswith('data')):
- callback_param.closure_index = i
+ callback_param.closure_name = param.argname
def _pass3_callable_throws(self, node):
"""Check to see if we have anything that looks like a
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 7f5fa12..08a7ef1 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -735,7 +735,7 @@ it is always biggest (i.e. last)."""
for i, param in enumerate(parameters):
if (param.type.target_fundamental == 'gpointer' and
param.argname == 'user_data'):
- param.closure_index = i
+ param.closure_name = param.argname
if member:
name = symbol.ident
diff --git a/tests/scanner/Annotation-1.0-expected.gir b/tests/scanner/Annotation-1.0-expected.gir
index 068fea8..a0ddb16 100644
--- a/tests/scanner/Annotation-1.0-expected.gir
+++ b/tests/scanner/Annotation-1.0-expected.gir
@@ -156,7 +156,7 @@ and/or use gtk-doc annotations. -->
<parameters>
<parameter name="nums" transfer-ownership="none">
<doc xml:whitespace="preserve">Sequence of numbers that are zero-terminated</doc>
- <array length="2" zero-terminated="0" c:type="int*">
+ <array length="1" zero-terminated="0" c:type="int*">
<type name="gint"/>
</array>
</parameter>
@@ -175,7 +175,7 @@ and/or use gtk-doc annotations. -->
<parameters>
<parameter name="nums" transfer-ownership="none">
<doc xml:whitespace="preserve">Sequence of numbers that are zero-terminated</doc>
- <array length="2" c:type="int*">
+ <array length="1" c:type="int*">
<type name="gint"/>
</array>
</parameter>
@@ -367,7 +367,7 @@ each string needs to be freed.</doc>
caller-allocates="0"
transfer-ownership="full">
<doc xml:whitespace="preserve">Argument vector</doc>
- <array length="1" c:type="char***">
+ <array length="0" c:type="char***">
<type name="utf8"/>
</array>
</parameter>
@@ -381,7 +381,7 @@ each string needs to be freed.</doc>
<parameters>
<parameter name="data" transfer-ownership="none">
<doc xml:whitespace="preserve">The data</doc>
- <array length="2" c:type="guchar*">
+ <array length="1" c:type="guchar*">
<type name="guint8"/>
</array>
</parameter>
@@ -399,7 +399,7 @@ each string needs to be freed.</doc>
<parameters>
<parameter name="data" transfer-ownership="none">
<doc xml:whitespace="preserve">The data</doc>
- <array length="2" c:type="gchar*">
+ <array length="1" c:type="gchar*">
<type name="gint8"/>
</array>
</parameter>
@@ -418,7 +418,7 @@ type.</doc>
<parameters>
<parameter name="data" transfer-ownership="none">
<doc xml:whitespace="preserve">The data</doc>
- <array length="2" c:type="gpointer">
+ <array length="1" c:type="gpointer">
<type name="guint8"/>
</array>
</parameter>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]