mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:25:11 +00:00
qapi: Allow anonymous base for flat union
Rather than requiring all flat unions to explicitly create a separate base struct, we can allow the qapi schema to specify the common members via an inline dictionary. This is similar to how commands can specify an inline anonymous type for its 'data'. We already have several struct types that only exist to serve as a single flat union's base; the next commit will clean them up. In particular, this patch's change to the BlockdevOptions example in qapi-code-gen.txt will actually be done in the real QAPI schema. Now that anonymous bases are legal, we need to rework the flat-union-bad-base negative test (as previously written, it forms what is now valid QAPI; tweak it to now provide coverage of a new error message path), and add a positive test in qapi-schema-test to use an anonymous base (making the integer argument optional, for even more coverage). Note that this patch only allows anonymous bases for flat unions; simple unions are already enough syntactic sugar that we do not want to burden them further. Meanwhile, while it would be easy to also allow an anonymous base for structs, that would be quite redundant, as the members can be put right into the struct instead. Backports commit ac4338f8eb783fd421aae492ca262a586918471e from qemu
This commit is contained in:
parent
8f4a64398a
commit
e16b731799
|
@ -73,12 +73,14 @@ struct %(c_name)s {
|
||||||
c_name=c_name(name))
|
c_name=c_name(name))
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
if not base.is_implicit():
|
||||||
|
ret += mcgen('''
|
||||||
/* Members inherited from %(c_name)s: */
|
/* Members inherited from %(c_name)s: */
|
||||||
''',
|
''',
|
||||||
c_name=base.c_name())
|
c_name=base.c_name())
|
||||||
ret += gen_struct_members(base.members)
|
ret += gen_struct_members(base.members)
|
||||||
ret += mcgen('''
|
if not base.is_implicit():
|
||||||
|
ret += mcgen('''
|
||||||
/* Own members: */
|
/* Own members: */
|
||||||
''')
|
''')
|
||||||
ret += gen_struct_members(members)
|
ret += gen_struct_members(members)
|
||||||
|
@ -258,7 +260,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
|
||||||
return
|
return
|
||||||
self._fwdecl += gen_fwd_object_or_array(name)
|
self._fwdecl += gen_fwd_object_or_array(name)
|
||||||
self.decl += gen_object(name, base, members, variants)
|
self.decl += gen_object(name, base, members, variants)
|
||||||
if base:
|
if base and not base.is_implicit():
|
||||||
self.decl += gen_upcast(name, base)
|
self.decl += gen_upcast(name, base)
|
||||||
# TODO Worth changing the visitor signature, so we could
|
# TODO Worth changing the visitor signature, so we could
|
||||||
# directly use rather than repeat type.is_implicit()?
|
# directly use rather than repeat type.is_implicit()?
|
||||||
|
|
|
@ -332,6 +332,8 @@ class QAPISchemaParser(object):
|
||||||
|
|
||||||
|
|
||||||
def find_base_members(base):
|
def find_base_members(base):
|
||||||
|
if isinstance(base, dict):
|
||||||
|
return base
|
||||||
base_struct_define = find_struct(base)
|
base_struct_define = find_struct(base)
|
||||||
if not base_struct_define:
|
if not base_struct_define:
|
||||||
return None
|
return None
|
||||||
|
@ -565,9 +567,10 @@ def check_union(expr, expr_info):
|
||||||
|
|
||||||
# Else, it's a flat union.
|
# Else, it's a flat union.
|
||||||
else:
|
else:
|
||||||
# The object must have a string member 'base'.
|
# The object must have a string or dictionary 'base'.
|
||||||
check_type(expr_info, "'base' for union '%s'" % name,
|
check_type(expr_info, "'base' for union '%s'" % name,
|
||||||
base, allow_metas=['struct'])
|
base, allow_dict=True, allow_optional=True,
|
||||||
|
allow_metas=['struct'])
|
||||||
if not base:
|
if not base:
|
||||||
raise QAPIExprError(expr_info,
|
raise QAPIExprError(expr_info,
|
||||||
"Flat union '%s' must have a base"
|
"Flat union '%s' must have a base"
|
||||||
|
@ -1045,6 +1048,8 @@ class QAPISchemaMember(object):
|
||||||
owner = owner[6:]
|
owner = owner[6:]
|
||||||
if owner.endswith('-arg'):
|
if owner.endswith('-arg'):
|
||||||
return '(parameter of %s)' % owner[:-4]
|
return '(parameter of %s)' % owner[:-4]
|
||||||
|
elif owner.endswith('-base'):
|
||||||
|
return '(base of %s)' % owner[:-5]
|
||||||
else:
|
else:
|
||||||
assert owner.endswith('-wrapper')
|
assert owner.endswith('-wrapper')
|
||||||
# Unreachable and not implemented
|
# Unreachable and not implemented
|
||||||
|
@ -1339,6 +1344,9 @@ class QAPISchema(object):
|
||||||
base = expr.get('base')
|
base = expr.get('base')
|
||||||
tag_name = expr.get('discriminator')
|
tag_name = expr.get('discriminator')
|
||||||
tag_member = None
|
tag_member = None
|
||||||
|
if isinstance(base, dict):
|
||||||
|
base = (self._make_implicit_object_type(
|
||||||
|
name, info, 'base', self._make_members(base, info)))
|
||||||
if tag_name:
|
if tag_name:
|
||||||
variants = [self._make_variant(key, value)
|
variants = [self._make_variant(key, value)
|
||||||
for (key, value) in data.iteritems()]
|
for (key, value) in data.iteritems()]
|
||||||
|
|
Loading…
Reference in a new issue