From: Luiz Capitulino <lcapitulino@redhat.com>
To: Wenchao Xia <wenchaoqemu@gmail.com>
Cc: kwolf@redhat.com, mdroth@linux.vnet.ibm.com,
Markus Armbruster <armbru@redhat.com>,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH V9 07/10] qapi script: support enum type as discriminator in union
Date: Thu, 6 Mar 2014 08:03:58 -0500 [thread overview]
Message-ID: <20140306080358.7fac2825@redhat.com> (raw)
In-Reply-To: <531861F9.1020608@gmail.com>
On Thu, 06 Mar 2014 19:54:33 +0800
Wenchao Xia <wenchaoqemu@gmail.com> wrote:
> 于 2014/3/6 16:25, Markus Armbruster 写道:
> > Wenchao Xia <wenchaoqemu@gmail.com> writes:
> >
> >> By default, any union will automatically generate a enum type as
> >> "[UnionName]Kind" in C code, and it is duplicated when the discriminator
> >> is specified as a pre-defined enum type in schema. After this patch,
> >> the pre-defined enum type will be really used as the switch case
> >> condition in generated C code, if discriminator is an enum field.
> >>
> >> Signed-off-by: Wenchao Xia <wenchaoqemu@gmail.com>
> >> Reviewed-by: Eric Blake <eblake@redhat.com>
> >> ---
> >> docs/qapi-code-gen.txt | 8 ++++-
> >> scripts/qapi-types.py | 18 +++++++++---
> >> scripts/qapi-visit.py | 29 +++++++++++++------
> >> scripts/qapi.py | 32 +++++++++++++++++++++-
> >> tests/Makefile | 2 +-
> >> tests/qapi-schema/flat-union-reverse-define.exit | 1 +
> >> tests/qapi-schema/flat-union-reverse-define.json | 17 +++++++++++
> >> tests/qapi-schema/flat-union-reverse-define.out | 9 ++++++
> >> 8 files changed, 99 insertions(+), 17 deletions(-)
> >> create mode 100644 tests/qapi-schema/flat-union-reverse-define.err
> >> create mode 100644 tests/qapi-schema/flat-union-reverse-define.exit
> >> create mode 100644 tests/qapi-schema/flat-union-reverse-define.json
> >> create mode 100644 tests/qapi-schema/flat-union-reverse-define.out
> >>
> >> diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
> >> index 0728f36..a2e7921 100644
> >> --- a/docs/qapi-code-gen.txt
> >> +++ b/docs/qapi-code-gen.txt
> >> @@ -123,11 +123,15 @@ And it looks like this on the wire:
> >>
> >> Flat union types avoid the nesting on the wire. They are used whenever a
> >> specific field of the base type is declared as the discriminator ('type' is
> >> -then no longer generated). The discriminator must always be a string field.
> >> +then no longer generated). The discriminator can be a string field or a
> >> +predefined enum field. If it is a string field, a hidden enum type will be
> >> +generated as "[UNION_NAME]Kind". If it is an enum field, a compile time check
> >> +will be done to verify the correctness. It is recommended to use an enum field.
> >> The above example can then be modified as follows:
> >>
> >> + { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] }
> >> { 'type': 'BlockdevCommonOptions',
> >> - 'data': { 'driver': 'str', 'readonly': 'bool' } }
> >> + 'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } }
> >> { 'union': 'BlockdevOptions',
> >> 'base': 'BlockdevCommonOptions',
> >> 'discriminator': 'driver',
> >> diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
> >> index 5885bac..10864ef 100644
> >> --- a/scripts/qapi-types.py
> >> +++ b/scripts/qapi-types.py
> >> @@ -201,14 +201,21 @@ def generate_union(expr):
> >> base = expr.get('base')
> >> discriminator = expr.get('discriminator')
> >>
> >> + enum_define = discriminator_find_enum_define(expr)
> >> + if enum_define:
> >> + discriminator_type_name = enum_define['enum_name']
> >> + else:
> >> + discriminator_type_name = '%sKind' % (name)
> >> +
> >> ret = mcgen('''
> >> struct %(name)s
> >> {
> >> - %(name)sKind kind;
> >> + %(discriminator_type_name)s kind;
> >> union {
> >> void *data;
> >> ''',
> >> - name=name)
> >> + name=name,
> >> + discriminator_type_name=discriminator_type_name)
> >>
> >> for key in typeinfo:
> >> ret += mcgen('''
> >> @@ -389,8 +396,11 @@ for expr in exprs:
> >> fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
> >> elif expr.has_key('union'):
> >> ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
> >> - ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
> >> - fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
> >> + enum_define = discriminator_find_enum_define(expr)
> >> + if not enum_define:
> >> + ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
> >> + fdef.write(generate_enum_lookup('%sKind' % expr['union'],
> >> + expr['data'].keys()))
> >> if expr.get('discriminator') == {}:
> >> fdef.write(generate_anon_union_qtypes(expr))
> >> else:
> >> diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
> >> index 0baaf60..45ce3a9 100644
> >> --- a/scripts/qapi-visit.py
> >> +++ b/scripts/qapi-visit.py
> >> @@ -259,10 +259,16 @@ def generate_visit_union(expr):
> >> assert not base
> >> return generate_visit_anon_union(name, members)
> >>
> >> - # There will always be a discriminator in the C switch code, by default it
> >> - # is an enum type generated silently as "'%sKind' % (name)"
> >> - ret = generate_visit_enum('%sKind' % name, members.keys())
> >> - disc_type = '%sKind' % (name)
> >> + enum_define = discriminator_find_enum_define(expr)
> >> + if enum_define:
> >> + # Use the enum type as discriminator
> >> + ret = ""
> >> + disc_type = enum_define['enum_name']
> >> + else:
> >> + # There will always be a discriminator in the C switch code, by default it
> >> + # is an enum type generated silently as "'%sKind' % (name)"
> >> + ret = generate_visit_enum('%sKind' % name, members.keys())
> >> + disc_type = '%sKind' % (name)
> >>
> >> if base:
> >> base_fields = find_struct(base)['data']
> >> @@ -298,15 +304,16 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
> >> pop_indent()
> >>
> >> if not discriminator:
> >> - desc_type = "type"
> >> + disc_key = "type"
> >> else:
> >> - desc_type = discriminator
> >> + disc_key = discriminator
> >> ret += mcgen('''
> >> - visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err);
> >> + visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err);
> >> if (!err) {
> >> switch ((*obj)->kind) {
> >> ''',
> >> - name=name, type=desc_type)
> >> + disc_type = disc_type,
> >> + disc_key = disc_key)
> >>
> >> for key in members:
> >> if not discriminator:
> >> @@ -517,7 +524,11 @@ for expr in exprs:
> >> ret += generate_visit_list(expr['union'], expr['data'])
> >> fdef.write(ret)
> >>
> >> - ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys())
> >> + enum_define = discriminator_find_enum_define(expr)
> >> + ret = ""
> >> + if not enum_define:
> >> + ret = generate_decl_enum('%sKind' % expr['union'],
> >> + expr['data'].keys())
> >> ret += generate_declaration(expr['union'], expr['data'])
> >> fdecl.write(ret)
> >> elif expr.has_key('enum'):
> >> diff --git a/scripts/qapi.py b/scripts/qapi.py
> >> index eebc8a7..0a504c4 100644
> >> --- a/scripts/qapi.py
> >> +++ b/scripts/qapi.py
> >> @@ -180,6 +180,25 @@ def find_base_fields(base):
> >> return None
> >> return base_struct_define['data']
> >>
> >> +# Return the discriminator enum define if discriminator is specified as an
> >> +# enum type, otherwise return None.
> >> +def discriminator_find_enum_define(expr):
> >> + base = expr.get('base')
> >> + discriminator = expr.get('discriminator')
> >> +
> >> + if not (discriminator and base):
> >> + return None
> >> +
> >> + base_fields = find_base_fields(base)
> >> + if not base_fields:
> >> + return None
> >> +
> >> + discriminator_type = base_fields.get(discriminator)
> >> + if not discriminator_type:
> >> + return None
> >> +
> >> + return find_enum(discriminator_type)
> >> +
> >> def check_union(expr, expr_info):
> >> name = expr['union']
> >> base = expr.get('base')
> >> @@ -254,11 +273,22 @@ def parse_schema(fp):
> >> add_enum(expr['enum'], expr['data'])
> >> elif expr.has_key('union'):
> >> add_union(expr)
> >> - add_enum('%sKind' % expr['union'])
> >> elif expr.has_key('type'):
> >> add_struct(expr)
> >> exprs.append(expr)
> >>
> >> + # Try again for hidden UnionKind enum
> >> + for expr_elem in schema.exprs:
> >> + expr = expr_elem['expr']
> >> + if expr.has_key('union'):
> >> + try:
> >> + enum_define = discriminator_find_enum_define(expr)
> >> + except QAPIExprError, e:
> >> + print >>sys.stderr, e
> >> + exit(1)
> > How can we get QAPIExprError here?
> >
> Ops, for this version Exception wouldn't happen, I forgot
> to remove the "try except". It should be simply:
>
> + # Try again for hidden UnionKind enum
> + for expr_elem in schema.exprs:
> + expr = expr_elem['expr']
> + if expr.has_key('union'):
> + enum_define = discriminator_find_enum_define(expr)
>
> Luiz, do you mind apply this series and correct above directly?
I do. Please, respin 07/10 only and send it as a reply to this thread.
> >> + if not enum_define:
> >> + add_enum('%sKind' % expr['union'])
> >> +
> >> try:
> >> check_exprs(schema)
> >> except QAPIExprError, e:
> > [...]
>
next prev parent reply other threads:[~2014-03-06 13:04 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-05 2:44 [Qemu-devel] [PATCH V9 00/10] qapi script: support enum as discriminator and better enum name Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 01/10] qapi script: remember explicitly defined enum values Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 02/10] qapi script: add check for duplicated key Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 03/10] qapi script: remember line number in schema parsing Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 04/10] qapi script: check correctness of union Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 05/10] qapi script: code move for generate_enum_name() Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 06/10] qapi script: use same function to generate enum string Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 07/10] qapi script: support enum type as discriminator in union Wenchao Xia
2014-03-06 8:25 ` Markus Armbruster
2014-03-06 11:54 ` Wenchao Xia
2014-03-06 13:03 ` Luiz Capitulino [this message]
2014-03-07 1:08 ` [Qemu-devel] [PATCH " Wenchao Xia
2014-03-07 14:50 ` Markus Armbruster
2014-03-07 1:11 ` [Qemu-devel] [PATCH V9 " Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 08/10] qapi: convert BlockdevOptions to use enum discriminator Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 09/10] qapi script: do not allow string discriminator Wenchao Xia
2014-03-05 2:44 ` [Qemu-devel] [PATCH V9 10/10] qapi script: do not add "_" for every capitalized char in enum Wenchao Xia
2014-03-06 8:26 ` [Qemu-devel] [PATCH V9 00/10] qapi script: support enum as discriminator and better enum name Markus Armbruster
2014-03-06 12:21 ` Markus Armbruster
2014-03-07 13:55 ` Luiz Capitulino
2014-03-07 13:55 ` Luiz Capitulino
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=20140306080358.7fac2825@redhat.com \
--to=lcapitulino@redhat.com \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=wenchaoqemu@gmail.com \
/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.