Allow parenthesis in annotations
authorJohan Dahlin <johan@gnome.org>
Sun, 27 Apr 2008 23:27:17 +0000 (23:27 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Sun, 27 Apr 2008 23:27:17 +0000 (23:27 +0000)
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.

svn path=/trunk/; revision=233

ChangeLog
giscanner/ast.py
giscanner/gidlwriter.py
giscanner/girwriter.py
giscanner/glibtransformer.py
giscanner/scannerlexer.l
giscanner/transformer.py

index e681e6b..9ba9ac0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 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),
index 7fe4d5f..4f7ad54 100644 (file)
@@ -40,10 +40,18 @@ class VFunction(Function):
     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'
 
@@ -79,10 +87,11 @@ class Struct(Node):
 
 
 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,)
@@ -117,9 +126,9 @@ class Interface(Node):
 
 
 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):
@@ -128,9 +137,9 @@ class Constant(Node):
 
 
 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)' % (
@@ -147,3 +156,10 @@ class Callback(Node):
     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
index db1aa79..8b28289 100644 (file)
@@ -69,7 +69,7 @@ class GIDLWriter(XMLWriter):
     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)
@@ -83,7 +83,7 @@ class GIDLWriter(XMLWriter):
 
     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':
@@ -147,7 +147,7 @@ class GIDLWriter(XMLWriter):
 
     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):
index bb3b033..4c0df8f 100644 (file)
@@ -19,7 +19,7 @@
 
 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
@@ -75,12 +75,12 @@ class GIRWriter(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:
@@ -95,8 +95,17 @@ class GIRWriter(XMLWriter):
             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)]
@@ -151,7 +160,7 @@ class GIRWriter(XMLWriter):
 
     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):
index 54ff49d..3812939 100644 (file)
@@ -23,10 +23,10 @@ import os
 
 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
@@ -131,10 +131,9 @@ class GLibTransformer(object):
         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):
@@ -176,7 +175,7 @@ class GLibTransformer(object):
         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
@@ -195,7 +194,7 @@ class GLibTransformer(object):
         # 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
 
@@ -207,10 +206,10 @@ class GLibTransformer(object):
         #        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):
index 9870efd..51355c2 100644 (file)
@@ -227,23 +227,32 @@ parse_gtkdoc (GISourceScanner *scanner,
         {
           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];
index 6a7a6bb..1bdc36b 100644 (file)
@@ -19,7 +19,7 @@
 
 import giscanner
 from giscanner.ast import (Callback, Enum, Function, Member, Parameter,
-                           Return, Struct)
+                           Return, Sequence, Struct)
 
 
 class Transformer(object):
@@ -120,11 +120,20 @@ 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,)
@@ -143,5 +152,11 @@ class Transformer(object):
 
     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