idl: allow to parse const specifiers for template arguments

This patch introduces very limited support for declaring `const`
template parameters in data members.

It's not covering all the cases, e.g.
`const type member_variable` and `const template_def<T1, T2, ...>`
syntax is not supported at the moment.

Though the changes are enough for raft-related use: this makes it
possible to declare `std::vector<raft::log_entries_ptr>` (aka
`std::vector<lw_shared_ptr<const raft::log_entry>>`) in the IDL.

Existing IDL files are not affected in any way.

Signed-off-by: Pavel Solodovnikov <pa.solodovnikov@scylladb.com>
This commit is contained in:
Pavel Solodovnikov
2020-11-26 02:29:13 +03:00
parent f02703fcd7
commit facf27dbe4

View File

@@ -92,12 +92,14 @@ def print_cw(f):
#pragma once
""")
class BasicType:
def __init__(self, name):
def __init__(self, name, is_const=False):
self.name = name
self.is_const = is_const
def __str__(self):
return f"BasicType(name={self.name})"
return f"BasicType(name={self.name}, is_const={self.is_const})"
def __repr__(self):
return self.__str__()
@@ -227,6 +229,24 @@ def template_type_parse_action(tokens):
return TemplateType(name=tokens['template_name'], template_parameters=tokens["template_parameters"].asList())
# Will be used after parsing is complete to determine which local types
# have usages with `const` specifiers: depending on that we should generate
# a serializer specialization for `const` type too.
types_with_const_appearances = set()
def type_parse_action(tokens):
if len(tokens) == 1:
return tokens[0]
# If we have two tokens in type parse action then
# it's because we have BasicType production with `const`
# NOTE: template types cannot have `const` modifier at the moment,
# this wouldn't parse.
tokens[1].is_const = True
types_with_const_appearances.add(tokens[1].name)
return tokens[1]
def enum_value_parse_action(tokens):
initializer = None
if len(tokens) == 2:
@@ -292,6 +312,7 @@ def parse_file(file_name):
template = pp.Keyword('template')
final = pp.Keyword('final')
stub = pp.Keyword('stub')
const = pp.Keyword('const')
with_colon = pp.Word(pp.alphanums + "_" + ":")
btype = with_colon.copy()
@@ -302,7 +323,8 @@ def parse_file(file_name):
tmpl = with_colon("template_name") + langle.suppress() + pp.Group(pp.delimitedList(type))("template_parameters") + rangle.suppress()
tmpl.setParseAction(template_type_parse_action)
type <<= tmpl | btype
type <<= tmpl | (pp.Optional(const) + btype)
type.setParseAction(type_parse_action)
enum_lit = pp.Keyword('enum')
enum_class = pp.Group(enum_lit + cls)
@@ -391,6 +413,14 @@ struct serializer<{name}> {{
static void skip(Input& buf);
}};
""")
if name in types_with_const_appearances:
fprintln(hout, f"""
template <{template_param}>
struct serializer<const {name}> : public serializer<{name}>
{{}};
""")
if config.ns != '':
fprintln(hout, "}")
@@ -421,7 +451,7 @@ def join_template(template_params):
def param_type(t):
if isinstance(t, BasicType):
return t.name
return 'const ' + t.name if t.is_const else t.name
elif isinstance(t, TemplateType):
return t.name + join_template(t.template_parameters)