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/filesystem.hpp>
19 #include <boost/lexical_cast.hpp>
20 #include <boost/range/algorithm.hpp>
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  boost::range::for_each(frame->variables.equal_range(name), [&](auto && name_and_value) {
81  return result.push_back(name_and_value.second);
82  });
83  }
84  return result;
85  }();
86 
87  switch (boost::range::count_if(objects, is_also<T>())) {
88  case 0:
89  frames = [&]() {
90  std::vector<const EnvironmentFrame *> result;
91  for (auto && current_frame : frames) {
92  boost::range::copy(current_frame->unnamed_inner_frames, std::back_inserter(result));
93  }
94  return result;
95  }();
96  break;
97  case 1:
98  return *boost::range::find_if(objects, is_also<T>());
99  default:
100  throw AmbiguousReferenceTo<T>(name);
101  }
102  }
103 
104  return isOutermost() ? throw NoSuchVariableNamed<T>(name) : outer_frame->find<T>(name);
105  }
106 
107  template <typename T>
108  auto find(const Prefixed<Name> & prefixed_name) const -> Object
109  {
110  if (not prefixed_name.prefixes.empty()) {
111  const auto found = resolvePrefix(prefixed_name);
112  switch (found.size()) {
113  case 0:
114  throw NoSuchVariableNamed<T>(boost::lexical_cast<std::string>(prefixed_name));
115  case 1:
116  return found.front()->find<T>(prefixed_name.strip<1>());
117  default:
118  throw AmbiguousReferenceTo<T>(boost::lexical_cast<std::string>(prefixed_name));
119  }
120  } else {
121  return find<T>(prefixed_name.name);
122  }
123  }
124 
125  template <typename T>
126  auto ref(const Prefixed<Name> & prefixed_name) const -> Object
127  {
128  if (prefixed_name.absolute) {
129  return outermostFrame().find<T>(prefixed_name);
130  } else if (prefixed_name.prefixes.empty()) {
131  return find<T>(prefixed_name.name);
132  } else {
133  return lookupFrame(prefixed_name)->find<T>(prefixed_name.strip<1>());
134  }
135  }
136 
137  auto isOutermost() const noexcept -> bool;
138 
139 private:
140  auto resolvePrefix(const Prefixed<Name> &) const -> std::list<const EnvironmentFrame *>;
141 
142  auto lookupFrame(const Prefixed<Name> &) const -> const EnvironmentFrame *;
143 
144  auto outermostFrame() const noexcept -> const EnvironmentFrame &;
145 };
146 
147 inline namespace syntax
148 {
149 struct Entities;
150 
151 struct OpenScenario;
152 } // namespace syntax
153 
154 class Scope
155 {
156  /*
157  In OpenSCENARIO, global resources are FileHeader, top-level
158  ParameterDeclaration, CatalogLocations, RoadNetwork, and Entities (These
159  are located directly under the `OpenSCENARIO` tag).
160 
161  The `Scope` data member `open_scenario` is provided to reference those
162  global resources. However, some constructors need access to global
163  resources during the construction of the OpenScenario class (corresponding
164  to the OpenSCENARIO tag) for processing order reasons. Here, the data
165  member `open_scenario` is a null pointer until the
166  `syntax::ScenarioDefinition` construction is complete. The inner class
167  `Scope::ScenarioDefinition` is provided to deal with this problem, which
168  implementors understand to be a DIRTY HACK.
169 
170  A fundamental solution to this problem will require a reworking of
171  CatalogReference, which is still in the pilot implementation stage at this
172  time, but the status quo will be maintained for the time being due to its
173  wide impact. If you want to access global resources via `Scope`, we
174  recommend that you go through the data member `open_scenario` instead of
175  `Scope::ScenarioDefinition` whenever possible.
176  */
177 
178  struct ScenarioDefinition
179  {
180  const Entities * entities = nullptr;
181 
182  const CatalogLocations * catalog_locations = nullptr;
183  };
184 
185  const OpenScenario * const open_scenario;
186 
187  const std::shared_ptr<EnvironmentFrame> frame;
188 
189  const std::shared_ptr<ScenarioDefinition> scenario_definition;
190 
191 public:
193 
194  std::list<Entity> actors;
195 
196  double seed; // NOTE: `seed` is used only for sharing randomSeed in Stochastic now
197 
198  Scope() = delete;
199 
200  Scope(const Scope &) = default; // NOTE: shallow copy
201 
202  Scope(Scope &&) = default;
203 
204  explicit Scope(const OpenScenario * const);
205 
206  explicit Scope(const std::string &, const Scope &);
207 
208  auto dirname() const -> std::string;
209 
210  template <typename... Ts>
211  auto ref(Ts &&... xs) const -> decltype(auto)
212  {
213  return frame->ref<Object>(std::forward<decltype(xs)>(xs)...);
214  }
215 
216  template <typename T, typename... Ts>
217  auto ref(Ts &&... xs) const -> decltype(auto)
218  {
219  return frame->ref<T>(std::forward<decltype(xs)>(xs)...).template as<T>();
220  }
221 
222  auto global() const -> const ScenarioDefinition &;
223 
224  auto global() -> ScenarioDefinition &;
225 
226  auto local() const noexcept -> const Scope &;
227 
228  auto local() noexcept -> Scope &;
229 
230  auto insert(const Name &, const Object &) -> void;
231 };
232 } // namespace openscenario_interpreter
233 
234 #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:108
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:126
Definition: scope.hpp:155
auto ref(Ts &&... xs) const -> decltype(auto)
Definition: scope.hpp:217
std::list< Entity > actors
Definition: scope.hpp:194
double seed
Definition: scope.hpp:196
const std::string name
Definition: scope.hpp:192
Scope(const Scope &)=default
Definition: hypot.hpp:22
Definition: lanelet_wrapper.hpp:40
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