scenario_simulator_v2 C++ API
scope.hpp
Go to the documentation of this file.
1 // Copyright 2015 TIER IV, Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef OPENSCENARIO_INTERPRETER__SCOPE_HPP_
16 #define OPENSCENARIO_INTERPRETER__SCOPE_HPP_
17 
18 #include <boost/lexical_cast.hpp>
19 #include <boost/range/algorithm.hpp>
20 #include <filesystem>
21 #include <functional>
22 #include <memory>
28 #include <unordered_map>
29 #include <utility>
30 #include <vector>
31 
33 {
35 {
36  friend struct Scope;
37 
38  std::multimap<std::string, Object> variables; // NOTE: must be ordered.
39 
40  EnvironmentFrame * const outer_frame = nullptr;
41 
42  std::multimap<std::string, EnvironmentFrame *> inner_frames; // NOTE: must be ordered.
43 
44  std::vector<EnvironmentFrame *> unnamed_inner_frames;
45 
46 #define DEFINE_SYNTAX_ERROR(TYPENAME, ...) \
47  template <typename T> \
48  struct TYPENAME : public SyntaxError \
49  { \
50  explicit TYPENAME(const std::string & variable) \
51  : SyntaxError(__VA_ARGS__, std::quoted(variable), " of type ", makeTypename(typeid(T)), ".") \
52  { \
53  } \
54  }
55 
56  DEFINE_SYNTAX_ERROR(AmbiguousReferenceTo, "Ambiguous reference to ");
57  DEFINE_SYNTAX_ERROR(NoSuchVariableNamed, "No such variable named ");
58 
59 #undef DEFINE_SYNTAX_ERROR
60 
61  EnvironmentFrame() = default;
62 
63  explicit EnvironmentFrame(EnvironmentFrame &, const std::string &);
64 
65 public:
66  explicit EnvironmentFrame(const EnvironmentFrame &) = delete;
67 
68  explicit EnvironmentFrame(EnvironmentFrame &&) = delete;
69 
70  auto define(const Name &, const Object &) -> void;
71 
72  template <typename T>
73  auto find(const Name & name) const -> Object
74  {
75  // NOTE: breadth first search
76  for (std::vector<const EnvironmentFrame *> frames{this}; not frames.empty();) {
77  auto objects = [&]() {
78  std::vector<Object> result;
79  for (auto && frame : frames) {
80  const auto it = frame->variables.equal_range(name);
81  std::for_each(it.first, it.second, [&](auto && name_and_value) {
82  return result.push_back(name_and_value.second);
83  });
84  }
85  return result;
86  }();
87 
88  switch (std::count_if(objects.begin(), objects.end(), is_also<T>())) {
89  case 0:
90  frames = [&]() {
91  std::vector<const EnvironmentFrame *> result;
92  for (auto && current_frame : frames) {
93  std::copy(
94  current_frame->unnamed_inner_frames.begin(),
95  current_frame->unnamed_inner_frames.end(), std::back_inserter(result));
96  }
97  return result;
98  }();
99  break;
100  case 1:
101  return *std::find_if(objects.begin(), objects.end(), is_also<T>());
102  default:
103  throw AmbiguousReferenceTo<T>(name);
104  }
105  }
106 
107  return isOutermost() ? throw NoSuchVariableNamed<T>(name) : outer_frame->find<T>(name);
108  }
109 
110  template <typename T>
111  auto find(const Prefixed<Name> & prefixed_name) const -> Object
112  {
113  if (not prefixed_name.prefixes.empty()) {
114  const auto found = resolvePrefix(prefixed_name);
115  switch (found.size()) {
116  case 0:
117  throw NoSuchVariableNamed<T>(boost::lexical_cast<std::string>(prefixed_name));
118  case 1:
119  return found.front()->find<T>(prefixed_name.strip<1>());
120  default:
121  throw AmbiguousReferenceTo<T>(boost::lexical_cast<std::string>(prefixed_name));
122  }
123  } else {
124  return find<T>(prefixed_name.name);
125  }
126  }
127 
128  template <typename T>
129  auto ref(const Prefixed<Name> & prefixed_name) const -> Object
130  {
131  if (prefixed_name.absolute) {
132  return outermostFrame().find<T>(prefixed_name);
133  } else if (prefixed_name.prefixes.empty()) {
134  return find<T>(prefixed_name.name);
135  } else {
136  return lookupFrame(prefixed_name)->find<T>(prefixed_name.strip<1>());
137  }
138  }
139 
140  auto isOutermost() const noexcept -> bool;
141 
142 private:
143  auto resolvePrefix(const Prefixed<Name> &) const -> std::list<const EnvironmentFrame *>;
144 
145  auto lookupFrame(const Prefixed<Name> &) const -> const EnvironmentFrame *;
146 
147  auto outermostFrame() const noexcept -> const EnvironmentFrame &;
148 };
149 
150 inline namespace syntax
151 {
152 struct Entities;
153 
154 struct OpenScenario;
155 } // namespace syntax
156 
157 class Scope
158 {
159  /*
160  In OpenSCENARIO, global resources are FileHeader, top-level
161  ParameterDeclaration, CatalogLocations, RoadNetwork, and Entities (These
162  are located directly under the `OpenSCENARIO` tag).
163 
164  The `Scope` data member `open_scenario` is provided to reference those
165  global resources. However, some constructors need access to global
166  resources during the construction of the OpenScenario class (corresponding
167  to the OpenSCENARIO tag) for processing order reasons. Here, the data
168  member `open_scenario` is a null pointer until the
169  `syntax::ScenarioDefinition` construction is complete. The inner class
170  `Scope::ScenarioDefinition` is provided to deal with this problem, which
171  implementors understand to be a DIRTY HACK.
172 
173  A fundamental solution to this problem will require a reworking of
174  CatalogReference, which is still in the pilot implementation stage at this
175  time, but the status quo will be maintained for the time being due to its
176  wide impact. If you want to access global resources via `Scope`, we
177  recommend that you go through the data member `open_scenario` instead of
178  `Scope::ScenarioDefinition` whenever possible.
179  */
180 
181  struct ScenarioDefinition
182  {
183  const Entities * entities = nullptr;
184 
185  const CatalogLocations * catalog_locations = nullptr;
186  };
187 
188  const OpenScenario * const open_scenario;
189 
190  const std::shared_ptr<EnvironmentFrame> frame;
191 
192  const std::shared_ptr<ScenarioDefinition> scenario_definition;
193 
194 public:
196 
197  std::list<Entity> actors;
198 
199  double seed; // NOTE: `seed` is used only for sharing randomSeed in Stochastic now
200 
201  Scope() = delete;
202 
203  Scope(const Scope &) = default; // NOTE: shallow copy
204 
205  Scope(Scope &&) = default;
206 
207  explicit Scope(const OpenScenario * const);
208 
209  explicit Scope(const std::string &, const Scope &);
210 
211  auto dirname() const -> std::string;
212 
213  template <typename... Ts>
214  auto ref(Ts &&... xs) const -> decltype(auto)
215  {
216  return frame->ref<Object>(std::forward<decltype(xs)>(xs)...);
217  }
218 
219  template <typename T, typename... Ts>
220  auto ref(Ts &&... xs) const -> decltype(auto)
221  {
222  return frame->ref<T>(std::forward<decltype(xs)>(xs)...).template as<T>();
223  }
224 
225  auto global() const -> const ScenarioDefinition &;
226 
227  auto global() -> ScenarioDefinition &;
228 
229  auto local() const noexcept -> const Scope &;
230 
231  auto local() noexcept -> Scope &;
232 
233  auto insert(const Name &, const Object &) -> void;
234 };
235 } // namespace openscenario_interpreter
236 
237 #endif // OPENSCENARIO_INTERPRETER__SCOPE_HPP_
EnvironmentFrame(const EnvironmentFrame &)=delete
auto define(const Name &, const Object &) -> void
Definition: scope.cpp:36
EnvironmentFrame(EnvironmentFrame &&)=delete
auto find(const Prefixed< Name > &prefixed_name) const -> Object
Definition: scope.hpp:111
auto find(const Name &name) const -> Object
Definition: scope.hpp:73
auto isOutermost() const noexcept -> bool
Definition: scope.cpp:41
friend struct Scope
Definition: scope.hpp:36
auto ref(const Prefixed< Name > &prefixed_name) const -> Object
Definition: scope.hpp:129
Definition: scope.hpp:158
auto ref(Ts &&... xs) const -> decltype(auto)
Definition: scope.hpp:220
std::list< Entity > actors
Definition: scope.hpp:197
double seed
Definition: scope.hpp:199
const std::string name
Definition: scope.hpp:195
Scope(const Scope &)=default
Definition: hypot.hpp:22
Definition: lanelet_wrapper.hpp:43
Definition: junit5.hpp:25
std::string string
Definition: junit5.hpp:26
#define DEFINE_SYNTAX_ERROR(TYPENAME,...)
Definition: scope.hpp:46
Definition: name.hpp:27
Definition: name.hpp:41
Definition: object.hpp:42
Definition: catalog_locations.hpp:44
Definition: entities.hpp:41
Definition: open_scenario.hpp:40
Definition: scenario_definition.hpp:44