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