All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@gmail.com>
Cc: Markus Armbruster <armbru@redhat.com>, QEMU <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check()
Date: Wed, 27 Jun 2018 07:26:02 +0200	[thread overview]
Message-ID: <876024by1h.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <CAJ+F1CKb8vgToF_VKyu2ARVQZP-XfHBoMm_cMd9YJRaziHWQNQ@mail.gmail.com> ("Marc-André Lureau"'s message of "Tue, 26 Jun 2018 15:39:51 +0200")

Marc-André Lureau <marcandre.lureau@gmail.com> writes:

> Hi
>
> On Tue, Jun 19, 2018 at 11:06 AM, Markus Armbruster <armbru@redhat.com> wrote:
>> Marc-André Lureau <marcandre.lureau@redhat.com> writes:
>>
>>> We commonly initialize attributes to None in .init(), then set their
>>> real value in .check().  Accessing the attribute before .check()
>>> yields None.  If we're lucky, the code that accesses the attribute
>>> prematurely chokes on None.
>>>
>>> It won't for .ifcond, because None is a legitimate value.
>>>
>>> Leave the ifcond attribute undefined until check().
>>
>> Drawback: pylint complains.  We'll live.
>>
>>>
>>> Suggested-by: Markus Armbruster <armbru@redhat.com>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>>
>> Shouldn't this be squashed into the previous patch?
>
> I would rather keep it seperate, as it makes reviewing both a bit
> easier to me. But feel free to squash on commit.

No need to decide right now.

>>
>>> ---
>>>  scripts/qapi/common.py | 21 +++++++++++++++++----
>>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
>>> index d8ab3d8f7f..eb07d641ab 100644
>>> --- a/scripts/qapi/common.py
>>> +++ b/scripts/qapi/common.py
>>> @@ -1026,13 +1026,19 @@ class QAPISchemaEntity(object):
>>>          # such place).
>>>          self.info = info
>>>          self.doc = doc
>>> -        self.ifcond = listify_cond(ifcond)
>>> +        self._ifcond = ifcond  # self.ifcond is set only after .check()
>>>
>>>      def c_name(self):
>>>          return c_name(self.name)
>>>
>>>      def check(self, schema):
>>> -        pass
>>> +        if isinstance(self._ifcond, QAPISchemaType):
>>> +            # inherit the condition from a type
>>> +            typ = self._ifcond
>>> +            typ.check(schema)
>>> +            self.ifcond = typ.ifcond
>>> +        else:
>>> +            self.ifcond = listify_cond(self._ifcond)
>>
>> Whenever we add a .check(), we need to prove QAPISchema.check()'s
>> recursion still terminates, and terminates the right way.
>>
>> Argument before this patch: we recurse only into types contained in
>> types, e.g. an object type's base type, and we detect and report cycles
>> as "Object %s contains itself", in QAPISchemaObjectType.check().
>>
>> The .check() added here recurses into a type.  If this creates a cycle,
>> it'll be caught and reported as "contains itself".  We still need to
>> show that the error message remains accurate.
>>
>> We .check() here to inherit .ifcond from a type.  As far as I can tell,
>> we use this inheritance feature only to inherit an array's condition
>> from its element type.  That's safe, because an array does contain its
>> elements.
>>
>> This is hardly a rigorous proof.  Just enough to make me believe your
>> code works.
>>
>> However, I suspect adding the inheritance feature at the entity level
>> complicates the correctness argument without real need.  Can we restrict
>> it to array elements?  Have QAPISchemaArrayType.check() resolve
>> type-valued ._ifcond, and all the others choke on it?
>
> There is also implicit object types.

Can you give an example?

>>>
>>>      def is_implicit(self):
>>>          return not self.info
>>> @@ -1169,6 +1175,7 @@ class QAPISchemaEnumType(QAPISchemaType):
>>>          self.prefix = prefix
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          seen = {}
>>>          for v in self.values:
>>>              v.check_clash(self.info, seen)
>>> @@ -1201,8 +1208,10 @@ class QAPISchemaArrayType(QAPISchemaType):
>>>          self.element_type = None
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          self.element_type = schema.lookup_type(self._element_type_name)
>>>          assert self.element_type
>>> +        self.element_type.check(schema)
>>>          self.ifcond = self.element_type.ifcond
>>>
>>>      def is_implicit(self):
>>> @@ -1245,6 +1254,7 @@ class QAPISchemaObjectType(QAPISchemaType):
>>>          self.members = None
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          if self.members is False:               # check for cycles
>>>              raise QAPISemError(self.info,
>>>                                 "Object %s contains itself" % self.name)
>>> @@ -1427,6 +1437,7 @@ class QAPISchemaAlternateType(QAPISchemaType):
>>>          self.variants = variants
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaType.check(self, schema)
>>>          self.variants.tag_member.check(schema)
>>>          # Not calling self.variants.check_clash(), because there's nothing
>>>          # to clash with
>>> @@ -1470,6 +1481,7 @@ class QAPISchemaCommand(QAPISchemaEntity):
>>>          self.allow_oob = allow_oob
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaEntity.check(self, schema)
>>>          if self._arg_type_name:
>>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>>> @@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity):
>>>          self.boxed = boxed
>>>
>>>      def check(self, schema):
>>> +        QAPISchemaEntity.check(self, schema)
>>>          if self._arg_type_name:
>>>              self.arg_type = schema.lookup_type(self._arg_type_name)
>>>              assert (isinstance(self.arg_type, QAPISchemaObjectType) or
>>> @@ -1633,7 +1646,7 @@ class QAPISchema(object):
>>>              # 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
>>> -            assert ifcond == typ.ifcond
>>> +            assert ifcond == typ._ifcond
>>
>> pylint complains
>>
>>     W:1649,29: Access to a protected member _ifcond of a client class (protected-access)
>>
>> Layering violation.  Tolerable, I think.
>>
>
> yeah, alternative would be to add an assert_ifcond() method in type..?
> I'll add a # pylint: disable=protected-access for now

Wortwhile only if we make an effort to clean up or suppress the other
pylint gripes.  I'll look into it.  Go ahead and add the directive
meanwhile; easily dropped it if we decide we don't want it.

>>>              self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
>>>                                                    None, members, None))
>>> @@ -1679,7 +1692,7 @@ class QAPISchema(object):
>>>              assert len(typ) == 1
>>>              typ = self._make_array_type(typ[0], info)
>>>          typ = self._make_implicit_object_type(
>>> -            typ, info, None, self.lookup_type(typ).ifcond,
>>> +            typ, info, None, self.lookup_type(typ),
>>>              'wrapper', [self._make_member('data', typ, info)])
>>>          return QAPISchemaObjectTypeVariant(case, typ)
>>
>> Perhaps other attributes that become valid only at .check() time should
>> receive the same treatment.  Not necessarily in this series, not
>> necessarily by you.  A TODO comment wouldn't hurt, though.
>>
>
> It doesn't look obvious to me which should receive the same
> treatement. I'll leave that to you to figure out :)

