qapi: Move exprs checking from parse_schema() to check_exprs()
To have expression semantic analysis in one place rather than two. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
e565d934d2
commit
4d076d67c2
142
scripts/qapi.py
142
scripts/qapi.py
@ -603,26 +603,6 @@ def check_struct(expr, expr_info):
|
|||||||
if expr.get('base'):
|
if expr.get('base'):
|
||||||
check_member_clash(expr_info, expr['base'], expr['data'])
|
check_member_clash(expr_info, expr['base'], expr['data'])
|
||||||
|
|
||||||
def check_exprs(schema):
|
|
||||||
for expr_elem in schema.exprs:
|
|
||||||
expr = expr_elem['expr']
|
|
||||||
info = expr_elem['info']
|
|
||||||
|
|
||||||
if expr.has_key('enum'):
|
|
||||||
check_enum(expr, info)
|
|
||||||
elif expr.has_key('union'):
|
|
||||||
check_union(expr, info)
|
|
||||||
elif expr.has_key('alternate'):
|
|
||||||
check_alternate(expr, info)
|
|
||||||
elif expr.has_key('struct'):
|
|
||||||
check_struct(expr, info)
|
|
||||||
elif expr.has_key('command'):
|
|
||||||
check_command(expr, info)
|
|
||||||
elif expr.has_key('event'):
|
|
||||||
check_event(expr, info)
|
|
||||||
else:
|
|
||||||
assert False, 'unexpected meta type'
|
|
||||||
|
|
||||||
def check_keys(expr_elem, meta, required, optional=[]):
|
def check_keys(expr_elem, meta, required, optional=[]):
|
||||||
expr = expr_elem['expr']
|
expr = expr_elem['expr']
|
||||||
info = expr_elem['info']
|
info = expr_elem['info']
|
||||||
@ -646,70 +626,80 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
|||||||
"Key '%s' is missing from %s '%s'"
|
"Key '%s' is missing from %s '%s'"
|
||||||
% (key, meta, name))
|
% (key, meta, name))
|
||||||
|
|
||||||
|
def check_exprs(exprs):
|
||||||
|
global all_names
|
||||||
|
|
||||||
|
# Learn the types and check for valid expression keys
|
||||||
|
for builtin in builtin_types.keys():
|
||||||
|
all_names[builtin] = 'built-in'
|
||||||
|
for expr_elem in exprs:
|
||||||
|
expr = expr_elem['expr']
|
||||||
|
info = expr_elem['info']
|
||||||
|
if expr.has_key('enum'):
|
||||||
|
check_keys(expr_elem, 'enum', ['data'])
|
||||||
|
add_enum(expr['enum'], info, expr['data'])
|
||||||
|
elif expr.has_key('union'):
|
||||||
|
check_keys(expr_elem, 'union', ['data'],
|
||||||
|
['base', 'discriminator'])
|
||||||
|
add_union(expr, info)
|
||||||
|
elif expr.has_key('alternate'):
|
||||||
|
check_keys(expr_elem, 'alternate', ['data'])
|
||||||
|
add_name(expr['alternate'], info, 'alternate')
|
||||||
|
elif expr.has_key('struct'):
|
||||||
|
check_keys(expr_elem, 'struct', ['data'], ['base'])
|
||||||
|
add_struct(expr, info)
|
||||||
|
elif expr.has_key('command'):
|
||||||
|
check_keys(expr_elem, 'command', [],
|
||||||
|
['data', 'returns', 'gen', 'success-response'])
|
||||||
|
add_name(expr['command'], info, 'command')
|
||||||
|
elif expr.has_key('event'):
|
||||||
|
check_keys(expr_elem, 'event', [], ['data'])
|
||||||
|
add_name(expr['event'], info, 'event')
|
||||||
|
else:
|
||||||
|
raise QAPIExprError(expr_elem['info'],
|
||||||
|
"Expression is missing metatype")
|
||||||
|
|
||||||
|
# Try again for hidden UnionKind enum
|
||||||
|
for expr_elem in exprs:
|
||||||
|
expr = expr_elem['expr']
|
||||||
|
if expr.has_key('union'):
|
||||||
|
if not discriminator_find_enum_define(expr):
|
||||||
|
add_enum('%sKind' % expr['union'], expr_elem['info'],
|
||||||
|
implicit=True)
|
||||||
|
elif expr.has_key('alternate'):
|
||||||
|
add_enum('%sKind' % expr['alternate'], expr_elem['info'],
|
||||||
|
implicit=True)
|
||||||
|
|
||||||
|
# Validate that exprs make sense
|
||||||
|
for expr_elem in exprs:
|
||||||
|
expr = expr_elem['expr']
|
||||||
|
info = expr_elem['info']
|
||||||
|
|
||||||
|
if expr.has_key('enum'):
|
||||||
|
check_enum(expr, info)
|
||||||
|
elif expr.has_key('union'):
|
||||||
|
check_union(expr, info)
|
||||||
|
elif expr.has_key('alternate'):
|
||||||
|
check_alternate(expr, info)
|
||||||
|
elif expr.has_key('struct'):
|
||||||
|
check_struct(expr, info)
|
||||||
|
elif expr.has_key('command'):
|
||||||
|
check_command(expr, info)
|
||||||
|
elif expr.has_key('event'):
|
||||||
|
check_event(expr, info)
|
||||||
|
else:
|
||||||
|
assert False, 'unexpected meta type'
|
||||||
|
|
||||||
|
return map(lambda expr_elem: expr_elem['expr'], exprs)
|
||||||
|
|
||||||
def parse_schema(fname):
|
def parse_schema(fname):
|
||||||
global all_names
|
|
||||||
exprs = []
|
|
||||||
|
|
||||||
# First pass: read entire file into memory
|
|
||||||
try:
|
try:
|
||||||
schema = QAPISchema(open(fname, "r"))
|
schema = QAPISchema(open(fname, "r"))
|
||||||
|
return check_exprs(schema.exprs)
|
||||||
except (QAPISchemaError, QAPIExprError), e:
|
except (QAPISchemaError, QAPIExprError), e:
|
||||||
print >>sys.stderr, e
|
print >>sys.stderr, e
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
try:
|
|
||||||
# Next pass: learn the types and check for valid expression keys. At
|
|
||||||
# this point, top-level 'include' has already been flattened.
|
|
||||||
for builtin in builtin_types.keys():
|
|
||||||
all_names[builtin] = 'built-in'
|
|
||||||
for expr_elem in schema.exprs:
|
|
||||||
expr = expr_elem['expr']
|
|
||||||
info = expr_elem['info']
|
|
||||||
if expr.has_key('enum'):
|
|
||||||
check_keys(expr_elem, 'enum', ['data'])
|
|
||||||
add_enum(expr['enum'], info, expr['data'])
|
|
||||||
elif expr.has_key('union'):
|
|
||||||
check_keys(expr_elem, 'union', ['data'],
|
|
||||||
['base', 'discriminator'])
|
|
||||||
add_union(expr, info)
|
|
||||||
elif expr.has_key('alternate'):
|
|
||||||
check_keys(expr_elem, 'alternate', ['data'])
|
|
||||||
add_name(expr['alternate'], info, 'alternate')
|
|
||||||
elif expr.has_key('struct'):
|
|
||||||
check_keys(expr_elem, 'struct', ['data'], ['base'])
|
|
||||||
add_struct(expr, info)
|
|
||||||
elif expr.has_key('command'):
|
|
||||||
check_keys(expr_elem, 'command', [],
|
|
||||||
['data', 'returns', 'gen', 'success-response'])
|
|
||||||
add_name(expr['command'], info, 'command')
|
|
||||||
elif expr.has_key('event'):
|
|
||||||
check_keys(expr_elem, 'event', [], ['data'])
|
|
||||||
add_name(expr['event'], info, 'event')
|
|
||||||
else:
|
|
||||||
raise QAPIExprError(expr_elem['info'],
|
|
||||||
"Expression is missing metatype")
|
|
||||||
exprs.append(expr)
|
|
||||||
|
|
||||||
# Try again for hidden UnionKind enum
|
|
||||||
for expr_elem in schema.exprs:
|
|
||||||
expr = expr_elem['expr']
|
|
||||||
if expr.has_key('union'):
|
|
||||||
if not discriminator_find_enum_define(expr):
|
|
||||||
add_enum('%sKind' % expr['union'], expr_elem['info'],
|
|
||||||
implicit=True)
|
|
||||||
elif expr.has_key('alternate'):
|
|
||||||
add_enum('%sKind' % expr['alternate'], expr_elem['info'],
|
|
||||||
implicit=True)
|
|
||||||
|
|
||||||
# Final pass - validate that exprs make sense
|
|
||||||
check_exprs(schema)
|
|
||||||
except QAPIExprError, e:
|
|
||||||
print >>sys.stderr, e
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
return exprs
|
|
||||||
|
|
||||||
def parse_args(typeinfo):
|
def parse_args(typeinfo):
|
||||||
if isinstance(typeinfo, str):
|
if isinstance(typeinfo, str):
|
||||||
struct = find_struct(typeinfo)
|
struct = find_struct(typeinfo)
|
||||||
|
Loading…
Reference in New Issue
Block a user