From patchwork Fri Oct 2 04:31:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 525372 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 123611402C4 for ; Fri, 2 Oct 2015 14:34:54 +1000 (AEST) Received: from localhost ([::1]:57412 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zhs3X-0008NB-LQ for incoming@patchwork.ozlabs.org; Fri, 02 Oct 2015 00:34:51 -0400 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 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 5A95E8C1D5; Fri, 2 Oct 2015 04:31:58 +0000 (UTC) Received: from red.redhat.com (ovpn-113-151.phx2.redhat.com [10.3.113.151]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t924VsGW027842; Fri, 2 Oct 2015 00:31:57 -0400 From: Eric Blake To: qemu-devel@nongnu.org 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> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Michael Roth , marcandre.lureau@redhat.com, armbru@redhat.com, ehabkost@redhat.com Subject: [Qemu-devel] [PATCH v6 05/12] qapi: Track location that created an implicit type X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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))