From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48790) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zhs0m-0003kU-Ga for qemu-devel@nongnu.org; Fri, 02 Oct 2015 00:32:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zhs0k-0006YM-V1 for qemu-devel@nongnu.org; Fri, 02 Oct 2015 00:32:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42790) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zhs0k-0006YI-MJ for qemu-devel@nongnu.org; Fri, 02 Oct 2015 00:31:58 -0400 From: Eric Blake Date: Thu, 1 Oct 2015 22:31:45 -0600 Message-Id: <1443760312-656-6-git-send-email-eblake@redhat.com> In-Reply-To: <1443760312-656-1-git-send-email-eblake@redhat.com> References: <1443760312-656-1-git-send-email-eblake@redhat.com> Subject: [Qemu-devel] [PATCH v6 05/12] qapi: Track location that created an implicit type List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Michael Roth , marcandre.lureau@redhat.com, armbru@redhat.com, ehabkost@redhat.com A future patch will enable deferred error detection in the various QAPISchema*.check() methods (rather than the current ad hoc parse checks). But that means the user can request a QAPI entity that will only fail validation after it has been initialized. Since all errors have to have an associated 'info' location, we need a location to be associated with all user-triggered implicit types. The intuitive info to use is the location of the enclosing entity that caused the creation of the implicit type. Note that we do not anticipate builtin types being used in an error message (as they are not part of the user's QAPI input, the user can't cause a semantic error in their behavior), so we exempt those types from requiring info, by setting a flag to track the completion of _def_predefineds(). No change to the generated code. RFC: I used a class-level static flag to track whether we expected 'info is None' when creating a QAPISchemaEntity. This is gross, because the flag will only be set on the first QAPISchema() instance (it works because none of our client scripts ever instantiate more than one schema). But the only other thing I could think of would be passing the QAPISchema instance into the constructor for each QAPISchemaEntity, which is a lot of churn. Any better ideas on how best to do the assertion, or should I just drop it? Signed-off-by: Eric Blake --- v6: improve commit message, track implicit enum info, rebase on new lazy array handling --- scripts/qapi.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index 255001a..19cca97 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -792,6 +792,7 @@ class QAPISchemaEntity(object): def __init__(self, name, info): assert isinstance(name, str) self.name = name + assert info or not QAPISchema.predefined_initialized self.info = info def c_name(self): @@ -1114,6 +1115,8 @@ class QAPISchemaEvent(QAPISchemaEntity): class QAPISchema(object): + predefined_initialized = False + def __init__(self, fname): try: self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs) @@ -1122,6 +1125,7 @@ class QAPISchema(object): exit(1) self._entity_dict = {} self._def_predefineds() + QAPISchema.predefined_initialized = True self._def_exprs() self.check() @@ -1163,9 +1167,9 @@ class QAPISchema(object): [], None) self._def_entity(self.the_empty_object_type) - def _make_implicit_enum_type(self, name, values): + def _make_implicit_enum_type(self, name, info, values): name = name + 'Kind' - self._def_entity(QAPISchemaEnumType(name, None, values, None)) + self._def_entity(QAPISchemaEnumType(name, info, values, None)) return name def _make_array_type(self, element_type, info): @@ -1174,12 +1178,12 @@ class QAPISchema(object): self._def_entity(QAPISchemaArrayType(name, info, element_type)) return name - def _make_implicit_object_type(self, name, role, members): + def _make_implicit_object_type(self, name, info, role, members): if not members: return None name = ':obj-%s-%s' % (name, role) if not self.lookup_entity(name, QAPISchemaObjectType): - self._def_entity(QAPISchemaObjectType(name, None, None, + self._def_entity(QAPISchemaObjectType(name, info, None, members, None)) return name @@ -1218,13 +1222,13 @@ class QAPISchema(object): if isinstance(typ, list): assert len(typ) == 1 typ = self._make_array_type(typ[0], info) - typ = self._make_implicit_object_type(typ, 'wrapper', + typ = self._make_implicit_object_type(typ, info, 'wrapper', [self._make_member('data', typ, info)]) return QAPISchemaObjectTypeVariant(case, typ) - def _make_tag_enum(self, type_name, variants): - typ = self._make_implicit_enum_type(type_name, + def _make_tag_enum(self, type_name, info, variants): + typ = self._make_implicit_enum_type(type_name, info, [v.name for v in variants]) return QAPISchemaObjectTypeMember('type', typ, False) @@ -1240,7 +1244,7 @@ class QAPISchema(object): else: variants = [self._make_simple_variant(key, value, info) for (key, value) in data.iteritems()] - tag_enum = self._make_tag_enum(name, variants) + tag_enum = self._make_tag_enum(name, info, variants) self._def_entity( QAPISchemaObjectType(name, info, base, self._make_members(OrderedDict(), info), @@ -1253,7 +1257,7 @@ class QAPISchema(object): data = expr['data'] variants = [self._make_variant(key, value) for (key, value) in data.iteritems()] - tag_enum = self._make_tag_enum(name, variants) + tag_enum = self._make_tag_enum(name, info, variants) self._def_entity( QAPISchemaAlternateType(name, info, QAPISchemaObjectTypeVariants(None, @@ -1267,7 +1271,7 @@ class QAPISchema(object): gen = expr.get('gen', True) success_response = expr.get('success-response', True) if isinstance(data, OrderedDict): - data = self._make_implicit_object_type(name, 'arg', + data = self._make_implicit_object_type(name, info, 'arg', self._make_members(data, info)) if isinstance(rets, list): @@ -1280,7 +1284,7 @@ class QAPISchema(object): name = expr['event'] data = expr.get('data') if isinstance(data, OrderedDict): - data = self._make_implicit_object_type(name, 'arg', + data = self._make_implicit_object_type(name, info, 'arg', self._make_members(data, info)) self._def_entity(QAPISchemaEvent(name, info, data)) -- 2.4.3