Fair enough.

  reply	other threads:[~2018-06-27  5:26 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-21 11:51 [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 01/49] qapi/visit: remove useless prefix argument Marc-André Lureau
2018-06-18 14:29   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 02/49] qapi/events: generate event enum in main module Marc-André Lureau
2018-06-18 14:33   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 03/49] qapi: add 'if' to top-level expressions Marc-André Lureau
2018-06-19  7:57   ` Markus Armbruster
2018-06-19  8:41     ` Marc-André Lureau
2018-06-19 11:35       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 04/49] qapi: pass 'if' condition into QAPISchemaEntity objects Marc-André Lureau
2018-06-19  8:09   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 05/49] qapi: leave the ifcond attribute undefined until check() Marc-André Lureau
2018-06-19  9:06   ` Markus Armbruster
2018-06-26 13:39     ` Marc-André Lureau
2018-06-27  5:26       ` Markus Armbruster [this message]
2018-06-29 10:30         ` Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 06/49] qapi: add 'ifcond' to visitor methods Marc-André Lureau
2018-06-21  8:18   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 07/49] qapi: mcgen() shouldn't indent # lines Marc-André Lureau
2018-06-20 15:14   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 08/49] qapi: add #if/#endif helpers Marc-André Lureau
2018-06-20 16:01   ` Markus Armbruster
2018-06-21  7:06   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 09/49] qapi-introspect: modify to_qlit() to append ', ' on level > 0 Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 10/49] qapi-introspect: add preprocessor conditions to generated QLit Marc-André Lureau
2018-06-21 13:05   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 11/49] qapi/commands: add #if conditions to commands Marc-André Lureau
2018-06-21 14:35   ` Markus Armbruster
2018-06-22  8:34   ` Markus Armbruster
2018-06-25 13:15     ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 12/49] qapi/events: add #if conditions to events Marc-André Lureau
2018-06-21 14:40   ` Markus Armbruster
2018-06-22  9:02   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 13/49] qapi-types: refactor variants handling Marc-André Lureau
2018-06-21 15:54   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 14/49] qapi-types: add #if conditions to types & visitors Marc-André Lureau
2018-06-21 16:12   ` Markus Armbruster
2018-06-27 11:59     ` Marc-André Lureau
2018-06-28  6:27       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 15/49] qapi: do not define enumeration value explicitely Marc-André Lureau
2018-06-22  8:08   ` Markus Armbruster
2018-06-27 12:13     ` Marc-André Lureau
2018-06-28  6:34       ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 16/49] qapi: rename QAPISchemaEnumType.values to .members Marc-André Lureau
2018-06-22 12:24   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 17/49] qapi: change enum visitor to take QAPISchemaMember Marc-André Lureau
2018-06-22 12:24   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 18/49] tests: modify visit_enum_type() in test-qapi to print members Marc-André Lureau
2018-06-22 14:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 19/49] qapi: factor out check_known_keys() Marc-André Lureau
2018-06-25 14:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 20/49] qapi: add a dictionnary form with 'name' key for enum members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 21/49] qapi: add 'if' to " Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 22/49] qapi-event: add 'if' condition to implicit event enum Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 23/49] qapi: rename allow_dict to allow_implicit Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 24/49] qapi: add a dictionary form with 'type' key for members Marc-André Lureau
2018-06-20 11:13   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 25/49] qapi: add 'if' to implicit struct members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 26/49] qapi: add an error in case a discriminator is conditionnal Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 27/49] qapi: add 'if' on union members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 28/49] qapi: add 'if' to alternate members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 29/49] qapi: add #if conditions to generated code members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 30/49] docs: document schema configuration Marc-André Lureau
2018-06-22 11:10   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 31/49] qapi2texi: add 'If:' section to generated documentation Marc-André Lureau
2018-06-21 16:29   ` Markus Armbruster
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 32/49] qapi2texi: add 'If:' condition to enum values Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 33/49] qapi2texi: add 'If:' condition to struct members Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 34/49] qapi2texi: add condition to variants Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 35/49] qapi: add conditions to VNC type/commands/events on the schema Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 36/49] qapi: add conditions to SPICE " Marc-André Lureau
2018-03-21 11:51 ` [Qemu-devel] [PATCH v3 37/49] qapi: add conditions to REPLICATION type/commands " Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 38/49] build-sys: move qmp-introspect per target Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 39/49] qapi-commands: don't initialize command list in qmp_init_marshall() Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 40/49] RFC: qapi: learn to split schema by 'top-unit' Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 41/49] qapi: add a top-unit 'target' schema Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 42/49] qapi: make rtc-reset-reinjection and SEV depend on TARGET_I386 Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 43/49] qapi: make s390 commands depend on TARGET_S390X Marc-André Lureau
2018-03-22  5:42   ` Thomas Huth
2018-03-22  9:41     ` Marc-André Lureau
2018-03-22 16:10       ` Thomas Huth
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 44/49] target.json: add a note about query-cpu* not being s390x-specific Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 45/49] qapi: make query-gic-capabilities depend on TARGET_ARM Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 46/49] qapi: make query-cpu-model-expansion depend on s390 or x86 Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 47/49] qapi: make query-cpu-definitions depend on specific targets Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 48/49] qapi: remove qmp_unregister_command() Marc-André Lureau
2018-03-21 11:52 ` [Qemu-devel] [PATCH v3 49/49] RFC: make RTC_CHANGE per-target Marc-André Lureau
2018-03-21 12:47 ` [Qemu-devel] [PATCH v3 00/49] qapi: add #if pre-processor conditions to generated code no-reply
2018-03-21 14:20 ` no-reply
2018-03-21 22:08 ` no-reply
2018-03-22  5:11 ` no-reply
2018-06-21 16:47 ` Markus Armbruster
2018-06-21 17:18   ` Marc-André Lureau
2018-06-22  6:56     ` Markus Armbruster
2018-06-22  9:06     ` 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=876024by1h.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=marcandre.lureau@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.