qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/2] qapi: allow flat unions with empty branches


From: Anton Nefedov
Subject: [Qemu-devel] [PATCH 1/2] qapi: allow flat unions with empty branches
Date: Fri, 11 May 2018 12:05:33 +0300

The patch makes possible to avoid introducing dummy empty types
for the flat union branches that have no data.

Signed-off-by: Anton Nefedov <address@hidden>
---
 scripts/qapi/common.py         | 18 ++++++++++++------
 scripts/qapi/doc.py            |  2 +-
 scripts/qapi/types.py          |  2 +-
 scripts/qapi/visit.py          | 12 +++++++-----
 tests/qapi-schema/test-qapi.py |  2 +-
 5 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index a032cec..ec5cf28 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -721,6 +721,7 @@ def check_union(expr, info):
     name = expr['union']
     base = expr.get('base')
     discriminator = expr.get('discriminator')
+    partial = expr.get('data-partial', False)
     members = expr['data']
 
     # Two types of unions, determined by discriminator.
@@ -783,7 +784,7 @@ def check_union(expr, info):
                                    % (key, enum_define['enum']))
 
     # If discriminator is user-defined, ensure all values are covered
-    if enum_define:
+    if enum_define and not partial:
         for value in enum_define['data']:
             if value not in members.keys():
                 raise QAPISemError(info, "Union '%s' data missing '%s' branch"
@@ -909,7 +910,7 @@ def check_exprs(exprs):
         elif 'union' in expr:
             meta = 'union'
             check_keys(expr_elem, 'union', ['data'],
-                       ['base', 'discriminator'])
+                       ['base', 'discriminator', 'data-partial'])
             union_types[expr[meta]] = expr
         elif 'alternate' in expr:
             meta = 'alternate'
@@ -1035,7 +1036,7 @@ class QAPISchemaVisitor(object):
     def visit_array_type(self, name, info, element_type):
         pass
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, partial):
         pass
 
     def visit_object_type_flat(self, name, info, members, variants):
@@ -1192,7 +1193,8 @@ class QAPISchemaArrayType(QAPISchemaType):
 
 
 class QAPISchemaObjectType(QAPISchemaType):
-    def __init__(self, name, info, doc, base, local_members, variants):
+    def __init__(self, name, info, doc, base, local_members, variants,
+                 partial = False):
         # struct has local_members, optional base, and no variants
         # flat union has base, variants, and no local_members
         # simple union has local_members, variants, and no base
@@ -1209,6 +1211,7 @@ class QAPISchemaObjectType(QAPISchemaType):
         self.local_members = local_members
         self.variants = variants
         self.members = None
+        self.partial = partial
 
     def check(self, schema):
         if self.members is False:               # check for cycles
@@ -1269,7 +1272,8 @@ class QAPISchemaObjectType(QAPISchemaType):
 
     def visit(self, visitor):
         visitor.visit_object_type(self.name, self.info,
-                                  self.base, self.local_members, self.variants)
+                                  self.base, self.local_members, self.variants,
+                                  self.partial)
         visitor.visit_object_type_flat(self.name, self.info,
                                        self.members, self.variants)
 
@@ -1636,6 +1640,7 @@ class QAPISchema(object):
         name = expr['union']
         data = expr['data']
         base = expr.get('base')
+        partial = expr.get('data-partial', False)
         tag_name = expr.get('discriminator')
         tag_member = None
         if isinstance(base, dict):
@@ -1656,7 +1661,8 @@ class QAPISchema(object):
             QAPISchemaObjectType(name, info, doc, base, members,
                                  QAPISchemaObjectTypeVariants(tag_name,
                                                               tag_member,
-                                                              variants)))
+                                                              variants),
+                                 partial))
 
     def _def_alternate_type(self, expr, info, doc):
         name = expr['alternate']
diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py
index 9b312b2..40dffc4 100644
--- a/scripts/qapi/doc.py
+++ b/scripts/qapi/doc.py
@@ -211,7 +211,7 @@ class 
QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor):
                                body=texi_entity(doc, 'Values',
                                                 member_func=texi_enum_value)))
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, partial):
         doc = self.cur_doc
         if base and base.is_implicit():
             base = None
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 64d9c0f..e805509 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -215,7 +215,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
         self._genh.add(gen_array(name, element_type))
         self._gen_type_cleanup(name)
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, partial):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 5d72d89..3ee64bb 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -34,7 +34,7 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s 
*obj, Error **errp);
                  c_name=c_name(name))
 
 
-def gen_visit_object_members(name, base, members, variants):
+def gen_visit_object_members(name, base, members, variants, partial):
     ret = mcgen('''
 
 void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
@@ -93,9 +93,10 @@ void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s 
*obj, Error **errp)
 
         ret += mcgen('''
     default:
-        abort();
+        %(action)s
     }
-''')
+''',
+                     action="break;" if partial else "abort();")
 
     # 'goto out' produced for base, for each member, and if variants were
     # present
@@ -309,12 +310,13 @@ class 
QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
         self._genh.add(gen_visit_decl(name))
         self._genc.add(gen_visit_list(name, element_type))
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, partial):
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
             return
         self._genh.add(gen_visit_members_decl(name))
-        self._genc.add(gen_visit_object_members(name, base, members, variants))
+        self._genc.add(gen_visit_object_members(name, base, members, variants,
+                                                partial))
         # TODO Worth changing the visitor signature, so we could
         # directly use rather than repeat type.is_implicit()?
         if not name.startswith('q_'):
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index c1a144b..95cd575 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -28,7 +28,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         if prefix:
             print('    prefix %s' % prefix)
 
-    def visit_object_type(self, name, info, base, members, variants):
+    def visit_object_type(self, name, info, base, members, variants, partial):
         print('object %s' % name)
         if base:
             print('    base %s' % base.name)
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]