From: Eric Blake <eblake@redhat.com>
To: Markus Armbruster <armbru@redhat.com>, qemu-devel@nongnu.org
Cc: kwolf@redhat.com, berto@igalia.com, mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH RFC v3 02/32] qapi: New QAPISchema intermediate reperesentation
Date: Tue, 4 Aug 2015 15:53:04 -0600 [thread overview]
Message-ID: <55C1343F.5060003@redhat.com> (raw)
In-Reply-To: <1438703896-12553-3-git-send-email-armbru@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 8332 bytes --]
On 08/04/2015 09:57 AM, Markus Armbruster wrote:
> The QAPI code generators work with a syntax tree (nested dictionaries)
> plus a few symbol tables (also dictionaries) on the side.
>
> They have clearly outgrown these simple data structures. There's lots
> of rummaging around in dictionaries, and information is recomputed on
> the fly. For the work I'm going to do, I want more clearly defined
> and more convenient interfaces.
>
> Going forward, I also want less coupling between the back-ends and the
> syntax tree, to make messing with the syntax easier.
>
> Create a bunch of classes to represent QAPI schemata.
>
> Have the QAPISchema initializer call the parser, then walk the syntax
> tree to create the new internal representation, and finally perform
> semantic analysis.
>
> Shortcut: the semantic analysis still relies on existing check_exprs()
> to do the actual semantic checking. All this code needs to move into
> the classes. Mark as TODO.
>
> We generate array types eagerly, even though most of them aren't used.
> Mark as TODO.
I'm not sure if there are any array types that the rest of the code base
uses even though it doesn't appear as a directly used type within the
schemata. Perhaps some of the builtin types (for example, if qom-get
needs to return ['uint8']). Besides builtins, maybe we can add some sort
of 'needs-array':'bool' key to each 'struct'/'union'/'enum'/'alternate',
which defaults to true only if the schema refers to the array type, but
which can be explicitly set to true to force the array type generation
even without a schema reference. But as it is all properly marked TODO,
the idle ramblings in this paragraph don't affect review.
>
> Nothing uses the new intermediate representation just yet, thus no
> change to generated files.
>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
> scripts/qapi-commands.py | 2 +-
> scripts/qapi-event.py | 2 +-
> scripts/qapi-types.py | 2 +-
> scripts/qapi-visit.py | 2 +-
> scripts/qapi.py | 361 ++++++++++++++++++++++++++++++++++++++++-
> tests/qapi-schema/test-qapi.py | 2 +-
> 6 files changed, 357 insertions(+), 14 deletions(-)
>
> +class QAPISchemaEnumType(QAPISchemaType):
> + def __init__(self, name, info, values):
> + QAPISchemaType.__init__(self, name, info)
> + for v in values:
> + assert isinstance(v, str)
> + self.values = values
> + def check(self, schema):
> + assert len(set(self.values)) == len(self.values)
Doesn't check whether any of the distinct values map to the same C name.
But not a show-stopper to this patch (the earlier semantic checking in
check_exprs() covers it, and your TODO about moving those checks here at
a later date is the right time to worry about it here).
> +
> +class QAPISchemaArrayType(QAPISchemaType):
> + def __init__(self, name, info, element_type):
> + QAPISchemaType.__init__(self, name, info)
> + assert isinstance(element_type, str)
> + self.element_type_name = element_type
> + self.element_type = None
> + def check(self, schema):
> + self.element_type = schema.lookup_type(self.element_type_name)
> + assert self.element_type
Is it worth adding:
assert not isinstance(self.element_type, QAPISchemaArrayType)
since we don't allow 2D arrays?
> +
> +class QAPISchemaObjectType(QAPISchemaType):
> + def __init__(self, name, info, base, local_members, variants):
> + QAPISchemaType.__init__(self, name, info)
> + assert base == None or isinstance(base, str)
> + for m in local_members:
> + assert isinstance(m, QAPISchemaObjectTypeMember)
> + if variants != None:
> + assert isinstance(variants, QAPISchemaObjectTypeVariants)
Style nit: the 'base' and 'variants' checks are identical patterns
(checking for None or specific type), but only one uses an 'if'.
Possibly because of line-length issues, though, so I can live with it.
> +
> +class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
> + def __init__(self, name, typ):
> + QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
> + def check(self, schema, tag_type, seen):
> + QAPISchemaObjectTypeMember.check(self, schema, [], seen)
> + assert self.name in tag_type.values
> + # TODO try to get rid of .simple_union_type()
> + def simple_union_type(self):
> + if isinstance(self.type, QAPISchemaObjectType) and not self.type.info:
> + assert len(self.type.members) == 1
> + assert not self.type.variants # not implemented
and probably never will be (looks like this assert is copy-and-pasted
from other locations where it makes sense that we might implement
support for variants, but I don't see it ever happening for the
generated ':obj-*-wrapper' type for the branch of a simple union)
At any rate, I concur that we have a difference in the generated code
for simple unions compared to flat unions (even if simple unions could
be rewritten in terms of a flat union from the QMP side, the generated C
side is not the same), so I agree that you need this function for now,
as well as the comment for if we later try to clean up the code base to
drop that difference.
> +class QAPISchema(object):
> + def _make_array_type(self, element_type):
> + name = element_type + 'List'
> + if not self.lookup_type(name):
> + self._def_entity(QAPISchemaArrayType(name, None, element_type))
> + return name
Hmm - we probably have collisions if a user tries to explicitly name a
'struct' or other type with a 'List' suffix. Not made worse by this
patch and not an actual problem with any of our existing .json files, so
we can save it for another day.
> +
> + def _make_members(self, data):
> + return [self._make_member(key, data[key]) for key in data.keys()]
You could write this as:
return [self._make_member(key, value) for (key, value) in data.iteritems()]
for fewer copies and lookups (dict.keys() and dict.items() creates
copies, while dict.iteritems() visits key/value pairs in place).
I don't care strongly enough to hold up review, whether or not you
change it.
> +
> + def _def_union_type(self, expr, info):
> + name = expr['union']
> + data = expr['data']
> + base = expr.get('base')
> + tag_name = expr.get('discriminator')
> + tag_enum = None
> + if tag_name:
> + variants = [self._make_variant(key, data[key])
> + for key in data.keys()]
> + else:
> + variants = [self._make_simple_variant(key, data[key])
> + for key in data.keys()]
Same comments about the possibility for writing these list
comprehensions more efficiently. [and "list comprehensions" is my
latest bit of cool python language terminology that I learned the name
of, in order to do this review]
> + def _def_command(self, expr, info):
> + name = expr['command']
> + data = expr.get('data')
> + rets = expr.get('returns')
> + gen = expr.get('gen', True)
> + success_response = expr.get('success-response', True)
> + if isinstance(data, OrderedDict):
> + data = self._make_implicit_object_type(name, 'arg',
> + self._make_members(data))
> + if isinstance(rets, list):
> + assert len(rets) == 1
> + rets = self._make_array_type(rets[0])
> + elif isinstance(rets, OrderedDict):
> + rets = self._make_implicit_object_type(name, 'ret',
> + self._make_members(rets))
Dead 'elif' branch (since you reject dictionaries in "[PATCH 21/26]
qapi: Command returning anonymous type doesn't work, outlaw")
Looks like there will be some minor tweaks when you drop the RFC, but
it's close enough at this point that I'm okay with:
Reviewed-by: Eric Blake <eblake@redhat.com>
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
next prev parent reply other threads:[~2015-08-04 21:53 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-04 15:57 [Qemu-devel] [PATCH RFC v3 00/32] qapi: QMP introspection Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 01/32] qapi: Rename class QAPISchema to QAPISchemaParser Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 02/32] qapi: New QAPISchema intermediate reperesentation Markus Armbruster
2015-08-04 21:53 ` Eric Blake [this message]
2015-08-05 6:23 ` Markus Armbruster
2015-08-05 14:27 ` Eric Blake
2015-08-06 5:46 ` Markus Armbruster
2015-08-31 18:09 ` Markus Armbruster
2015-09-03 14:52 ` Eric Blake
2015-09-03 16:13 ` Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 03/32] qapi: QAPISchema code generation helper methods Markus Armbruster
2015-08-04 22:18 ` Eric Blake
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 04/32] qapi: New QAPISchemaVisitor Markus Armbruster
2015-08-04 22:26 ` Eric Blake
2015-08-05 6:24 ` Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 05/32] tests/qapi-schema: Convert test harness to QAPISchemaVisitor Markus Armbruster
2015-08-04 22:35 ` Eric Blake
2015-08-05 6:26 ` Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 06/32] qapi: Split up some typedefs to ease review Markus Armbruster
2015-08-04 22:37 ` Eric Blake
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 07/32] qapi: Generate comments to simplify splitting for review Markus Armbruster
2015-08-04 22:54 ` Eric Blake
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 08/32] Revert "qapi: Generate comments to simplify splitting for review" Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 09/32] Revert "qapi: Split up some typedefs to ease review" Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 10/32] qapi-types: Convert to QAPISchemaVisitor, fixing flat unions Markus Armbruster
2015-08-05 15:15 ` Eric Blake
2015-08-06 5:50 ` Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 11/32] qapi-visit: Convert to QAPISchemaVisitor, fixing bugs Markus Armbruster
2015-08-05 16:03 ` Eric Blake
2015-08-06 22:53 ` Eric Blake
2015-08-08 6:07 ` Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 12/32] qapi-commands: Convert to QAPISchemaVisitor Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 13/32] qapi: De-duplicate enum code generation Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 14/32] qapi-event: Eliminate global variable event_enum_value Markus Armbruster
2015-08-04 15:57 ` [Qemu-devel] [PATCH RFC v3 15/32] qapi-event: Convert to QAPISchemaVisitor, fixing data with base Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 16/32] qapi: Generate comments to simplify splitting for review Markus Armbruster
2015-08-04 23:02 ` Eric Blake
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 17/32] Revert "qapi: Generate comments to simplify splitting for review" Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 18/32] qapi: Replace dirty is_c_ptr() by method c_null() Markus Armbruster
2015-08-05 16:13 ` Eric Blake
2015-08-06 5:52 ` Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 19/32] qapi: Clean up after recent conversions to QAPISchemaVisitor Markus Armbruster
2015-08-05 16:29 ` Eric Blake
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 20/32] qapi-visit: Rearrange code a bit Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 21/32] qapi-commands: Rearrange code Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 22/32] qapi: Rename qmp_marshal_input_FOO() to qmp_marshal_FOO() Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 23/32] qapi: De-duplicate parameter list generation Markus Armbruster
2015-08-05 17:00 ` Eric Blake
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 24/32] qapi-commands: De-duplicate output marshaling functions Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 25/32] qapi: Improve built-in type documentation Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 26/32] qapi: Introduce a first class 'any' type Markus Armbruster
2015-08-07 19:30 ` Eric Blake
2015-08-08 6:24 ` Markus Armbruster
2015-08-31 9:07 ` Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 27/32] qom: Don't use 'gen': false for qom-get, qom-set, object-add Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 28/32] qapi-schema: Fix up misleading specification of netdev_add Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 29/32] qapi: Pseudo-type '**' is now unused, drop it Markus Armbruster
2015-08-05 17:13 ` Eric Blake
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 30/32] qapi: New QMP command query-schema for QMP schema introspection Markus Armbruster
2015-08-05 20:20 ` Eric Blake
2015-08-06 6:23 ` Markus Armbruster
2015-09-01 13:09 ` Markus Armbruster
2015-09-01 15:48 ` Eric Blake
2015-08-05 20:54 ` Eric Blake
2015-08-06 6:47 ` Markus Armbruster
2015-08-23 4:17 ` Eric Blake
2015-08-24 11:30 ` Markus Armbruster
2015-08-24 13:07 ` Eric Blake
2015-08-24 16:51 ` Eric Blake
2015-08-24 16:55 ` Markus Armbruster
2015-08-24 17:14 ` Eric Blake
2015-08-25 8:33 ` Markus Armbruster
2015-09-01 18:40 ` Michael Roth
2015-09-01 19:12 ` Eric Blake
2015-09-01 20:23 ` Michael Roth
2015-09-02 8:56 ` Markus Armbruster
2015-09-02 16:21 ` Michael Roth
2015-09-03 9:26 ` Markus Armbruster
2015-09-03 14:31 ` Eric Blake
2015-09-03 15:59 ` Michael Roth
2015-09-03 17:01 ` Markus Armbruster
2015-09-03 19:59 ` Michael Roth
2015-09-04 6:39 ` Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 31/32] qapi-introspect: Map all integer types to 'int' Markus Armbruster
2015-08-04 15:58 ` [Qemu-devel] [PATCH RFC v3 32/32] qapi-introspect: Hide type names Markus Armbruster
2015-08-05 21:06 ` Eric Blake
2015-08-05 21:50 ` Eric Blake
2015-08-06 6:49 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55C1343F.5060003@redhat.com \
--to=eblake@redhat.com \
--cc=armbru@redhat.com \
--cc=berto@igalia.com \
--cc=kwolf@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).