Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions ev-dev-tools/src/ev_cli/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def setup_jinja_env():
})


def generate_tmpl_data_for_if(interface, if_def, type_file):
def generate_tmpl_data_for_if(interface, if_def, type_file, quantity=1):
helpers.parsed_enums.clear()
helpers.parsed_types.clear()
helpers.type_headers.clear()
Expand Down Expand Up @@ -93,7 +93,7 @@ def generate_tmpl_data_for_if(interface, if_def, type_file):
if enum_info and type_file:
enums.append(enum_info)

cmds.append({'name': cmd, 'args': args, 'result': result_type_info})
cmds.append({'name': cmd, 'args': args, 'result': result_type_info, 'quantity': quantity})

if type_file:
for parsed_enum in helpers.parsed_enums:
Expand Down Expand Up @@ -133,9 +133,13 @@ def generate_tmpl_data_for_if(interface, if_def, type_file):
for value in errors_dict.values():
errors.extend(value.values())

base_class_header = f'generated/interfaces/{interface}/Implementation.hpp'
if quantity > 1:
base_class_header = f'generated/interfaces/{interface}/ImplementationMultiple.hpp'

tmpl_data = {
'info': {
'base_class_header': f'generated/interfaces/{interface}/Implementation.hpp',
'base_class_header': base_class_header,
'interface': interface,
'desc': if_def['description'],
'type_headers': sorted(helpers.type_headers)
Expand All @@ -158,14 +162,20 @@ def generate_tmpl_data_for_module(module, module_def):
type_info = helpers.build_type_info(conf_id, conf_info['type'])
config.append(type_info)

base_class = f'{impl_info["interface"]}ImplBase'
base_class_header = f'generated/interfaces/{impl_info["interface"]}/Implementation.hpp'
if impl_info.get('quantity', 1) > 1:
base_class_header = f'generated/interfaces/{impl_info["interface"]}/ImplementationMultiple.hpp'
base_class = f'{impl_info["interface"]}ImplBaseMultiple'
provides.append({
'id': impl,
'type': impl_info['interface'],
'quantity': impl_info.get('quantity', 1),
'desc': impl_info['description'],
'config': config,
'class_name': f'{impl_info["interface"]}Impl',
'base_class': f'{impl_info["interface"]}ImplBase',
'base_class_header': f'generated/interfaces/{impl_info["interface"]}/Implementation.hpp'
'base_class': base_class,
'base_class_header': base_class_header
})

requires = []
Expand Down Expand Up @@ -360,16 +370,21 @@ def generate_module_files(rel_mod_dir, update_flag, licenses):
# load template data for interface
if_def, last_mtime = load_interface_definition(interface)

if_tmpl_data = generate_tmpl_data_for_if(interface, if_def, False)
if_tmpl_data = generate_tmpl_data_for_if(interface, if_def, False, impl['quantity'])

impl_base = 'ImplBase'
if impl['quantity'] > 1:
impl_base = f'{impl_base}Multiple'

if_tmpl_data['info'].update({
'hpp_guard': helpers.snake_case(f'{impl["id"]}_{interface}').upper() + '_IMPL_HPP',
'config': impl['config'],
'class_name': interface + 'Impl',
'class_parent': interface + 'ImplBase',
'class_parent': interface + impl_base,
'module_header': f'../{mod}.hpp',
'module_class': mod,
'interface_implementation_id': impl['id']
'interface_implementation_id': impl['id'],
'multiple': impl['quantity'] > 1
})

if_tmpl_data['info']['blocks'] = helpers.load_tmpl_blocks(
Expand Down Expand Up @@ -495,6 +510,7 @@ def generate_interface_headers(interface, all_interfaces_flag, output_dir):
# generate Base file (providers view)
tmpl_data['info']['hpp_guard'] = helpers.snake_case(interface).upper() + '_IMPLEMENTATION_HPP'
tmpl_data['info']['class_name'] = f'{interface}ImplBase'
tmpl_data['info']['multiple'] = False

base_file = output_path / 'Implementation.hpp'

Expand All @@ -506,6 +522,23 @@ def generate_interface_headers(interface, all_interfaces_flag, output_dir):
'printable_name': base_file.relative_to(output_path.parent)
}

# generate Base-multiple file (providers view)
tmpl_data['info']['hpp_guard'] = helpers.snake_case(interface).upper() + '_IMPLEMENTATION_MULTIPLE_HPP'
tmpl_data['info']['class_name'] = f'{interface}ImplBaseMultiple'
tmpl_data['info']['multiple'] = True

base_multiple_file = output_path / 'ImplementationMultiple.hpp'

if_parts['base_multiple'] = {
'path': base_multiple_file,
'content': templates['interface_base'].render(tmpl_data),
'template_path': Path(templates['interface_base'].filename),
'last_mtime': last_mtime,
'printable_name': base_multiple_file.relative_to(output_path.parent)
}

del tmpl_data['info']['multiple']

# generate Exports file (users view)
tmpl_data['info']['hpp_guard'] = helpers.snake_case(interface).upper() + '_INTERFACE_HPP'
tmpl_data['info']['class_name'] = f'{interface}Intf'
Expand Down Expand Up @@ -651,10 +684,12 @@ def interface_genhdr(args):
if not args.disable_clang_format:
# FIXME (aw): this broken, because in case all_interfaces is true, if_parts might be none for invalid interface files
helpers.clang_format(args.clang_format_file, if_parts['base'])
helpers.clang_format(args.clang_format_file, if_parts['base_multiple'])
helpers.clang_format(args.clang_format_file, if_parts['exports'])
helpers.clang_format(args.clang_format_file, if_parts['types'])

helpers.write_content_to_file_and_check_template(if_parts['base'], primary_update_strategy, args.diff)
helpers.write_content_to_file_and_check_template(if_parts['base_multiple'], primary_update_strategy, args.diff)
helpers.write_content_to_file_and_check_template(if_parts['exports'], primary_update_strategy, args.diff)
helpers.write_content_to_file_and_check_template(if_parts['types'], primary_update_strategy, args.diff)

Expand Down
5 changes: 4 additions & 1 deletion ev-dev-tools/src/ev_cli/templates/helper_macros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ static_cast<{{ arg.cpp_type }}>
)
{%- endmacro %}

{% macro handle_cmd_signature(cmd, class_name=None, interface=none) -%}
{% macro handle_cmd_signature(cmd, class_name=None, interface=none, multiple=false) -%}
{% if not class_name %}virtual {% endif -%}
{{ result_type(cmd.result, interface) }} {% if class_name %}{{ class_name }}::{% endif -%}
handle_{{ cmd.name }}(
{%- if multiple -%}
std::size_t index,
{%- endif -%}
{%- for arg in cmd.args -%}
{{ cpp_type(arg) }}& {{ arg.name }}{{ ', ' if not loop.last }}
{%- endfor -%}
Expand Down
69 changes: 44 additions & 25 deletions ev-dev-tools/src/ev_cli/templates/interface-Base.hpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,34 @@ public:
_name(name) {
if (ev == nullptr) {
EVLOG_error << "ev is nullptr, please check the initialization of the module";
error_manager = nullptr;
error_state_monitor = nullptr;
{% if not info.multiple %}
error_factory = nullptr;
EVLOG_error << "error_manager, error_state_monitor and error_factory are nullptr";
{% endif %}
EVLOG_error << "error_manager, error_state_monitor are empty and error_factory is nullptr";
} else {
error_manager = ev->get_error_manager_impl(name);
if (error_manager == nullptr) {
EVLOG_error << "error_manager is nullptr";
if (error_manager.empty()) {
EVLOG_error << "error_manager is empty";
}
{% if info.multiple %}
error_state_monitor = ev->get_error_state_monitor_impl(name);
if (error_state_monitor.empty()) {
EVLOG_error << "error_state_monitor is empty";
}
error_factory = ev->get_error_factory(name);
if (error_factory.empty()) {
EVLOG_error << "error_factory is empty";
}
{% else %}
error_state_monitor = ev->get_error_state_monitor_impl(name).at(0);
if (error_state_monitor == nullptr) {
EVLOG_error << "error_state_monitor is nullptr";
}
error_factory = ev->get_error_factory(name);
error_factory = ev->get_error_factory(name).at(0);
if (error_factory == nullptr) {
EVLOG_error << "error_factory is nullptr";
}
{% endif %}
impl_mapping = Everest::get_impl_mapping(ev->get_mapping(), name);
}
}
Expand All @@ -49,6 +60,9 @@ public:
// publish functions for variables
{% for var in vars %}
void publish_{{ var.name }}(
{%- if info.multiple -%}
std::size_t _index,
{%- endif -%}
{% if 'array_type' in var %}
const std::vector<{{ var.array_type }}>&
{%- elif 'object_type' in var %}
Expand All @@ -62,50 +76,55 @@ public:
{% if 'object_type' in var %}
json json_value = value;
Object object_value = json_value;
_ev->publish(_name, "{{ var.name }}", object_value);
_ev->publish({{ '_index' if info.multiple else '0'}}, _name, "{{ var.name }}", object_value);
{% elif 'enum_type' in var %}
auto value_string = {{ enum_to_string(var.enum_type) }}(value);
_ev->publish(_name, "{{ var.name }}", value_string);
_ev->publish({{ '_index' if info.multiple else '0'}}, _name, "{{ var.name }}", value_string);
{% elif 'array_type' in var %}
{% if 'array_type_contains_enum' in var %}
std::vector<std::string> string_array;
string_array.reserve(value.size());
for (const auto& entry : value) {
string_array.push_back({{ enum_to_string(var.array_type) }}(entry));
}
_ev->publish(_name, "{{ var.name }}", string_array);
_ev->publish({{ '_index' if info.multiple else '0'}}, _name, "{{ var.name }}", string_array);
{% else %}
_ev->publish(_name, "{{ var.name }}", value);
_ev->publish({{ '_index' if info.multiple else '0'}}, _name, "{{ var.name }}", value);
{% endif %}
{% else %}
_ev->publish(_name, "{{ var.name }}", value);
_ev->publish({{ '_index' if info.multiple else '0'}}, _name, "{{ var.name }}", value);
{% endif %}
}
{% endfor %}
{% endif %}

void raise_error(const Everest::error::Error& error) {
error_manager->raise_error(error);
void raise_error({{ 'std::size_t _index, ' if info.multiple}}const Everest::error::Error& error) {
error_manager.at({{ '_index' if info.multiple else '0'}})->raise_error(error);
}

void clear_error(const Everest::error::ErrorType& type) {
error_manager->clear_error(type);
void clear_error({{ 'std::size_t _index, ' if info.multiple}}const Everest::error::ErrorType& type) {
error_manager.at({{ '_index' if info.multiple else '0'}})->clear_error(type);
}

void clear_error(const Everest::error::ErrorType& type, const Everest::error::ErrorSubType& sub_type) {
error_manager->clear_error(type, sub_type);
void clear_error({{ 'std::size_t _index, ' if info.multiple}}const Everest::error::ErrorType& type, const Everest::error::ErrorSubType& sub_type) {
error_manager.at({{ '_index' if info.multiple else '0'}})->clear_error(type, sub_type);
}

void clear_all_errors_of_impl() {
error_manager->clear_all_errors();
void clear_all_errors_of_impl({{ 'std::size_t _index' if info.multiple}}) {
error_manager.at({{ '_index' if info.multiple else '0'}})->clear_all_errors();
}

void clear_all_errors_of_impl(const Everest::error::ErrorType& type) {
error_manager->clear_all_errors(type);
void clear_all_errors_of_impl({{ 'std::size_t _index, ' if info.multiple}}const Everest::error::ErrorType& type) {
error_manager.at({{ '_index' if info.multiple else '0'}})->clear_all_errors(type);
}

{% if info.multiple %}
std::vector<std::shared_ptr<Everest::error::ErrorStateMonitor>> error_state_monitor;
std::vector<std::shared_ptr<Everest::error::ErrorFactory>> error_factory;
{% else %}
std::shared_ptr<Everest::error::ErrorStateMonitor> error_state_monitor;
std::shared_ptr<Everest::error::ErrorFactory> error_factory;
{% endif %}

std::optional<Mapping> get_mapping() {
return impl_mapping;
Expand All @@ -117,14 +136,14 @@ protected:
{% else %}
// command handler functions (virtual)
{% for cmd in cmds %}
{{ handle_cmd_signature(cmd, none, info.interface_name) }} = 0;
{{ handle_cmd_signature(cmd, none, info.interface_name, info.multiple) }} = 0;
{% endfor %}
{% endif %}

private:
Everest::ModuleAdapter* const _ev;
const std::string _name;
std::shared_ptr<Everest::error::ErrorManagerImpl> error_manager;
std::vector<std::shared_ptr<Everest::error::ErrorManagerImpl>> error_manager;
std::optional<Mapping> impl_mapping;

// helper function for getting all commands
Expand All @@ -146,7 +165,7 @@ private:
{% endfor %}
};
{% endif %}
{{ cmd.name }}_cmd.cmd = [this](Parameters args) -> Result {
{{ cmd.name }}_cmd.cmd = [this](std::size_t{{ ' index' if info.multiple}}, Parameters args) -> Result {
{% for arg in cmd.args %}
{% if 'object_type' in arg %}
{{ arg.object_type }} {{ arg.name }} = args["{{ arg.name }}"];
Expand All @@ -169,7 +188,7 @@ private:
(void) args; // no arguments used for this callback
{% endfor %}

{{ 'auto result = ' if cmd.result }}this->handle_{{ cmd.name }}(
{{ 'auto result = ' if cmd.result }}this->handle_{{ cmd.name }}({{ 'index,' if info.multiple}}
{%- for arg in cmd.args -%}
{{ arg.name }}{{ ', ' if not loop.last }}
{%- endfor -%}
Expand Down
2 changes: 1 addition & 1 deletion ev-dev-tools/src/ev_cli/templates/interface-Impl.hpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected:
{% else %}
// command handler functions (virtual)
{% for cmd in cmds %}
{{ handle_cmd_signature(cmd, none, '::'+info.interface) }} override;
{{ handle_cmd_signature(cmd, none, '::'+info.interface, cmd.quantity > 1) }} override;
{% endfor %}
{% endif %}

Expand Down