qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 03/14] qapi: Introduce default values for str


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH v4 03/14] qapi: Introduce default values for struct members
Date: Fri, 22 Nov 2019 08:29:00 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux)

Eric Blake <address@hidden> writes:

> On 11/21/19 1:46 PM, Markus Armbruster wrote:
>
>>>> The '*' is redundant in this form.
>>>>
>>>> Can anyone think of reasons for keeping it anyway?  Against?
>>>
>>> Is there ever a reason to allow an optional member but without a
>>> 'default' value?  Or can we just blindly state that if 'default' is
>>> not present, that is the same as 'default':0/'default':null?
>>>
>>> Or, applying your statement further,
>>>
>>> 'data': { '*a':'int', '*b':'str' }
>>>
>>> is shorthand for:
>>>
>>> 'data': { 'a': { 'type':'int', 'default':0 },
>>>            'b': { 'type':'str', 'default':null } }
>>
>> You propose to default 'default' to a type-specific value.
>>
>> I don't think that's a good idea.
>
> ...
>
>
>> When an absent member behaves just like it was present with a certain
>> value DFLT, we want to be able to say in the schema 'default': DFLT.
>>
>> But the schema language also needs to let us say "absent member behaves
>> unlike any value".
>>
>> If we define 'default' to default to a value, then that value must have
>> this special meaning.
>>
>> Where that value is also a valid value, the schema language cannot
>> express "absent member behaves like it was present with that value".
>>
>> I think this makes 0 a poor default value for 'default': "behaves like
>> member was present with value 0" is fairly common, I think.
>>
>> Defaulting 'default' to null regardless of member type could work.
>>
>> null is a valid value of the 'null' type and of alternate types with a
>> member of type 'null'.  For optional members of such types, the schema
>> language then can't express ""absent member behaves like it was present
>> with value null".  I think the need to say that is much less common than
>> the needs to say "like value 0".
>>
>> Checking...  *sigh*: there are a few optional members that can take null
>> values, e.g. MigrateSetParameters member @tls-creds.  I read its doc
>> comment twice, and I have to admit I can't make heads or tails of it.
>> Can't say for sure whether absent behaves like null, or some other
>> value, or unlike any value.
>>
>> QAPI/QMP introspection already specifies null to have exactly this
>> special meaning.
>
> Maybe that means we need '*name':'t' to expand into something longer, maybe
>  'name':{'type':'t', 'optional':true}
> which in  turn would be synonymous with your idea of ALL types
> accepting a default of null:
>  'name':{'type':'t', 'optional':true, 'default':null}

Yes, this is something we can consider.

Currently, we normalize away the '*' prefix when we go from the abstract
parse tree (which we call "expressions") to the internal representation:

    def _make_member(self, name, typ, ifcond, info):
        optional = False
        if name.startswith('*'):
            name = name[1:]
            optional = True
        if isinstance(typ, list):
            assert len(typ) == 1
            typ = self._make_array_type(typ[0], info)
        return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcond)

This keeps the normalization internal.

Other normalizations we perform on the abstract parse tree.  For
instance, here's the one that normalizes shorthand member "'KEY': 'ARG'"
to longhand "'KEY': { 'type': 'ARG' }":

    def normalize_members(members):
        if isinstance(members, OrderedDict):
            for key, arg in members.items():
                if isinstance(arg, dict):
                    continue
                members[key] = {'type': arg}

For these normalizations, both the shorthand and the longhand form are
part of the schema language.  We could do the same for '*'.

> At any rate, your counterpoint is taken - whatever we pick, we'll want
> to make sure that introspection can expose semantics, and whether we
> can make '*' redundant with some other form of longhand in the qapi
> language is in part determined by whether we also reflect that through
> introspection.

Introspection has the true member name, without the '*' prefix.

We'll also want to avoid unnecessary compromises on QAPI schema
expressiveness.  If we use null to mean "schema does not specify
behavior when member is absent", we can't use it to mean "absent member
behaves like the value null".  A bit of a blemish, but I think it's a
tolerable one.

>                 If that means that keeping '*' in the longhand form of
> optional members (whether or not those members have a default value),
> then so be it.

I believe both

    '*KEY': { 'type': ARG': 'default': null }

and

    'KEY': { 'type': ARG': 'default': null }

are viable longhand forms for '*KEY': 'ARG'.

I prefer the latter, but I'm open to arguments.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]