All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: marcandre.lureau@redhat.com, qemu-devel@nongnu.org,
	Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH v9 31/37] qapi-visit: Unify struct and union visit
Date: Wed, 27 Jan 2016 15:12:38 +0100	[thread overview]
Message-ID: <87egd3jell.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <1453219845-30939-32-git-send-email-eblake@redhat.com> (Eric Blake's message of "Tue, 19 Jan 2016 09:10:39 -0700")

I'm sending this out even though it's unfinished.  It's probably more
useful for documenting my difficulties and confusion than for improving
the code.

Eric Blake <eblake@redhat.com> writes:

> We are finally at the point where gen_visit_struct() and
> gen_visit_union() can be unified to a generic gen_visit_object().
>
> The generated code for structs and for flat unions is unchanged.
> For simple unions, a new visit_type_FOO_fields() is created,
> wrapping the visit of the non-variant tag field:
>
> |+static void visit_type_ChardevBackend_fields(Visitor *v, ChardevBackend **obj, Error **errp)
> |+{
> |+    Error *err = NULL;
> |+
> |+    visit_type_ChardevBackendKind(v, "type", &(*obj)->type, &err);
> |+    if (err) {
> |+        goto out;
> |+    }
> |+
> |+out:
> |+    error_propagate(errp, err);
> |+}
> |+
> | void visit_type_ChardevBackend(Visitor *v, const char *name, ChardevBackend **obj, Error **errp)
> | {
> |     Error *err = NULL;
> |@@ -2319,7 +2332,7 @@ void visit_type_ChardevBackend(Visitor *
> |     if (!*obj) {
> |         goto out_obj;
> |     }
> |-    visit_type_ChardevBackendKind(v, "type", &(*obj)->type, &err);
> |+    visit_type_ChardevBackend_fields(v, obj, &err);
> |     if (err) {
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> ---
> v9: no change
> v8: rebase to 'name' motion
> v7: rebase to earlier changes
> v6: new patch
> ---
>  scripts/qapi-visit.py | 133 +++++++++++++++++++-------------------------------
>  1 file changed, 51 insertions(+), 82 deletions(-)
>
> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> index 6d5c3d9..feef17f 100644
> --- a/scripts/qapi-visit.py
> +++ b/scripts/qapi-visit.py
> @@ -109,46 +109,6 @@ out:
>      return ret
>
>
> -def gen_visit_struct(name, base, members):
> -    ret = gen_visit_struct_fields(name, base, members)
> -
> -    # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
> -    # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
> -    # rather than leaving it non-NULL. As currently written, the caller must
> -    # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
> -    ret += mcgen('''
> -
> -void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
> -{
> -    Error *err = NULL;
> -
> -    visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), &err);
> -    if (err) {
> -        goto out;
> -    }
> -    if (!*obj) {
> -        goto out_obj;
> -    }
> -''',
> -                 name=name, c_name=c_name(name))
> -    if (base and not base.is_empty()) or members:
> -        ret += mcgen('''
> -    visit_type_%(c_name)s_fields(v, obj, &err);
> -''',
> -                     c_name=c_name(name))
> -    ret += mcgen('''
> -out_obj:
> -    error_propagate(errp, err);
> -    err = NULL;
> -    visit_end_struct(v, &err);
> -out:
> -    error_propagate(errp, err);
> -}
> -''')
> -
> -    return ret
> -
> -
>  def gen_visit_list(name, element_type):
>      # FIXME: if *obj is NULL on entry, and the first visit_next_list()
>      # assigns to *obj, while a later one fails, we should clean up *obj
> @@ -244,18 +204,24 @@ out:
>      return ret
>

You're merging gen_visit_struct() and gen_visit_union() into
gen_visit_object().  Need to review both the change from
gen_visit_struct() to gen_visit_object(), and from gen_visit_union() to
gen_visit_object().  Diff shows the latter, but not the former.  A
manual diff of the old gen_visit_struct() and new gen_visit_union()
doesn't come out helpful.

Recap differences between structs, flat unions and simple unions:

                    base           members        variants
    struct          may be empty   may be empty   no
    flat union      non-empty      empty          yes
    simple union    empty          just the tag   yes

>
> -def gen_visit_union(name, base, variants):
> +def gen_visit_object(name, base, members, variants):
>      ret = ''
>
>      assert base
>      if not base.is_empty():
>          ret += gen_visit_fields_decl(base)
> +    if members:
> +        ret += gen_visit_struct_fields(name, base, members)

Flat unions have no members: the new code does nothing.

Simple unions have a single member: we now generate a
visit_type_UNION_fields() for it.

Respective part of gen_visit_struct():

       ret = gen_visit_struct_fields(name, base, members)

It looks like you add a gen_visit_fields_decl() when the struct's base
is non-empty.  You actually don't, because the additional one in
gen_visit_object() suppresses the one in gen_visit_struct_fields().  I
think.

> +    if variants:
> +        for var in variants.variants:
> +            # Ugly special case for simple union TODO get rid of it
> +            if not var.simple_union_type():
> +                ret += gen_visit_implicit_struct(var.type)
>
> -    for var in variants.variants:
> -        # Ugly special case for simple union TODO get rid of it
> -        if not var.simple_union_type():
> -            ret += gen_visit_implicit_struct(var.type)
> -

Unions always have variants: no change.

Struct's don't: no change.

> +    # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
> +    # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
> +    # rather than leaving it non-NULL. As currently written, the caller must
> +    # call qapi_free_FOO() to avoid a memory leak of the partial FOO.

Comment inherited from gen_visit_struct().  Does it apply to unions as
well?

>      ret += mcgen('''
>
>  void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
> @@ -272,61 +238,71 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
>  ''',
>                   c_name=c_name(name))
>
> -    if not base.is_empty():
> +    if not base.is_empty() or members:
> +        if members:
> +            type_name = c_name(name)
> +            cast = ''
> +        else:
> +            type_name = base.c_name()
> +            cast = '(%s **)' % type_name
>          ret += mcgen('''
> -    visit_type_%(c_name)s_fields(v, (%(c_name)s **)obj, &err);
> +    visit_type_%(c_name)s_fields(v, %(cast)sobj, &err);
>  ''',
> -                     c_name=base.c_name())
> -    else:
> +                     c_name=type_name, cast=cast)
> +        if variants:
> +            ret += gen_err_check(label='out_obj')
> +
> +    if variants:
>          ret += mcgen('''
> -    visit_type_%(c_type)s(v, "%(name)s", &(*obj)->%(c_name)s, &err);
> -''',
> -                     c_type=variants.tag_member.type.c_name(),
> -                     c_name=c_name(variants.tag_member.name),
> -                     name=variants.tag_member.name)
> -    ret += gen_err_check(label='out_obj')

Around here, the diff becomes too hard to read for me.

Please have a look at my "[PATCH 0/3] qapi-visit: Unify struct and union
visit".

> -    ret += mcgen('''
>      if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
>          goto out_obj;
>      }
>      switch ((*obj)->%(c_name)s) {
>  ''',
> -                 c_name=c_name(variants.tag_member.name))
> +                     c_name=c_name(variants.tag_member.name))
>
> -    for var in variants.variants:
> -        # TODO ugly special case for simple union
> -        simple_union_type = var.simple_union_type()
> -        ret += mcgen('''
> +        for var in variants.variants:
> +            # TODO ugly special case for simple union
> +            simple_union_type = var.simple_union_type()
> +            ret += mcgen('''
>      case %(case)s:
>  ''',
> -                     case=c_enum_const(variants.tag_member.type.name,
> -                                       var.name))
> -        if simple_union_type:
> -            ret += mcgen('''
> +                         case=c_enum_const(variants.tag_member.type.name,
> +                                           var.name))
> +            if simple_union_type:
> +                ret += mcgen('''
>          visit_type_%(c_type)s(v, "data", &(*obj)->u.%(c_name)s, &err);
>  ''',
> -                         c_type=simple_union_type.c_name(),
> -                         c_name=c_name(var.name))
> -        elif not var.type.is_empty():
> -            ret += mcgen('''
> +                             c_type=simple_union_type.c_name(),
> +                             c_name=c_name(var.name))
> +            elif not var.type.is_empty():
> +                ret += mcgen('''
>          visit_type_implicit_%(c_type)s(v, &(*obj)->u.%(c_name)s, &err);
>  ''',
> -                         c_type=var.type.c_name(),
> -                         c_name=c_name(var.name))
> -        ret += mcgen('''
> +                             c_type=var.type.c_name(),
> +                             c_name=c_name(var.name))
> +            ret += mcgen('''
>          break;
>  ''')
>
> -    ret += mcgen('''
> +        ret += mcgen('''
>      default:
>          abort();
>      }
> +''')
> +
> +    ret += mcgen('''
>  out_obj:
> +''')
> +    if variants:
> +        ret += mcgen('''
>      error_propagate(errp, err);
>      err = NULL;
>      if (*obj) {
>          visit_end_union(v, !!(*obj)->u.data, &err);
>      }
> +''')
> +    ret += mcgen('''
>      error_propagate(errp, err);
>      err = NULL;
>      visit_end_struct(v, &err);
> @@ -387,14 +363,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
>
>      def visit_object_type(self, name, info, base, members, variants):
>          self.decl += gen_visit_decl(name)
> -        if variants:
> -            if members:
> -                # Members other than variants.tag_member not implemented
> -                assert len(members) == 1
> -                assert members[0] == variants.tag_member
> -            self.defn += gen_visit_union(name, base, variants)
> -        else:
> -            self.defn += gen_visit_struct(name, base, members)
> +        self.defn += gen_visit_object(name, base, members, variants)
>
>      def visit_alternate_type(self, name, info, variants):
>          self.decl += gen_visit_decl(name)

  reply	other threads:[~2016-01-27 14:12 UTC|newest]

Thread overview: 128+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-19 16:10 [Qemu-devel] [PATCH v9 00/37] qapi visitor cleanups (post-introspection cleanups subset E) Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 01/37] qobject: Document more shortcomings in our number handling Eric Blake
2016-01-20  9:02   ` Markus Armbruster
2016-01-20 15:55     ` Eric Blake
2016-01-21  6:21       ` Markus Armbruster
2016-01-21 17:12         ` Eric Blake
2016-01-21 17:29         ` Daniel P. Berrange
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 02/37] qapi: Avoid use of misnamed DO_UPCAST() Eric Blake
2016-01-20 10:04   ` Markus Armbruster
2016-01-20 15:59     ` Eric Blake
2016-01-21  6:22       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 03/37] qapi: Drop dead dealloc visitor variable Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 04/37] hmp: Improve use of qapi visitor Eric Blake
2016-01-20 13:05   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 05/37] vl: " Eric Blake
2016-01-20 13:43   ` Markus Armbruster
2016-01-20 16:18     ` Eric Blake
2016-01-21  6:45       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 06/37] balloon: " Eric Blake
2016-01-20 14:09   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 07/37] qapi: Improve generated event " Eric Blake
2016-01-20 15:19   ` Markus Armbruster
2016-01-20 17:10     ` Eric Blake
2016-01-21  7:16       ` Markus Armbruster
2016-01-26 23:40       ` Eric Blake
2016-01-28 22:51     ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 08/37] qapi: Track all failures between visit_start/stop Eric Blake
2016-01-20 16:03   ` Markus Armbruster
2016-01-20 17:15     ` Eric Blake
2016-01-21  7:19       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 09/37] qapi: Prefer type_int64 over type_int in visitors Eric Blake
2016-01-20 17:07   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 10/37] qapi: Make all visitors supply uint64 callbacks Eric Blake
2016-01-20 17:29   ` Markus Armbruster
2016-01-20 18:10     ` Eric Blake
2016-01-21  8:56       ` Markus Armbruster
2016-01-21 17:22         ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 11/37] qapi: Consolidate visitor small integer callbacks Eric Blake
2016-01-20 17:34   ` Markus Armbruster
2016-01-20 18:17     ` Eric Blake
2016-01-21  9:05       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 12/37] qapi: Don't cast Enum* to int* Eric Blake
2016-01-20 18:08   ` Markus Armbruster
2016-01-20 19:58     ` Eric Blake
2016-01-21  9:08       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 13/37] qom: Use typedef for Visitor Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 14/37] qapi: Swap visit_* arguments for consistent 'name' placement Eric Blake
2016-01-20 18:28   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 15/37] qom: Swap 'name' next to visitor in ObjectPropertyAccessor Eric Blake
2016-01-20 18:49   ` Markus Armbruster
2016-01-20 20:54     ` Eric Blake
2016-01-21  9:18       ` Markus Armbruster
2016-01-21  9:46         ` Kevin Wolf
2016-01-21 10:04           ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 16/37] qapi: Swap 'name' in visit_* callbacks to match public API Eric Blake
2016-01-20 18:55   ` Markus Armbruster
2016-01-20 21:01     ` Eric Blake
2016-01-21  9:19       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 17/37] qapi: Drop unused 'kind' for struct/enum visit Eric Blake
2016-01-20 18:59   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 18/37] qapi: Drop unused error argument for list and implicit struct Eric Blake
2016-01-20 19:03   ` Markus Armbruster
2016-01-20 21:58     ` Eric Blake
2016-01-21  9:47       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 19/37] qmp: Fix reference-counting of qnull on empty output visit Eric Blake
2016-01-21 10:27   ` Markus Armbruster
2016-01-21 13:19     ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 20/37] qmp: Don't abuse stack to track qmp-output root Eric Blake
2016-01-21 13:58   ` Markus Armbruster
2016-01-29  3:06     ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 21/37] qapi: Document visitor interfaces, add assertions Eric Blake
2016-01-21 20:08   ` Markus Armbruster
2016-01-22  0:30     ` Eric Blake
2016-01-22 12:18       ` Markus Armbruster
2016-02-10  0:23         ` Eric Blake
2016-02-10  7:38           ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 22/37] qapi: Add visit_type_null() visitor Eric Blake
2016-01-22 17:00   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 23/37] qmp: Support explicit null during input visit Eric Blake
2016-01-22 17:12   ` Markus Armbruster
2016-02-01 23:52     ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 24/37] qmp: Tighten output visitor rules Eric Blake
2016-01-22 19:11   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 25/37] spapr_drc: Expose 'null' in qom-get when there is no fdt Eric Blake
2016-01-22 19:15   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 26/37] qapi: Simplify excess input reporting in input visitors Eric Blake
2016-01-22 19:24   ` Markus Armbruster
2016-01-22 19:37     ` Eric Blake
2016-01-25  9:27       ` Markus Armbruster
2016-01-25 10:43         ` Laszlo Ersek
2016-01-27 13:54   ` [Qemu-devel] [PATCH 0/3] qapi-visit: Unify struct and union visit Markus Armbruster
2016-01-27 13:54     ` [Qemu-devel] [PATCH 1/3] qapi-visit: Simplify how we visit common union members Markus Armbruster
2016-01-27 21:48       ` Eric Blake
2016-01-27 13:54     ` [Qemu-devel] [PATCH 2/3] qapi-visit: Clean up code generated around visit_end_union() Markus Armbruster
2016-01-27 14:02       ` Eric Blake
2016-01-27 14:46         ` Markus Armbruster
2016-01-27 13:54     ` [Qemu-devel] [PATCH 3/3] qapi-visit: Unify struct and union visit Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 27/37] qapi: Add type.is_empty() helper Eric Blake
2016-01-25 14:15   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 28/37] qapi: Fix command with named empty argument type Eric Blake
2016-01-25 15:03   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 29/37] qapi: Eliminate empty visit_type_FOO_fields Eric Blake
2016-01-25 17:04   ` Markus Armbruster
2016-02-17  4:57     ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 30/37] qapi: Canonicalize missing object to :empty Eric Blake
2016-01-25 19:04   ` Markus Armbruster
2016-01-26 16:29     ` Markus Armbruster
2016-01-27  8:00       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 31/37] qapi-visit: Unify struct and union visit Eric Blake
2016-01-27 14:12   ` Markus Armbruster [this message]
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 32/37] qapi: Rework deallocation of partial struct Eric Blake
2016-01-27 16:41   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 33/37] qapi: Split visit_end_struct() into pieces Eric Blake
2016-01-27 17:20   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 34/37] qapi: Simplify semantics of visit_next_list() Eric Blake
2016-01-28 13:37   ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 35/37] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2016-01-28 15:24   ` Markus Armbruster
2016-01-28 17:05     ` Eric Blake
2016-01-29 12:03       ` Markus Armbruster
2016-01-29 15:13         ` Eric Blake
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 36/37] RFC: qapi: Adjust layout of FooList types Eric Blake
2016-01-28 15:34   ` Markus Armbruster
2016-01-28 17:23     ` Eric Blake
2016-01-29  8:19       ` Markus Armbruster
2016-01-19 16:10 ` [Qemu-devel] [PATCH v9 37/37] qapi: Update docs to match recent generator changes Eric Blake
2016-01-28 15:37   ` Markus Armbruster
2016-01-28 17:56 ` [Qemu-devel] [PATCH v9 00/37] qapi visitor cleanups (post-introspection cleanups subset E) Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87egd3jell.fsf@blackfin.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.