Salome HOME
WIP
[modules/yacs.git] / src / yacsloader / loopParsers.hxx
1 // Copyright (C) 2006-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #ifndef _LOOPPARSER_HXX_
21 #define _LOOPPARSER_HXX_
22
23 #include "parserBase.hxx"
24
25 #include "Bloc.hxx"
26 #include "Proc.hxx"
27 #include "Logger.hxx"
28 #include "Exception.hxx"
29 #include "InlineNode.hxx"
30 #include "ServiceNode.hxx"
31 #include "ServiceInlineNode.hxx"
32 #include "OutputDataStreamPort.hxx"
33 #include "InputDataStreamPort.hxx"
34 #include "ForLoop.hxx"
35 #include "WhileLoop.hxx"
36 #include "Switch.hxx"
37 #include "ForEachLoop.hxx"
38 #include "OptimizerLoop.hxx"
39
40 #include <vector>
41 #include <string>
42 #include <sstream>
43
44 namespace YACS
45 {
46
47 template <class T=ENGINE::Loop*>
48 struct looptypeParser:parser
49 {
50   virtual void onStart(const XML_Char* el, const XML_Char** attr);
51   virtual void onEnd(const char *el,parser* child);
52   virtual void buildAttr(const XML_Char** attr);
53   virtual void pre ();
54   virtual void name (const std::string& name);
55   virtual void state (const std::string& name);
56   virtual void property (const myprop& prop);
57   virtual void inline_ (ENGINE::InlineNode* const& n);
58   virtual void sinline (ENGINE::ServiceInlineNode* const& n);
59   virtual void service (ENGINE::ServiceNode* const& n);
60   virtual void server (ENGINE::ServerNode* const& n);
61   virtual void remote (ENGINE::InlineNode* const& n);
62   virtual void node (ENGINE::InlineNode* const& n);
63   virtual void forloop (ENGINE::ForLoop* const& b);
64   virtual void foreach (ENGINE::ForEachLoop* const& b);
65   virtual void foreachdyn (ENGINE::ForEachLoopDyn* const& b);
66   virtual void optimizer (ENGINE::OptimizerLoop* const& b);
67   virtual void while_ (ENGINE::WhileLoop* const& b);
68   virtual void switch_ (ENGINE::Switch* const& b);
69   virtual void bloc (ENGINE::Bloc* const& b);
70   virtual void datalink (const mylink& l);
71   std::string _state;
72   T _cnode;
73   std::vector<T> _cnodes;
74 };
75
76 }
77
78 namespace YACS
79 {
80   // A loop can contain forloop, whileloop or foreachloop
81   // We must respect the order : definition of loop, then while, for, .. and then onStart, onEnd for loop !!!
82   //
83   static std::string t3[]={"inline","sinline","service","server", "remote", "node","forloop","foreach","optimizer","while","switch","bloc",""};
84
85 template <class T>
86 void looptypeParser<T>::buildAttr(const XML_Char** attr)
87     {
88       if (!attr)
89         return;
90       this->required("name",attr);
91       for (int i = 0; attr[i]; i += 2) 
92         {
93           if(std::string(attr[i]) == "name")name(attr[i+1]);
94           if(std::string(attr[i]) == "state")state(attr[i+1]);
95         }
96     }
97 template <class T>
98 void looptypeParser<T>::pre ()
99     {
100       _state="";
101       _cnode=0;
102     }
103 template <class T>
104 void looptypeParser<T>::name (const std::string& name)
105     {
106       DEBTRACE( "bloc_name: " << name );
107     }
108 template <class T>
109 void looptypeParser<T>::state (const std::string& name)
110     {
111       DEBTRACE( "bloc_state: " << name );
112       _state=name;
113     }
114 template <class T>
115 void looptypeParser<T>::property (const myprop& prop)
116     {
117       DEBTRACE( "property_set" << prop._name << prop._value );
118     }
119
120 template <class T>
121 void looptypeParser<T>::inline_ (ENGINE::InlineNode* const& n)
122     {
123       DEBTRACE( "loop_inline" << n->getName() );
124       _cnode->edSetNode(n);
125       std::string fullname=currentProc->names.back()+ n->getName();
126       currentProc->nodeMap[fullname]=n;
127       currentProc->inlineMap[fullname]=n;
128     }
129 template <class T>
130 void looptypeParser<T>::sinline (ENGINE::ServiceInlineNode* const& n)
131     {
132       DEBTRACE( "loop_sinline" << n->getName() )             
133       _cnode->edSetNode(n);
134       std::string fullname=currentProc->names.back()+ n->getName();
135       currentProc->nodeMap[fullname]=n;
136       currentProc->serviceMap[fullname]=n;
137     }
138 template <class T>
139 void looptypeParser<T>::service (ENGINE::ServiceNode* const& n)
140     {
141       DEBTRACE( "loop_service" << n->getName() )             
142       _cnode->edSetNode(n);
143       std::string fullname=currentProc->names.back()+ n->getName();
144       currentProc->nodeMap[fullname]=n;
145       currentProc->serviceMap[fullname]=n;
146     }
147 template <class T>
148 void looptypeParser<T>::server (ENGINE::ServerNode* const& n)
149     {
150       DEBTRACE( "loop_server" << n->getName() )             
151       _cnode->edSetNode(n);
152       std::string fullname=currentProc->names.back()+ n->getName();
153       currentProc->nodeMap[fullname]=n;
154       currentProc->inlineMap[fullname]=n;
155     }
156
157 template <class T>
158 void looptypeParser<T>::remote (YACS::ENGINE::InlineNode* const& n)
159     {
160       DEBTRACE( "loop_remote: " << n->getName() )
161       _cnode->edSetNode(n);
162       std::string fullname = currentProc->names.back()+n->getName();
163       currentProc->nodeMap[fullname]=n;
164       currentProc->inlineMap[fullname]=n;
165     }
166
167 template <class T>
168 void looptypeParser<T>::node (ENGINE::InlineNode* const& n)
169     {
170       DEBTRACE( "loop_node" << n->getName() )             
171       _cnode->edSetNode(n);
172       std::string fullname=currentProc->names.back()+ n->getName();
173       currentProc->nodeMap[fullname]=n;
174       currentProc->inlineMap[fullname]=n;
175     }
176 template <class T>
177 void looptypeParser<T>::forloop (ENGINE::ForLoop* const& b)
178     {
179       DEBTRACE( "loop_forloop" << b->getName() )             
180       _cnode->edSetNode(b);
181       std::string fullname=currentProc->names.back()+ b->getName();
182       currentProc->nodeMap[fullname]=b;
183     }
184 template <class T>
185 void looptypeParser<T>::foreach (ENGINE::ForEachLoop* const& b)
186     {
187       DEBTRACE("loop_foreach" << b->getName())
188       _cnode->edSetNode(b);
189       std::string fullname=currentProc->names.back()+ b->getName();
190       currentProc->nodeMap[fullname]=b;
191       fullname += ".splitter";
192       currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
193     }
194 template <class T>
195 void looptypeParser<T>::foreachdyn (ENGINE::ForEachLoopDyn* const& b)
196 {
197       DEBTRACE("loop_foreachdyn" << b->getName())
198       _cnode->edSetNode(b);
199       std::string fullname=currentProc->names.back()+ b->getName();
200       currentProc->nodeMap[fullname]=b;
201       fullname += ".splitter";
202       currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
203 }
204 template <class T>
205 void looptypeParser<T>::optimizer (ENGINE::OptimizerLoop* const& b)
206   {
207     DEBTRACE( "loop_optimizer: " << b->getName() );
208     _cnode->edSetNode(b);
209     std::string fullname = currentProc->names.back()+b->getName();
210     currentProc->nodeMap[fullname]=b;
211     //fullname += ".splitter";
212     //currentProc->nodeMap[fullname]=b->getChildByShortName("splitter");
213   }
214 template <class T>
215 void looptypeParser<T>::while_ (ENGINE::WhileLoop* const& b)
216     {
217       DEBTRACE( "loop_while: " << b->getName() )             
218       _cnode->edSetNode(b);
219       std::string fullname=currentProc->names.back()+ b->getName();
220       currentProc->nodeMap[fullname]=b;
221     }
222 template <class T>
223 void looptypeParser<T>::switch_ (ENGINE::Switch* const& b)
224     {
225       DEBTRACE( "loop_switch: " << b->getName() )             
226       _cnode->edSetNode(b);
227       std::string fullname=currentProc->names.back()+ b->getName();
228       currentProc->nodeMap[fullname]=b;
229     }
230 template <class T>
231 void looptypeParser<T>::bloc (ENGINE::Bloc* const& b)
232     {
233       DEBTRACE( "loop_bloc " << b->getName() )             
234       _cnode->edSetNode(b);
235       std::string fullname=currentProc->names.back()+ b->getName();
236       currentProc->nodeMap[fullname]=b;
237     }
238
239 template <class T>
240 void looptypeParser<T>::datalink (const mylink& l)
241     {
242       DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport())
243       std::string msg;
244
245       //Try only relative name for from node
246       std::string fromname = currentProc->names.back()+l.fromnode();
247       if(currentProc->nodeMap.count(fromname) == 0)
248         {
249           msg="from node " + l.fromnode() + " does not exist in data link: ";
250           msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
251           this->logError(msg);
252           return;
253         }
254       //Try relative name for to node and then absolute one
255       std::string toname = currentProc->names.back()+l.tonode();
256       if(currentProc->nodeMap.count(toname) == 0)
257         {
258           //It's not a relative name. Try an absolute one (I think it's not possible)
259           toname=l.tonode();
260           if(currentProc->nodeMap.count(toname) == 0)
261             {
262               // The TO node does not exist -> error
263               msg="to node " + l.tonode() + " does not exist in data link: ";
264               msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")";
265               this->logError(msg);
266               return;
267             }
268         }
269       // We only link local node and other nodes (relative or absolute name in this order)
270       DEBTRACE(fromname <<":"<<l.fromport()<<toname<<":"<<l.toport());
271       try
272         {
273           if (l.withControl())
274             _cnode->edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
275                                 currentProc->nodeMap[toname]->getInputPort(l.toport()));
276           else
277             _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()),
278                               currentProc->nodeMap[toname]->getInputPort(l.toport()));
279         }
280       catch(Exception& e)
281         {
282             this->logError(e.what());
283         }
284     }
285
286
287 }
288
289 namespace YACS
290 {
291
292   // While loop specialization
293
294 template <class T=ENGINE::WhileLoop*>
295 struct whilelooptypeParser:looptypeParser<T>
296 {
297   static whilelooptypeParser<T> whileloopParser;
298   virtual void name (const std::string& name);
299   virtual T post();
300 };
301
302 template <class T> whilelooptypeParser<T> whilelooptypeParser<T>::whileloopParser;
303
304 template <class T>
305 void whilelooptypeParser<T>::name (const std::string& name)
306     {
307       DEBTRACE( "while_name: " << name )             
308       std::string fullname=currentProc->names.back()+name;
309       this->_cnode=theRuntime->createWhileLoop(name);
310       currentProc->nodeMap[fullname]=this->_cnode;
311       this->_cnodes.push_back(this->_cnode);
312       currentProc->names.push_back(fullname+'.');
313     }
314
315 template <class T>
316 T whilelooptypeParser<T>::post()
317     {
318       DEBTRACE( "while_post" << this->_cnode->getName() )             
319       ENGINE::InputPort *cond=this->_cnode->edGetConditionPort();
320       cond->edInit(true);
321       T b=this->_cnode;
322       this->_cnodes.pop_back();
323       currentProc->names.pop_back();
324       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
325       return b;
326     }
327 }
328
329
330
331
332 namespace YACS
333 {
334   // For loop specialization
335
336 template <class T=ENGINE::ForLoop*>
337 struct forlooptypeParser:looptypeParser<T>
338 {
339   static forlooptypeParser<T> forloopParser;
340   virtual void buildAttr(const XML_Char** attr);
341   virtual void name (const std::string& name);
342   virtual void nsteps (const int& n);
343   virtual T post();
344   int _nsteps;
345 };
346
347 template <class T> forlooptypeParser<T> forlooptypeParser<T>::forloopParser;
348
349 template <class T>
350 void forlooptypeParser<T>::buildAttr(const XML_Char** attr)
351     {
352       if (!attr)
353         return;
354       this->required("name",attr);
355       for (int i = 0; attr[i]; i += 2) 
356         {
357           if(std::string(attr[i]) == "name")name(attr[i+1]);
358           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
359           if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1]));
360         }
361     }
362
363 template <class T>
364   void forlooptypeParser<T>::name (const std::string& name)
365     {
366       DEBTRACE( "forloop_name: " << name );
367       std::string fullname=currentProc->names.back()+name;
368       this->_cnode=theRuntime->createForLoop(name);
369       currentProc->nodeMap[fullname]=this->_cnode;
370       this->_cnodes.push_back(this->_cnode);
371       currentProc->names.push_back(fullname+'.');
372       _nsteps=0;
373     }
374
375 template <class T>
376 void forlooptypeParser<T>::nsteps (const int& n)
377     {
378       DEBTRACE( "forloop_nsteps: " << n )             
379       if(!this->_cnode)
380           throw Exception("Node name must be defined before nsteps");
381       ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort();
382       iNbTimes->edInit(n);
383     }
384
385 template <class T>
386    T forlooptypeParser<T>::post()
387     {
388       DEBTRACE( "forloop_post" )             
389       T b=this->_cnode;
390       this->_cnodes.pop_back();
391       currentProc->names.pop_back();
392       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
393       return b;
394     }
395
396 }
397
398 namespace YACS
399 {
400 // pseudo composed node, used to store the init or finalize node of a DynParaLoop
401 class PseudoComposedNode
402 {
403 public:
404   void edSetNode(ENGINE::Node * node) { _node = node; }
405   ENGINE::Node * getNode() { return _node; }
406
407   // Those two methods should never be called
408   bool edAddLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
409   bool edAddDFLink(ENGINE::OutPort *start, ENGINE::InPort *end) throw(Exception) { YASSERT(false); }
410
411 protected:
412   ENGINE::Node * _node;
413 };
414
415 // pseudo composed node parser specialization for DynParaLoop init and finalize nodes
416 template <class T=PseudoComposedNode*>
417 struct pseudocomposednodetypeParser:looptypeParser<T>
418 {
419   static pseudocomposednodetypeParser<T> pseudocomposednodeParser;
420
421   virtual void buildAttr(const XML_Char** attr)
422     {
423       this->_cnode = new PseudoComposedNode();
424       this->_cnodes.push_back(this->_cnode);
425     }
426
427   virtual T post()
428     {
429       DEBTRACE("pseudocomposednode_post" << this->_cnode->getNode()->getName())
430       T b = this->_cnode;
431       this->_cnodes.pop_back();
432       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
433       return b;
434     }
435
436   virtual void datalink(const mylink & l)
437     {
438       throw YACS::Exception("Unexpected datalink element in DynParaLoop init or finalize node");
439     }
440
441 };
442
443 template <class T> pseudocomposednodetypeParser<T> pseudocomposednodetypeParser<T>::pseudocomposednodeParser;
444
445 }
446
447 namespace YACS
448 {
449 // dynparaloop specialization
450
451 template <class T=ENGINE::DynParaLoop*>
452 struct dynparalooptypeParser:looptypeParser<T>
453 {
454   virtual void onStart(const XML_Char* el, const XML_Char** attr)
455     {
456       DEBTRACE( "dynparalooptypeParser::onStart: " << el )
457       std::string element(el);
458       this->maxcount("initnode",1,element);
459       this->maxcount("finalizenode",1,element);
460       if (element == "initnode" || element == "finalizenode")
461         {
462           parser* pp = &pseudocomposednodetypeParser<>::pseudocomposednodeParser;
463           this->SetUserDataAndPush(pp);
464           pp->init();
465           pp->pre();
466           pp->buildAttr(attr);
467         }
468       else
469         {
470           this->looptypeParser<T>::onStart(el, attr);
471         }
472     }
473
474   virtual void onEnd(const char *el, parser* child)
475     {
476       DEBTRACE( "dynparalooptypeParser::onEnd: " << el )
477       std::string element(el);
478       if (element == "initnode") initnode(((pseudocomposednodetypeParser<>*)child)->post());
479       else if (element == "finalizenode") finalizenode(((pseudocomposednodetypeParser<>*)child)->post());
480       else this->looptypeParser<T>::onEnd(el, child);
481     }
482
483   virtual void initnode(PseudoComposedNode * const& n)
484     {
485       DEBTRACE( "dynparaloop_initnode: " << n->getNode()->getName() )
486       this->_cnode->edSetInitNode(n->getNode());
487       delete n;
488     }
489
490   virtual void finalizenode(PseudoComposedNode * const& n)
491     {
492       DEBTRACE( "dynparaloop_finalizenode: " << n->getNode()->getName() )
493       this->_cnode->edSetFinalizeNode(n->getNode());
494       delete n;
495     }
496 };
497
498 }
499
500 namespace YACS
501 {
502   // Foreach loop specialization
503
504 template <class T=ENGINE::ForEachLoop*>
505 struct foreachlooptypeParser:dynparalooptypeParser<T>
506 {
507   static foreachlooptypeParser<T> foreachloopParser;
508
509   virtual void buildAttr(const XML_Char** attr)
510     {
511       if (!attr)
512         return;
513       this->required("name",attr);
514       this->required("type",attr);
515       for (int i = 0; attr[i]; i += 2) 
516         {
517           if(std::string(attr[i]) == "name")name(attr[i+1]);
518           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
519           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
520           if(std::string(attr[i]) == "loopWeight")weight(atof(attr[i+1]));
521           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
522         }
523       postAttr();
524     }
525   virtual void pre ()
526     {
527       _nbranch=0;
528       _weight=-1.;
529       this->looptypeParser<T>::pre();
530     }
531   virtual void name (const std::string& name)
532     {
533       DEBTRACE("foreach_name: " << name)
534       _name=name;
535       _fullname=currentProc->names.back()+name;
536     }
537   virtual void nbranch (const int& n)
538     {
539       DEBTRACE("foreach_nbranch: " << n )
540       _nbranch=n;
541     }
542   virtual void weight (const double& x)
543     {
544       DEBTRACE("foreach_weight: " << x )
545       _weight=x;
546     }
547   virtual void datatype (const std::string& type)
548     {
549       DEBTRACE("foreach_datatype: "<< type)
550       _datatype=type;
551     }
552   virtual void postAttr()
553     {
554       if(currentProc->typeMap.count(_datatype)==0)
555       {
556         //Check if the typecode is defined in the runtime
557         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
558         if(t==0)
559         {
560           std::stringstream msg;
561           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
562           throw Exception(msg.str());
563         }
564         else
565         {
566           currentProc->typeMap[_datatype]=t;
567           t->incrRef();
568         }
569       }
570       this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]);
571       //set number of branches
572       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
573       if(_weight > 0)this->_cnode->setWeight(_weight);
574       this->_cnodes.push_back(this->_cnode);
575       currentProc->names.push_back(_fullname + '.');
576     }
577   virtual T post()
578     {
579       DEBTRACE("foreach_post" << this->_cnode->getName())
580       T b=this->_cnode;
581       this->_cnodes.pop_back();
582       currentProc->names.pop_back();
583       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
584       return b;
585     }
586   int _nbranch;
587   double _weight;
588   std::string _fullname;
589   std::string _name;
590   std::string _datatype;
591 };
592
593 template <class T> foreachlooptypeParser<T> foreachlooptypeParser<T>::foreachloopParser;
594
595 //FIXME
596 template <class T=ENGINE::ForEachLoopDyn*>
597 struct foreachloopdyntypeParser:dynparalooptypeParser<T>
598 {
599   static foreachloopdyntypeParser<T> foreachloopdynParser;
600
601   virtual void buildAttr(const XML_Char** attr)
602     {
603       if (!attr)
604         return;
605       this->required("name",attr);
606       this->required("type",attr);
607       for (int i = 0; attr[i]; i += 2) 
608         {
609           if(std::string(attr[i]) == "name")name(attr[i+1]);
610           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
611           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
612           if(std::string(attr[i]) == "loopWeight")weight(atof(attr[i+1]));
613           if(std::string(attr[i]) == "type")datatype(attr[i+1]);
614         }
615       postAttr();
616     }
617   virtual void pre ()
618     {
619       _nbranch=0;
620       _weight=-1.;
621       this->looptypeParser<T>::pre();
622     }
623   virtual void name (const std::string& name)
624     {
625       DEBTRACE("foreach_name: " << name)
626       _name=name;
627       _fullname=currentProc->names.back()+name;
628     }
629   virtual void nbranch (const int& n)
630     {
631       DEBTRACE("foreach_nbranch: " << n )
632       _nbranch=n;
633     }
634   virtual void weight (const double& x)
635     {
636       DEBTRACE("foreach_weight: " << x )
637       _weight=x;
638     }
639   virtual void datatype (const std::string& type)
640     {
641       DEBTRACE("foreach_datatype: "<< type)
642       _datatype=type;
643     }
644   virtual void postAttr()
645     {
646       if(currentProc->typeMap.count(_datatype)==0)
647       {
648         //Check if the typecode is defined in the runtime
649         YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype);
650         if(t==0)
651         {
652           std::stringstream msg;
653           msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")";
654           throw Exception(msg.str());
655         }
656         else
657         {
658           currentProc->typeMap[_datatype]=t;
659           t->incrRef();
660         }
661       }
662       this->_cnode=theRuntime->createForEachLoopDyn(_name,currentProc->typeMap[_datatype]);
663       //set number of branches
664       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
665       if(_weight > 0)this->_cnode->setWeight(_weight);
666       this->_cnodes.push_back(this->_cnode);
667       currentProc->names.push_back(_fullname + '.');
668     }
669   virtual T post()
670     {
671       DEBTRACE("foreach_post" << this->_cnode->getName())
672       T b=this->_cnode;
673       this->_cnodes.pop_back();
674       currentProc->names.pop_back();
675       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
676       return b;
677     }
678   int _nbranch;
679   double _weight;
680   std::string _fullname;
681   std::string _name;
682   std::string _datatype;
683 };
684
685 template <class T> foreachloopdyntypeParser<T> foreachloopdyntypeParser<T>::foreachloopdynParser;
686 }
687
688 namespace YACS
689 {
690   // optimizer loop specialization
691
692 template <class T=ENGINE::OptimizerLoop*>
693 struct optimizerlooptypeParser:dynparalooptypeParser<T>
694 {
695   static optimizerlooptypeParser<T> optimizerloopParser;
696
697   virtual void buildAttr(const XML_Char** attr)
698     {
699       if (!attr)
700         return;
701       this->required("name",attr);
702       this->required("lib",attr);
703       this->required("entry",attr);
704       for (int i = 0; attr[i]; i += 2)
705         {
706           if(std::string(attr[i]) == "name")name(attr[i+1]);
707           if(std::string(attr[i]) == "state")this->state(attr[i+1]);
708           if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1]));
709           if(std::string(attr[i]) == "loopWeight")weight(atof(attr[i+1]));
710           if(std::string(attr[i]) == "lib")lib(attr[i+1]);
711           if(std::string(attr[i]) == "entry")entry(attr[i+1]);
712           if(std::string(attr[i]) == "kind")kind(attr[i+1]);
713         }
714       postAttr();
715     }
716   virtual void pre ()
717     {
718       _nbranch=0;
719       _weight=-1.;
720       this->looptypeParser<T>::pre();
721     }
722   virtual void name (const std::string& name)
723     {
724       DEBTRACE("optimizer_name: " << name)
725       _name=name;
726       _fullname=currentProc->names.back()+name;
727     }
728   virtual void lib (const std::string& name)
729     {
730       _lib=name;
731     }
732   virtual void entry (const std::string& name)
733     {
734       _entry=name;
735     }
736   virtual void nbranch (const int& n)
737     {
738       DEBTRACE("optimizer_nbranch: " << n )
739       _nbranch=n;
740     }
741   virtual void weight (const double& x)
742     {
743       DEBTRACE("foreach_weight: " << x )
744       _weight=x;
745     }
746   virtual void kind (const std::string& name)
747     {
748       _kind=name;
749     }
750   virtual void postAttr()
751     {
752       this->_cnode=theRuntime->createOptimizerLoop(_name,_lib,_entry,true,_kind, currentProc);
753       //set number of branches
754       if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch);
755       if(_weight > 0)this->_cnode->setWeight(_weight);
756       this->_cnodes.push_back(this->_cnode);
757       currentProc->names.push_back(_fullname + '.');
758     }
759   virtual T post()
760     {
761       DEBTRACE("optimizer_post" << this->_cnode->getName())
762       T b=this->_cnode;
763       this->_cnodes.pop_back();
764       currentProc->names.pop_back();
765       this->_cnode=this->_cnodes.empty() ? 0 : this->_cnodes.back();
766       return b;
767     }
768
769   int _nbranch;
770   double _weight;
771   std::string _fullname;
772   std::string _name;
773   std::string _entry;
774   std::string _kind;
775   std::string _lib;
776
777 };
778
779 template <class T> optimizerlooptypeParser<T> optimizerlooptypeParser<T>::optimizerloopParser;
780
781 }
782
783 #include "blocParsers.hxx"
784 #include "switchParsers.hxx"
785
786 namespace YACS
787 {
788
789 template <class T>
790 void looptypeParser<T>::onStart(const XML_Char* el, const XML_Char** attr)
791 {
792   DEBTRACE( "looptypeParser::onStart: " << el )
793   std::string element(el);
794   this->maxcount("inline",1,element);
795   this->maxcount("sinline",1,element);
796   this->maxcount("service",1,element);
797   this->maxcount("server",1,element);
798   this->maxcount("remote",1,element);
799   this->maxcount("node",1,element);
800   this->maxcount("forloop",1,element);
801   this->maxcount("foreach",1,element);
802   this->maxcount("foreachdyn",1,element);
803   this->maxcount("optimizer",1,element);
804   this->maxcount("while",1,element);
805   this->maxcount("switch",1,element);
806   this->maxcount("bloc",1,element);
807   this->maxchoice(t3,1,element);
808   parser* pp=&parser::main_parser;
809   if(element == "property")pp=&propertytypeParser::propertyParser;
810   else if(element == "inline")pp=&inlinetypeParser<>::inlineParser;
811   else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser;
812   else if(element == "service")pp=&servicetypeParser<>::serviceParser;
813   else if(element == "server")pp=&servertypeParser<>::serverParser;
814   else if(element == "remote")pp=&remotetypeParser<>::remoteParser;
815   else if(element == "node")pp=&nodetypeParser<>::nodeParser;
816
817   else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser;
818   else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser;
819   else if(element == "foreachdyn")pp=&foreachloopdyntypeParser<>::foreachloopdynParser;
820   else if(element == "optimizer")pp=&optimizerlooptypeParser<>::optimizerloopParser;
821   else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser;
822   else if(element == "switch")pp=&switchtypeParser::switchParser;
823   else if(element == "bloc")pp=&bloctypeParser<>::blocParser;
824   else if(element == "datalink")pp=&linktypeParser<>::linkParser;
825   this->SetUserDataAndPush(pp);
826   pp->init();
827   pp->pre();
828   pp->buildAttr(attr);
829 }
830
831 template <class T>
832 void looptypeParser<T>::onEnd(const char *el,parser* child)
833 {
834   DEBTRACE( "looptypeParser::onEnd: " << el )
835   std::string element(el);
836   if(element == "property")property(((propertytypeParser*)child)->post());
837   else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post());
838   else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post());
839   else if(element == "service")service(((servicetypeParser<>*)child)->post());
840   else if(element == "server")server(((servertypeParser<>*)child)->post());
841   else if(element == "remote")remote(((remotetypeParser<>*)child)->post());
842   else if(element == "node")node(((nodetypeParser<>*)child)->post());
843
844   else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post());
845   else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post());
846   else if(element == "foreachdyn")foreachdyn(((foreachloopdyntypeParser<>*)child)->post());
847   else if(element == "optimizer")optimizer(((optimizerlooptypeParser<>*)child)->post());
848   else if(element == "while")while_(((whilelooptypeParser<>*)child)->post());
849   else if(element == "switch")switch_(((switchtypeParser*)child)->post());
850   else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post());
851
852   else if(element == "datalink") datalink(((linktypeParser<>*)child)->post());
853 }
854
855 }
856 #endif