aGrUM  0.14.2
O3InterfaceFactory_tpl.h
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
20 
30 
31 namespace gum {
32  namespace prm {
33  namespace o3prm {
34 
35  template < typename GUM_SCALAR >
37  PRM< GUM_SCALAR >& prm,
38  O3PRM& o3_prm,
40  ErrorsContainer& errors) :
41  __prm(&prm),
42  __o3_prm(&o3_prm), __solver(&solver), __errors(&errors) {
43  GUM_CONSTRUCTOR(O3InterfaceFactory);
44  }
45 
46  template < typename GUM_SCALAR >
49  __prm(src.__prm),
51  GUM_CONS_CPY(O3InterfaceFactory);
52  }
53 
54  template < typename GUM_SCALAR >
57  __prm(std::move(src.__prm)),
58  __o3_prm(std::move(src.__o3_prm)), __solver(std::move(src.__solver)),
59  __errors(std::move(src.__errors)) {
60  GUM_CONS_MOV(O3InterfaceFactory);
61  }
62 
63  template < typename GUM_SCALAR >
65  GUM_DESTRUCTOR(O3InterfaceFactory);
66  }
67 
68  template < typename GUM_SCALAR >
71  if (this == &src) { return *this; }
72  __prm = src.__prm;
73  __o3_prm = src.__o3_prm;
74  __solver = src.__solver;
75  __errors = src.__errors;
76  return *this;
77  }
78 
79  template < typename GUM_SCALAR >
82  if (this == &src) { return *this; }
83  __prm = std::move(src.__prm);
84  __o3_prm = std::move(src.__o3_prm);
85  __solver = std::move(src.__solver);
86  __errors = std::move(src.__errors);
87  return *this;
88  }
89 
90  template < typename GUM_SCALAR >
93  if (__checkO3Interfaces()) {
95 
96  for (auto i : __o3Interface) {
97  if (__solver->resolveInterface(i->superLabel())) {
98  factory.startInterface(
99  i->name().label(), i->superLabel().label(), true);
100  factory.endInterface();
101  }
102  }
103  }
104  }
105 
106  template < typename GUM_SCALAR >
108  return __addInterface2Dag() && __addArcs2Dag();
109  }
110 
111  template < typename GUM_SCALAR >
113  // Adding nodes to the type inheritance graph
114  for (auto& i : __o3_prm->interfaces()) {
115  auto id = __dag.addNode();
116  try {
117  __nameMap.insert(i->name().label(), id);
118  __interfaceMap.insert(i->name().label(), i.get());
119  __nodeMap.insert(id, i.get());
120 
121  } catch (DuplicateElement&) {
122  // Raised if duplicate type names
123  O3PRM_INTERFACE_DUPLICATE(i->name(), *__errors);
124  return false;
125  }
126  }
127  return true;
128  }
129 
130  template < typename GUM_SCALAR >
132  // Adding arcs to the graph inheritance graph
133  for (auto& i : __o3_prm->interfaces()) {
134  if (i->superLabel().label() != "") {
135  if (!__solver->resolveInterface(i->superLabel())) { return false; }
136 
137  auto head = __nameMap[i->superLabel().label()];
138  auto tail = __nameMap[i->name().label()];
139 
140  try {
141  __dag.addArc(tail, head);
142 
143  } catch (InvalidDirectedCycle&) {
144  // Cyclic inheritance
145  O3PRM_INTERFACE_CYCLIC_INHERITANCE(
146  i->name(), i->superLabel(), *__errors);
147  return false;
148  }
149  }
150  }
151  return true;
152  }
153 
154  template < typename GUM_SCALAR >
155  INLINE void
157  auto topo_order = __dag.topologicalOrder();
158  for (auto id = topo_order.rbegin(); id != topo_order.rend(); --id) {
159  __o3Interface.push_back(__nodeMap[*id]);
160  }
161  }
162 
163  template < typename GUM_SCALAR >
166 
167  for (auto i : __o3Interface) {
168  __prm->getInterface(i->name().label()).inheritInterface();
169 
170  factory.continueInterface(i->name().label());
171 
172  for (auto& elt : i->elements()) {
173  if (__checkInterfaceElement(*i, elt)) {
174  try {
175  if (__prm->isType(elt.type().label())) {
176  factory.addAttribute(elt.type().label(), elt.name().label());
177  } else {
178  factory.addReferenceSlot(
179  elt.type().label(), elt.name().label(), elt.isArray());
180  }
181 
182  } catch (OperationNotAllowed&) {
183  // Duplicate or Wrong overload
184  O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *__errors);
185  }
186  }
187  }
188  factory.endInterface();
189  }
190  }
191 
192  template < typename GUM_SCALAR >
194  O3Interface& i, O3InterfaceElement& elt) {
195  if (!__solver->resolveClassElement(elt.type())) { return false; }
196 
197  if (__prm->isType(elt.type().label()) && elt.isArray()) {
198  O3PRM_INTERFACE_ILLEGAL_ARRAY(elt.name(), *__errors);
199  return false;
200  }
201 
202  const auto& real_i = __prm->getInterface(i.name().label());
203 
204  if (real_i.exists(elt.name().label())) {
205  if (!__checkOverloadLegality(i, elt)) { return false; }
206  }
207 
208  if (!__checkCyclicReference(i, elt)) { return false; }
209 
210  return true;
211  }
212 
213  template < typename GUM_SCALAR >
215  O3Interface& i, O3InterfaceElement& elt) {
216  const auto& real_i = __prm->getInterface(i.name().label());
217  const auto& real_elt = real_i.get(elt.name().label());
218 
220  return __checkAttributeOverloadLegality(i, elt);
221  }
222 
224  return __checkReferenceOverloadLegality(i, elt);
225  }
226 
227  return false;
228  }
229 
230  template < typename GUM_SCALAR >
231  INLINE bool
233  O3Interface& i, O3InterfaceElement& elt) {
234  const auto& real_i = __prm->getInterface(i.name().label());
235  const auto& real_elt = real_i.get(elt.name().label());
236 
237  const auto& sub_type = __prm->type(elt.type().label());
238  const auto& super_type = real_elt.type();
239 
240  if (!sub_type.isSubTypeOf(super_type)) {
241  O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *__errors);
242  return false;
243  }
244 
245  if (sub_type.name() == super_type.name()) {
246  O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *__errors);
247  return false;
248  }
249 
250  return true;
251  }
252 
253  template < typename GUM_SCALAR >
254  INLINE bool
256  O3Interface& i, O3InterfaceElement& elt) {
257  const auto& real_i = __prm->getInterface(i.name().label());
258  const auto& real_elt =
259  static_cast< const PRMReferenceSlot< GUM_SCALAR >& >(
260  real_i.get(elt.name().label()));
261 
262  auto sub_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
263 
264  if (__prm->isClass(elt.type().label())) {
265  sub_type = &(__prm->getClass(elt.type().label()));
266  } else {
267  sub_type = &(__prm->getInterface(elt.type().label()));
268  }
269 
270  auto super_type = &(real_elt.slotType());
271 
272  if (!sub_type->isSubTypeOf(*super_type)) {
273  O3PRM_INTERFACE_ILLEGAL_OVERLOAD(elt, *__errors);
274  return false;
275  }
276 
277  if (sub_type->name() == super_type->name()) {
278  O3PRM_INTERFACE_DUPLICATE_ELEMENT(elt, *__errors);
279  return false;
280  }
281 
282  return true;
283  }
284 
285  template < typename GUM_SCALAR >
287  O3Interface& i, O3InterfaceElement& elt) {
288  if (__prm->isInterface(elt.type().label())
289  || __prm->isClass(elt.type().label())) {
290  auto ref_type = (const PRMClassElementContainer< GUM_SCALAR >*)nullptr;
291 
292  if (__prm->isInterface(elt.type().label())) {
293  ref_type = &(__prm->getInterface(elt.type().label()));
294  } else {
295  ref_type = &(__prm->getClass(elt.type().label()));
296  }
297 
298  const auto& real_i = __prm->getInterface(i.name().label());
299 
300  if (&real_i == ref_type) {
301  O3PRM_INTERFACE_SELF_REFERENCE(i, elt, *__errors);
302  return false;
303  }
304 
305  if (ref_type->isSubTypeOf(real_i)) {
306  O3PRM_INTERFACE_ILLEGAL_SUB_REFERENCE(i, elt, *__errors);
307  return false;
308  }
309  }
310 
311  return true;
312  }
313 
314  } // namespace o3prm
315  } // namespace prm
316 } // namespace gum
virtual void endInterface() override
Tells the factory that we finished an interface declaration.
bool __checkReferenceOverloadLegality(O3Interface &i, O3InterfaceElement &elt)
bool __checkAttributeOverloadLegality(O3Interface &i, O3InterfaceElement &elt)
STL namespace.
O3InterfaceFactory(PRM< GUM_SCALAR > &prm, O3PRM &o3_prm, O3NameSolver< GUM_SCALAR > &solver, ErrorsContainer &errors)
virtual void continueInterface(const std::string &name) override
Continue the declaration of an interface.
Abstract class representing an element of PRM class.
virtual void startInterface(const std::string &i, const std::string &ext="", bool delayInheritance=false) override
Tells the factory that we start an interface declaration.
virtual void addReferenceSlot(const std::string &type, const std::string &name, bool isArray) override
Tells the factory that we started declaring a slot.
This class is used contain and manipulate gum::ParseError.
bool __checkOverloadLegality(O3Interface &i, O3InterfaceElement &elt)
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
O3InterfaceFactory< GUM_SCALAR > & operator=(const O3InterfaceFactory< GUM_SCALAR > &src)
HashTable< NodeId, O3Interface *> __nodeMap
virtual void addAttribute(const std::string &type, const std::string &name) override
Add an attribute to an interface.
virtual NodeId addNode()
insert a new node and return its id
A PRMReferenceSlot represent a relation between two PRMClassElementContainer.
Definition: PRMObject.h:220
O3NameSolver< GUM_SCALAR > * __solver
std::string & label()
Definition: O3prm.cpp:240
Bulds gum::prm:PRMInterface from gum::prm::o3prm::O3Interface.
Resolves names for the different O3PRM factories.
Definition: O3NameSolver.h:55
Factory which builds a PRM<GUM_SCALAR>.
Definition: PRMType.h:47
virtual void addArc(const NodeId tail, const NodeId head)
insert a new arc into the directed graph
Definition: DAG_inl.h:40
Headers for the O3InterfaceFactory class.
const Sequence< NodeId > & topologicalOrder(bool clear=true) const
The topological order stays the same as long as no variable or arcs are added or erased src the topol...
Definition: diGraph.cpp:88
O3InterfaceList & interfaces()
Definition: O3prm.cpp:496
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition: PRM.h:63
<agrum/PRM/classElementContainer.h>
HashTable< std::string, gum::NodeId > __nameMap
bool __checkCyclicReference(O3Interface &i, O3InterfaceElement &elt)
HashTable< std::string, O3Interface *> __interfaceMap
The O3InterfaceElement is part of the AST of the O3PRM language.
Definition: O3prm.h:321
The O3PRM is part of the AST of the O3PRM language.
Definition: O3prm.h:890
bool __checkInterfaceElement(O3Interface &i, O3InterfaceElement &elt)
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
The O3Interface is part of the AST of the O3PRM language.
Definition: O3prm.h:354
std::vector< O3Interface *> __o3Interface