From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, famz@redhat.com, armbru@redhat.com,
wenchaoqemu@gmail.com, lcapitulino@redhat.com
Subject: [Qemu-devel] [PATCH v5 10/28] qapi: Segregate anonymous unions into alternates in generator
Date: Tue, 24 Mar 2015 14:03:35 -0600 [thread overview]
Message-ID: <1427227433-5030-11-git-send-email-eblake@redhat.com> (raw)
In-Reply-To: <1427227433-5030-1-git-send-email-eblake@redhat.com>
Special-casing 'discriminator == {}' for handling anonymous unions
is getting awkward; since this particular type is not always a
dictionary on the wire, it is easier to treat it as a completely
different class of type, "alternate", so that if a type is listed
in the union_types array, we know it is not an anonymous union.
This patch just further segregates union handling, to make sure that
anonymous unions are not stored in union_types, and splitting up
check_union() into separate functions. A future patch will change
the qapi grammar, and having the segregation already in place will
make it easier to deal with the distinct meta-type.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
scripts/qapi-types.py | 6 ++--
scripts/qapi-visit.py | 4 +--
scripts/qapi.py | 94 +++++++++++++++++++++++++++++----------------------
3 files changed, 58 insertions(+), 46 deletions(-)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 2390887..c9e0201 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -170,7 +170,7 @@ typedef enum %(name)s
return lookup_decl + enum_decl
-def generate_anon_union_qtypes(expr):
+def generate_alternate_qtypes(expr):
name = expr['union']
members = expr['data']
@@ -181,7 +181,7 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
name=name)
for key in members:
- qtype = find_anonymous_member_qtype(members[key])
+ qtype = find_alternate_member_qtype(members[key])
assert qtype, "Invalid anonymous union member"
ret += mcgen('''
@@ -408,7 +408,7 @@ for expr in exprs:
fdef.write(generate_enum_lookup('%sKind' % expr['union'],
expr['data'].keys()))
if expr.get('discriminator') == {}:
- fdef.write(generate_anon_union_qtypes(expr))
+ fdef.write(generate_alternate_qtypes(expr))
else:
continue
fdecl.write(ret)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 3f82bd4..77b0a1f 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -237,7 +237,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **er
''',
name=name)
-def generate_visit_anon_union(name, members):
+def generate_visit_alternate(name, members):
ret = mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
@@ -302,7 +302,7 @@ def generate_visit_union(expr):
if discriminator == {}:
assert not base
- return generate_visit_anon_union(name, members)
+ return generate_visit_alternate(name, members)
enum_define = discriminator_find_enum_define(expr)
if enum_define:
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 39cc88b..17252e9 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -224,21 +224,16 @@ def find_base_fields(base):
return None
return base_struct_define['data']
-# Return the qtype of an anonymous union branch, or None on error.
-def find_anonymous_member_qtype(qapi_type):
+# Return the qtype of an alternate branch, or None on error.
+def find_alternate_member_qtype(qapi_type):
if builtin_types.has_key(qapi_type):
return builtin_types[qapi_type]
elif find_struct(qapi_type):
return "QTYPE_QDICT"
elif find_enum(qapi_type):
return "QTYPE_QSTRING"
- else:
- union = find_union(qapi_type)
- if union:
- discriminator = union.get('discriminator')
- if discriminator == {}:
- return None
- return "QTYPE_QDICT"
+ elif find_union(qapi_type):
+ return "QTYPE_QDICT"
return None
# Return the discriminator enum define if discriminator is specified as an
@@ -276,22 +271,13 @@ def check_union(expr, expr_info):
discriminator = expr.get('discriminator')
members = expr['data']
values = { 'MAX': '(automatic)' }
- types_seen = {}
- # Three types of unions, determined by discriminator.
+ # Two types of unions, determined by discriminator.
+ assert discriminator != {}
- # If the value of member 'discriminator' is {}, it's an
- # anonymous union, and must not have a base.
- if discriminator == {}:
- enum_define = None
- if base:
- raise QAPIExprError(expr_info,
- "Anonymous union '%s' must not have a base"
- % name)
-
- # Else if the union object has no member 'discriminator', it's an
+ # If the union object has no member 'discriminator', it's an
# ordinary union. For now, it must not have a base.
- elif not discriminator:
+ if not discriminator:
enum_define = None
if base:
raise QAPIExprError(expr_info,
@@ -346,24 +332,46 @@ def check_union(expr, expr_info):
% (name, key, values[c_key]))
values[c_key] = key
- # Ensure anonymous unions have no type conflicts.
- if discriminator == {}:
- if isinstance(value, list):
- raise QAPIExprError(expr_info,
- "Anonymous union '%s' member '%s' must "
- "not be array type" % (name, key))
- qtype = find_anonymous_member_qtype(value)
- if not qtype:
- raise QAPIExprError(expr_info,
- "Anonymous union '%s' member '%s' has "
- "invalid type '%s'" % (name, key, value))
- if qtype in types_seen:
- raise QAPIExprError(expr_info,
- "Anonymous union '%s' member '%s' has "
- "same QObject type as member '%s'"
- % (name, key, types_seen[qtype]))
- types_seen[qtype] = key
+def check_alternate(expr, expr_info):
+ name = expr['union']
+ base = expr.get('base')
+ discriminator = expr.get('discriminator')
+ members = expr['data']
+ values = { 'MAX': '(automatic)' }
+ types_seen = {}
+ assert discriminator == {}
+ if base:
+ raise QAPIExprError(expr_info,
+ "Anonymous union '%s' must not have a base"
+ % name)
+
+ # Check every branch
+ for (key, value) in members.items():
+ # Check for conflicts in the generated enum
+ c_key = _generate_enum_string(key)
+ if c_key in values:
+ raise QAPIExprError(expr_info,
+ "Union '%s' member '%s' clashes with '%s'"
+ % (name, key, values[c_key]))
+ values[c_key] = key
+
+ # Ensure alternates have no type conflicts.
+ if isinstance(value, list):
+ raise QAPIExprError(expr_info,
+ "Anonymous union '%s' member '%s' must "
+ "not be array type" % (name, key))
+ qtype = find_alternate_member_qtype(value)
+ if not qtype:
+ raise QAPIExprError(expr_info,
+ "Anonymous union '%s' member '%s' has "
+ "invalid type '%s'" % (name, key, value))
+ if qtype in types_seen:
+ raise QAPIExprError(expr_info,
+ "Anonymous union '%s' member '%s' has "
+ "same QObject type as member '%s'"
+ % (name, key, types_seen[qtype]))
+ types_seen[qtype] = key
def check_enum(expr, expr_info):
name = expr['enum']
@@ -393,7 +401,10 @@ def check_exprs(schema):
if expr.has_key('enum'):
check_enum(expr, info)
elif expr.has_key('union'):
- check_union(expr, info)
+ if expr.get('discriminator') == {}:
+ check_alternate(expr, info)
+ else:
+ check_union(expr, info)
elif expr.has_key('event'):
check_event(expr, info)
@@ -535,7 +546,8 @@ def find_struct(name):
def add_union(definition):
global union_types
- union_types.append(definition)
+ if definition.get('discriminator') != {}:
+ union_types.append(definition)
def find_union(name):
global union_types
--
2.1.0
next prev parent reply other threads:[~2015-03-24 20:04 UTC|newest]
Thread overview: 124+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-24 20:03 [Qemu-devel] [PATCH v5 00/28] drop qapi nested structs Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 01/28] qapi: Document type-safety considerations Eric Blake
2015-03-25 18:31 ` Markus Armbruster
2015-03-25 20:11 ` Eric Blake
2015-03-25 21:15 ` Eric Blake
2015-03-26 9:09 ` Markus Armbruster
2015-03-26 7:52 ` Markus Armbruster
2015-03-30 15:23 ` Eric Blake
2015-03-26 8:09 ` Markus Armbruster
2015-03-31 15:09 ` Kevin Wolf
2015-03-31 17:07 ` Eric Blake
2015-03-31 17:15 ` Kevin Wolf
2015-04-01 15:29 ` Markus Armbruster
2015-04-01 15:36 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 02/28] qapi: Fix generation of 'size' builtin type Eric Blake
2015-03-26 9:52 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 03/28] qapi: Require ASCII in schema Eric Blake
2015-03-24 20:33 ` Eric Blake
2015-03-26 9:54 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 04/28] qapi: Add some enum tests Eric Blake
2015-03-26 10:01 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 05/28] qapi: Better error messages for bad enums Eric Blake
2015-03-26 10:08 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 06/28] qapi: Add some union tests Eric Blake
2015-03-26 13:18 ` Markus Armbruster
2015-03-26 15:04 ` Eric Blake
2015-03-27 12:30 ` Markus Armbruster
2015-03-27 19:47 ` Eric Blake
2015-03-31 17:13 ` Kevin Wolf
2015-03-31 18:15 ` Eric Blake
2015-03-31 18:31 ` Eric Blake
2015-03-31 18:34 ` Kevin Wolf
2015-03-31 20:46 ` Markus Armbruster
2015-04-01 8:23 ` Kevin Wolf
2015-04-01 9:14 ` Markus Armbruster
2015-03-26 13:23 ` Markus Armbruster
2015-03-26 13:51 ` Eric Blake
2015-03-26 15:58 ` Markus Armbruster
2015-03-30 22:45 ` Eric Blake
2015-03-31 23:40 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 07/28] qapi: Simplify tests of simple unions Eric Blake
2015-03-26 13:41 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 08/28] qapi: Better error messages for bad unions Eric Blake
2015-03-24 20:38 ` Eric Blake
2015-03-26 14:20 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 09/28] qapi: Prepare for catching more semantic parse errors Eric Blake
2015-03-26 14:22 ` Markus Armbruster
2015-03-24 20:03 ` Eric Blake [this message]
2015-03-26 14:47 ` [Qemu-devel] [PATCH v5 10/28] qapi: Segregate anonymous unions into alternates in generator Markus Armbruster
2015-03-26 15:26 ` Eric Blake
2015-03-27 12:32 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 11/28] qapi: Rename anonymous union type in test Eric Blake
2015-03-26 14:55 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 12/28] qapi: Introduce 'alternate' to replace anonymous union Eric Blake
2015-03-24 20:41 ` Eric Blake
2015-03-26 15:42 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 13/28] qapi: Add some expr tests Eric Blake
2015-03-26 15:55 ` Markus Armbruster
2015-03-26 19:02 ` Eric Blake
2015-03-27 12:38 ` Markus Armbruster
2015-03-27 19:39 ` Eric Blake
2015-03-29 8:27 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 14/28] qapi: Better error messages for bad expressions Eric Blake
2015-03-26 16:27 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 15/28] qapi: Add tests of redefined expressions Eric Blake
2015-03-26 17:05 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 16/28] qapi: Better error messages for duplicated expressions Eric Blake
2015-03-26 17:21 ` Markus Armbruster
2015-03-27 7:52 ` Markus Armbruster
2015-03-27 19:53 ` Eric Blake
2015-03-29 8:38 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 17/28] qapi: Allow true, false and null in schema json Eric Blake
2015-03-26 17:32 ` Markus Armbruster
2015-03-31 15:23 ` Kevin Wolf
2015-03-31 20:09 ` Markus Armbruster
2015-04-01 8:31 ` Kevin Wolf
2015-04-01 9:33 ` Markus Armbruster
2015-04-01 9:58 ` Kevin Wolf
2015-04-01 11:03 ` Markus Armbruster
2015-04-01 11:17 ` Kevin Wolf
2015-04-01 14:51 ` Markus Armbruster
2015-04-01 12:17 ` Eric Blake
2015-04-01 14:55 ` Markus Armbruster
2015-04-01 15:43 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 18/28] qapi: Unify type bypass and add tests Eric Blake
2015-03-26 17:38 ` Markus Armbruster
2015-03-26 19:05 ` Eric Blake
2015-03-27 12:40 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 19/28] qapi: Add some type check tests Eric Blake
2015-03-26 17:58 ` Markus Armbruster
2015-03-26 19:07 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 20/28] qapi: More rigourous checking of types Eric Blake
2015-03-27 8:23 ` Markus Armbruster
2015-03-27 20:03 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 21/28] qapi: Require valid names Eric Blake
2015-03-27 8:48 ` Markus Armbruster
2015-03-27 20:15 ` Eric Blake
2015-03-29 10:17 ` Markus Armbruster
2015-03-29 14:23 ` Markus Armbruster
2015-03-27 17:14 ` Markus Armbruster
2015-03-27 20:17 ` Eric Blake
2015-03-29 9:06 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 22/28] qapi: Whitelist commands that don't return dictionary Eric Blake
2015-03-27 9:11 ` Markus Armbruster
2015-03-27 20:20 ` Eric Blake
2015-03-27 16:19 ` Markus Armbruster
2015-03-27 20:29 ` Eric Blake
2015-03-29 10:22 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 23/28] qapi: More rigorous checking for type safety bypass Eric Blake
2015-03-27 9:45 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 24/28] qapi: Merge UserDefTwo and UserDefNested in tests Eric Blake
2015-03-27 9:52 ` Markus Armbruster
2015-03-27 20:30 ` Eric Blake
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 25/28] qapi: Drop tests for inline nested structs Eric Blake
2015-03-27 10:30 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 26/28] qapi: Drop inline nested type in query-version Eric Blake
2015-03-27 10:34 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 27/28] qapi: Drop inline nested types in query-pci Eric Blake
2015-03-27 10:37 ` Markus Armbruster
2015-03-24 20:03 ` [Qemu-devel] [PATCH v5 28/28] qapi: Drop support for inline nested types Eric Blake
2015-03-27 10:45 ` Markus Armbruster
2015-03-27 12:50 ` [Qemu-devel] [PATCH v5 00/28] drop qapi nested structs Markus Armbruster
2015-03-29 16:03 ` Markus Armbruster
2015-03-31 4:30 ` Eric Blake
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=1427227433-5030-11-git-send-email-eblake@redhat.com \
--to=eblake@redhat.com \
--cc=armbru@redhat.com \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=lcapitulino@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).