Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce build time by suppressing template instantiation #1419

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions openscenario/openscenario_interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ ament_export_include_directories(${boost_json_SOURCE_DIR}/include)
file(GLOB ${PROJECT_NAME}_POSIX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/posix/*.cpp)
file(GLOB ${PROJECT_NAME}_SYNTAX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/syntax/*.cpp)
file(GLOB ${PROJECT_NAME}_UTILITY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/utility/*.cpp)
file(GLOB ${PROJECT_NAME}_READER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/reader/*.cpp)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sort in lexicographic order unless there is a technical reason not to.


ament_auto_add_library(${PROJECT_NAME} SHARED
${${PROJECT_NAME}_POSIX_SOURCES}
${${PROJECT_NAME}_SYNTAX_SOURCES}
${${PROJECT_NAME}_UTILITY_SOURCES}
${${PROJECT_NAME}_READER_SOURCES}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sort in lexicographic order unless there is a technical reason not to.

src/object.cpp
src/evaluate.cpp
src/openscenario_interpreter.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,74 +31,16 @@

namespace openscenario_interpreter
{
inline namespace reader
{
template <typename Scope>
auto substitute(std::string attribute, Scope & scope)
{
auto dirname = [](auto &&, auto && scope) { return scope.dirname(); };
struct Scope;

auto find_pkg_share = [](auto && package_name, auto &&) {
return ament_index_cpp::get_package_share_directory(package_name);
};

auto ros2 = [](auto && arguments, auto &&) {
auto remove_trailing_newline = [](auto && s) {
while (s.back() == '\n') {
s.pop_back();
}
return s;
};
if (auto && result = remove_trailing_newline(concealer::dollar("ros2 " + arguments));
result.find('\n') != std::string::npos) {
throw SyntaxError(
"The substitution result by `$(ros2 ...)` must not contain a newline character. "
"You gave `$(ros2 ",
arguments, ")` and the result was ",
std::quoted(boost::replace_all_copy(result, "\n", "\\n")),
", which is unacceptable for the reasons stated above.");
} else {
return result;
}
};

auto var = [](auto && name, auto && scope) {
// TODO: Return the value of the launch configuration variable instead of the OpenSCENARIO parameter.
if (const auto found = scope.ref(name); found) {
return boost::lexical_cast<String>(found);
} else {
return String();
}
};

// NOTE: https://design.ros2.org/articles/roslaunch_xml.html#dynamic-configuration
static const std::unordered_map<
std::string, std::function<std::string(const std::string &, Scope &)> >
substitutions{
{"dirname", dirname},
// TODO {"env", env},
// TODO {"eval", eval},
// TODO {"exec-in-package", exec_in_package},
// TODO {"find-exec", find_exec},
// TODO {"find-pkg-prefix", find_pkg_prefix},
{"find-pkg-share", find_pkg_share},
{"ros2",
ros2}, // NOTE: TIER IV extension (Not included in the ROS 2 Launch XML Substitution)
{"var", var},
};

static const auto pattern = std::regex(R"((.*)\$\((([\w-]+)\s?([^\)]*))\)(.*))");

for (std::smatch result; std::regex_match(attribute, result, pattern);) {
if (const auto iter = substitutions.find(result.str(3)); iter != std::end(substitutions)) {
attribute = result.str(1) + std::get<1>(*iter)(result.str(4), scope) + result.str(5);
} else {
throw SyntaxError("Unknown substitution ", std::quoted(result.str(3)), " specified");
}
}
inline namespace syntax
{
struct Rule;
} // namespace syntax

return attribute;
}
inline namespace reader
{
auto substitute(std::string attribute, const Scope & scope) -> String;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto substitute(std::string attribute, const Scope & scope) -> String;
auto substitute(const std::string & attribute, const Scope & scope) -> String;


template <typename T, typename Node, typename Scope>
auto readAttribute(const std::string & name, const Node & node, const Scope & scope) -> T
Expand Down Expand Up @@ -156,8 +98,22 @@ auto readAttribute(const std::string & name, const Node & node, const Scope & sc
}
}

extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> Boolean;
extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> UnsignedShort;
extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> UnsignedInteger;
extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> Double;
extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> String;
extern template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> syntax::Rule;
Comment on lines +101 to +112
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sort in lexicographic order unless there is a technical reason not to.


template <typename T, typename Node, typename Scope>
auto readAttribute(const std::string & name, const Node & node, const Scope & scope, T && value)
-> T
{
if (node.attribute(name.c_str())) {
return readAttribute<T>(name, node, scope);
Expand All @@ -177,5 +133,4 @@ auto readAttribute(const std::string & name, const Node & node, const Scope & sc
}
} // namespace reader
} // namespace openscenario_interpreter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} // namespace openscenario_interpreter
} // namespace openscenario_interpreter


#endif // OPENSCENARIO_INTERPRETER__READER__ATTRIBUTE_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@

namespace openscenario_interpreter
{

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

struct Scope;

inline namespace syntax
{
struct Orientation;
struct Position;
struct Properties;
struct Range;
} // namespace syntax

inline namespace reader
{
using Cardinality =
Expand Down Expand Up @@ -72,7 +83,7 @@ auto traverse(const pugi::xml_node & parent, const std::string & name, F && f) -
}

template <typename T, typename Scope>
auto readElement(const std::string & name, const pugi::xml_node & parent, Scope & scope)
auto readElement(const std::string & name, const pugi::xml_node & parent, Scope & scope) -> T
{
if (const auto child = parent.child(name.c_str())) {
return T(child, scope);
Expand All @@ -89,6 +100,15 @@ auto readElement(const std::string & name, const pugi::xml_node & parent, Scope
}
}

extern template auto readElement(const std::string &, const pugi::xml_node &, Scope &)
-> syntax::Orientation;
extern template auto readElement(const std::string &, const pugi::xml_node &, Scope &)
-> syntax::Position;
extern template auto readElement(const std::string &, const pugi::xml_node &, Scope &)
-> syntax::Properties;
extern template auto readElement(const std::string &, const pugi::xml_node &, Scope &)
-> syntax::Range;

template <typename T, typename U, typename Scope>
auto readElement(const std::string & name, const pugi::xml_node & parent, Scope & scope, U && value)
{
Expand Down Expand Up @@ -153,62 +173,9 @@ auto readGroups(const pugi::xml_node & node, Ts &&... xs)
return groups;
}

template <typename... Ts>
auto choice(const pugi::xml_node & node, Ts &&... xs) -> decltype(auto)
{
const std::unordered_map<std::string, std::function<Object(const pugi::xml_node &)>> callees{
std::forward<decltype(xs)>(xs)...};

std::unordered_map<std::string, pugi::xml_node> specs{};

for (const auto & each : callees) {
if (const auto child = node.child(std::get<0>(each).c_str())) {
specs.emplace(std::get<0>(each), child);
}
}

auto print_keys_to = [&](auto & os, const auto & xs) -> decltype(auto) {
if (not xs.empty()) {
for (auto iter = std::begin(xs); iter != std::end(xs); ++iter) {
os << std::get<0>(*iter);

switch (std::distance(iter, std::end(xs))) {
case 1:
return os;

case 2:
os << " and ";
break;

default:
os << ", ";
break;
}
}
}

return os;
};

if (specs.empty()) {
std::stringstream what;
what << "Class " << node.name() << " requires one of following elements: ";
print_keys_to(what, callees);
what << ". But no element specified";
throw SyntaxError(what.str());
} else if (1 < specs.size()) {
std::stringstream what;
what << "Class " << node.name() << " requires just one of following elements: ";
print_keys_to(what, callees);
what << ". But " << specs.size() << " element" << (1 < specs.size() ? "s" : "") << " (";
print_keys_to(what, specs);
what << ") specified";
throw SyntaxError(what.str());
} else {
const auto iter = std::cbegin(specs);
return callees.at(std::get<0>(*iter))(std::get<1>(*iter));
}
}
auto choice(
const pugi::xml_node & node,
std::unordered_map<std::string, std::function<Object(const pugi::xml_node &)>> callees) -> Object;
Comment on lines +176 to +178
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto choice(
const pugi::xml_node & node,
std::unordered_map<std::string, std::function<Object(const pugi::xml_node &)>> callees) -> Object;
auto choice(
const pugi::xml_node & node,
const std::unordered_map<std::string, std::function<Object(const pugi::xml_node &)>> & callees) -> Object;

} // namespace reader
} // namespace openscenario_interpreter

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,26 +126,6 @@ struct DistanceCondition : private Scope, private SimulatorCore::ConditionEvalua

auto evaluate() -> Object;
};

// Ignore spell miss due to OpenSCENARIO standard.
// cspell: ignore euclidian

// clang-format off
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::euclidianDistance, RoutingAlgorithm::undefined, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::euclidianDistance, RoutingAlgorithm::undefined, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::shortest, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::shortest, true >(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::shortest, false>(const EntityRef &) const -> double;
template <> auto DistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::shortest, true >(const EntityRef &) const -> double;
// clang-format on
} // namespace syntax
} // namespace openscenario_interpreter

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,6 @@ struct RelativeDistanceCondition : private Scope, private SimulatorCore::Conditi

auto evaluate() -> Object;
};

// Ignore spell miss due to OpenSCENARIO standard.
// cspell: ignore euclidian

// clang-format off
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::euclidianDistance, RoutingAlgorithm::undefined, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::euclidianDistance, RoutingAlgorithm::undefined, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::entity, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::undefined, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::undefined, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::shortest, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::lateral, RoutingAlgorithm::shortest, true >(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::shortest, false>(const EntityRef &) -> double;
template <> auto RelativeDistanceCondition::distance<CoordinateSystem::lane, RelativeDistanceType::longitudinal, RoutingAlgorithm::shortest, true >(const EntityRef &) -> double;
// clang-format on
} // namespace syntax
} // namespace openscenario_interpreter

Expand Down
99 changes: 99 additions & 0 deletions openscenario/openscenario_interpreter/src/reader/attribute.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2015 TIER IV, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <openscenario_interpreter/reader/attribute.hpp>
#include <openscenario_interpreter/scope.hpp>
#include <openscenario_interpreter/syntax/rule.hpp>

namespace openscenario_interpreter
{
inline namespace reader
{
auto substitute(std::string attribute, const Scope & scope) -> String
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto substitute(std::string attribute, const Scope & scope) -> String
auto substitute(const std::string & attribute, const Scope & scope) -> String

{
auto dirname = [](auto &&, auto && scope) { return scope.dirname(); };

auto find_pkg_share = [](auto && package_name, const auto &) {
return ament_index_cpp::get_package_share_directory(package_name);
};

auto ros2 = [](auto && arguments, const auto &) {
auto remove_trailing_newline = [](auto && s) {
while (s.back() == '\n') {
s.pop_back();
}
return s;
};
if (auto && result = remove_trailing_newline(concealer::dollar("ros2 " + arguments));
result.find('\n') != std::string::npos) {
throw SyntaxError(
"The substitution result by `$(ros2 ...)` must not contain a newline character. "
"You gave `$(ros2 ",
arguments, ")` and the result was ",
std::quoted(boost::replace_all_copy(result, "\n", "\\n")),
", which is unacceptable for the reasons stated above.");
} else {
return result;
}
};

auto var = [](auto && name, const auto & scope) {
// TODO: Return the value of the launch configuration variable instead of the OpenSCENARIO parameter.
if (const auto found = scope.ref(name); found) {
return boost::lexical_cast<String>(found);
} else {
return String();
}
};

// NOTE: https://design.ros2.org/articles/roslaunch_xml.html#dynamic-configuration
static const std::unordered_map<
std::string, std::function<std::string(const std::string &, const Scope &)> >
substitutions{
{"dirname", dirname},
// TODO {"env", env},
// TODO {"eval", eval},
// TODO {"exec-in-package", exec_in_package},
// TODO {"find-exec", find_exec},
// TODO {"find-pkg-prefix", find_pkg_prefix},
{"find-pkg-share", find_pkg_share},
{"ros2",
ros2}, // NOTE: TIER IV extension (Not included in the ROS 2 Launch XML Substitution)
{"var", var},
};

static const auto pattern = std::regex(R"((.*)\$\((([\w-]+)\s?([^\)]*))\)(.*))");

for (std::smatch result; std::regex_match(attribute, result, pattern);) {
if (const auto iter = substitutions.find(result.str(3)); iter != std::end(substitutions)) {
attribute = result.str(1) + std::get<1>(*iter)(result.str(4), scope) + result.str(5);
} else {
throw SyntaxError("Unknown substitution ", std::quoted(result.str(3)), " specified");
}
}

return attribute;
}

template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &) -> Boolean;
template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> UnsignedShort;
template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> UnsignedInteger;
template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &) -> Double;
template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &) -> String;
template auto readAttribute(const std::string &, const pugi::xml_node &, const Scope &)
-> syntax::Rule;
Comment on lines +89 to +97
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sort in lexicographic order unless there is a technical reason not to.

} // namespace reader
} // namespace openscenario_interpreter
Loading
Loading