summaryrefslogtreecommitdiffstats
path: root/scripts/qapi
diff options
context:
space:
mode:
authorPeter Maydell2021-09-27 16:03:42 +0200
committerPeter Maydell2021-09-27 16:03:42 +0200
commitde8ed1055c2ce18c95f597eb10df360dcb534f99 (patch)
tree2554d4c016c5c7cc5bf9a8bc0dcde28b7ceef9b1 /scripts/qapi
parentMerge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-for-6.2-pul... (diff)
parenttests/qapi-schema: Make test-qapi.py -u work when files are absent (diff)
downloadqemu-de8ed1055c2ce18c95f597eb10df360dcb534f99.tar.gz
qemu-de8ed1055c2ce18c95f597eb10df360dcb534f99.tar.xz
qemu-de8ed1055c2ce18c95f597eb10df360dcb534f99.zip
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-25-v2' into staging
QAPI patches patches for 2021-09-25 # gpg: Signature made Mon 27 Sep 2021 13:44:23 BST # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2021-09-25-v2: (25 commits) tests/qapi-schema: Make test-qapi.py -u work when files are absent tests/qapi-schema: Use Python OSError instead of outmoded IOError test-clone-visitor: Correct an accidental rename tests/qapi-schema: Rename flat-union-* test cases to union-* qapi: Drop simple unions tests/qapi-schema: Purge simple unions from tests tests/qapi-schema: Drop simple union __org.qemu_x-Union1 test-clone-visitor: Wean off __org.qemu_x-Union1 tests/qapi-schema: Rewrite simple union TestIfUnion to be flat tests/qapi-schema: Simple union UserDefListUnion is now unused, drop tests/qapi-schema: Wean off UserDefListUnion test-clone-visitor: Wean off UserDefListUnion test-qobject-output-visitor: Wean off UserDefListUnion test-qobject-input-visitor: Wean off UserDefListUnion tests/qapi-schema: Prepare for simple union UserDefListUnion removal qapi: Convert simple union TransactionAction to flat one qapi: Convert simple union ImageInfoSpecific to flat one qapi: Convert simple union SocketAddressLegacy to flat one qapi: Convert simple union ChardevBackend to flat one qapi: Convert simple union MemoryDeviceInfo to flat one ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'scripts/qapi')
-rw-r--r--scripts/qapi/expr.py27
-rw-r--r--scripts/qapi/schema.py101
2 files changed, 31 insertions, 97 deletions
diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
index 90bde501b0..819ea6ad97 100644
--- a/scripts/qapi/expr.py
+++ b/scripts/qapi/expr.py
@@ -171,7 +171,7 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None:
- 'event' names adhere to `check_name_upper()`.
- 'command' names adhere to `check_name_lower()`.
- Else, meta is a type, and must pass `check_name_camel()`.
- These names must not end with ``Kind`` nor ``List``.
+ These names must not end with ``List``.
:param name: Name to check.
:param info: QAPI schema source file information.
@@ -187,9 +187,9 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None:
permit_underscore=name in info.pragma.command_name_exceptions)
else:
check_name_camel(name, info, meta)
- if name.endswith('Kind') or name.endswith('List'):
+ if name.endswith('List'):
raise QAPISemError(
- info, "%s name should not end in '%s'" % (meta, name[-4:]))
+ info, "%s name should not end in 'List'" % meta)
def check_keys(value: _JSONObject,
@@ -513,27 +513,18 @@ def check_union(expr: _JSONObject, info: QAPISourceInfo) -> None:
:return: None, ``expr`` is normalized in-place as needed.
"""
name = cast(str, expr['union']) # Checked in check_exprs
- base = expr.get('base')
- discriminator = expr.get('discriminator')
+ base = expr['base']
+ discriminator = expr['discriminator']
members = expr['data']
- if discriminator is None: # simple union
- if base is not None:
- raise QAPISemError(info, "'base' requires 'discriminator'")
- else: # flat union
- check_type(base, info, "'base'", allow_dict=name)
- if not base:
- raise QAPISemError(info, "'discriminator' requires 'base'")
- check_name_is_str(discriminator, info, "'discriminator'")
+ check_type(base, info, "'base'", allow_dict=name)
+ check_name_is_str(discriminator, info, "'discriminator'")
if not isinstance(members, dict):
raise QAPISemError(info, "'data' must be an object")
for (key, value) in members.items():
source = "'data' member '%s'" % key
- if discriminator is None:
- check_name_lower(key, info, source)
- # else: name is in discriminator enum, which gets checked
check_keys(value, info, source, ['type'], ['if'])
check_if(value, info, source)
check_type(value['type'], info, source, allow_array=not base)
@@ -664,8 +655,8 @@ def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]:
check_enum(expr, info)
elif meta == 'union':
check_keys(expr, info, meta,
- ['union', 'data'],
- ['base', 'discriminator', 'if', 'features'])
+ ['union', 'base', 'discriminator', 'data'],
+ ['if', 'features'])
normalize_members(expr.get('base'))
normalize_members(expr['data'])
check_union(expr, info)
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 3d72c7dfc9..004d7095ff 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -321,8 +321,8 @@ class QAPISchemaEnumType(QAPISchemaType):
m.connect_doc(doc)
def is_implicit(self):
- # See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
- return self.name.endswith('Kind') or self.name == 'QType'
+ # See QAPISchema._def_predefineds()
+ return self.name == 'QType'
def c_type(self):
return c_name(self.name)
@@ -393,8 +393,7 @@ class QAPISchemaObjectType(QAPISchemaType):
def __init__(self, name, info, doc, ifcond, features,
base, local_members, variants):
# 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
+ # union has base, variants, and no local_members
super().__init__(name, info, doc, ifcond, features)
self.meta = 'union' if variants else 'struct'
assert base is None or isinstance(base, str)
@@ -465,15 +464,6 @@ class QAPISchemaObjectType(QAPISchemaType):
for m in self.local_members:
m.connect_doc(doc)
- @property
- def ifcond(self):
- assert self._checked
- if isinstance(self._ifcond, QAPISchemaType):
- # Simple union wrapper type inherits from wrapped type;
- # see _make_implicit_object_type()
- return self._ifcond.ifcond
- return self._ifcond
-
def is_implicit(self):
# See QAPISchema._make_implicit_object_type(), as well as
# _def_predefineds()
@@ -576,10 +566,9 @@ class QAPISchemaAlternateType(QAPISchemaType):
class QAPISchemaVariants:
def __init__(self, tag_name, info, tag_member, variants):
- # Flat unions pass tag_name but not tag_member.
- # Simple unions and alternates pass tag_member but not tag_name.
- # After check(), tag_member is always set, and tag_name remains
- # a reliable witness of being used by a flat union.
+ # Unions pass tag_name but not tag_member.
+ # Alternates pass tag_member but not tag_name.
+ # After check(), tag_member is always set.
assert bool(tag_member) != bool(tag_name)
assert (isinstance(tag_name, str) or
isinstance(tag_member, QAPISchemaObjectTypeMember))
@@ -595,7 +584,7 @@ class QAPISchemaVariants:
v.set_defined_in(name)
def check(self, schema, seen):
- if not self.tag_member: # flat union
+ if self._tag_name: # union
self.tag_member = seen.get(c_name(self._tag_name))
base = "'base'"
# Pointing to the base type when not implicit would be
@@ -625,11 +614,11 @@ class QAPISchemaVariants:
self.info,
"discriminator member '%s' of %s must not be conditional"
% (self._tag_name, base))
- else: # simple union
+ else: # alternate
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
assert not self.tag_member.optional
assert not self.tag_member.ifcond.is_present()
- if self._tag_name: # flat union
+ if self._tag_name: # union
# branches that are not explicitly covered get an empty type
cases = {v.name for v in self.variants}
for m in self.tag_member.type.members:
@@ -707,18 +696,10 @@ class QAPISchemaMember:
assert role == 'member'
role = 'parameter'
elif defined_in.endswith('-base'):
- # Implicit type created for a flat union's dict 'base'
+ # Implicit type created for a union's dict 'base'
role = 'base ' + role
else:
- # Implicit type created for a simple union's branch
- assert defined_in.endswith('-wrapper')
- # Unreachable and not implemented
assert False
- elif defined_in.endswith('Kind'):
- # See QAPISchema._make_implicit_enum_type()
- # Implicit enum created for simple union's branches
- assert role == 'value'
- role = 'branch'
elif defined_in != info.defn_name:
return "%s '%s' of type '%s'" % (role, self.name, defined_in)
return "%s '%s'" % (role, self.name)
@@ -1004,15 +985,6 @@ class QAPISchema:
QAPISchemaIfCond(v.get('if')))
for v in values]
- def _make_implicit_enum_type(self, name, info, ifcond, values):
- # See also QAPISchemaObjectTypeMember.describe()
- name = name + 'Kind' # reserved by check_defn_name_str()
- self._def_entity(QAPISchemaEnumType(
- name, info, None, ifcond, None,
- self._make_enum_members(values, info),
- None))
- return name
-
def _make_array_type(self, element_type, info):
name = element_type + 'List' # reserved by check_defn_name_str()
if not self.lookup_type(name):
@@ -1026,17 +998,9 @@ class QAPISchema:
name = 'q_obj_%s-%s' % (name, role)
typ = self.lookup_entity(name, QAPISchemaObjectType)
if typ:
- # The implicit object type has multiple users. This is
- # either a duplicate definition (which will be flagged
- # later), or an implicit wrapper type used for multiple
- # simple unions. In the latter case, ifcond should be the
- # disjunction of its user's ifconds. Not implemented.
- # Instead, we always pass the wrapped type's ifcond, which
- # is trivially the same for all users. It's also
- # necessary for the wrapper to compile. But it's not
- # tight: the disjunction need not imply it. We may end up
- # compiling useless wrapper types.
- # TODO kill simple unions or implement the disjunction
+ # The implicit object type has multiple users. This can
+ # only be a duplicate definition, which will be flagged
+ # later.
pass
else:
self._def_entity(QAPISchemaObjectType(
@@ -1084,49 +1048,28 @@ class QAPISchema:
def _make_variant(self, case, typ, ifcond, info):
return QAPISchemaVariant(case, info, typ, ifcond)
- def _make_simple_variant(self, case, typ, ifcond, info):
- if isinstance(typ, list):
- assert len(typ) == 1
- typ = self._make_array_type(typ[0], info)
- typ = self._make_implicit_object_type(
- typ, info, self.lookup_type(typ),
- 'wrapper', [self._make_member('data', typ, None, None, info)])
- return QAPISchemaVariant(case, info, typ, ifcond)
-
def _def_union_type(self, expr, info, doc):
name = expr['union']
+ base = expr['base']
+ tag_name = expr['discriminator']
data = expr['data']
- base = expr.get('base')
ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info)
- tag_name = expr.get('discriminator')
- tag_member = None
if isinstance(base, dict):
base = self._make_implicit_object_type(
name, info, ifcond,
'base', self._make_members(base, info))
- if tag_name:
- variants = [
- self._make_variant(key, value['type'],
- QAPISchemaIfCond(value.get('if')),
- info)
- for (key, value) in data.items()]
- members = []
- else:
- variants = [
- self._make_simple_variant(key, value['type'],
- QAPISchemaIfCond(value.get('if')),
- info)
- for (key, value) in data.items()]
- enum = [{'name': v.name, 'if': v.ifcond.ifcond} for v in variants]
- typ = self._make_implicit_enum_type(name, info, ifcond, enum)
- tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
- members = [tag_member]
+ variants = [
+ self._make_variant(key, value['type'],
+ QAPISchemaIfCond(value.get('if')),
+ info)
+ for (key, value) in data.items()]
+ members = []
self._def_entity(
QAPISchemaObjectType(name, info, doc, ifcond, features,
base, members,
QAPISchemaVariants(
- tag_name, info, tag_member, variants)))
+ tag_name, info, None, variants)))
def _def_alternate_type(self, expr, info, doc):
name = expr['alternate']