mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-03-26 18:22:55 -07:00
qapi: replace if condition list with dict {'all': [...]}
Replace the simple list sugar form with a recursive structure that will accept other operators in the following commits (all, any or not). Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20210804083105.97531-7-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Accidental code motion undone. Degenerate :forms: comment dropped. Helper _check_if() moved. Error messages tweaked. ui.json updated. Accidental changes to qapi-schema-test.json dropped.] Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
committed by
Markus Armbruster
parent
d806f89f87
commit
5d83b9a130
@@ -1136,7 +1136,8 @@
|
||||
{ 'name': 'gtk', 'if': 'defined(CONFIG_GTK)' },
|
||||
{ 'name': 'sdl', 'if': 'defined(CONFIG_SDL)' },
|
||||
{ 'name': 'egl-headless',
|
||||
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' },
|
||||
'if': { 'all': [ 'defined(CONFIG_OPENGL)',
|
||||
'defined(CONFIG_GBM)' ] } },
|
||||
{ 'name': 'curses', 'if': 'defined(CONFIG_CURSES)' },
|
||||
{ 'name': 'cocoa', 'if': 'defined(CONFIG_COCOA)' },
|
||||
{ 'name': 'spice-app', 'if': 'defined(CONFIG_SPICE)'} ] }
|
||||
@@ -1167,7 +1168,8 @@
|
||||
'gtk': { 'type': 'DisplayGTK', 'if': 'defined(CONFIG_GTK)' },
|
||||
'curses': { 'type': 'DisplayCurses', 'if': 'defined(CONFIG_CURSES)' },
|
||||
'egl-headless': { 'type': 'DisplayEGLHeadless',
|
||||
'if': 'defined(CONFIG_OPENGL) && defined(CONFIG_GBM)' }
|
||||
'if': { 'all': [ 'defined(CONFIG_OPENGL)',
|
||||
'defined(CONFIG_GBM)' ] } }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
import re
|
||||
from typing import (
|
||||
List,
|
||||
Any,
|
||||
Dict,
|
||||
Match,
|
||||
Optional,
|
||||
Union,
|
||||
@@ -199,17 +200,29 @@ def guardend(name: str) -> str:
|
||||
name=c_fname(name).upper())
|
||||
|
||||
|
||||
def cgen_ifcond(ifcond: Union[str, List[str]]) -> str:
|
||||
def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
|
||||
if not ifcond:
|
||||
return ''
|
||||
return '(' + ') && ('.join(ifcond) + ')'
|
||||
if isinstance(ifcond, str):
|
||||
return ifcond
|
||||
|
||||
oper, operands = next(iter(ifcond.items()))
|
||||
oper = {'all': '&&'}[oper]
|
||||
operands = [cgen_ifcond(o) for o in operands]
|
||||
return '(' + (') ' + oper + ' (').join(operands) + ')'
|
||||
|
||||
|
||||
def docgen_ifcond(ifcond: Union[str, List[str]]) -> str:
|
||||
def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str:
|
||||
# TODO Doc generated for conditions needs polish
|
||||
if not ifcond:
|
||||
return ''
|
||||
return ' and '.join(ifcond)
|
||||
if isinstance(ifcond, str):
|
||||
return ifcond
|
||||
|
||||
oper, operands = next(iter(ifcond.items()))
|
||||
oper = {'all': ' and '}[oper]
|
||||
operands = [docgen_ifcond(o) for o in operands]
|
||||
return '(' + oper.join(operands) + ')'
|
||||
|
||||
|
||||
def gen_if(cond: str) -> str:
|
||||
|
||||
@@ -259,14 +259,9 @@ def check_flags(expr: _JSONObject, info: QAPISourceInfo) -> None:
|
||||
|
||||
def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
||||
"""
|
||||
Normalize and validate the ``if`` member of an object.
|
||||
Validate the ``if`` member of an object.
|
||||
|
||||
The ``if`` member may be either a ``str`` or a ``List[str]``.
|
||||
A ``str`` value will be normalized to ``List[str]``.
|
||||
|
||||
:forms:
|
||||
:sugared: ``Union[str, List[str]]``
|
||||
:canonical: ``List[str]``
|
||||
The ``if`` member may be either a ``str`` or a dict.
|
||||
|
||||
:param expr: The expression containing the ``if`` member to validate.
|
||||
:param info: QAPI schema source file information.
|
||||
@@ -275,31 +270,46 @@ def check_if(expr: _JSONObject, info: QAPISourceInfo, source: str) -> None:
|
||||
:raise QAPISemError:
|
||||
When the "if" member fails validation, or when there are no
|
||||
non-empty conditions.
|
||||
:return: None, ``expr`` is normalized in-place as needed.
|
||||
:return: None
|
||||
"""
|
||||
|
||||
def _check_if(cond: Union[str, object]) -> None:
|
||||
if isinstance(cond, str):
|
||||
if not cond.strip():
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition '%s' of %s makes no sense"
|
||||
% (cond, source))
|
||||
return
|
||||
|
||||
if not isinstance(cond, dict):
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition of %s must be a string or an object" % source)
|
||||
if len(cond) != 1:
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition dict of %s must have one key: "
|
||||
"'all'" % source)
|
||||
check_keys(cond, info, "'if' condition", [],
|
||||
["all"])
|
||||
|
||||
oper, operands = next(iter(cond.items()))
|
||||
if not operands:
|
||||
raise QAPISemError(
|
||||
info, "'if' condition [] of %s is useless" % source)
|
||||
|
||||
if oper in ("all") and not isinstance(operands, list):
|
||||
raise QAPISemError(
|
||||
info, "'%s' condition of %s must be an array" % (oper, source))
|
||||
for operand in operands:
|
||||
_check_if(operand)
|
||||
|
||||
ifcond = expr.get('if')
|
||||
if ifcond is None:
|
||||
return
|
||||
|
||||
if isinstance(ifcond, list):
|
||||
if not ifcond:
|
||||
raise QAPISemError(
|
||||
info, "'if' condition [] of %s is useless" % source)
|
||||
else:
|
||||
# Normalize to a list
|
||||
ifcond = expr['if'] = [ifcond]
|
||||
|
||||
for elt in ifcond:
|
||||
if not isinstance(elt, str):
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition of %s must be a string or a list of strings"
|
||||
% source)
|
||||
if not elt.strip():
|
||||
raise QAPISemError(
|
||||
info,
|
||||
"'if' condition '%s' of %s makes no sense"
|
||||
% (elt, source))
|
||||
_check_if(ifcond)
|
||||
|
||||
|
||||
def normalize_members(members: object) -> None:
|
||||
|
||||
@@ -32,7 +32,7 @@ from .parser import QAPISchemaParser
|
||||
|
||||
class QAPISchemaIfCond:
|
||||
def __init__(self, ifcond=None):
|
||||
self.ifcond = ifcond or []
|
||||
self.ifcond = ifcond or {}
|
||||
|
||||
def cgen(self):
|
||||
return cgen_ifcond(self.ifcond)
|
||||
|
||||
2
tests/qapi-schema/bad-if-all.err
Normal file
2
tests/qapi-schema/bad-if-all.err
Normal file
@@ -0,0 +1,2 @@
|
||||
bad-if-all.json: In struct 'TestIfStruct':
|
||||
bad-if-all.json:2: 'all' condition of struct must be an array
|
||||
3
tests/qapi-schema/bad-if-all.json
Normal file
3
tests/qapi-schema/bad-if-all.json
Normal file
@@ -0,0 +1,3 @@
|
||||
# check 'if all' is not a list
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'all': 'ALL' } }
|
||||
0
tests/qapi-schema/bad-if-all.out
Normal file
0
tests/qapi-schema/bad-if-all.out
Normal file
@@ -1,3 +1,3 @@
|
||||
# check empty 'if' list
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': [] }
|
||||
'if': { 'all': [] } }
|
||||
|
||||
3
tests/qapi-schema/bad-if-key.err
Normal file
3
tests/qapi-schema/bad-if-key.err
Normal file
@@ -0,0 +1,3 @@
|
||||
bad-if-key.json: In struct 'TestIfStruct':
|
||||
bad-if-key.json:2: 'if' condition has unknown key 'value'
|
||||
Valid keys are 'all'.
|
||||
3
tests/qapi-schema/bad-if-key.json
Normal file
3
tests/qapi-schema/bad-if-key.json
Normal file
@@ -0,0 +1,3 @@
|
||||
# check unknown 'if' dict key
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
|
||||
0
tests/qapi-schema/bad-if-key.out
Normal file
0
tests/qapi-schema/bad-if-key.out
Normal file
2
tests/qapi-schema/bad-if-keys.err
Normal file
2
tests/qapi-schema/bad-if-keys.err
Normal file
@@ -0,0 +1,2 @@
|
||||
bad-if-keys.json: In struct 'TestIfStruct':
|
||||
bad-if-keys.json:2: 'if' condition dict of struct must have one key: 'all'
|
||||
3
tests/qapi-schema/bad-if-keys.json
Normal file
3
tests/qapi-schema/bad-if-keys.json
Normal file
@@ -0,0 +1,3 @@
|
||||
# check multiple 'if' keys
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'any': ['ANY'], 'all': ['ALL'] } }
|
||||
0
tests/qapi-schema/bad-if-keys.out
Normal file
0
tests/qapi-schema/bad-if-keys.out
Normal file
@@ -1,3 +1,3 @@
|
||||
# check invalid 'if' content
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': ['foo', ' '] }
|
||||
'if': { 'all': ['foo', ' '] } }
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
bad-if.json: In struct 'TestIfStruct':
|
||||
bad-if.json:2: 'if' condition of struct must be a string or a list of strings
|
||||
bad-if.json:2: 'if' condition of struct must be a string or an object
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# check invalid 'if' type
|
||||
{ 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
|
||||
'if': { 'value': 'defined(TEST_IF_STRUCT)' } }
|
||||
'if': ['defined(TEST_IF_STRUCT)'] }
|
||||
|
||||
@@ -70,7 +70,8 @@
|
||||
# @base1:
|
||||
# the first member
|
||||
##
|
||||
{ 'struct': 'Base', 'data': { 'base1': 'Enum' } }
|
||||
{ 'struct': 'Base', 'data': { 'base1': 'Enum' },
|
||||
'if': { 'all': ['IFALL1', 'IFALL2'] } }
|
||||
|
||||
##
|
||||
# @Variant1:
|
||||
|
||||
@@ -12,15 +12,16 @@ enum QType
|
||||
module doc-good.json
|
||||
enum Enum
|
||||
member one
|
||||
if ['defined(IFONE)']
|
||||
if defined(IFONE)
|
||||
member two
|
||||
if ['defined(IFCOND)']
|
||||
if defined(IFCOND)
|
||||
feature enum-feat
|
||||
object Base
|
||||
member base1: Enum optional=False
|
||||
if OrderedDict([('all', ['IFALL1', 'IFALL2'])])
|
||||
object Variant1
|
||||
member var1: str optional=False
|
||||
if ['defined(IFSTR)']
|
||||
if defined(IFSTR)
|
||||
feature member-feat
|
||||
feature variant1-feat
|
||||
object Variant2
|
||||
@@ -29,7 +30,7 @@ object Object
|
||||
tag base1
|
||||
case one: Variant1
|
||||
case two: Variant2
|
||||
if ['IFTWO']
|
||||
if IFTWO
|
||||
feature union-feat1
|
||||
object q_obj_Variant1-wrapper
|
||||
member data: Variant1 optional=False
|
||||
@@ -38,13 +39,13 @@ object q_obj_Variant2-wrapper
|
||||
enum SugaredUnionKind
|
||||
member one
|
||||
member two
|
||||
if ['IFTWO']
|
||||
if IFTWO
|
||||
object SugaredUnion
|
||||
member type: SugaredUnionKind optional=False
|
||||
tag type
|
||||
case one: q_obj_Variant1-wrapper
|
||||
case two: q_obj_Variant2-wrapper
|
||||
if ['IFTWO']
|
||||
if IFTWO
|
||||
feature union-feat2
|
||||
alternate Alternate
|
||||
tag type
|
||||
|
||||
@@ -76,6 +76,12 @@ Members
|
||||
the first member
|
||||
|
||||
|
||||
If
|
||||
~~
|
||||
|
||||
"(IFALL1 and IFALL2)"
|
||||
|
||||
|
||||
"Variant1" (Object)
|
||||
-------------------
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user