diff options
Diffstat (limited to 'scripts/qapi/schema.py')
-rw-r--r-- | scripts/qapi/schema.py | 101 |
1 files changed, 22 insertions, 79 deletions
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'] |